1 //===-- CommandInterpreter.h ------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_INTERPRETER_COMMANDINTERPRETER_H 10 #define LLDB_INTERPRETER_COMMANDINTERPRETER_H 11 12 #include "lldb/Core/Debugger.h" 13 #include "lldb/Core/IOHandler.h" 14 #include "lldb/Interpreter/CommandAlias.h" 15 #include "lldb/Interpreter/CommandHistory.h" 16 #include "lldb/Interpreter/CommandObject.h" 17 #include "lldb/Interpreter/ScriptInterpreter.h" 18 #include "lldb/Utility/Args.h" 19 #include "lldb/Utility/Baton.h" 20 #include "lldb/Utility/Broadcaster.h" 21 #include "lldb/Utility/CompletionRequest.h" 22 #include "lldb/Utility/Event.h" 23 #include "lldb/Utility/Log.h" 24 #include "lldb/Utility/StreamString.h" 25 #include "lldb/Utility/StringList.h" 26 #include "lldb/Utility/StructuredData.h" 27 #include "lldb/lldb-forward.h" 28 #include "lldb/lldb-private.h" 29 30 #include <mutex> 31 #include <optional> 32 #include <stack> 33 #include <unordered_map> 34 35 namespace lldb_private { 36 class CommandInterpreter; 37 38 class CommandInterpreterRunResult { 39 public: 40 CommandInterpreterRunResult() = default; 41 GetNumErrors()42 uint32_t GetNumErrors() const { return m_num_errors; } 43 GetResult()44 lldb::CommandInterpreterResult GetResult() const { return m_result; } 45 IsResult(lldb::CommandInterpreterResult result)46 bool IsResult(lldb::CommandInterpreterResult result) { 47 return m_result == result; 48 } 49 50 protected: 51 friend CommandInterpreter; 52 IncrementNumberOfErrors()53 void IncrementNumberOfErrors() { m_num_errors++; } 54 SetResult(lldb::CommandInterpreterResult result)55 void SetResult(lldb::CommandInterpreterResult result) { m_result = result; } 56 57 private: 58 int m_num_errors = 0; 59 lldb::CommandInterpreterResult m_result = 60 lldb::eCommandInterpreterResultSuccess; 61 }; 62 63 class CommandInterpreterRunOptions { 64 public: 65 /// Construct a CommandInterpreterRunOptions object. This class is used to 66 /// control all the instances where we run multiple commands, e.g. 67 /// HandleCommands, HandleCommandsFromFile, RunCommandInterpreter. 68 /// 69 /// The meanings of the options in this object are: 70 /// 71 /// \param[in] stop_on_continue 72 /// If \b true, execution will end on the first command that causes the 73 /// process in the execution context to continue. If \b false, we won't 74 /// check the execution status. 75 /// \param[in] stop_on_error 76 /// If \b true, execution will end on the first command that causes an 77 /// error. 78 /// \param[in] stop_on_crash 79 /// If \b true, when a command causes the target to run, and the end of the 80 /// run is a signal or exception, stop executing the commands. 81 /// \param[in] echo_commands 82 /// If \b true, echo the command before executing it. If \b false, execute 83 /// silently. 84 /// \param[in] echo_comments 85 /// If \b true, echo command even if it is a pure comment line. If 86 /// \b false, print no ouput in this case. This setting has an effect only 87 /// if echo_commands is \b true. 88 /// \param[in] print_results 89 /// If \b true and the command succeeds, print the results of the command 90 /// after executing it. If \b false, execute silently. 91 /// \param[in] print_errors 92 /// If \b true and the command fails, print the results of the command 93 /// after executing it. If \b false, execute silently. 94 /// \param[in] add_to_history 95 /// If \b true add the commands to the command history. If \b false, don't 96 /// add them. 97 /// \param[in] handle_repeats 98 /// If \b true then treat empty lines as repeat commands even if the 99 /// interpreter is non-interactive. CommandInterpreterRunOptions(LazyBool stop_on_continue,LazyBool stop_on_error,LazyBool stop_on_crash,LazyBool echo_commands,LazyBool echo_comments,LazyBool print_results,LazyBool print_errors,LazyBool add_to_history,LazyBool handle_repeats)100 CommandInterpreterRunOptions(LazyBool stop_on_continue, 101 LazyBool stop_on_error, LazyBool stop_on_crash, 102 LazyBool echo_commands, LazyBool echo_comments, 103 LazyBool print_results, LazyBool print_errors, 104 LazyBool add_to_history, LazyBool handle_repeats) 105 : m_stop_on_continue(stop_on_continue), m_stop_on_error(stop_on_error), 106 m_stop_on_crash(stop_on_crash), m_echo_commands(echo_commands), 107 m_echo_comment_commands(echo_comments), m_print_results(print_results), 108 m_print_errors(print_errors), m_add_to_history(add_to_history), 109 m_allow_repeats(handle_repeats) {} 110 111 CommandInterpreterRunOptions() = default; 112 SetSilent(bool silent)113 void SetSilent(bool silent) { 114 LazyBool value = silent ? eLazyBoolNo : eLazyBoolYes; 115 116 m_print_results = value; 117 m_print_errors = value; 118 m_echo_commands = value; 119 m_echo_comment_commands = value; 120 m_add_to_history = value; 121 } 122 // These return the default behaviors if the behavior is not 123 // eLazyBoolCalculate. But I've also left the ivars public since for 124 // different ways of running the interpreter you might want to force 125 // different defaults... In that case, just grab the LazyBool ivars directly 126 // and do what you want with eLazyBoolCalculate. GetStopOnContinue()127 bool GetStopOnContinue() const { return DefaultToNo(m_stop_on_continue); } 128 SetStopOnContinue(bool stop_on_continue)129 void SetStopOnContinue(bool stop_on_continue) { 130 m_stop_on_continue = stop_on_continue ? eLazyBoolYes : eLazyBoolNo; 131 } 132 GetStopOnError()133 bool GetStopOnError() const { return DefaultToNo(m_stop_on_error); } 134 SetStopOnError(bool stop_on_error)135 void SetStopOnError(bool stop_on_error) { 136 m_stop_on_error = stop_on_error ? eLazyBoolYes : eLazyBoolNo; 137 } 138 GetStopOnCrash()139 bool GetStopOnCrash() const { return DefaultToNo(m_stop_on_crash); } 140 SetStopOnCrash(bool stop_on_crash)141 void SetStopOnCrash(bool stop_on_crash) { 142 m_stop_on_crash = stop_on_crash ? eLazyBoolYes : eLazyBoolNo; 143 } 144 GetEchoCommands()145 bool GetEchoCommands() const { return DefaultToYes(m_echo_commands); } 146 SetEchoCommands(bool echo_commands)147 void SetEchoCommands(bool echo_commands) { 148 m_echo_commands = echo_commands ? eLazyBoolYes : eLazyBoolNo; 149 } 150 GetEchoCommentCommands()151 bool GetEchoCommentCommands() const { 152 return DefaultToYes(m_echo_comment_commands); 153 } 154 SetEchoCommentCommands(bool echo_comments)155 void SetEchoCommentCommands(bool echo_comments) { 156 m_echo_comment_commands = echo_comments ? eLazyBoolYes : eLazyBoolNo; 157 } 158 GetPrintResults()159 bool GetPrintResults() const { return DefaultToYes(m_print_results); } 160 SetPrintResults(bool print_results)161 void SetPrintResults(bool print_results) { 162 m_print_results = print_results ? eLazyBoolYes : eLazyBoolNo; 163 } 164 GetPrintErrors()165 bool GetPrintErrors() const { return DefaultToYes(m_print_errors); } 166 SetPrintErrors(bool print_errors)167 void SetPrintErrors(bool print_errors) { 168 m_print_errors = print_errors ? eLazyBoolYes : eLazyBoolNo; 169 } 170 GetAddToHistory()171 bool GetAddToHistory() const { return DefaultToYes(m_add_to_history); } 172 SetAddToHistory(bool add_to_history)173 void SetAddToHistory(bool add_to_history) { 174 m_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; 175 } 176 GetAutoHandleEvents()177 bool GetAutoHandleEvents() const { 178 return DefaultToYes(m_auto_handle_events); 179 } 180 SetAutoHandleEvents(bool auto_handle_events)181 void SetAutoHandleEvents(bool auto_handle_events) { 182 m_auto_handle_events = auto_handle_events ? eLazyBoolYes : eLazyBoolNo; 183 } 184 GetSpawnThread()185 bool GetSpawnThread() const { return DefaultToNo(m_spawn_thread); } 186 SetSpawnThread(bool spawn_thread)187 void SetSpawnThread(bool spawn_thread) { 188 m_spawn_thread = spawn_thread ? eLazyBoolYes : eLazyBoolNo; 189 } 190 GetAllowRepeats()191 bool GetAllowRepeats() const { return DefaultToNo(m_allow_repeats); } 192 SetAllowRepeats(bool allow_repeats)193 void SetAllowRepeats(bool allow_repeats) { 194 m_allow_repeats = allow_repeats ? eLazyBoolYes : eLazyBoolNo; 195 } 196 197 LazyBool m_stop_on_continue = eLazyBoolCalculate; 198 LazyBool m_stop_on_error = eLazyBoolCalculate; 199 LazyBool m_stop_on_crash = eLazyBoolCalculate; 200 LazyBool m_echo_commands = eLazyBoolCalculate; 201 LazyBool m_echo_comment_commands = eLazyBoolCalculate; 202 LazyBool m_print_results = eLazyBoolCalculate; 203 LazyBool m_print_errors = eLazyBoolCalculate; 204 LazyBool m_add_to_history = eLazyBoolCalculate; 205 LazyBool m_auto_handle_events; 206 LazyBool m_spawn_thread; 207 LazyBool m_allow_repeats = eLazyBoolCalculate; 208 209 private: DefaultToYes(LazyBool flag)210 static bool DefaultToYes(LazyBool flag) { 211 switch (flag) { 212 case eLazyBoolNo: 213 return false; 214 default: 215 return true; 216 } 217 } 218 DefaultToNo(LazyBool flag)219 static bool DefaultToNo(LazyBool flag) { 220 switch (flag) { 221 case eLazyBoolYes: 222 return true; 223 default: 224 return false; 225 } 226 } 227 }; 228 229 class CommandInterpreter : public Broadcaster, 230 public Properties, 231 public IOHandlerDelegate { 232 public: 233 enum { 234 eBroadcastBitThreadShouldExit = (1 << 0), 235 eBroadcastBitResetPrompt = (1 << 1), 236 eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit 237 eBroadcastBitAsynchronousOutputData = (1 << 3), 238 eBroadcastBitAsynchronousErrorData = (1 << 4) 239 }; 240 241 /// Tristate boolean to manage children omission warnings. 242 enum ChildrenOmissionWarningStatus { 243 eNoOmission = 0, ///< No children were omitted. 244 eUnwarnedOmission = 1, ///< Children omitted, and not yet notified. 245 eWarnedOmission = 2 ///< Children omitted and notified. 246 }; 247 248 enum CommandTypes { 249 eCommandTypesBuiltin = 0x0001, ///< native commands such as "frame" 250 eCommandTypesUserDef = 0x0002, ///< scripted commands 251 eCommandTypesUserMW = 0x0004, ///< multiword commands (command containers) 252 eCommandTypesAliases = 0x0008, ///< aliases such as "po" 253 eCommandTypesHidden = 0x0010, ///< commands prefixed with an underscore 254 eCommandTypesAllThem = 0xFFFF ///< all commands 255 }; 256 257 using CommandReturnObjectCallback = 258 std::function<lldb::CommandReturnObjectCallbackResult( 259 CommandReturnObject &)>; 260 261 // The CommandAlias and CommandInterpreter both have a hand in 262 // substituting for alias commands. They work by writing special tokens 263 // in the template form of the Alias command, and then detecting them when the 264 // command is executed. These are the special tokens: 265 static const char *g_no_argument; 266 static const char *g_need_argument; 267 static const char *g_argument; 268 269 CommandInterpreter(Debugger &debugger, bool synchronous_execution); 270 271 ~CommandInterpreter() override = default; 272 273 // These two functions fill out the Broadcaster interface: 274 275 static llvm::StringRef GetStaticBroadcasterClass(); 276 GetBroadcasterClass()277 llvm::StringRef GetBroadcasterClass() const override { 278 return GetStaticBroadcasterClass(); 279 } 280 281 void SourceInitFileCwd(CommandReturnObject &result); 282 void SourceInitFileHome(CommandReturnObject &result, bool is_repl); 283 void SourceInitFileGlobal(CommandReturnObject &result); 284 285 bool AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, 286 bool can_replace); 287 288 Status AddUserCommand(llvm::StringRef name, 289 const lldb::CommandObjectSP &cmd_sp, bool can_replace); 290 291 lldb::CommandObjectSP GetCommandSPExact(llvm::StringRef cmd, 292 bool include_aliases = false) const; 293 294 CommandObject *GetCommandObject(llvm::StringRef cmd, 295 StringList *matches = nullptr, 296 StringList *descriptions = nullptr) const; 297 298 CommandObject *GetUserCommandObject(llvm::StringRef cmd, 299 StringList *matches = nullptr, 300 StringList *descriptions = nullptr) const; 301 302 CommandObject * 303 GetAliasCommandObject(llvm::StringRef cmd, StringList *matches = nullptr, 304 StringList *descriptions = nullptr) const; 305 306 /// Determine whether a root level, built-in command with this name exists. 307 bool CommandExists(llvm::StringRef cmd) const; 308 309 /// Determine whether an alias command with this name exists 310 bool AliasExists(llvm::StringRef cmd) const; 311 312 /// Determine whether a root-level user command with this name exists. 313 bool UserCommandExists(llvm::StringRef cmd) const; 314 315 /// Determine whether a root-level user multiword command with this name 316 /// exists. 317 bool UserMultiwordCommandExists(llvm::StringRef cmd) const; 318 319 /// Look up the command pointed to by path encoded in the arguments of 320 /// the incoming command object. If all the path components exist 321 /// and are all actual commands - not aliases, and the leaf command is a 322 /// multiword command, return the command. Otherwise return nullptr, and put 323 /// a useful diagnostic in the Status object. 324 /// 325 /// \param[in] path 326 /// An Args object holding the path in its arguments 327 /// \param[in] leaf_is_command 328 /// If true, return the container of the leaf name rather than looking up 329 /// the whole path as a leaf command. The leaf needn't exist in this case. 330 /// \param[in,out] result 331 /// If the path is not found, this error shows where we got off track. 332 /// \return 333 /// If found, a pointer to the CommandObjectMultiword pointed to by path, 334 /// or to the container of the leaf element is is_leaf_command. 335 /// Returns nullptr under two circumstances: 336 /// 1) The command in not found (check error.Fail) 337 /// 2) is_leaf is true and the path has only a leaf. We don't have a 338 /// dummy "contains everything MWC, so we return null here, but 339 /// in this case error.Success is true. 340 341 CommandObjectMultiword * 342 VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result); 343 344 CommandAlias *AddAlias(llvm::StringRef alias_name, 345 lldb::CommandObjectSP &command_obj_sp, 346 llvm::StringRef args_string = llvm::StringRef()); 347 348 /// Remove a command if it is removable (python or regex command). If \b force 349 /// is provided, the command is removed regardless of its removable status. 350 bool RemoveCommand(llvm::StringRef cmd, bool force = false); 351 352 bool RemoveAlias(llvm::StringRef alias_name); 353 354 bool GetAliasFullName(llvm::StringRef cmd, std::string &full_name) const; 355 356 bool RemoveUserMultiword(llvm::StringRef multiword_name); 357 358 // Do we want to allow top-level user multiword commands to be deleted? RemoveAllUserMultiword()359 void RemoveAllUserMultiword() { m_user_mw_dict.clear(); } 360 361 bool RemoveUser(llvm::StringRef alias_name); 362 RemoveAllUser()363 void RemoveAllUser() { m_user_dict.clear(); } 364 365 const CommandAlias *GetAlias(llvm::StringRef alias_name) const; 366 367 CommandObject *BuildAliasResult(llvm::StringRef alias_name, 368 std::string &raw_input_string, 369 std::string &alias_result, 370 CommandReturnObject &result); 371 372 bool HandleCommand(const char *command_line, LazyBool add_to_history, 373 const ExecutionContext &override_context, 374 CommandReturnObject &result); 375 376 bool HandleCommand(const char *command_line, LazyBool add_to_history, 377 CommandReturnObject &result, 378 bool force_repeat_command = false); 379 380 bool InterruptCommand(); 381 382 /// Execute a list of commands in sequence. 383 /// 384 /// \param[in] commands 385 /// The list of commands to execute. 386 /// \param[in,out] context 387 /// The execution context in which to run the commands. 388 /// \param[in] options 389 /// This object holds the options used to control when to stop, whether to 390 /// execute commands, 391 /// etc. 392 /// \param[out] result 393 /// This is marked as succeeding with no output if all commands execute 394 /// safely, 395 /// and failed with some explanation if we aborted executing the commands 396 /// at some point. 397 void HandleCommands(const StringList &commands, 398 const ExecutionContext &context, 399 const CommandInterpreterRunOptions &options, 400 CommandReturnObject &result); 401 402 void HandleCommands(const StringList &commands, 403 const CommandInterpreterRunOptions &options, 404 CommandReturnObject &result); 405 406 /// Execute a list of commands from a file. 407 /// 408 /// \param[in] file 409 /// The file from which to read in commands. 410 /// \param[in,out] context 411 /// The execution context in which to run the commands. 412 /// \param[in] options 413 /// This object holds the options used to control when to stop, whether to 414 /// execute commands, 415 /// etc. 416 /// \param[out] result 417 /// This is marked as succeeding with no output if all commands execute 418 /// safely, 419 /// and failed with some explanation if we aborted executing the commands 420 /// at some point. 421 void HandleCommandsFromFile(FileSpec &file, const ExecutionContext &context, 422 const CommandInterpreterRunOptions &options, 423 CommandReturnObject &result); 424 425 void HandleCommandsFromFile(FileSpec &file, 426 const CommandInterpreterRunOptions &options, 427 CommandReturnObject &result); 428 429 CommandObject *GetCommandObjectForCommand(llvm::StringRef &command_line); 430 431 /// Returns the auto-suggestion string that should be added to the given 432 /// command line. 433 std::optional<std::string> GetAutoSuggestionForCommand(llvm::StringRef line); 434 435 // This handles command line completion. 436 void HandleCompletion(CompletionRequest &request); 437 438 // This version just returns matches, and doesn't compute the substring. It 439 // is here so the Help command can call it for the first argument. 440 void HandleCompletionMatches(CompletionRequest &request); 441 442 int GetCommandNamesMatchingPartialString(const char *cmd_cstr, 443 bool include_aliases, 444 StringList &matches, 445 StringList &descriptions); 446 447 void GetHelp(CommandReturnObject &result, 448 uint32_t types = eCommandTypesAllThem); 449 450 void GetAliasHelp(const char *alias_name, StreamString &help_string); 451 452 void OutputFormattedHelpText(Stream &strm, llvm::StringRef prefix, 453 llvm::StringRef help_text); 454 455 void OutputFormattedHelpText(Stream &stream, llvm::StringRef command_word, 456 llvm::StringRef separator, 457 llvm::StringRef help_text, size_t max_word_len); 458 459 // this mimics OutputFormattedHelpText but it does perform a much simpler 460 // formatting, basically ensuring line alignment. This is only good if you 461 // have some complicated layout for your help text and want as little help as 462 // reasonable in properly displaying it. Most of the times, you simply want 463 // to type some text and have it printed in a reasonable way on screen. If 464 // so, use OutputFormattedHelpText 465 void OutputHelpText(Stream &stream, llvm::StringRef command_word, 466 llvm::StringRef separator, llvm::StringRef help_text, 467 uint32_t max_word_len); 468 GetDebugger()469 Debugger &GetDebugger() { return m_debugger; } 470 471 ExecutionContext GetExecutionContext() const; 472 473 lldb::PlatformSP GetPlatform(bool prefer_target_platform); 474 475 const char *ProcessEmbeddedScriptCommands(const char *arg); 476 477 void UpdatePrompt(llvm::StringRef prompt); 478 479 void UpdateUseColor(bool use_color); 480 481 bool Confirm(llvm::StringRef message, bool default_answer); 482 483 void LoadCommandDictionary(); 484 485 void Initialize(); 486 487 void Clear(); 488 489 bool HasCommands() const; 490 491 bool HasAliases() const; 492 493 bool HasUserCommands() const; 494 495 bool HasUserMultiwordCommands() const; 496 497 bool HasAliasOptions() const; 498 499 void BuildAliasCommandArgs(CommandObject *alias_cmd_obj, 500 const char *alias_name, Args &cmd_args, 501 std::string &raw_input_string, 502 CommandReturnObject &result); 503 504 /// Picks the number out of a string of the form "%NNN", otherwise return 0. 505 int GetOptionArgumentPosition(const char *in_string); 506 SkipLLDBInitFiles(bool skip_lldbinit_files)507 void SkipLLDBInitFiles(bool skip_lldbinit_files) { 508 m_skip_lldbinit_files = skip_lldbinit_files; 509 } 510 SkipAppInitFiles(bool skip_app_init_files)511 void SkipAppInitFiles(bool skip_app_init_files) { 512 m_skip_app_init_files = skip_app_init_files; 513 } 514 515 bool GetSynchronous(); 516 517 void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, 518 StringList &commands_help, 519 bool search_builtin_commands, 520 bool search_user_commands, 521 bool search_alias_commands, 522 bool search_user_mw_commands); 523 GetBatchCommandMode()524 bool GetBatchCommandMode() { return m_batch_command_mode; } 525 SetBatchCommandMode(bool value)526 bool SetBatchCommandMode(bool value) { 527 const bool old_value = m_batch_command_mode; 528 m_batch_command_mode = value; 529 return old_value; 530 } 531 ChildrenTruncated()532 void ChildrenTruncated() { 533 if (m_truncation_warning == eNoOmission) 534 m_truncation_warning = eUnwarnedOmission; 535 } 536 SetReachedMaximumDepth()537 void SetReachedMaximumDepth() { 538 if (m_max_depth_warning == eNoOmission) 539 m_max_depth_warning = eUnwarnedOmission; 540 } 541 PrintWarningsIfNecessary(Stream & s,const std::string & cmd_name)542 void PrintWarningsIfNecessary(Stream &s, const std::string &cmd_name) { 543 if (m_truncation_warning == eUnwarnedOmission) { 544 s.Printf("*** Some of the displayed variables have more members than the " 545 "debugger will show by default. To show all of them, you can " 546 "either use the --show-all-children option to %s or raise the " 547 "limit by changing the target.max-children-count setting.\n", 548 cmd_name.c_str()); 549 m_truncation_warning = eWarnedOmission; 550 } 551 552 if (m_max_depth_warning == eUnwarnedOmission) { 553 s.Printf("*** Some of the displayed variables have a greater depth of " 554 "members than the debugger will show by default. To increase " 555 "the limit, use the --depth option to %s, or raise the limit by " 556 "changing the target.max-children-depth setting.\n", 557 cmd_name.c_str()); 558 m_max_depth_warning = eWarnedOmission; 559 } 560 } 561 GetCommandHistory()562 CommandHistory &GetCommandHistory() { return m_command_history; } 563 564 bool IsActive(); 565 566 CommandInterpreterRunResult 567 RunCommandInterpreter(CommandInterpreterRunOptions &options); 568 569 void GetLLDBCommandsFromIOHandler(const char *prompt, 570 IOHandlerDelegate &delegate, 571 void *baton = nullptr); 572 573 void GetPythonCommandsFromIOHandler(const char *prompt, 574 IOHandlerDelegate &delegate, 575 void *baton = nullptr); 576 577 const char *GetCommandPrefix(); 578 579 // Properties 580 bool GetExpandRegexAliases() const; 581 582 bool GetPromptOnQuit() const; 583 void SetPromptOnQuit(bool enable); 584 585 bool GetSaveTranscript() const; 586 void SetSaveTranscript(bool enable); 587 588 bool GetSaveSessionOnQuit() const; 589 void SetSaveSessionOnQuit(bool enable); 590 591 bool GetOpenTranscriptInEditor() const; 592 void SetOpenTranscriptInEditor(bool enable); 593 594 FileSpec GetSaveSessionDirectory() const; 595 void SetSaveSessionDirectory(llvm::StringRef path); 596 597 bool GetEchoCommands() const; 598 void SetEchoCommands(bool enable); 599 600 bool GetEchoCommentCommands() const; 601 void SetEchoCommentCommands(bool enable); 602 603 bool GetRepeatPreviousCommand() const; 604 605 bool GetRequireCommandOverwrite() const; 606 GetUserCommands()607 const CommandObject::CommandMap &GetUserCommands() const { 608 return m_user_dict; 609 } 610 GetUserMultiwordCommands()611 const CommandObject::CommandMap &GetUserMultiwordCommands() const { 612 return m_user_mw_dict; 613 } 614 GetCommands()615 const CommandObject::CommandMap &GetCommands() const { 616 return m_command_dict; 617 } 618 GetAliases()619 const CommandObject::CommandMap &GetAliases() const { return m_alias_dict; } 620 621 /// Specify if the command interpreter should allow that the user can 622 /// specify a custom exit code when calling 'quit'. 623 void AllowExitCodeOnQuit(bool allow); 624 625 /// Sets the exit code for the quit command. 626 /// \param[in] exit_code 627 /// The exit code that the driver should return on exit. 628 /// \return True if the exit code was successfully set; false if the 629 /// interpreter doesn't allow custom exit codes. 630 /// \see AllowExitCodeOnQuit 631 [[nodiscard]] bool SetQuitExitCode(int exit_code); 632 633 /// Returns the exit code that the user has specified when running the 634 /// 'quit' command. 635 /// \param[out] exited 636 /// Set to true if the user has called quit with a custom exit code. 637 int GetQuitExitCode(bool &exited) const; 638 639 void ResolveCommand(const char *command_line, CommandReturnObject &result); 640 641 bool GetStopCmdSourceOnError() const; 642 643 lldb::IOHandlerSP 644 GetIOHandler(bool force_create = false, 645 CommandInterpreterRunOptions *options = nullptr); 646 647 bool GetSpaceReplPrompts() const; 648 649 /// Save the current debugger session transcript to a file on disk. 650 /// \param output_file 651 /// The file path to which the session transcript will be written. Since 652 /// the argument is optional, an arbitrary temporary file will be create 653 /// when no argument is passed. 654 /// \param result 655 /// This is used to pass function output and error messages. 656 /// \return \b true if the session transcript was successfully written to 657 /// disk, \b false otherwise. 658 bool SaveTranscript(CommandReturnObject &result, 659 std::optional<std::string> output_file = std::nullopt); 660 661 FileSpec GetCurrentSourceDir(); 662 663 bool IsInteractive(); 664 665 bool IOHandlerInterrupt(IOHandler &io_handler) override; 666 667 Status PreprocessCommand(std::string &command); 668 Status PreprocessToken(std::string &token); 669 IncreaseCommandUsage(const CommandObject & cmd_obj)670 void IncreaseCommandUsage(const CommandObject &cmd_obj) { 671 ++m_command_usages[cmd_obj.GetCommandName()]; 672 } 673 674 void SetPrintCallback(CommandReturnObjectCallback callback); 675 676 llvm::json::Value GetStatistics(); 677 const StructuredData::Array &GetTranscript() const; 678 679 protected: 680 friend class Debugger; 681 682 // This checks just the RunCommandInterpreter interruption state. It is only 683 // meant to be used in Debugger::InterruptRequested 684 bool WasInterrupted() const; 685 686 // IOHandlerDelegate functions 687 void IOHandlerInputComplete(IOHandler &io_handler, 688 std::string &line) override; 689 IOHandlerGetControlSequence(char ch)690 llvm::StringRef IOHandlerGetControlSequence(char ch) override { 691 static constexpr llvm::StringLiteral control_sequence("quit\n"); 692 if (ch == 'd') 693 return control_sequence; 694 return {}; 695 } 696 697 void GetProcessOutput(); 698 699 bool DidProcessStopAbnormally() const; 700 701 void SetSynchronous(bool value); 702 703 lldb::CommandObjectSP GetCommandSP(llvm::StringRef cmd, 704 bool include_aliases = true, 705 bool exact = true, 706 StringList *matches = nullptr, 707 StringList *descriptions = nullptr) const; 708 709 private: 710 void OverrideExecutionContext(const ExecutionContext &override_context); 711 712 void RestoreExecutionContext(); 713 714 void SourceInitFile(FileSpec file, CommandReturnObject &result); 715 716 // Completely resolves aliases and abbreviations, returning a pointer to the 717 // final command object and updating command_line to the fully substituted 718 // and translated command. 719 CommandObject *ResolveCommandImpl(std::string &command_line, 720 CommandReturnObject &result); 721 722 void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, 723 StringList &commands_help, 724 const CommandObject::CommandMap &command_map); 725 726 // An interruptible wrapper around the stream output 727 void PrintCommandOutput(IOHandler &io_handler, llvm::StringRef str, 728 bool is_stdout); 729 730 bool EchoCommandNonInteractive(llvm::StringRef line, 731 const Flags &io_handler_flags) const; 732 733 /// Return the language specific command object for the current frame. 734 /// 735 /// For example, when stopped on a C++ frame, this returns the command object 736 /// for "language cplusplus" (`CommandObjectMultiwordItaniumABI`). 737 lldb::CommandObjectSP GetFrameLanguageCommand() const; 738 739 // A very simple state machine which models the command handling transitions 740 enum class CommandHandlingState { 741 eIdle, 742 eInProgress, 743 eInterrupted, 744 }; 745 746 std::atomic<CommandHandlingState> m_command_state{ 747 CommandHandlingState::eIdle}; 748 749 int m_iohandler_nesting_level = 0; 750 751 void StartHandlingCommand(); 752 void FinishHandlingCommand(); 753 754 Debugger &m_debugger; // The debugger session that this interpreter is 755 // associated with 756 // Execution contexts that were temporarily set by some of HandleCommand* 757 // overloads. 758 std::stack<ExecutionContext> m_overriden_exe_contexts; 759 bool m_synchronous_execution; 760 bool m_skip_lldbinit_files; 761 bool m_skip_app_init_files; 762 CommandObject::CommandMap m_command_dict; // Stores basic built-in commands 763 // (they cannot be deleted, removed 764 // or overwritten). 765 CommandObject::CommandMap 766 m_alias_dict; // Stores user aliases/abbreviations for commands 767 CommandObject::CommandMap m_user_dict; // Stores user-defined commands 768 CommandObject::CommandMap 769 m_user_mw_dict; // Stores user-defined multiword commands 770 CommandHistory m_command_history; 771 std::string m_repeat_command; // Stores the command that will be executed for 772 // an empty command string. 773 lldb::IOHandlerSP m_command_io_handler_sp; 774 char m_comment_char; 775 bool m_batch_command_mode; 776 /// Whether we truncated a value's list of children and whether the user has 777 /// been told. 778 ChildrenOmissionWarningStatus m_truncation_warning; 779 /// Whether we reached the maximum child nesting depth and whether the user 780 /// has been told. 781 ChildrenOmissionWarningStatus m_max_depth_warning; 782 783 // FIXME: Stop using this to control adding to the history and then replace 784 // this with m_command_source_dirs.size(). 785 uint32_t m_command_source_depth; 786 /// A stack of directory paths. When not empty, the last one is the directory 787 /// of the file that's currently sourced. 788 std::vector<FileSpec> m_command_source_dirs; 789 std::vector<uint32_t> m_command_source_flags; 790 CommandInterpreterRunResult m_result; 791 792 /// An optional callback to handle printing the CommandReturnObject. 793 CommandReturnObjectCallback m_print_callback; 794 795 // The exit code the user has requested when calling the 'quit' command. 796 // No value means the user hasn't set a custom exit code so far. 797 std::optional<int> m_quit_exit_code; 798 // If the driver is accepts custom exit codes for the 'quit' command. 799 bool m_allow_exit_code = false; 800 801 /// Command usage statistics. 802 typedef llvm::StringMap<uint64_t> CommandUsageMap; 803 CommandUsageMap m_command_usages; 804 805 /// Turn on settings `interpreter.save-transcript` for LLDB to populate 806 /// this stream. Otherwise this stream is empty. 807 StreamString m_transcript_stream; 808 809 /// Contains a list of handled commands and their details. Each element in 810 /// the list is a dictionary with the following keys/values: 811 /// - "command" (string): The command that was given by the user. 812 /// - "commandName" (string): The name of the executed command. 813 /// - "commandArguments" (string): The arguments of the executed command. 814 /// - "output" (string): The output of the command. Empty ("") if no output. 815 /// - "error" (string): The error of the command. Empty ("") if no error. 816 /// - "durationInSeconds" (float): The time it took to execute the command. 817 /// - "timestampInEpochSeconds" (int): The timestamp when the command is 818 /// executed. 819 /// 820 /// Turn on settings `interpreter.save-transcript` for LLDB to populate 821 /// this list. Otherwise this list is empty. 822 StructuredData::Array m_transcript; 823 }; 824 825 } // namespace lldb_private 826 827 #endif // LLDB_INTERPRETER_COMMANDINTERPRETER_H 828