1696bd635SAlexander Shaposhnikov //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===// 2ebc09c36SJim Ingham // 3ebc09c36SJim Ingham // The LLVM Compiler Infrastructure 4ebc09c36SJim Ingham // 5ebc09c36SJim Ingham // This file is distributed under the University of Illinois Open Source 6ebc09c36SJim Ingham // License. See LICENSE.TXT for details. 7ebc09c36SJim Ingham // 8ebc09c36SJim Ingham //===----------------------------------------------------------------------===// 9ebc09c36SJim Ingham 10ebc09c36SJim Ingham // C Includes 11ebc09c36SJim Ingham // C++ Includes 12ebc09c36SJim Ingham // Other libraries and framework includes 130e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h" 140e5e5a79SGreg Clayton 15ebc09c36SJim Ingham // Project includes 166e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h" 1746d4aa21SEnrico Granata #include "CommandObjectHelp.h" 18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 1944d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 20be93a35aSEnrico Granata #include "lldb/Core/StringList.h" 21de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h" 227594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h" 23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 24de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h" 25ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 26012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h" 2745d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h" 287594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h" 29ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 3099f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h" 31ebc09c36SJim Ingham 32ebc09c36SJim Ingham using namespace lldb; 33ebc09c36SJim Ingham using namespace lldb_private; 34ebc09c36SJim Ingham 35ebc09c36SJim Ingham //------------------------------------------------------------------------- 36ebc09c36SJim Ingham // CommandObjectCommandsSource 37ebc09c36SJim Ingham //------------------------------------------------------------------------- 38ebc09c36SJim Ingham 391f0f5b5bSZachary Turner static OptionDefinition g_history_options[] = { 401f0f5b5bSZachary Turner // clang-format off 411f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, 421f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, 431f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, 441f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." }, 451f0f5b5bSZachary Turner // clang-format on 461f0f5b5bSZachary Turner }; 471f0f5b5bSZachary Turner 48b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed { 495a988416SJim Ingham public: 50b9c1b51eSKate Stone CommandObjectCommandsHistory(CommandInterpreter &interpreter) 51b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command history", 525a988416SJim Ingham "Dump the history of commands in this session.", 536e3d8e7fSEugene Zelenko nullptr), 54b9c1b51eSKate Stone m_options() {} 555a988416SJim Ingham 566e3d8e7fSEugene Zelenko ~CommandObjectCommandsHistory() override = default; 575a988416SJim Ingham 58b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 595a988416SJim Ingham 605a988416SJim Ingham protected: 61b9c1b51eSKate Stone class CommandOptions : public Options { 62a5a97ebeSJim Ingham public: 63b9c1b51eSKate Stone CommandOptions() 64b9c1b51eSKate Stone : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 65a5a97ebeSJim Ingham } 66a5a97ebeSJim Ingham 676e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 68a5a97ebeSJim Ingham 69fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 70b9c1b51eSKate Stone ExecutionContext *execution_context) override { 71a5a97ebeSJim Ingham Error error; 723bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 73a5a97ebeSJim Ingham 74b9c1b51eSKate Stone switch (short_option) { 75a5a97ebeSJim Ingham case 'c': 76fe11483bSZachary Turner error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 77a5a97ebeSJim Ingham break; 78a5a97ebeSJim Ingham case 's': 79fe11483bSZachary Turner if (option_arg == "end") { 807594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 817594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 82b9c1b51eSKate Stone } else 83fe11483bSZachary Turner error = m_start_idx.SetValueFromString(option_arg, 84b9c1b51eSKate Stone eVarSetOperationAssign); 857594f14fSEnrico Granata break; 867594f14fSEnrico Granata case 'e': 87fe11483bSZachary Turner error = 88fe11483bSZachary Turner m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 897594f14fSEnrico Granata break; 9063123b64SEnrico Granata case 'C': 9163123b64SEnrico Granata m_clear.SetCurrentValue(true); 9263123b64SEnrico Granata m_clear.SetOptionWasSet(); 93a5a97ebeSJim Ingham break; 94a5a97ebeSJim Ingham default: 95b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 96b9c1b51eSKate Stone short_option); 97a5a97ebeSJim Ingham break; 98a5a97ebeSJim Ingham } 99a5a97ebeSJim Ingham 100a5a97ebeSJim Ingham return error; 101a5a97ebeSJim Ingham } 102a5a97ebeSJim Ingham 103b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1047594f14fSEnrico Granata m_start_idx.Clear(); 1057594f14fSEnrico Granata m_stop_idx.Clear(); 1067594f14fSEnrico Granata m_count.Clear(); 10763123b64SEnrico Granata m_clear.Clear(); 108a5a97ebeSJim Ingham } 109a5a97ebeSJim Ingham 1101f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 11170602439SZachary Turner return llvm::makeArrayRef(g_history_options); 1121f0f5b5bSZachary Turner } 113a5a97ebeSJim Ingham 114a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 115a5a97ebeSJim Ingham 1167594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1177594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1187594f14fSEnrico Granata OptionValueUInt64 m_count; 11963123b64SEnrico Granata OptionValueBoolean m_clear; 120a5a97ebeSJim Ingham }; 121a5a97ebeSJim Ingham 122b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 123b9c1b51eSKate Stone if (m_options.m_clear.GetCurrentValue() && 124b9c1b51eSKate Stone m_options.m_clear.OptionWasSet()) { 1257594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1267594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 127b9c1b51eSKate Stone } else { 128b9c1b51eSKate Stone if (m_options.m_start_idx.OptionWasSet() && 129b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet() && 130b9c1b51eSKate Stone m_options.m_count.OptionWasSet()) { 131b9c1b51eSKate Stone result.AppendError("--count, --start-index and --end-index cannot be " 132b9c1b51eSKate Stone "all specified in the same invocation"); 1337594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 134b9c1b51eSKate Stone } else { 135b9c1b51eSKate Stone std::pair<bool, uint64_t> start_idx( 136b9c1b51eSKate Stone m_options.m_start_idx.OptionWasSet(), 137b9c1b51eSKate Stone m_options.m_start_idx.GetCurrentValue()); 138b9c1b51eSKate Stone std::pair<bool, uint64_t> stop_idx( 139b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet(), 140b9c1b51eSKate Stone m_options.m_stop_idx.GetCurrentValue()); 141b9c1b51eSKate Stone std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 142b9c1b51eSKate Stone m_options.m_count.GetCurrentValue()); 143a5a97ebeSJim Ingham 1447594f14fSEnrico Granata const CommandHistory &history(m_interpreter.GetCommandHistory()); 1457594f14fSEnrico Granata 146b9c1b51eSKate Stone if (start_idx.first && start_idx.second == UINT64_MAX) { 147b9c1b51eSKate Stone if (count.first) { 1487594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1497594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 150b9c1b51eSKate Stone } else if (stop_idx.first) { 1517594f14fSEnrico Granata start_idx.second = stop_idx.second; 1527594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 153b9c1b51eSKate Stone } else { 1547594f14fSEnrico Granata start_idx.second = 0; 1557594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1567594f14fSEnrico Granata } 157b9c1b51eSKate Stone } else { 158b9c1b51eSKate Stone if (!start_idx.first && !stop_idx.first && !count.first) { 1597594f14fSEnrico Granata start_idx.second = 0; 1607594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 161b9c1b51eSKate Stone } else if (start_idx.first) { 162b9c1b51eSKate Stone if (count.first) { 1637594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 164b9c1b51eSKate Stone } else if (!stop_idx.first) { 1657594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1667594f14fSEnrico Granata } 167b9c1b51eSKate Stone } else if (stop_idx.first) { 168b9c1b51eSKate Stone if (count.first) { 1697594f14fSEnrico Granata if (stop_idx.second >= count.second) 1707594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 1717594f14fSEnrico Granata else 1727594f14fSEnrico Granata start_idx.second = 0; 1737594f14fSEnrico Granata } 174b9c1b51eSKate Stone } else /* if (count.first) */ 1757594f14fSEnrico Granata { 1767594f14fSEnrico Granata start_idx.second = 0; 1777594f14fSEnrico Granata stop_idx.second = count.second - 1; 1787594f14fSEnrico Granata } 1797594f14fSEnrico Granata } 180b9c1b51eSKate Stone history.Dump(result.GetOutputStream(), start_idx.second, 181b9c1b51eSKate Stone stop_idx.second); 1827594f14fSEnrico Granata } 1837594f14fSEnrico Granata } 184a5a97ebeSJim Ingham return result.Succeeded(); 185a5a97ebeSJim Ingham } 1865a988416SJim Ingham 1875a988416SJim Ingham CommandOptions m_options; 188a5a97ebeSJim Ingham }; 189a5a97ebeSJim Ingham 190a5a97ebeSJim Ingham //------------------------------------------------------------------------- 191a5a97ebeSJim Ingham // CommandObjectCommandsSource 192a5a97ebeSJim Ingham //------------------------------------------------------------------------- 193a5a97ebeSJim Ingham 1941f0f5b5bSZachary Turner static OptionDefinition g_source_options[] = { 1951f0f5b5bSZachary Turner // clang-format off 1961f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, 1971f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, 1981f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, 1991f0f5b5bSZachary Turner // clang-format on 2001f0f5b5bSZachary Turner }; 2011f0f5b5bSZachary Turner 202b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed { 2035a988416SJim Ingham public: 2047428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 205b9c1b51eSKate Stone : CommandObjectParsed( 206b9c1b51eSKate Stone interpreter, "command source", 207b9c1b51eSKate Stone "Read and execute LLDB commands from the file <filename>.", 2086e3d8e7fSEugene Zelenko nullptr), 209b9c1b51eSKate Stone m_options() { 2105a988416SJim Ingham CommandArgumentEntry arg; 2115a988416SJim Ingham CommandArgumentData file_arg; 2125a988416SJim Ingham 2135a988416SJim Ingham // Define the first (and only) variant of this arg. 2145a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2155a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2165a988416SJim Ingham 217b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 218b9c1b51eSKate Stone // argument entry. 2195a988416SJim Ingham arg.push_back(file_arg); 2205a988416SJim Ingham 2215a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2225a988416SJim Ingham m_arguments.push_back(arg); 2235a988416SJim Ingham } 2245a988416SJim Ingham 2256e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2265a988416SJim Ingham 227b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 228b9c1b51eSKate Stone uint32_t index) override { 2295a988416SJim Ingham return ""; 2305a988416SJim Ingham } 2315a988416SJim Ingham 232b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 2335a988416SJim Ingham int &cursor_char_position, 2345a988416SJim Ingham OptionElementVector &opt_element_vector, 235b9c1b51eSKate Stone int match_start_point, int max_return_elements, 2365a988416SJim Ingham bool &word_complete, 237b9c1b51eSKate Stone StringList &matches) override { 238*4574a890SZachary Turner auto completion_str = input[cursor_index].ref; 239*4574a890SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 2405a988416SJim Ingham 241b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 242b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 243*4574a890SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 244b9c1b51eSKate Stone word_complete, matches); 2455a988416SJim Ingham return matches.GetSize(); 2465a988416SJim Ingham } 2475a988416SJim Ingham 248b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 2495a988416SJim Ingham 2505a988416SJim Ingham protected: 251b9c1b51eSKate Stone class CommandOptions : public Options { 252e16c50a1SJim Ingham public: 253b9c1b51eSKate Stone CommandOptions() 254b9c1b51eSKate Stone : Options(), m_stop_on_error(true), m_silent_run(false), 255b9c1b51eSKate Stone m_stop_on_continue(true) {} 256e16c50a1SJim Ingham 2576e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 258e16c50a1SJim Ingham 259fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 260b9c1b51eSKate Stone ExecutionContext *execution_context) override { 261e16c50a1SJim Ingham Error error; 2623bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 263e16c50a1SJim Ingham 264b9c1b51eSKate Stone switch (short_option) { 265e16c50a1SJim Ingham case 'e': 266fe11483bSZachary Turner error = m_stop_on_error.SetValueFromString(option_arg); 267e16c50a1SJim Ingham break; 268340b0309SGreg Clayton 269e16c50a1SJim Ingham case 'c': 270fe11483bSZachary Turner error = m_stop_on_continue.SetValueFromString(option_arg); 271e16c50a1SJim Ingham break; 272340b0309SGreg Clayton 27360986174SMichael Sartain case 's': 274fe11483bSZachary Turner error = m_silent_run.SetValueFromString(option_arg); 27560986174SMichael Sartain break; 276340b0309SGreg Clayton 277e16c50a1SJim Ingham default: 278b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 279b9c1b51eSKate Stone short_option); 280e16c50a1SJim Ingham break; 281e16c50a1SJim Ingham } 282e16c50a1SJim Ingham 283e16c50a1SJim Ingham return error; 284e16c50a1SJim Ingham } 285e16c50a1SJim Ingham 286b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 287012d4fcaSEnrico Granata m_stop_on_error.Clear(); 288340b0309SGreg Clayton m_silent_run.Clear(); 289340b0309SGreg Clayton m_stop_on_continue.Clear(); 290e16c50a1SJim Ingham } 291e16c50a1SJim Ingham 2921f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 29370602439SZachary Turner return llvm::makeArrayRef(g_source_options); 2941f0f5b5bSZachary Turner } 295e16c50a1SJim Ingham 296e16c50a1SJim Ingham // Instance variables to hold the values for command options. 297e16c50a1SJim Ingham 298012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 299340b0309SGreg Clayton OptionValueBoolean m_silent_run; 300340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 301e16c50a1SJim Ingham }; 302e16c50a1SJim Ingham 303b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 304*4574a890SZachary Turner if (command.GetArgumentCount() != 1) { 305*4574a890SZachary Turner result.AppendErrorWithFormat( 306*4574a890SZachary Turner "'%s' takes exactly one executable filename argument.\n", 307*4574a890SZachary Turner GetCommandName().str().c_str()); 308*4574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 309*4574a890SZachary Turner return false; 310*4574a890SZachary Turner } 311ebc09c36SJim Ingham 312*4574a890SZachary Turner FileSpec cmd_file(command[0].ref, true); 3136e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 314ebc09c36SJim Ingham 315340b0309SGreg Clayton // If any options were set, then use them 316340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 317340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 318b9c1b51eSKate Stone m_options.m_stop_on_continue.OptionWasSet()) { 319340b0309SGreg Clayton // Use user set settings 32026c7bf93SJim Ingham CommandInterpreterRunOptions options; 321*4574a890SZachary Turner options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 32226c7bf93SJim Ingham options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 3237d8555c4SJim Ingham options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue()); 3247d8555c4SJim Ingham options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue()); 32526c7bf93SJim Ingham 326*4574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 327b9c1b51eSKate Stone } else { 328b9c1b51eSKate Stone // No options were set, inherit any settings from nested "command 329b9c1b51eSKate Stone // source" commands, 330340b0309SGreg Clayton // or set to sane default settings... 33126c7bf93SJim Ingham CommandInterpreterRunOptions options; 332*4574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 333ebc09c36SJim Ingham } 334ebc09c36SJim Ingham return result.Succeeded(); 335ebc09c36SJim Ingham } 3366e3d8e7fSEugene Zelenko 3375a988416SJim Ingham CommandOptions m_options; 338ebc09c36SJim Ingham }; 339ebc09c36SJim Ingham 340ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 341ebc09c36SJim Ingham //------------------------------------------------------------------------- 342ebc09c36SJim Ingham // CommandObjectCommandsAlias 343ebc09c36SJim Ingham //------------------------------------------------------------------------- 344ebc09c36SJim Ingham 3451f0f5b5bSZachary Turner static OptionDefinition g_alias_options[] = { 3461f0f5b5bSZachary Turner // clang-format off 3471f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" }, 3481f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" }, 3491f0f5b5bSZachary Turner // clang-format on 3501f0f5b5bSZachary Turner }; 3511f0f5b5bSZachary Turner 352b9c1b51eSKate Stone static const char *g_python_command_instructions = 353b9c1b51eSKate Stone "Enter your Python command(s). Type 'DONE' to end.\n" 354be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 35544d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 356be93a35aSEnrico Granata 357b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw { 35845d0e238SEnrico Granata protected: 359b9c1b51eSKate Stone class CommandOptions : public OptionGroup { 360ebc09c36SJim Ingham public: 361b9c1b51eSKate Stone CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 36245d0e238SEnrico Granata 36345d0e238SEnrico Granata ~CommandOptions() override = default; 36445d0e238SEnrico Granata 3651f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 36670602439SZachary Turner return llvm::makeArrayRef(g_alias_options); 3671f0f5b5bSZachary Turner } 36845d0e238SEnrico Granata 3698cef4b0bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 370b9c1b51eSKate Stone ExecutionContext *execution_context) override { 37145d0e238SEnrico Granata Error error; 37245d0e238SEnrico Granata 3731f0f5b5bSZachary Turner const int short_option = GetDefinitions()[option_idx].short_option; 3748cef4b0bSZachary Turner std::string option_str(option_value); 37545d0e238SEnrico Granata 376b9c1b51eSKate Stone switch (short_option) { 37745d0e238SEnrico Granata case 'h': 3788cef4b0bSZachary Turner m_help.SetCurrentValue(option_str); 37945d0e238SEnrico Granata m_help.SetOptionWasSet(); 38045d0e238SEnrico Granata break; 38145d0e238SEnrico Granata 38245d0e238SEnrico Granata case 'H': 3838cef4b0bSZachary Turner m_long_help.SetCurrentValue(option_str); 38445d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 38545d0e238SEnrico Granata break; 38645d0e238SEnrico Granata 38745d0e238SEnrico Granata default: 388b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid short option character '%c'", 389b9c1b51eSKate Stone short_option); 39045d0e238SEnrico Granata break; 39145d0e238SEnrico Granata } 39245d0e238SEnrico Granata 39345d0e238SEnrico Granata return error; 39445d0e238SEnrico Granata } 39545d0e238SEnrico Granata 396b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 39745d0e238SEnrico Granata m_help.Clear(); 39845d0e238SEnrico Granata m_long_help.Clear(); 39945d0e238SEnrico Granata } 40045d0e238SEnrico Granata 40145d0e238SEnrico Granata OptionValueString m_help; 40245d0e238SEnrico Granata OptionValueString m_long_help; 40345d0e238SEnrico Granata }; 40445d0e238SEnrico Granata 40545d0e238SEnrico Granata OptionGroupOptions m_option_group; 40645d0e238SEnrico Granata CommandOptions m_command_options; 40745d0e238SEnrico Granata 40845d0e238SEnrico Granata public: 409b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 41045d0e238SEnrico Granata 4117428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 412b9c1b51eSKate Stone : CommandObjectRaw( 413b9c1b51eSKate Stone interpreter, "command alias", 414a449698cSZachary Turner "Define a custom command in terms of an existing command."), 415b9c1b51eSKate Stone m_option_group(), m_command_options() { 41645d0e238SEnrico Granata m_option_group.Append(&m_command_options); 41745d0e238SEnrico Granata m_option_group.Finalize(); 41845d0e238SEnrico Granata 419ebc09c36SJim Ingham SetHelpLong( 420ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 421ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 422b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:" 423b9c1b51eSKate Stone R"( 424ea671fbdSKate Stone 425ea671fbdSKate Stone (lldb) command alias sc script 426ea671fbdSKate Stone 427ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 428ea671fbdSKate Stone 429ea671fbdSKate Stone (lldb) command alias bp breakpoint 430ea671fbdSKate Stone 431b9c1b51eSKate Stone )" 432b9c1b51eSKate Stone " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 433ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 434b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 435b9c1b51eSKate Stone R"( 436ea671fbdSKate Stone 437ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 438ea671fbdSKate Stone 439ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 440ea671fbdSKate Stone 441b9c1b51eSKate Stone )" 442b9c1b51eSKate Stone "An alias can include some options for the command, with the values either \ 443ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 444ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 445b9c1b51eSKate Stone shows how to create aliases with options:" 446b9c1b51eSKate Stone R"( 447ea671fbdSKate Stone 448ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 449ea671fbdSKate Stone 450b9c1b51eSKate Stone )" 451b9c1b51eSKate Stone " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 452ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 453ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 454ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 455ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 456ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 457ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 458ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 459ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 460ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 461b9c1b51eSKate Stone launch' example below)." 462b9c1b51eSKate Stone R"( 463ea671fbdSKate Stone 464b9c1b51eSKate Stone )" 465b9c1b51eSKate Stone "Note: the positional arguments must substitute as whole words in the resultant \ 466ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 467b9c1b51eSKate Stone \".cpp\":" 468b9c1b51eSKate Stone R"( 469ea671fbdSKate Stone 470ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 471ea671fbdSKate Stone 472b9c1b51eSKate Stone )" 473b9c1b51eSKate Stone "For more complex aliasing, use the \"command regex\" command instead. In the \ 474ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 475ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 476b9c1b51eSKate Stone argument. The user would use this alias as follows:" 477b9c1b51eSKate Stone R"( 478ea671fbdSKate Stone 479ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 480ea671fbdSKate Stone (lldb) bfl my-file.c 137 481ea671fbdSKate Stone 482ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 483ea671fbdSKate Stone 484ea671fbdSKate Stone Another example: 485ea671fbdSKate Stone 486ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 487ea671fbdSKate Stone (lldb) pltty /dev/tty0 488ea671fbdSKate Stone 489ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 490ea671fbdSKate Stone 491b9c1b51eSKate Stone )" 492b9c1b51eSKate Stone "If the user always wanted to pass the same value to a particular option, the \ 493ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 494b9c1b51eSKate Stone rather than using a positional placeholder:" 495b9c1b51eSKate Stone R"( 496ea671fbdSKate Stone 497ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 498ea671fbdSKate Stone 499b9c1b51eSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)"); 500ebc09c36SJim Ingham 501405fe67fSCaroline Tice CommandArgumentEntry arg1; 502405fe67fSCaroline Tice CommandArgumentEntry arg2; 503405fe67fSCaroline Tice CommandArgumentEntry arg3; 504405fe67fSCaroline Tice CommandArgumentData alias_arg; 505405fe67fSCaroline Tice CommandArgumentData cmd_arg; 506405fe67fSCaroline Tice CommandArgumentData options_arg; 507405fe67fSCaroline Tice 508405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 509405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 510405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 511405fe67fSCaroline Tice 512b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 513b9c1b51eSKate Stone // argument entry. 514405fe67fSCaroline Tice arg1.push_back(alias_arg); 515405fe67fSCaroline Tice 516405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 517405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 518405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 519405fe67fSCaroline Tice 520b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 521b9c1b51eSKate Stone // argument entry. 522405fe67fSCaroline Tice arg2.push_back(cmd_arg); 523405fe67fSCaroline Tice 524405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 525405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 526405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 527405fe67fSCaroline Tice 528b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 529b9c1b51eSKate Stone // argument entry. 530405fe67fSCaroline Tice arg3.push_back(options_arg); 531405fe67fSCaroline Tice 532405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 533405fe67fSCaroline Tice m_arguments.push_back(arg1); 534405fe67fSCaroline Tice m_arguments.push_back(arg2); 535405fe67fSCaroline Tice m_arguments.push_back(arg3); 536ebc09c36SJim Ingham } 537ebc09c36SJim Ingham 5386e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 539ebc09c36SJim Ingham 5405a988416SJim Ingham protected: 541b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 542b9c1b51eSKate Stone CommandReturnObject &result) override { 543b9c1b51eSKate Stone if (!raw_command_line || !raw_command_line[0]) { 544d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 54545d0e238SEnrico Granata return false; 54645d0e238SEnrico Granata } 54745d0e238SEnrico Granata 548e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 549e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 55045d0e238SEnrico Granata 55145d0e238SEnrico Granata const char *remainder = nullptr; 55245d0e238SEnrico Granata 553b9c1b51eSKate Stone if (raw_command_line[0] == '-') { 55445d0e238SEnrico Granata // We have some options and these options MUST end with --. 55545d0e238SEnrico Granata const char *end_options = nullptr; 55645d0e238SEnrico Granata const char *s = raw_command_line; 557b9c1b51eSKate Stone while (s && s[0]) { 55845d0e238SEnrico Granata end_options = ::strstr(s, "--"); 559b9c1b51eSKate Stone if (end_options) { 56045d0e238SEnrico Granata end_options += 2; // Get past the "--" 561b9c1b51eSKate Stone if (::isspace(end_options[0])) { 56245d0e238SEnrico Granata remainder = end_options; 56345d0e238SEnrico Granata while (::isspace(*remainder)) 56445d0e238SEnrico Granata ++remainder; 56545d0e238SEnrico Granata break; 56645d0e238SEnrico Granata } 56745d0e238SEnrico Granata } 56845d0e238SEnrico Granata s = end_options; 56945d0e238SEnrico Granata } 57045d0e238SEnrico Granata 571b9c1b51eSKate Stone if (end_options) { 572b9c1b51eSKate Stone Args args( 573b9c1b51eSKate Stone llvm::StringRef(raw_command_line, end_options - raw_command_line)); 57445d0e238SEnrico Granata if (!ParseOptions(args, result)) 57545d0e238SEnrico Granata return false; 57645d0e238SEnrico Granata 577e1cfbc79STodd Fiala Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); 578b9c1b51eSKate Stone if (error.Fail()) { 57945d0e238SEnrico Granata result.AppendError(error.AsCString()); 58045d0e238SEnrico Granata result.SetStatus(eReturnStatusFailed); 58145d0e238SEnrico Granata return false; 58245d0e238SEnrico Granata } 58345d0e238SEnrico Granata } 58445d0e238SEnrico Granata } 58545d0e238SEnrico Granata if (nullptr == remainder) 58645d0e238SEnrico Granata remainder = raw_command_line; 58745d0e238SEnrico Granata 588a01bccdbSZachary Turner llvm::StringRef raw_command_string(remainder); 589a01bccdbSZachary Turner Args args(raw_command_string); 590844d2303SCaroline Tice 59111eb9c64SZachary Turner if (args.GetArgumentCount() < 2) { 592d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 593844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 594844d2303SCaroline Tice return false; 595844d2303SCaroline Tice } 596844d2303SCaroline Tice 597844d2303SCaroline Tice // Get the alias command. 598844d2303SCaroline Tice 599*4574a890SZachary Turner auto alias_command = args[0].ref; 600*4574a890SZachary Turner if (alias_command.startswith("-")) { 601d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 602b9c1b51eSKate Stone if (alias_command == "--help" || alias_command == "--long-help") { 603b9c1b51eSKate Stone result.AppendWarning("if trying to pass options to 'command alias' add " 604b9c1b51eSKate Stone "a -- at the end of the options"); 605d72e412fSEnrico Granata } 606d72e412fSEnrico Granata result.SetStatus(eReturnStatusFailed); 607d72e412fSEnrico Granata return false; 608d72e412fSEnrico Granata } 609844d2303SCaroline Tice 610b9c1b51eSKate Stone // Strip the new alias name off 'raw_command_string' (leave it on args, 611b9c1b51eSKate Stone // which gets passed to 'Execute', which 612844d2303SCaroline Tice // does the stripping itself. 613844d2303SCaroline Tice size_t pos = raw_command_string.find(alias_command); 614b9c1b51eSKate Stone if (pos == 0) { 615844d2303SCaroline Tice raw_command_string = raw_command_string.substr(alias_command.size()); 616844d2303SCaroline Tice pos = raw_command_string.find_first_not_of(' '); 617844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 618844d2303SCaroline Tice raw_command_string = raw_command_string.substr(pos); 619b9c1b51eSKate Stone } else { 620844d2303SCaroline Tice result.AppendError("Error parsing command string. No alias created."); 621844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 622844d2303SCaroline Tice return false; 623844d2303SCaroline Tice } 624844d2303SCaroline Tice 625844d2303SCaroline Tice // Verify that the command is alias-able. 626771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 627b9c1b51eSKate Stone result.AppendErrorWithFormat( 628b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 629*4574a890SZachary Turner args[0].c_str()); 630844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 631844d2303SCaroline Tice return false; 632844d2303SCaroline Tice } 633844d2303SCaroline Tice 634b9c1b51eSKate Stone // Get CommandObject that is being aliased. The command name is read from 635a01bccdbSZachary Turner // the front of raw_command_string. raw_command_string is returned with the 636a01bccdbSZachary Turner // name of the command object stripped off the front. 637a01bccdbSZachary Turner llvm::StringRef original_raw_command_string = raw_command_string; 638b9c1b51eSKate Stone CommandObject *cmd_obj = 639b9c1b51eSKate Stone m_interpreter.GetCommandObjectForCommand(raw_command_string); 640844d2303SCaroline Tice 641b9c1b51eSKate Stone if (!cmd_obj) { 642b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command given to 'command alias'. " 643b9c1b51eSKate Stone "'%s' does not begin with a valid command." 644b9c1b51eSKate Stone " No alias created.", 645a01bccdbSZachary Turner original_raw_command_string.str().c_str()); 646844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 647844d2303SCaroline Tice return false; 648b9c1b51eSKate Stone } else if (!cmd_obj->WantsRawCommandString()) { 649b9c1b51eSKate Stone // Note that args was initialized with the original command, and has not 650b9c1b51eSKate Stone // been updated to this point. 651b9c1b51eSKate Stone // Therefore can we pass it to the version of Execute that does not 652b9c1b51eSKate Stone // need/expect raw input in the alias. 6535a988416SJim Ingham return HandleAliasingNormalCommand(args, result); 654b9c1b51eSKate Stone } else { 655b9c1b51eSKate Stone return HandleAliasingRawCommand(alias_command, raw_command_string, 656b9c1b51eSKate Stone *cmd_obj, result); 6575a988416SJim Ingham } 6585a988416SJim Ingham return result.Succeeded(); 6595a988416SJim Ingham } 6605a988416SJim Ingham 661a01bccdbSZachary Turner bool HandleAliasingRawCommand(llvm::StringRef alias_command, 662a01bccdbSZachary Turner llvm::StringRef raw_command_string, 663b9c1b51eSKate Stone CommandObject &cmd_obj, 664b9c1b51eSKate Stone CommandReturnObject &result) { 665844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 666844d2303SCaroline Tice 667b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 668b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 669844d2303SCaroline Tice 670b9c1b51eSKate Stone if (CommandObjectSP cmd_obj_sp = 671b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 672a01bccdbSZachary Turner if (m_interpreter.AliasExists(alias_command) || 673a01bccdbSZachary Turner m_interpreter.UserCommandExists(alias_command)) { 674b9c1b51eSKate Stone result.AppendWarningWithFormat( 675b9c1b51eSKate Stone "Overwriting existing definition for '%s'.\n", 676a01bccdbSZachary Turner alias_command.str().c_str()); 677844d2303SCaroline Tice } 678b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 679a01bccdbSZachary Turner alias_command, cmd_obj_sp, raw_command_string)) { 68045d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 68145d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 68245d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 68345d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 684844d2303SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 685b9c1b51eSKate Stone } else { 686472362e6SCaroline Tice result.AppendError("Unable to create requested alias.\n"); 687472362e6SCaroline Tice result.SetStatus(eReturnStatusFailed); 688472362e6SCaroline Tice } 689212130acSEnrico Granata 690b9c1b51eSKate Stone } else { 691212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 692212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 693212130acSEnrico Granata } 694212130acSEnrico Granata 695844d2303SCaroline Tice return result.Succeeded(); 696844d2303SCaroline Tice } 697ebc09c36SJim Ingham 698b9c1b51eSKate Stone bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 699867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 700ebc09c36SJim Ingham 701b9c1b51eSKate Stone if (argc < 2) { 702d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 703ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 704ebc09c36SJim Ingham return false; 705ebc09c36SJim Ingham } 706ebc09c36SJim Ingham 707*4574a890SZachary Turner // Save these in std::strings since we're going to shift them off. 708*4574a890SZachary Turner const std::string alias_command(args[0].ref); 709*4574a890SZachary Turner const std::string actual_command(args[1].ref); 710ebc09c36SJim Ingham 711ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 712ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 713ebc09c36SJim Ingham 714b9c1b51eSKate Stone // Verify that the command is alias'able, and get the appropriate command 715b9c1b51eSKate Stone // object. 716ebc09c36SJim Ingham 717771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 718b9c1b51eSKate Stone result.AppendErrorWithFormat( 719b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 720ebc09c36SJim Ingham alias_command.c_str()); 721ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 722*4574a890SZachary Turner return false; 723*4574a890SZachary Turner } 724*4574a890SZachary Turner 725b9c1b51eSKate Stone CommandObjectSP command_obj_sp( 726a449698cSZachary Turner m_interpreter.GetCommandSPExact(actual_command, true)); 727ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 728ebc09c36SJim Ingham bool use_subcommand = false; 729*4574a890SZachary Turner if (!command_obj_sp) { 730*4574a890SZachary Turner result.AppendErrorWithFormat("'%s' is not an existing command.\n", 731*4574a890SZachary Turner actual_command.c_str()); 732*4574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 733*4574a890SZachary Turner return false; 734*4574a890SZachary Turner } 735ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 7366e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 737b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 738b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 739ebc09c36SJim Ingham 74011eb9c64SZachary Turner while (cmd_obj->IsMultiwordObject() && !args.empty()) { 741*4574a890SZachary Turner auto sub_command = args[0].ref; 74211eb9c64SZachary Turner assert(!sub_command.empty()); 743*4574a890SZachary Turner subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 744*4574a890SZachary Turner if (!subcommand_obj_sp) { 745b9c1b51eSKate Stone result.AppendErrorWithFormat( 746b9c1b51eSKate Stone "'%s' is not a valid sub-command of '%s'. " 747f415eeb4SCaroline Tice "Unable to create alias.\n", 748*4574a890SZachary Turner args[0].c_str(), actual_command.c_str()); 749ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 750ebc09c36SJim Ingham return false; 751ebc09c36SJim Ingham } 752*4574a890SZachary Turner 753*4574a890SZachary Turner sub_cmd_obj = subcommand_obj_sp.get(); 754*4574a890SZachary Turner use_subcommand = true; 755*4574a890SZachary Turner args.Shift(); // Shift the sub_command word off the argument vector. 756*4574a890SZachary Turner cmd_obj = sub_cmd_obj; 757ebc09c36SJim Ingham } 758ebc09c36SJim Ingham 759ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 760ebc09c36SJim Ingham 761212130acSEnrico Granata std::string args_string; 762212130acSEnrico Granata 76311eb9c64SZachary Turner if (!args.empty()) { 764b9c1b51eSKate Stone CommandObjectSP tmp_sp = 765b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 766ebc09c36SJim Ingham if (use_subcommand) 767*4574a890SZachary Turner tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 768*4574a890SZachary Turner false); 769ca90c47eSCaroline Tice 770ca90c47eSCaroline Tice args.GetCommandString(args_string); 771867b185dSCaroline Tice } 772ebc09c36SJim Ingham 773771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 774771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 775b9c1b51eSKate Stone result.AppendWarningWithFormat( 776*4574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 777ebc09c36SJim Ingham } 778ebc09c36SJim Ingham 779b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 780*4574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 781771ef6d4SMalcolm Parsons args_string)) { 78245d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 78345d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 78445d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 78545d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 786ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 787b9c1b51eSKate Stone } else { 788212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 789212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 790212130acSEnrico Granata return false; 791212130acSEnrico Granata } 792ebc09c36SJim Ingham 793ebc09c36SJim Ingham return result.Succeeded(); 794ebc09c36SJim Ingham } 795ebc09c36SJim Ingham }; 796ebc09c36SJim Ingham 797ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 798ebc09c36SJim Ingham //------------------------------------------------------------------------- 799ebc09c36SJim Ingham // CommandObjectCommandsUnalias 800ebc09c36SJim Ingham //------------------------------------------------------------------------- 801ebc09c36SJim Ingham 802b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 803ebc09c36SJim Ingham public: 8047428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 805b9c1b51eSKate Stone : CommandObjectParsed( 806b9c1b51eSKate Stone interpreter, "command unalias", 807b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 808b9c1b51eSKate Stone nullptr) { 809405fe67fSCaroline Tice CommandArgumentEntry arg; 810405fe67fSCaroline Tice CommandArgumentData alias_arg; 811405fe67fSCaroline Tice 812405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 813405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 814405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 815405fe67fSCaroline Tice 816b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 817b9c1b51eSKate Stone // argument entry. 818405fe67fSCaroline Tice arg.push_back(alias_arg); 819405fe67fSCaroline Tice 820405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 821405fe67fSCaroline Tice m_arguments.push_back(arg); 822ebc09c36SJim Ingham } 823ebc09c36SJim Ingham 8246e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 825ebc09c36SJim Ingham 8265a988416SJim Ingham protected: 827b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 828ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 829ebc09c36SJim Ingham CommandObject *cmd_obj; 830ebc09c36SJim Ingham 83111eb9c64SZachary Turner if (args.empty()) { 83211eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 83311eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 83411eb9c64SZachary Turner return false; 83511eb9c64SZachary Turner } 83611eb9c64SZachary Turner 837*4574a890SZachary Turner auto command_name = args[0].ref; 838a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 839*4574a890SZachary Turner if (!cmd_obj) { 840*4574a890SZachary Turner result.AppendErrorWithFormat( 841*4574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 842*4574a890SZachary Turner "current list of commands.\n", 843*4574a890SZachary Turner command_name); 844*4574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 845*4574a890SZachary Turner return false; 846*4574a890SZachary Turner } 847*4574a890SZachary Turner 848b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 849b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 850b9c1b51eSKate Stone result.AppendErrorWithFormat( 851b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 852b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 853b547278cSGreg Clayton command_name); 854b9c1b51eSKate Stone } else { 855b9c1b51eSKate Stone result.AppendErrorWithFormat( 856b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 857ebc09c36SJim Ingham command_name); 858b547278cSGreg Clayton } 859ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 860*4574a890SZachary Turner return false; 861*4574a890SZachary Turner } 862*4574a890SZachary Turner 863b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 864a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 865b9c1b51eSKate Stone result.AppendErrorWithFormat( 866*4574a890SZachary Turner "Error occurred while attempting to unalias '%s'.\n", command_name); 867ebc09c36SJim Ingham else 868b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 869b9c1b51eSKate Stone command_name); 870ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 871*4574a890SZachary Turner return false; 872ebc09c36SJim Ingham } 873ebc09c36SJim Ingham 874*4574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 875ebc09c36SJim Ingham return result.Succeeded(); 876ebc09c36SJim Ingham } 877ebc09c36SJim Ingham }; 878ebc09c36SJim Ingham 879b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 880b547278cSGreg Clayton //------------------------------------------------------------------------- 881b547278cSGreg Clayton // CommandObjectCommandsDelete 882b547278cSGreg Clayton //------------------------------------------------------------------------- 883b547278cSGreg Clayton 884b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 885b547278cSGreg Clayton public: 8867428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 887b9c1b51eSKate Stone : CommandObjectParsed( 888b9c1b51eSKate Stone interpreter, "command delete", 889b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 890b9c1b51eSKate Stone nullptr) { 891b547278cSGreg Clayton CommandArgumentEntry arg; 892b547278cSGreg Clayton CommandArgumentData alias_arg; 893b547278cSGreg Clayton 894b547278cSGreg Clayton // Define the first (and only) variant of this arg. 895b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 896b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 897b547278cSGreg Clayton 898b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 899b9c1b51eSKate Stone // argument entry. 900b547278cSGreg Clayton arg.push_back(alias_arg); 901b547278cSGreg Clayton 902b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 903b547278cSGreg Clayton m_arguments.push_back(arg); 904b547278cSGreg Clayton } 905b547278cSGreg Clayton 9066e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 907b547278cSGreg Clayton 908b547278cSGreg Clayton protected: 909b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 910b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 911b547278cSGreg Clayton 91211eb9c64SZachary Turner if (args.empty()) { 91311eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 91411eb9c64SZachary Turner "defined regular expression command names", 915a449698cSZachary Turner GetCommandName().str().c_str()); 91611eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 91711eb9c64SZachary Turner } 91811eb9c64SZachary Turner 919*4574a890SZachary Turner auto command_name = args[0].ref; 920*4574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 92146d4aa21SEnrico Granata StreamString error_msg_stream; 92246d4aa21SEnrico Granata const bool generate_apropos = true; 92346d4aa21SEnrico Granata const bool generate_type_lookup = false; 924b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 925*4574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 926*4574a890SZachary Turner generate_apropos, generate_type_lookup); 927c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 928b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 929*4574a890SZachary Turner return false; 930b547278cSGreg Clayton } 931b547278cSGreg Clayton 932*4574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 933*4574a890SZachary Turner result.AppendErrorWithFormat( 934*4574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 935*4574a890SZachary Turner command_name); 936*4574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 937*4574a890SZachary Turner return false; 938*4574a890SZachary Turner } 939*4574a890SZachary Turner 940*4574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 941*4574a890SZachary Turner return true; 942b547278cSGreg Clayton } 943b547278cSGreg Clayton }; 944b547278cSGreg Clayton 945de164aaaSGreg Clayton //------------------------------------------------------------------------- 946de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 947de164aaaSGreg Clayton //------------------------------------------------------------------------- 9481f0f5b5bSZachary Turner 9491f0f5b5bSZachary Turner static OptionDefinition g_regex_options[] = { 9501f0f5b5bSZachary Turner // clang-format off 9511f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." }, 9521f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, 9531f0f5b5bSZachary Turner // clang-format on 9541f0f5b5bSZachary Turner }; 9551f0f5b5bSZachary Turner 9565a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 957de164aaaSGreg Clayton 958b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 959b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 960de164aaaSGreg Clayton public: 9617428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 962b9c1b51eSKate Stone : CommandObjectParsed( 963b9c1b51eSKate Stone interpreter, "command regex", "Define a custom command in terms of " 964b9c1b51eSKate Stone "existing commands by matching " 965b9c1b51eSKate Stone "regular expressions.", 9660e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 967b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 968b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 969b9c1b51eSKate Stone m_options() { 970b9c1b51eSKate Stone SetHelpLong( 971b9c1b51eSKate Stone R"( 972b9c1b51eSKate Stone )" 973b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 974ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 975b9c1b51eSKate Stone using the regular expression substitution format of:" 976b9c1b51eSKate Stone R"( 977ea671fbdSKate Stone 978ea671fbdSKate Stone s/<regex>/<subst>/ 979ea671fbdSKate Stone 980b9c1b51eSKate Stone )" 981b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 982ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 983b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 984b9c1b51eSKate Stone R"( 985ea671fbdSKate Stone 986b9c1b51eSKate Stone )" 987b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 988ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 989ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 990b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 991b9c1b51eSKate Stone R"( 992ea671fbdSKate Stone 993ea671fbdSKate Stone EXAMPLES 994ea671fbdSKate Stone 995b9c1b51eSKate Stone )" 996b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 997ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 998b9c1b51eSKate Stone a number follows 'f':" 999b9c1b51eSKate Stone R"( 1000ea671fbdSKate Stone 1001b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 1002de164aaaSGreg Clayton } 1003de164aaaSGreg Clayton 10046e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 1005de164aaaSGreg Clayton 10065a988416SJim Ingham protected: 1007b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 100844d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1009b9c1b51eSKate Stone if (output_sp) { 1010b9c1b51eSKate Stone output_sp->PutCString("Enter one of more sed substitution commands in " 1011b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 1012b9c1b51eSKate Stone "substitution list with an empty line.\n"); 101344d93782SGreg Clayton output_sp->Flush(); 101444d93782SGreg Clayton } 101544d93782SGreg Clayton } 101644d93782SGreg Clayton 1017b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1018b9c1b51eSKate Stone std::string &data) override { 101944d93782SGreg Clayton io_handler.SetIsDone(true); 1020b9c1b51eSKate Stone if (m_regex_cmd_ap) { 102144d93782SGreg Clayton StringList lines; 1022b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 102344d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 102444d93782SGreg Clayton bool check_only = false; 1025b9c1b51eSKate Stone for (size_t i = 0; i < num_lines; ++i) { 102644d93782SGreg Clayton llvm::StringRef bytes_strref(lines[i]); 102744d93782SGreg Clayton Error error = AppendRegexSubstitution(bytes_strref, check_only); 1028b9c1b51eSKate Stone if (error.Fail()) { 1029b9c1b51eSKate Stone if (!m_interpreter.GetDebugger() 1030b9c1b51eSKate Stone .GetCommandInterpreter() 1031b9c1b51eSKate Stone .GetBatchCommandMode()) { 1032b9c1b51eSKate Stone StreamSP out_stream = 1033b9c1b51eSKate Stone m_interpreter.GetDebugger().GetAsyncOutputStream(); 103444d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 103544d93782SGreg Clayton } 103644d93782SGreg Clayton } 103744d93782SGreg Clayton } 103844d93782SGreg Clayton } 1039b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 104044d93782SGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 104144d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 104244d93782SGreg Clayton } 104344d93782SGreg Clayton } 104444d93782SGreg Clayton } 104544d93782SGreg Clayton 1046b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 10475a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 1048b9c1b51eSKate Stone if (argc == 0) { 1049b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 1050b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 10510e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 105211eb9c64SZachary Turner return false; 105311eb9c64SZachary Turner } 105411eb9c64SZachary Turner 10550e5e5a79SGreg Clayton Error error; 1056*4574a890SZachary Turner auto name = command[0].ref; 1057*4574a890SZachary Turner m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>( 1058*4574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 1059*4574a890SZachary Turner true); 10600e5e5a79SGreg Clayton 1061b9c1b51eSKate Stone if (argc == 1) { 106244d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1063e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 106444d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 1065b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 1066b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 106773d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1068514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 1069514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 1070b9c1b51eSKate Stone multiple_lines, color_prompt, 1071f6913cd7SGreg Clayton 0, // Don't show line numbers 107244d93782SGreg Clayton *this)); 107344d93782SGreg Clayton 1074b9c1b51eSKate Stone if (io_handler_sp) { 107544d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1076de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 1077de164aaaSGreg Clayton } 1078b9c1b51eSKate Stone } else { 107997d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 108044d93782SGreg Clayton bool check_only = false; 108197d2c401SZachary Turner error = AppendRegexSubstitution(entry.ref, check_only); 10820e5e5a79SGreg Clayton if (error.Fail()) 10830e5e5a79SGreg Clayton break; 10840e5e5a79SGreg Clayton } 10850e5e5a79SGreg Clayton 1086b9c1b51eSKate Stone if (error.Success()) { 10870e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 10880e5e5a79SGreg Clayton } 10890e5e5a79SGreg Clayton } 1090b9c1b51eSKate Stone if (error.Fail()) { 10910e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 1092de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 1093de164aaaSGreg Clayton } 10940e5e5a79SGreg Clayton 1095de164aaaSGreg Clayton return result.Succeeded(); 1096de164aaaSGreg Clayton } 1097de164aaaSGreg Clayton 1098b9c1b51eSKate Stone Error AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 1099b9c1b51eSKate Stone bool check_only) { 11000e5e5a79SGreg Clayton Error error; 11010e5e5a79SGreg Clayton 1102b9c1b51eSKate Stone if (!m_regex_cmd_ap) { 1103b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1104b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 1105b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11060e5e5a79SGreg Clayton return error; 1107de164aaaSGreg Clayton } 11080e5e5a79SGreg Clayton 11090e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 11100e5e5a79SGreg Clayton 1111b9c1b51eSKate Stone if (regex_sed_size <= 1) { 1112b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1113b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 1114b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11150e5e5a79SGreg Clayton return error; 11160e5e5a79SGreg Clayton } 11170e5e5a79SGreg Clayton 1118b9c1b51eSKate Stone if (regex_sed[0] != 's') { 1119b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 1120b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 1121b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11220e5e5a79SGreg Clayton return error; 11230e5e5a79SGreg Clayton } 11240e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 11250e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 11260e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 11270e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 1128b9c1b51eSKate Stone const size_t second_separator_char_pos = 1129b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 11300e5e5a79SGreg Clayton 1131b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 1132b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1133b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 11340e5e5a79SGreg Clayton separator_char, 11350e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1136ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1137b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11380e5e5a79SGreg Clayton return error; 11390e5e5a79SGreg Clayton } 11400e5e5a79SGreg Clayton 1141b9c1b51eSKate Stone const size_t third_separator_char_pos = 1142b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 11430e5e5a79SGreg Clayton 1144b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 1145b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1146b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 11470e5e5a79SGreg Clayton separator_char, 11480e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1149ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1150b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11510e5e5a79SGreg Clayton return error; 11520e5e5a79SGreg Clayton } 11530e5e5a79SGreg Clayton 1154b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 11550e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 11560e5e5a79SGreg Clayton // separator char 1157b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 1158b9c1b51eSKate Stone third_separator_char_pos + 1) != 1159b9c1b51eSKate Stone std::string::npos) { 1160b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1161b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 1162b9c1b51eSKate Stone "string: '%.*s'", 1163b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 11640e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 11650e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 11660e5e5a79SGreg Clayton return error; 11670e5e5a79SGreg Clayton } 1168b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 1169b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1170b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1171b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11720e5e5a79SGreg Clayton regex_sed.data()); 11730e5e5a79SGreg Clayton return error; 1174b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 1175b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1176b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1177b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11780e5e5a79SGreg Clayton regex_sed.data()); 11790e5e5a79SGreg Clayton return error; 11800e5e5a79SGreg Clayton } 118144d93782SGreg Clayton 1182b9c1b51eSKate Stone if (!check_only) { 1183b9c1b51eSKate Stone std::string regex(regex_sed.substr(first_separator_char_pos + 1, 1184b9c1b51eSKate Stone second_separator_char_pos - 1185b9c1b51eSKate Stone first_separator_char_pos - 1)); 1186b9c1b51eSKate Stone std::string subst(regex_sed.substr(second_separator_char_pos + 1, 1187b9c1b51eSKate Stone third_separator_char_pos - 1188b9c1b51eSKate Stone second_separator_char_pos - 1)); 1189b9c1b51eSKate Stone m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str()); 119044d93782SGreg Clayton } 11910e5e5a79SGreg Clayton return error; 1192de164aaaSGreg Clayton } 1193de164aaaSGreg Clayton 1194b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 1195b9c1b51eSKate Stone if (m_regex_cmd_ap) { 1196b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 1197de164aaaSGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 1198de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1199de164aaaSGreg Clayton } 1200de164aaaSGreg Clayton } 1201de164aaaSGreg Clayton } 1202de164aaaSGreg Clayton 1203de164aaaSGreg Clayton private: 12047b0992d9SGreg Clayton std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1205de164aaaSGreg Clayton 1206b9c1b51eSKate Stone class CommandOptions : public Options { 1207de164aaaSGreg Clayton public: 1208b9c1b51eSKate Stone CommandOptions() : Options() {} 1209de164aaaSGreg Clayton 12106e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1211de164aaaSGreg Clayton 1212fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1213b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1214de164aaaSGreg Clayton Error error; 12153bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1216de164aaaSGreg Clayton 1217b9c1b51eSKate Stone switch (short_option) { 1218de164aaaSGreg Clayton case 'h': 1219de164aaaSGreg Clayton m_help.assign(option_arg); 1220de164aaaSGreg Clayton break; 1221de164aaaSGreg Clayton case 's': 1222de164aaaSGreg Clayton m_syntax.assign(option_arg); 1223de164aaaSGreg Clayton break; 1224de164aaaSGreg Clayton default: 1225b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1226b9c1b51eSKate Stone short_option); 1227de164aaaSGreg Clayton break; 1228de164aaaSGreg Clayton } 1229de164aaaSGreg Clayton 1230de164aaaSGreg Clayton return error; 1231de164aaaSGreg Clayton } 1232de164aaaSGreg Clayton 1233b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1234de164aaaSGreg Clayton m_help.clear(); 1235de164aaaSGreg Clayton m_syntax.clear(); 1236de164aaaSGreg Clayton } 1237de164aaaSGreg Clayton 12381f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 123970602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 12401f0f5b5bSZachary Turner } 1241de164aaaSGreg Clayton 124211eb9c64SZachary Turner // TODO: Convert these functions to return StringRefs. 1243b9c1b51eSKate Stone const char *GetHelp() { 12446e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1245de164aaaSGreg Clayton } 12466e3d8e7fSEugene Zelenko 1247b9c1b51eSKate Stone const char *GetSyntax() { 12486e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1249de164aaaSGreg Clayton } 12506e3d8e7fSEugene Zelenko 1251de164aaaSGreg Clayton protected: 12526e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 12536e3d8e7fSEugene Zelenko 1254de164aaaSGreg Clayton std::string m_help; 1255de164aaaSGreg Clayton std::string m_syntax; 1256de164aaaSGreg Clayton }; 1257de164aaaSGreg Clayton 1258b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1259de164aaaSGreg Clayton 12605a988416SJim Ingham CommandOptions m_options; 1261de164aaaSGreg Clayton }; 1262de164aaaSGreg Clayton 1263b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1264223383edSEnrico Granata public: 1265b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1266b9c1b51eSKate Stone std::string funct, std::string help, 1267b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1268a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1269b9c1b51eSKate Stone m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { 1270735152e3SEnrico Granata if (!help.empty()) 1271442f6530SZachary Turner SetHelp(help); 1272b9c1b51eSKate Stone else { 1273735152e3SEnrico Granata StreamString stream; 1274735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1275c156427dSZachary Turner SetHelp(stream.GetString()); 1276735152e3SEnrico Granata } 1277223383edSEnrico Granata } 1278223383edSEnrico Granata 12796e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1280223383edSEnrico Granata 1281b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 12825a988416SJim Ingham 1283b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 12845a988416SJim Ingham 1285b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 12865a988416SJim Ingham 1287442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1288442f6530SZachary Turner if (m_fetched_help_long) 1289442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1290442f6530SZachary Turner 1291fac939e9SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1292442f6530SZachary Turner if (!scripter) 1293442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1294442f6530SZachary Turner 1295fac939e9SEnrico Granata std::string docstring; 1296442f6530SZachary Turner m_fetched_help_long = 1297442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1298fac939e9SEnrico Granata if (!docstring.empty()) 1299442f6530SZachary Turner SetHelpLong(docstring); 1300fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1301fac939e9SEnrico Granata } 1302fac939e9SEnrico Granata 13035a988416SJim Ingham protected: 1304b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1305b9c1b51eSKate Stone CommandReturnObject &result) override { 1306223383edSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1307223383edSEnrico Granata 1308223383edSEnrico Granata Error error; 1309223383edSEnrico Granata 131070f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 131170f11f88SJim Ingham 1312b9c1b51eSKate Stone if (!scripter || 1313b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1314b9c1b51eSKate Stone raw_command_line, m_synchro, result, 1315b9c1b51eSKate Stone error, m_exe_ctx)) { 1316223383edSEnrico Granata result.AppendError(error.AsCString()); 1317223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1318b9c1b51eSKate Stone } else { 131970f11f88SJim Ingham // Don't change the status if the command already set it... 1320b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1321c156427dSZachary Turner if (result.GetOutputData().empty()) 1322223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 132370f11f88SJim Ingham else 132470f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 132570f11f88SJim Ingham } 132670f11f88SJim Ingham } 1327223383edSEnrico Granata 1328223383edSEnrico Granata return result.Succeeded(); 1329223383edSEnrico Granata } 1330223383edSEnrico Granata 13316e3d8e7fSEugene Zelenko private: 13326e3d8e7fSEugene Zelenko std::string m_function_name; 13336e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 13346e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1335223383edSEnrico Granata }; 1336223383edSEnrico Granata 1337b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 13389fe00e52SEnrico Granata public: 13399fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 13409fe00e52SEnrico Granata std::string name, 13410641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1342b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1343a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1344b9c1b51eSKate Stone m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), 1345b9c1b51eSKate Stone m_fetched_help_long(false) { 13469fe00e52SEnrico Granata StreamString stream; 13479fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1348c156427dSZachary Turner SetHelp(stream.GetString()); 1349e87764f2SEnrico Granata if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter()) 1350e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 13519fe00e52SEnrico Granata } 13529fe00e52SEnrico Granata 13536e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 13549fe00e52SEnrico Granata 1355b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 13569fe00e52SEnrico Granata 1357b9c1b51eSKate Stone StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } 13589fe00e52SEnrico Granata 1359b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 13609fe00e52SEnrico Granata 1361442f6530SZachary Turner llvm::StringRef GetHelp() override { 1362442f6530SZachary Turner if (m_fetched_help_short) 1363442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13646f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1365442f6530SZachary Turner if (!scripter) 1366442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13676f79bb2dSEnrico Granata std::string docstring; 1368b9c1b51eSKate Stone m_fetched_help_short = 1369b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 13706f79bb2dSEnrico Granata if (!docstring.empty()) 1371442f6530SZachary Turner SetHelp(docstring); 1372442f6530SZachary Turner 13736f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 13746f79bb2dSEnrico Granata } 13756f79bb2dSEnrico Granata 1376442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1377442f6530SZachary Turner if (m_fetched_help_long) 1378442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1379442f6530SZachary Turner 13806f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1381442f6530SZachary Turner if (!scripter) 1382442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1383442f6530SZachary Turner 13846f79bb2dSEnrico Granata std::string docstring; 1385b9c1b51eSKate Stone m_fetched_help_long = 1386b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 13876f79bb2dSEnrico Granata if (!docstring.empty()) 1388442f6530SZachary Turner SetHelpLong(docstring); 13899fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 13909fe00e52SEnrico Granata } 13919fe00e52SEnrico Granata 13929fe00e52SEnrico Granata protected: 1393b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1394b9c1b51eSKate Stone CommandReturnObject &result) override { 13959fe00e52SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 13969fe00e52SEnrico Granata 13979fe00e52SEnrico Granata Error error; 13989fe00e52SEnrico Granata 13999fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 14009fe00e52SEnrico Granata 1401b9c1b51eSKate Stone if (!scripter || 1402b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1403b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 14049fe00e52SEnrico Granata result.AppendError(error.AsCString()); 14059fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1406b9c1b51eSKate Stone } else { 14079fe00e52SEnrico Granata // Don't change the status if the command already set it... 1408b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1409c156427dSZachary Turner if (result.GetOutputData().empty()) 14109fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 14119fe00e52SEnrico Granata else 14129fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 14139fe00e52SEnrico Granata } 14149fe00e52SEnrico Granata } 14159fe00e52SEnrico Granata 14169fe00e52SEnrico Granata return result.Succeeded(); 14179fe00e52SEnrico Granata } 14189fe00e52SEnrico Granata 14196e3d8e7fSEugene Zelenko private: 14206e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 14216e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 14226e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 14236e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 14249fe00e52SEnrico Granata }; 14259fe00e52SEnrico Granata 1426a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1427a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1428a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1429a9dbf432SEnrico Granata 14301f0f5b5bSZachary Turner OptionDefinition g_script_import_options[] = { 14311f0f5b5bSZachary Turner // clang-format off 14321f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." }, 14331f0f5b5bSZachary Turner // clang-format on 14341f0f5b5bSZachary Turner }; 14351f0f5b5bSZachary Turner 1436b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 14375a988416SJim Ingham public: 1438b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1439b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1440b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1441b9c1b51eSKate Stone m_options() { 14425a988416SJim Ingham CommandArgumentEntry arg1; 14435a988416SJim Ingham CommandArgumentData cmd_arg; 14445a988416SJim Ingham 14455a988416SJim Ingham // Define the first (and only) variant of this arg. 14465a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 14473b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 14485a988416SJim Ingham 1449b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1450b9c1b51eSKate Stone // argument entry. 14515a988416SJim Ingham arg1.push_back(cmd_arg); 14525a988416SJim Ingham 14535a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 14545a988416SJim Ingham m_arguments.push_back(arg1); 14555a988416SJim Ingham } 14565a988416SJim Ingham 14576e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 14585a988416SJim Ingham 1459b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 14605a988416SJim Ingham int &cursor_char_position, 14615a988416SJim Ingham OptionElementVector &opt_element_vector, 1462b9c1b51eSKate Stone int match_start_point, int max_return_elements, 14635a988416SJim Ingham bool &word_complete, 1464b9c1b51eSKate Stone StringList &matches) override { 1465d6a24757SZachary Turner llvm::StringRef completion_str = input[cursor_index].ref; 1466d6a24757SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 14675a988416SJim Ingham 1468b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1469b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1470d6a24757SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 1471b9c1b51eSKate Stone word_complete, matches); 14725a988416SJim Ingham return matches.GetSize(); 14735a988416SJim Ingham } 14745a988416SJim Ingham 1475b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14765a988416SJim Ingham 14775a988416SJim Ingham protected: 1478b9c1b51eSKate Stone class CommandOptions : public Options { 14790a305db7SEnrico Granata public: 1480b9c1b51eSKate Stone CommandOptions() : Options() {} 14810a305db7SEnrico Granata 14826e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 14830a305db7SEnrico Granata 1484fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1485b9c1b51eSKate Stone ExecutionContext *execution_context) override { 14860a305db7SEnrico Granata Error error; 14873bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14880a305db7SEnrico Granata 1489b9c1b51eSKate Stone switch (short_option) { 14900a305db7SEnrico Granata case 'r': 14910a305db7SEnrico Granata m_allow_reload = true; 14920a305db7SEnrico Granata break; 14930a305db7SEnrico Granata default: 1494b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1495b9c1b51eSKate Stone short_option); 14960a305db7SEnrico Granata break; 14970a305db7SEnrico Granata } 14980a305db7SEnrico Granata 14990a305db7SEnrico Granata return error; 15000a305db7SEnrico Granata } 15010a305db7SEnrico Granata 1502b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1503e0c70f1bSEnrico Granata m_allow_reload = true; 15040a305db7SEnrico Granata } 15050a305db7SEnrico Granata 15061f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 150770602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 15081f0f5b5bSZachary Turner } 15090a305db7SEnrico Granata 15100a305db7SEnrico Granata // Instance variables to hold the values for command options. 15110a305db7SEnrico Granata 15120a305db7SEnrico Granata bool m_allow_reload; 15130a305db7SEnrico Granata }; 15140a305db7SEnrico Granata 1515b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1516b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1517b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1518b9c1b51eSKate Stone result.AppendError("only scripting language supported for module " 1519b9c1b51eSKate Stone "importing is currently Python"); 1520a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1521a9dbf432SEnrico Granata return false; 1522a9dbf432SEnrico Granata } 1523a9dbf432SEnrico Granata 152411eb9c64SZachary Turner if (command.empty()) { 15253b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1526a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1527a9dbf432SEnrico Granata return false; 1528a9dbf432SEnrico Granata } 1529a9dbf432SEnrico Granata 153011eb9c64SZachary Turner for (auto &entry : command.entries()) { 1531a9dbf432SEnrico Granata Error error; 1532a9dbf432SEnrico Granata 1533c9d645d3SGreg Clayton const bool init_session = true; 1534b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 153511eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 153611eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 153711eb9c64SZachary Turner // script imports" in __lldb_init_module the real fix is to have recursive 153811eb9c64SZachary Turner // commands possible with a CommandInvocation object separate from the 153911eb9c64SZachary Turner // CommandObject itself, so that recursive command invocations won't stomp 154011eb9c64SZachary Turner // on each other (wrt to execution contents, options, and more) 1541078551c7SEnrico Granata m_exe_ctx.Clear(); 1542b9c1b51eSKate Stone if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule( 154311eb9c64SZachary Turner entry.c_str(), m_options.m_allow_reload, init_session, error)) { 1544a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1545b9c1b51eSKate Stone } else { 1546b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1547b9c1b51eSKate Stone error.AsCString()); 1548a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1549a9dbf432SEnrico Granata } 15503b00e35bSEnrico Granata } 1551a9dbf432SEnrico Granata 1552a9dbf432SEnrico Granata return result.Succeeded(); 1553a9dbf432SEnrico Granata } 15540a305db7SEnrico Granata 15555a988416SJim Ingham CommandOptions m_options; 1556a9dbf432SEnrico Granata }; 1557223383edSEnrico Granata 1558223383edSEnrico Granata //------------------------------------------------------------------------- 1559223383edSEnrico Granata // CommandObjectCommandsScriptAdd 1560223383edSEnrico Granata //------------------------------------------------------------------------- 1561223383edSEnrico Granata 15621f0f5b5bSZachary Turner static OptionEnumValueElement g_script_synchro_type[] = { 15631f0f5b5bSZachary Turner {eScriptedCommandSynchronicitySynchronous, "synchronous", 15641f0f5b5bSZachary Turner "Run synchronous"}, 15651f0f5b5bSZachary Turner {eScriptedCommandSynchronicityAsynchronous, "asynchronous", 15661f0f5b5bSZachary Turner "Run asynchronous"}, 15671f0f5b5bSZachary Turner {eScriptedCommandSynchronicityCurrentValue, "current", 15681f0f5b5bSZachary Turner "Do not alter current setting"}, 15691f0f5b5bSZachary Turner {0, nullptr, nullptr}}; 15701f0f5b5bSZachary Turner 15711f0f5b5bSZachary Turner static OptionDefinition g_script_add_options[] = { 15721f0f5b5bSZachary Turner // clang-format off 15731f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, 15741f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, 15751f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." }, 15761f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, 15771f0f5b5bSZachary Turner // clang-format on 15781f0f5b5bSZachary Turner }; 15791f0f5b5bSZachary Turner 1580b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1581b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 15825a988416SJim Ingham public: 1583b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1584b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 15855a988416SJim Ingham "Add a scripted function as an LLDB command.", 15866e3d8e7fSEugene Zelenko nullptr), 1587b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 15885a988416SJim Ingham CommandArgumentEntry arg1; 15895a988416SJim Ingham CommandArgumentData cmd_arg; 15905a988416SJim Ingham 15915a988416SJim Ingham // Define the first (and only) variant of this arg. 15925a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 15935a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 15945a988416SJim Ingham 1595b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1596b9c1b51eSKate Stone // argument entry. 15975a988416SJim Ingham arg1.push_back(cmd_arg); 15985a988416SJim Ingham 15995a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 16005a988416SJim Ingham m_arguments.push_back(arg1); 16015a988416SJim Ingham } 16025a988416SJim Ingham 16036e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 16045a988416SJim Ingham 1605b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 16065a988416SJim Ingham 16075a988416SJim Ingham protected: 1608b9c1b51eSKate Stone class CommandOptions : public Options { 1609223383edSEnrico Granata public: 1610b9c1b51eSKate Stone CommandOptions() 1611b9c1b51eSKate Stone : Options(), m_class_name(), m_funct_name(), m_short_help(), 1612b9c1b51eSKate Stone m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1613223383edSEnrico Granata 16146e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1615223383edSEnrico Granata 1616fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1617b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1618223383edSEnrico Granata Error error; 16193bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1620223383edSEnrico Granata 1621b9c1b51eSKate Stone switch (short_option) { 1622223383edSEnrico Granata case 'f': 1623fe11483bSZachary Turner if (!option_arg.empty()) 1624fe11483bSZachary Turner m_funct_name = option_arg; 1625735152e3SEnrico Granata break; 16269fe00e52SEnrico Granata case 'c': 1627fe11483bSZachary Turner if (!option_arg.empty()) 1628fe11483bSZachary Turner m_class_name = option_arg; 16299fe00e52SEnrico Granata break; 1630735152e3SEnrico Granata case 'h': 1631fe11483bSZachary Turner if (!option_arg.empty()) 1632fe11483bSZachary Turner m_short_help = option_arg; 1633223383edSEnrico Granata break; 16340a305db7SEnrico Granata case 's': 1635b9c1b51eSKate Stone m_synchronicity = 1636b9c1b51eSKate Stone (ScriptedCommandSynchronicity)Args::StringToOptionEnum( 1637fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 16380a305db7SEnrico Granata if (!error.Success()) 1639b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1640fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1641fe11483bSZachary Turner option_arg.str().c_str()); 16420a305db7SEnrico Granata break; 1643223383edSEnrico Granata default: 1644b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1645b9c1b51eSKate Stone short_option); 1646223383edSEnrico Granata break; 1647223383edSEnrico Granata } 1648223383edSEnrico Granata 1649223383edSEnrico Granata return error; 1650223383edSEnrico Granata } 1651223383edSEnrico Granata 1652b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16539fe00e52SEnrico Granata m_class_name.clear(); 1654735152e3SEnrico Granata m_funct_name.clear(); 1655735152e3SEnrico Granata m_short_help.clear(); 165644d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1657223383edSEnrico Granata } 1658223383edSEnrico Granata 16591f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 166070602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 16611f0f5b5bSZachary Turner } 1662223383edSEnrico Granata 1663223383edSEnrico Granata // Instance variables to hold the values for command options. 1664223383edSEnrico Granata 16659fe00e52SEnrico Granata std::string m_class_name; 1666223383edSEnrico Granata std::string m_funct_name; 1667735152e3SEnrico Granata std::string m_short_help; 166844d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1669223383edSEnrico Granata }; 1670223383edSEnrico Granata 1671b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 167244d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1673b9c1b51eSKate Stone if (output_sp) { 167444d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 167544d93782SGreg Clayton output_sp->Flush(); 1676223383edSEnrico Granata } 1677223383edSEnrico Granata } 1678223383edSEnrico Granata 1679b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1680b9c1b51eSKate Stone std::string &data) override { 168144d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 168244d93782SGreg Clayton 168344d93782SGreg Clayton ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1684b9c1b51eSKate Stone if (interpreter) { 168544d93782SGreg Clayton 168644d93782SGreg Clayton StringList lines; 168744d93782SGreg Clayton lines.SplitIntoLines(data); 1688b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1689a73b7df7SEnrico Granata std::string funct_name_str; 1690b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1691b9c1b51eSKate Stone if (funct_name_str.empty()) { 1692b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1693b9c1b51eSKate Stone "add python command.\n"); 169444d93782SGreg Clayton error_sp->Flush(); 1695b9c1b51eSKate Stone } else { 1696223383edSEnrico Granata // everything should be fine now, let's add this alias 1697223383edSEnrico Granata 1698b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1699771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 170044d93782SGreg Clayton m_synchronicity)); 1701223383edSEnrico Granata 1702b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1703b9c1b51eSKate Stone true)) { 1704b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1705b9c1b51eSKate Stone "add python command.\n"); 170644d93782SGreg Clayton error_sp->Flush(); 1707223383edSEnrico Granata } 1708223383edSEnrico Granata } 1709b9c1b51eSKate Stone } else { 1710b9c1b51eSKate Stone error_sp->Printf( 1711b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 171244d93782SGreg Clayton error_sp->Flush(); 171344d93782SGreg Clayton } 1714b9c1b51eSKate Stone } else { 171544d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 171644d93782SGreg Clayton error_sp->Flush(); 171744d93782SGreg Clayton } 1718b9c1b51eSKate Stone } else { 1719b9c1b51eSKate Stone error_sp->Printf( 1720b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 172144d93782SGreg Clayton error_sp->Flush(); 172244d93782SGreg Clayton } 172344d93782SGreg Clayton 172444d93782SGreg Clayton io_handler.SetIsDone(true); 172544d93782SGreg Clayton } 1726223383edSEnrico Granata 17275a988416SJim Ingham protected: 1728b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1729b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1730b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1731b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1732b9c1b51eSKate Stone "commands is currently Python"); 173399f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 173499f0b8f9SEnrico Granata return false; 173599f0b8f9SEnrico Granata } 173699f0b8f9SEnrico Granata 173711eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1738223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1739223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1740223383edSEnrico Granata return false; 1741223383edSEnrico Granata } 1742223383edSEnrico Granata 1743735152e3SEnrico Granata // Store the options in case we get multi-line input 1744*4574a890SZachary Turner m_cmd_name = command[0].ref; 1745735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 174644d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1747223383edSEnrico Granata 1748b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1749b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1750b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1751b9c1b51eSKate Stone " ", // Prompt 175244d93782SGreg Clayton *this, // IOHandlerDelegate 175344d93782SGreg Clayton true, // Run IOHandler in async mode 1754b9c1b51eSKate Stone nullptr); // Baton for the "io_handler" that will be passed back 1755b9c1b51eSKate Stone // into our IOHandlerDelegate functions 1756b9c1b51eSKate Stone } else { 1757b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1758b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1759b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1760b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1761223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1762b9c1b51eSKate Stone } else { 1763223383edSEnrico Granata result.AppendError("cannot add command"); 1764223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1765223383edSEnrico Granata } 1766223383edSEnrico Granata } 1767b9c1b51eSKate Stone } else { 1768b9c1b51eSKate Stone ScriptInterpreter *interpreter = 1769b9c1b51eSKate Stone GetCommandInterpreter().GetScriptInterpreter(); 1770b9c1b51eSKate Stone if (!interpreter) { 17719fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 17729fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17739fe00e52SEnrico Granata return false; 17749fe00e52SEnrico Granata } 17759fe00e52SEnrico Granata 1776b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1777b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1778b9c1b51eSKate Stone if (!cmd_obj_sp) { 17799fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 17809fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17819fe00e52SEnrico Granata return false; 17829fe00e52SEnrico Granata } 17839fe00e52SEnrico Granata 1784b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1785b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1786b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 17879fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1788b9c1b51eSKate Stone } else { 17899fe00e52SEnrico Granata result.AppendError("cannot add command"); 17909fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17919fe00e52SEnrico Granata } 17929fe00e52SEnrico Granata } 1793223383edSEnrico Granata 1794223383edSEnrico Granata return result.Succeeded(); 1795223383edSEnrico Granata } 17965a988416SJim Ingham 17975a988416SJim Ingham CommandOptions m_options; 179844d93782SGreg Clayton std::string m_cmd_name; 1799735152e3SEnrico Granata std::string m_short_help; 180044d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1801223383edSEnrico Granata }; 1802223383edSEnrico Granata 1803223383edSEnrico Granata //------------------------------------------------------------------------- 1804223383edSEnrico Granata // CommandObjectCommandsScriptList 1805223383edSEnrico Granata //------------------------------------------------------------------------- 1806223383edSEnrico Granata 1807b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1808223383edSEnrico Granata public: 1809b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1810b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1811b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1812223383edSEnrico Granata 18136e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1814223383edSEnrico Granata 1815b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1816b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1817223383edSEnrico Granata 1818223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1819223383edSEnrico Granata 1820223383edSEnrico Granata return true; 1821223383edSEnrico Granata } 1822223383edSEnrico Granata }; 1823223383edSEnrico Granata 1824223383edSEnrico Granata //------------------------------------------------------------------------- 1825223383edSEnrico Granata // CommandObjectCommandsScriptClear 1826223383edSEnrico Granata //------------------------------------------------------------------------- 1827223383edSEnrico Granata 1828b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1829223383edSEnrico Granata public: 1830b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1831b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1832b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1833223383edSEnrico Granata 18346e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1835223383edSEnrico Granata 18365a988416SJim Ingham protected: 1837b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1838223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1839223383edSEnrico Granata 1840223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1841223383edSEnrico Granata 1842223383edSEnrico Granata return true; 1843223383edSEnrico Granata } 1844223383edSEnrico Granata }; 1845223383edSEnrico Granata 1846223383edSEnrico Granata //------------------------------------------------------------------------- 1847223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1848223383edSEnrico Granata //------------------------------------------------------------------------- 1849223383edSEnrico Granata 1850b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1851223383edSEnrico Granata public: 1852b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1853b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1854b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1855223383edSEnrico Granata CommandArgumentEntry arg1; 1856223383edSEnrico Granata CommandArgumentData cmd_arg; 1857223383edSEnrico Granata 1858223383edSEnrico Granata // Define the first (and only) variant of this arg. 1859223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1860223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1861223383edSEnrico Granata 1862b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1863b9c1b51eSKate Stone // argument entry. 1864223383edSEnrico Granata arg1.push_back(cmd_arg); 1865223383edSEnrico Granata 1866223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1867223383edSEnrico Granata m_arguments.push_back(arg1); 1868223383edSEnrico Granata } 1869223383edSEnrico Granata 18706e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1871223383edSEnrico Granata 18725a988416SJim Ingham protected: 1873b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1874223383edSEnrico Granata 187511eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1876223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1877223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1878223383edSEnrico Granata return false; 1879223383edSEnrico Granata } 1880223383edSEnrico Granata 1881*4574a890SZachary Turner auto cmd_name = command[0].ref; 1882223383edSEnrico Granata 1883*4574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 1884*4574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1885223383edSEnrico Granata result.AppendErrorWithFormat("command %s not found", cmd_name); 1886223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1887*4574a890SZachary Turner return false; 1888223383edSEnrico Granata } 1889223383edSEnrico Granata 1890*4574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 1891*4574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 1892*4574a890SZachary Turner return true; 1893223383edSEnrico Granata } 1894223383edSEnrico Granata }; 1895223383edSEnrico Granata 1896223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1897223383edSEnrico Granata 1898223383edSEnrico Granata //------------------------------------------------------------------------- 1899223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1900223383edSEnrico Granata //------------------------------------------------------------------------- 1901223383edSEnrico Granata 1902b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1903223383edSEnrico Granata public: 19047428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1905b9c1b51eSKate Stone : CommandObjectMultiword( 1906b9c1b51eSKate Stone interpreter, "command script", "Commands for managing custom " 1907b9c1b51eSKate Stone "commands implemented by " 1908b9c1b51eSKate Stone "interpreter scripts.", 1909b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1910b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1911b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1912b9c1b51eSKate Stone LoadSubCommand( 1913b9c1b51eSKate Stone "delete", 1914b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1915b9c1b51eSKate Stone LoadSubCommand( 1916b9c1b51eSKate Stone "clear", 1917b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1918b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1919b9c1b51eSKate Stone interpreter))); 1920b9c1b51eSKate Stone LoadSubCommand( 1921b9c1b51eSKate Stone "import", 1922b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1923223383edSEnrico Granata } 1924223383edSEnrico Granata 19256e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1926223383edSEnrico Granata }; 1927223383edSEnrico Granata 1928ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1929ebc09c36SJim Ingham 1930ebc09c36SJim Ingham //------------------------------------------------------------------------- 1931ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1932ebc09c36SJim Ingham //------------------------------------------------------------------------- 1933ebc09c36SJim Ingham 1934b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1935b9c1b51eSKate Stone CommandInterpreter &interpreter) 1936b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1937b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1938b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1939b9c1b51eSKate Stone LoadSubCommand("source", 1940b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1941b9c1b51eSKate Stone LoadSubCommand("alias", 1942b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1943b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1944b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1945b9c1b51eSKate Stone LoadSubCommand("delete", 1946b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1947b9c1b51eSKate Stone LoadSubCommand( 1948b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1949b9c1b51eSKate Stone LoadSubCommand("history", CommandObjectSP( 1950b9c1b51eSKate Stone new CommandObjectCommandsHistory(interpreter))); 1951b9c1b51eSKate Stone LoadSubCommand( 1952b9c1b51eSKate Stone "script", 1953b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1954ebc09c36SJim Ingham } 1955ebc09c36SJim Ingham 19566e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1957