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" 20*3eb2b44dSZachary Turner #include "lldb/Host/OptionParser.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" 31573ab909SZachary Turner #include "lldb/Utility/StringList.h" 32ebc09c36SJim Ingham 33ebc09c36SJim Ingham using namespace lldb; 34ebc09c36SJim Ingham using namespace lldb_private; 35ebc09c36SJim Ingham 36ebc09c36SJim Ingham //------------------------------------------------------------------------- 37ebc09c36SJim Ingham // CommandObjectCommandsSource 38ebc09c36SJim Ingham //------------------------------------------------------------------------- 39ebc09c36SJim Ingham 401f0f5b5bSZachary Turner static OptionDefinition g_history_options[] = { 411f0f5b5bSZachary Turner // clang-format off 421f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, 431f0f5b5bSZachary 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)." }, 441f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, 451f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." }, 461f0f5b5bSZachary Turner // clang-format on 471f0f5b5bSZachary Turner }; 481f0f5b5bSZachary Turner 49b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed { 505a988416SJim Ingham public: 51b9c1b51eSKate Stone CommandObjectCommandsHistory(CommandInterpreter &interpreter) 52b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command history", 535a988416SJim Ingham "Dump the history of commands in this session.", 546e3d8e7fSEugene Zelenko nullptr), 55b9c1b51eSKate Stone m_options() {} 565a988416SJim Ingham 576e3d8e7fSEugene Zelenko ~CommandObjectCommandsHistory() override = default; 585a988416SJim Ingham 59b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 605a988416SJim Ingham 615a988416SJim Ingham protected: 62b9c1b51eSKate Stone class CommandOptions : public Options { 63a5a97ebeSJim Ingham public: 64b9c1b51eSKate Stone CommandOptions() 65b9c1b51eSKate Stone : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 66a5a97ebeSJim Ingham } 67a5a97ebeSJim Ingham 686e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 69a5a97ebeSJim Ingham 70fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 71b9c1b51eSKate Stone ExecutionContext *execution_context) override { 72a5a97ebeSJim Ingham Error error; 733bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 74a5a97ebeSJim Ingham 75b9c1b51eSKate Stone switch (short_option) { 76a5a97ebeSJim Ingham case 'c': 77fe11483bSZachary Turner error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 78a5a97ebeSJim Ingham break; 79a5a97ebeSJim Ingham case 's': 80fe11483bSZachary Turner if (option_arg == "end") { 817594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 827594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 83b9c1b51eSKate Stone } else 84fe11483bSZachary Turner error = m_start_idx.SetValueFromString(option_arg, 85b9c1b51eSKate Stone eVarSetOperationAssign); 867594f14fSEnrico Granata break; 877594f14fSEnrico Granata case 'e': 88fe11483bSZachary Turner error = 89fe11483bSZachary Turner m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 907594f14fSEnrico Granata break; 9163123b64SEnrico Granata case 'C': 9263123b64SEnrico Granata m_clear.SetCurrentValue(true); 9363123b64SEnrico Granata m_clear.SetOptionWasSet(); 94a5a97ebeSJim Ingham break; 95a5a97ebeSJim Ingham default: 96b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 97b9c1b51eSKate Stone short_option); 98a5a97ebeSJim Ingham break; 99a5a97ebeSJim Ingham } 100a5a97ebeSJim Ingham 101a5a97ebeSJim Ingham return error; 102a5a97ebeSJim Ingham } 103a5a97ebeSJim Ingham 104b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1057594f14fSEnrico Granata m_start_idx.Clear(); 1067594f14fSEnrico Granata m_stop_idx.Clear(); 1077594f14fSEnrico Granata m_count.Clear(); 10863123b64SEnrico Granata m_clear.Clear(); 109a5a97ebeSJim Ingham } 110a5a97ebeSJim Ingham 1111f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 11270602439SZachary Turner return llvm::makeArrayRef(g_history_options); 1131f0f5b5bSZachary Turner } 114a5a97ebeSJim Ingham 115a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 116a5a97ebeSJim Ingham 1177594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1187594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1197594f14fSEnrico Granata OptionValueUInt64 m_count; 12063123b64SEnrico Granata OptionValueBoolean m_clear; 121a5a97ebeSJim Ingham }; 122a5a97ebeSJim Ingham 123b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 124b9c1b51eSKate Stone if (m_options.m_clear.GetCurrentValue() && 125b9c1b51eSKate Stone m_options.m_clear.OptionWasSet()) { 1267594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1277594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 128b9c1b51eSKate Stone } else { 129b9c1b51eSKate Stone if (m_options.m_start_idx.OptionWasSet() && 130b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet() && 131b9c1b51eSKate Stone m_options.m_count.OptionWasSet()) { 132b9c1b51eSKate Stone result.AppendError("--count, --start-index and --end-index cannot be " 133b9c1b51eSKate Stone "all specified in the same invocation"); 1347594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 135b9c1b51eSKate Stone } else { 136b9c1b51eSKate Stone std::pair<bool, uint64_t> start_idx( 137b9c1b51eSKate Stone m_options.m_start_idx.OptionWasSet(), 138b9c1b51eSKate Stone m_options.m_start_idx.GetCurrentValue()); 139b9c1b51eSKate Stone std::pair<bool, uint64_t> stop_idx( 140b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet(), 141b9c1b51eSKate Stone m_options.m_stop_idx.GetCurrentValue()); 142b9c1b51eSKate Stone std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 143b9c1b51eSKate Stone m_options.m_count.GetCurrentValue()); 144a5a97ebeSJim Ingham 1457594f14fSEnrico Granata const CommandHistory &history(m_interpreter.GetCommandHistory()); 1467594f14fSEnrico Granata 147b9c1b51eSKate Stone if (start_idx.first && start_idx.second == UINT64_MAX) { 148b9c1b51eSKate Stone if (count.first) { 1497594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1507594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 151b9c1b51eSKate Stone } else if (stop_idx.first) { 1527594f14fSEnrico Granata start_idx.second = stop_idx.second; 1537594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 154b9c1b51eSKate Stone } else { 1557594f14fSEnrico Granata start_idx.second = 0; 1567594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1577594f14fSEnrico Granata } 158b9c1b51eSKate Stone } else { 159b9c1b51eSKate Stone if (!start_idx.first && !stop_idx.first && !count.first) { 1607594f14fSEnrico Granata start_idx.second = 0; 1617594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 162b9c1b51eSKate Stone } else if (start_idx.first) { 163b9c1b51eSKate Stone if (count.first) { 1647594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 165b9c1b51eSKate Stone } else if (!stop_idx.first) { 1667594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1677594f14fSEnrico Granata } 168b9c1b51eSKate Stone } else if (stop_idx.first) { 169b9c1b51eSKate Stone if (count.first) { 1707594f14fSEnrico Granata if (stop_idx.second >= count.second) 1717594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 1727594f14fSEnrico Granata else 1737594f14fSEnrico Granata start_idx.second = 0; 1747594f14fSEnrico Granata } 175b9c1b51eSKate Stone } else /* if (count.first) */ 1767594f14fSEnrico Granata { 1777594f14fSEnrico Granata start_idx.second = 0; 1787594f14fSEnrico Granata stop_idx.second = count.second - 1; 1797594f14fSEnrico Granata } 1807594f14fSEnrico Granata } 181b9c1b51eSKate Stone history.Dump(result.GetOutputStream(), start_idx.second, 182b9c1b51eSKate Stone stop_idx.second); 1837594f14fSEnrico Granata } 1847594f14fSEnrico Granata } 185a5a97ebeSJim Ingham return result.Succeeded(); 186a5a97ebeSJim Ingham } 1875a988416SJim Ingham 1885a988416SJim Ingham CommandOptions m_options; 189a5a97ebeSJim Ingham }; 190a5a97ebeSJim Ingham 191a5a97ebeSJim Ingham //------------------------------------------------------------------------- 192a5a97ebeSJim Ingham // CommandObjectCommandsSource 193a5a97ebeSJim Ingham //------------------------------------------------------------------------- 194a5a97ebeSJim Ingham 1951f0f5b5bSZachary Turner static OptionDefinition g_source_options[] = { 1961f0f5b5bSZachary Turner // clang-format off 1971f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, 1981f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, 1991f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, 2001f0f5b5bSZachary Turner // clang-format on 2011f0f5b5bSZachary Turner }; 2021f0f5b5bSZachary Turner 203b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed { 2045a988416SJim Ingham public: 2057428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 206b9c1b51eSKate Stone : CommandObjectParsed( 207b9c1b51eSKate Stone interpreter, "command source", 208b9c1b51eSKate Stone "Read and execute LLDB commands from the file <filename>.", 2096e3d8e7fSEugene Zelenko nullptr), 210b9c1b51eSKate Stone m_options() { 2115a988416SJim Ingham CommandArgumentEntry arg; 2125a988416SJim Ingham CommandArgumentData file_arg; 2135a988416SJim Ingham 2145a988416SJim Ingham // Define the first (and only) variant of this arg. 2155a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2165a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2175a988416SJim Ingham 218b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 219b9c1b51eSKate Stone // argument entry. 2205a988416SJim Ingham arg.push_back(file_arg); 2215a988416SJim Ingham 2225a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2235a988416SJim Ingham m_arguments.push_back(arg); 2245a988416SJim Ingham } 2255a988416SJim Ingham 2266e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2275a988416SJim Ingham 228b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 229b9c1b51eSKate Stone uint32_t index) override { 2305a988416SJim Ingham return ""; 2315a988416SJim Ingham } 2325a988416SJim Ingham 233b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 2345a988416SJim Ingham int &cursor_char_position, 2355a988416SJim Ingham OptionElementVector &opt_element_vector, 236b9c1b51eSKate Stone int match_start_point, int max_return_elements, 2375a988416SJim Ingham bool &word_complete, 238b9c1b51eSKate Stone StringList &matches) override { 2394574a890SZachary Turner auto completion_str = input[cursor_index].ref; 2404574a890SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 2415a988416SJim Ingham 242b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 243b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 2444574a890SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 245b9c1b51eSKate Stone word_complete, matches); 2465a988416SJim Ingham return matches.GetSize(); 2475a988416SJim Ingham } 2485a988416SJim Ingham 249b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 2505a988416SJim Ingham 2515a988416SJim Ingham protected: 252b9c1b51eSKate Stone class CommandOptions : public Options { 253e16c50a1SJim Ingham public: 254b9c1b51eSKate Stone CommandOptions() 255b9c1b51eSKate Stone : Options(), m_stop_on_error(true), m_silent_run(false), 256b9c1b51eSKate Stone m_stop_on_continue(true) {} 257e16c50a1SJim Ingham 2586e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 259e16c50a1SJim Ingham 260fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 261b9c1b51eSKate Stone ExecutionContext *execution_context) override { 262e16c50a1SJim Ingham Error error; 2633bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 264e16c50a1SJim Ingham 265b9c1b51eSKate Stone switch (short_option) { 266e16c50a1SJim Ingham case 'e': 267fe11483bSZachary Turner error = m_stop_on_error.SetValueFromString(option_arg); 268e16c50a1SJim Ingham break; 269340b0309SGreg Clayton 270e16c50a1SJim Ingham case 'c': 271fe11483bSZachary Turner error = m_stop_on_continue.SetValueFromString(option_arg); 272e16c50a1SJim Ingham break; 273340b0309SGreg Clayton 27460986174SMichael Sartain case 's': 275fe11483bSZachary Turner error = m_silent_run.SetValueFromString(option_arg); 27660986174SMichael Sartain break; 277340b0309SGreg Clayton 278e16c50a1SJim Ingham default: 279b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 280b9c1b51eSKate Stone short_option); 281e16c50a1SJim Ingham break; 282e16c50a1SJim Ingham } 283e16c50a1SJim Ingham 284e16c50a1SJim Ingham return error; 285e16c50a1SJim Ingham } 286e16c50a1SJim Ingham 287b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 288012d4fcaSEnrico Granata m_stop_on_error.Clear(); 289340b0309SGreg Clayton m_silent_run.Clear(); 290340b0309SGreg Clayton m_stop_on_continue.Clear(); 291e16c50a1SJim Ingham } 292e16c50a1SJim Ingham 2931f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 29470602439SZachary Turner return llvm::makeArrayRef(g_source_options); 2951f0f5b5bSZachary Turner } 296e16c50a1SJim Ingham 297e16c50a1SJim Ingham // Instance variables to hold the values for command options. 298e16c50a1SJim Ingham 299012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 300340b0309SGreg Clayton OptionValueBoolean m_silent_run; 301340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 302e16c50a1SJim Ingham }; 303e16c50a1SJim Ingham 304b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 3054574a890SZachary Turner if (command.GetArgumentCount() != 1) { 3064574a890SZachary Turner result.AppendErrorWithFormat( 3074574a890SZachary Turner "'%s' takes exactly one executable filename argument.\n", 3084574a890SZachary Turner GetCommandName().str().c_str()); 3094574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 3104574a890SZachary Turner return false; 3114574a890SZachary Turner } 312ebc09c36SJim Ingham 3134574a890SZachary Turner FileSpec cmd_file(command[0].ref, true); 3146e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 315ebc09c36SJim Ingham 316340b0309SGreg Clayton // If any options were set, then use them 317340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 318340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 319b9c1b51eSKate Stone m_options.m_stop_on_continue.OptionWasSet()) { 320340b0309SGreg Clayton // Use user set settings 32126c7bf93SJim Ingham CommandInterpreterRunOptions options; 3224574a890SZachary Turner options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 32326c7bf93SJim Ingham options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 3247d8555c4SJim Ingham options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue()); 3257d8555c4SJim Ingham options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue()); 32626c7bf93SJim Ingham 3274574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 328b9c1b51eSKate Stone } else { 329b9c1b51eSKate Stone // No options were set, inherit any settings from nested "command 330b9c1b51eSKate Stone // source" commands, 331340b0309SGreg Clayton // or set to sane default settings... 33226c7bf93SJim Ingham CommandInterpreterRunOptions options; 3334574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 334ebc09c36SJim Ingham } 335ebc09c36SJim Ingham return result.Succeeded(); 336ebc09c36SJim Ingham } 3376e3d8e7fSEugene Zelenko 3385a988416SJim Ingham CommandOptions m_options; 339ebc09c36SJim Ingham }; 340ebc09c36SJim Ingham 341ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 342ebc09c36SJim Ingham //------------------------------------------------------------------------- 343ebc09c36SJim Ingham // CommandObjectCommandsAlias 344ebc09c36SJim Ingham //------------------------------------------------------------------------- 345ebc09c36SJim Ingham 3461f0f5b5bSZachary Turner static OptionDefinition g_alias_options[] = { 3471f0f5b5bSZachary Turner // clang-format off 3481f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" }, 3491f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" }, 3501f0f5b5bSZachary Turner // clang-format on 3511f0f5b5bSZachary Turner }; 3521f0f5b5bSZachary Turner 353b9c1b51eSKate Stone static const char *g_python_command_instructions = 354b9c1b51eSKate Stone "Enter your Python command(s). Type 'DONE' to end.\n" 355be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 35644d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 357be93a35aSEnrico Granata 358b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw { 35945d0e238SEnrico Granata protected: 360b9c1b51eSKate Stone class CommandOptions : public OptionGroup { 361ebc09c36SJim Ingham public: 362b9c1b51eSKate Stone CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 36345d0e238SEnrico Granata 36445d0e238SEnrico Granata ~CommandOptions() override = default; 36545d0e238SEnrico Granata 3661f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 36770602439SZachary Turner return llvm::makeArrayRef(g_alias_options); 3681f0f5b5bSZachary Turner } 36945d0e238SEnrico Granata 3708cef4b0bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 371b9c1b51eSKate Stone ExecutionContext *execution_context) override { 37245d0e238SEnrico Granata Error error; 37345d0e238SEnrico Granata 3741f0f5b5bSZachary Turner const int short_option = GetDefinitions()[option_idx].short_option; 3758cef4b0bSZachary Turner std::string option_str(option_value); 37645d0e238SEnrico Granata 377b9c1b51eSKate Stone switch (short_option) { 37845d0e238SEnrico Granata case 'h': 3798cef4b0bSZachary Turner m_help.SetCurrentValue(option_str); 38045d0e238SEnrico Granata m_help.SetOptionWasSet(); 38145d0e238SEnrico Granata break; 38245d0e238SEnrico Granata 38345d0e238SEnrico Granata case 'H': 3848cef4b0bSZachary Turner m_long_help.SetCurrentValue(option_str); 38545d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 38645d0e238SEnrico Granata break; 38745d0e238SEnrico Granata 38845d0e238SEnrico Granata default: 389b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid short option character '%c'", 390b9c1b51eSKate Stone short_option); 39145d0e238SEnrico Granata break; 39245d0e238SEnrico Granata } 39345d0e238SEnrico Granata 39445d0e238SEnrico Granata return error; 39545d0e238SEnrico Granata } 39645d0e238SEnrico Granata 397b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 39845d0e238SEnrico Granata m_help.Clear(); 39945d0e238SEnrico Granata m_long_help.Clear(); 40045d0e238SEnrico Granata } 40145d0e238SEnrico Granata 40245d0e238SEnrico Granata OptionValueString m_help; 40345d0e238SEnrico Granata OptionValueString m_long_help; 40445d0e238SEnrico Granata }; 40545d0e238SEnrico Granata 40645d0e238SEnrico Granata OptionGroupOptions m_option_group; 40745d0e238SEnrico Granata CommandOptions m_command_options; 40845d0e238SEnrico Granata 40945d0e238SEnrico Granata public: 410b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 41145d0e238SEnrico Granata 4127428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 413b9c1b51eSKate Stone : CommandObjectRaw( 414b9c1b51eSKate Stone interpreter, "command alias", 415a449698cSZachary Turner "Define a custom command in terms of an existing command."), 416b9c1b51eSKate Stone m_option_group(), m_command_options() { 41745d0e238SEnrico Granata m_option_group.Append(&m_command_options); 41845d0e238SEnrico Granata m_option_group.Finalize(); 41945d0e238SEnrico Granata 420ebc09c36SJim Ingham SetHelpLong( 421ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 422ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 423b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:" 424b9c1b51eSKate Stone R"( 425ea671fbdSKate Stone 426ea671fbdSKate Stone (lldb) command alias sc script 427ea671fbdSKate Stone 428ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 429ea671fbdSKate Stone 430ea671fbdSKate Stone (lldb) command alias bp breakpoint 431ea671fbdSKate Stone 432b9c1b51eSKate Stone )" 433b9c1b51eSKate Stone " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 434ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 435b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 436b9c1b51eSKate Stone R"( 437ea671fbdSKate Stone 438ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 439ea671fbdSKate Stone 440ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 441ea671fbdSKate Stone 442b9c1b51eSKate Stone )" 443b9c1b51eSKate Stone "An alias can include some options for the command, with the values either \ 444ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 445ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 446b9c1b51eSKate Stone shows how to create aliases with options:" 447b9c1b51eSKate Stone R"( 448ea671fbdSKate Stone 449ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 450ea671fbdSKate Stone 451b9c1b51eSKate Stone )" 452b9c1b51eSKate Stone " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 453ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 454ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 455ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 456ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 457ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 458ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 459ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 460ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 461ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 462b9c1b51eSKate Stone launch' example below)." 463b9c1b51eSKate Stone R"( 464ea671fbdSKate Stone 465b9c1b51eSKate Stone )" 466b9c1b51eSKate Stone "Note: the positional arguments must substitute as whole words in the resultant \ 467ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 468b9c1b51eSKate Stone \".cpp\":" 469b9c1b51eSKate Stone R"( 470ea671fbdSKate Stone 471ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 472ea671fbdSKate Stone 473b9c1b51eSKate Stone )" 474b9c1b51eSKate Stone "For more complex aliasing, use the \"command regex\" command instead. In the \ 475ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 476ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 477b9c1b51eSKate Stone argument. The user would use this alias as follows:" 478b9c1b51eSKate Stone R"( 479ea671fbdSKate Stone 480ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 481ea671fbdSKate Stone (lldb) bfl my-file.c 137 482ea671fbdSKate Stone 483ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 484ea671fbdSKate Stone 485ea671fbdSKate Stone Another example: 486ea671fbdSKate Stone 487ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 488ea671fbdSKate Stone (lldb) pltty /dev/tty0 489ea671fbdSKate Stone 490ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 491ea671fbdSKate Stone 492b9c1b51eSKate Stone )" 493b9c1b51eSKate Stone "If the user always wanted to pass the same value to a particular option, the \ 494ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 495b9c1b51eSKate Stone rather than using a positional placeholder:" 496b9c1b51eSKate Stone R"( 497ea671fbdSKate Stone 498ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 499ea671fbdSKate Stone 500b9c1b51eSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)"); 501ebc09c36SJim Ingham 502405fe67fSCaroline Tice CommandArgumentEntry arg1; 503405fe67fSCaroline Tice CommandArgumentEntry arg2; 504405fe67fSCaroline Tice CommandArgumentEntry arg3; 505405fe67fSCaroline Tice CommandArgumentData alias_arg; 506405fe67fSCaroline Tice CommandArgumentData cmd_arg; 507405fe67fSCaroline Tice CommandArgumentData options_arg; 508405fe67fSCaroline Tice 509405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 510405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 511405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 512405fe67fSCaroline Tice 513b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 514b9c1b51eSKate Stone // argument entry. 515405fe67fSCaroline Tice arg1.push_back(alias_arg); 516405fe67fSCaroline Tice 517405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 518405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 519405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 520405fe67fSCaroline Tice 521b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 522b9c1b51eSKate Stone // argument entry. 523405fe67fSCaroline Tice arg2.push_back(cmd_arg); 524405fe67fSCaroline Tice 525405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 526405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 527405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 528405fe67fSCaroline Tice 529b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 530b9c1b51eSKate Stone // argument entry. 531405fe67fSCaroline Tice arg3.push_back(options_arg); 532405fe67fSCaroline Tice 533405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 534405fe67fSCaroline Tice m_arguments.push_back(arg1); 535405fe67fSCaroline Tice m_arguments.push_back(arg2); 536405fe67fSCaroline Tice m_arguments.push_back(arg3); 537ebc09c36SJim Ingham } 538ebc09c36SJim Ingham 5396e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 540ebc09c36SJim Ingham 5415a988416SJim Ingham protected: 542b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 543b9c1b51eSKate Stone CommandReturnObject &result) override { 544b9c1b51eSKate Stone if (!raw_command_line || !raw_command_line[0]) { 545d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 54645d0e238SEnrico Granata return false; 54745d0e238SEnrico Granata } 54845d0e238SEnrico Granata 549e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 550e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 55145d0e238SEnrico Granata 55245d0e238SEnrico Granata const char *remainder = nullptr; 55345d0e238SEnrico Granata 554b9c1b51eSKate Stone if (raw_command_line[0] == '-') { 55545d0e238SEnrico Granata // We have some options and these options MUST end with --. 55645d0e238SEnrico Granata const char *end_options = nullptr; 55745d0e238SEnrico Granata const char *s = raw_command_line; 558b9c1b51eSKate Stone while (s && s[0]) { 55945d0e238SEnrico Granata end_options = ::strstr(s, "--"); 560b9c1b51eSKate Stone if (end_options) { 56145d0e238SEnrico Granata end_options += 2; // Get past the "--" 562b9c1b51eSKate Stone if (::isspace(end_options[0])) { 56345d0e238SEnrico Granata remainder = end_options; 56445d0e238SEnrico Granata while (::isspace(*remainder)) 56545d0e238SEnrico Granata ++remainder; 56645d0e238SEnrico Granata break; 56745d0e238SEnrico Granata } 56845d0e238SEnrico Granata } 56945d0e238SEnrico Granata s = end_options; 57045d0e238SEnrico Granata } 57145d0e238SEnrico Granata 572b9c1b51eSKate Stone if (end_options) { 573b9c1b51eSKate Stone Args args( 574b9c1b51eSKate Stone llvm::StringRef(raw_command_line, end_options - raw_command_line)); 57545d0e238SEnrico Granata if (!ParseOptions(args, result)) 57645d0e238SEnrico Granata return false; 57745d0e238SEnrico Granata 578e1cfbc79STodd Fiala Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); 579b9c1b51eSKate Stone if (error.Fail()) { 58045d0e238SEnrico Granata result.AppendError(error.AsCString()); 58145d0e238SEnrico Granata result.SetStatus(eReturnStatusFailed); 58245d0e238SEnrico Granata return false; 58345d0e238SEnrico Granata } 58445d0e238SEnrico Granata } 58545d0e238SEnrico Granata } 58645d0e238SEnrico Granata if (nullptr == remainder) 58745d0e238SEnrico Granata remainder = raw_command_line; 58845d0e238SEnrico Granata 589a01bccdbSZachary Turner llvm::StringRef raw_command_string(remainder); 590a01bccdbSZachary Turner Args args(raw_command_string); 591844d2303SCaroline Tice 59211eb9c64SZachary Turner if (args.GetArgumentCount() < 2) { 593d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 594844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 595844d2303SCaroline Tice return false; 596844d2303SCaroline Tice } 597844d2303SCaroline Tice 598844d2303SCaroline Tice // Get the alias command. 599844d2303SCaroline Tice 6004574a890SZachary Turner auto alias_command = args[0].ref; 6014574a890SZachary Turner if (alias_command.startswith("-")) { 602d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 603b9c1b51eSKate Stone if (alias_command == "--help" || alias_command == "--long-help") { 604b9c1b51eSKate Stone result.AppendWarning("if trying to pass options to 'command alias' add " 605b9c1b51eSKate Stone "a -- at the end of the options"); 606d72e412fSEnrico Granata } 607d72e412fSEnrico Granata result.SetStatus(eReturnStatusFailed); 608d72e412fSEnrico Granata return false; 609d72e412fSEnrico Granata } 610844d2303SCaroline Tice 611b9c1b51eSKate Stone // Strip the new alias name off 'raw_command_string' (leave it on args, 612b9c1b51eSKate Stone // which gets passed to 'Execute', which 613844d2303SCaroline Tice // does the stripping itself. 614844d2303SCaroline Tice size_t pos = raw_command_string.find(alias_command); 615b9c1b51eSKate Stone if (pos == 0) { 616844d2303SCaroline Tice raw_command_string = raw_command_string.substr(alias_command.size()); 617844d2303SCaroline Tice pos = raw_command_string.find_first_not_of(' '); 618844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 619844d2303SCaroline Tice raw_command_string = raw_command_string.substr(pos); 620b9c1b51eSKate Stone } else { 621844d2303SCaroline Tice result.AppendError("Error parsing command string. No alias created."); 622844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 623844d2303SCaroline Tice return false; 624844d2303SCaroline Tice } 625844d2303SCaroline Tice 626844d2303SCaroline Tice // Verify that the command is alias-able. 627771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 628b9c1b51eSKate Stone result.AppendErrorWithFormat( 629b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 6304574a890SZachary Turner args[0].c_str()); 631844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 632844d2303SCaroline Tice return false; 633844d2303SCaroline Tice } 634844d2303SCaroline Tice 635b9c1b51eSKate Stone // Get CommandObject that is being aliased. The command name is read from 636a01bccdbSZachary Turner // the front of raw_command_string. raw_command_string is returned with the 637a01bccdbSZachary Turner // name of the command object stripped off the front. 638a01bccdbSZachary Turner llvm::StringRef original_raw_command_string = raw_command_string; 639b9c1b51eSKate Stone CommandObject *cmd_obj = 640b9c1b51eSKate Stone m_interpreter.GetCommandObjectForCommand(raw_command_string); 641844d2303SCaroline Tice 642b9c1b51eSKate Stone if (!cmd_obj) { 643b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command given to 'command alias'. " 644b9c1b51eSKate Stone "'%s' does not begin with a valid command." 645b9c1b51eSKate Stone " No alias created.", 646a01bccdbSZachary Turner original_raw_command_string.str().c_str()); 647844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 648844d2303SCaroline Tice return false; 649b9c1b51eSKate Stone } else if (!cmd_obj->WantsRawCommandString()) { 650b9c1b51eSKate Stone // Note that args was initialized with the original command, and has not 651b9c1b51eSKate Stone // been updated to this point. 652b9c1b51eSKate Stone // Therefore can we pass it to the version of Execute that does not 653b9c1b51eSKate Stone // need/expect raw input in the alias. 6545a988416SJim Ingham return HandleAliasingNormalCommand(args, result); 655b9c1b51eSKate Stone } else { 656b9c1b51eSKate Stone return HandleAliasingRawCommand(alias_command, raw_command_string, 657b9c1b51eSKate Stone *cmd_obj, result); 6585a988416SJim Ingham } 6595a988416SJim Ingham return result.Succeeded(); 6605a988416SJim Ingham } 6615a988416SJim Ingham 662a01bccdbSZachary Turner bool HandleAliasingRawCommand(llvm::StringRef alias_command, 663a01bccdbSZachary Turner llvm::StringRef raw_command_string, 664b9c1b51eSKate Stone CommandObject &cmd_obj, 665b9c1b51eSKate Stone CommandReturnObject &result) { 666844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 667844d2303SCaroline Tice 668b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 669b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 670844d2303SCaroline Tice 671b9c1b51eSKate Stone if (CommandObjectSP cmd_obj_sp = 672b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 673a01bccdbSZachary Turner if (m_interpreter.AliasExists(alias_command) || 674a01bccdbSZachary Turner m_interpreter.UserCommandExists(alias_command)) { 675b9c1b51eSKate Stone result.AppendWarningWithFormat( 676b9c1b51eSKate Stone "Overwriting existing definition for '%s'.\n", 677a01bccdbSZachary Turner alias_command.str().c_str()); 678844d2303SCaroline Tice } 679b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 680a01bccdbSZachary Turner alias_command, cmd_obj_sp, raw_command_string)) { 68145d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 68245d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 68345d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 68445d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 685844d2303SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 686b9c1b51eSKate Stone } else { 687472362e6SCaroline Tice result.AppendError("Unable to create requested alias.\n"); 688472362e6SCaroline Tice result.SetStatus(eReturnStatusFailed); 689472362e6SCaroline Tice } 690212130acSEnrico Granata 691b9c1b51eSKate Stone } else { 692212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 693212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 694212130acSEnrico Granata } 695212130acSEnrico Granata 696844d2303SCaroline Tice return result.Succeeded(); 697844d2303SCaroline Tice } 698ebc09c36SJim Ingham 699b9c1b51eSKate Stone bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 700867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 701ebc09c36SJim Ingham 702b9c1b51eSKate Stone if (argc < 2) { 703d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 704ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 705ebc09c36SJim Ingham return false; 706ebc09c36SJim Ingham } 707ebc09c36SJim Ingham 7084574a890SZachary Turner // Save these in std::strings since we're going to shift them off. 7094574a890SZachary Turner const std::string alias_command(args[0].ref); 7104574a890SZachary Turner const std::string actual_command(args[1].ref); 711ebc09c36SJim Ingham 712ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 713ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 714ebc09c36SJim Ingham 715b9c1b51eSKate Stone // Verify that the command is alias'able, and get the appropriate command 716b9c1b51eSKate Stone // object. 717ebc09c36SJim Ingham 718771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 719b9c1b51eSKate Stone result.AppendErrorWithFormat( 720b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 721ebc09c36SJim Ingham alias_command.c_str()); 722ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 7234574a890SZachary Turner return false; 7244574a890SZachary Turner } 7254574a890SZachary Turner 726b9c1b51eSKate Stone CommandObjectSP command_obj_sp( 727a449698cSZachary Turner m_interpreter.GetCommandSPExact(actual_command, true)); 728ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 729ebc09c36SJim Ingham bool use_subcommand = false; 7304574a890SZachary Turner if (!command_obj_sp) { 7314574a890SZachary Turner result.AppendErrorWithFormat("'%s' is not an existing command.\n", 7324574a890SZachary Turner actual_command.c_str()); 7334574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 7344574a890SZachary Turner return false; 7354574a890SZachary Turner } 736ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 7376e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 738b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 739b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 740ebc09c36SJim Ingham 74111eb9c64SZachary Turner while (cmd_obj->IsMultiwordObject() && !args.empty()) { 7424574a890SZachary Turner auto sub_command = args[0].ref; 74311eb9c64SZachary Turner assert(!sub_command.empty()); 7444574a890SZachary Turner subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 7454574a890SZachary Turner if (!subcommand_obj_sp) { 746b9c1b51eSKate Stone result.AppendErrorWithFormat( 747b9c1b51eSKate Stone "'%s' is not a valid sub-command of '%s'. " 748f415eeb4SCaroline Tice "Unable to create alias.\n", 7494574a890SZachary Turner args[0].c_str(), actual_command.c_str()); 750ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 751ebc09c36SJim Ingham return false; 752ebc09c36SJim Ingham } 7534574a890SZachary Turner 7544574a890SZachary Turner sub_cmd_obj = subcommand_obj_sp.get(); 7554574a890SZachary Turner use_subcommand = true; 7564574a890SZachary Turner args.Shift(); // Shift the sub_command word off the argument vector. 7574574a890SZachary Turner cmd_obj = sub_cmd_obj; 758ebc09c36SJim Ingham } 759ebc09c36SJim Ingham 760ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 761ebc09c36SJim Ingham 762212130acSEnrico Granata std::string args_string; 763212130acSEnrico Granata 76411eb9c64SZachary Turner if (!args.empty()) { 765b9c1b51eSKate Stone CommandObjectSP tmp_sp = 766b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 767ebc09c36SJim Ingham if (use_subcommand) 7684574a890SZachary Turner tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 7694574a890SZachary Turner false); 770ca90c47eSCaroline Tice 771ca90c47eSCaroline Tice args.GetCommandString(args_string); 772867b185dSCaroline Tice } 773ebc09c36SJim Ingham 774771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 775771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 776b9c1b51eSKate Stone result.AppendWarningWithFormat( 7774574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 778ebc09c36SJim Ingham } 779ebc09c36SJim Ingham 780b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 7814574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 782771ef6d4SMalcolm Parsons args_string)) { 78345d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 78445d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 78545d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 78645d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 787ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 788b9c1b51eSKate Stone } else { 789212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 790212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 791212130acSEnrico Granata return false; 792212130acSEnrico Granata } 793ebc09c36SJim Ingham 794ebc09c36SJim Ingham return result.Succeeded(); 795ebc09c36SJim Ingham } 796ebc09c36SJim Ingham }; 797ebc09c36SJim Ingham 798ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 799ebc09c36SJim Ingham //------------------------------------------------------------------------- 800ebc09c36SJim Ingham // CommandObjectCommandsUnalias 801ebc09c36SJim Ingham //------------------------------------------------------------------------- 802ebc09c36SJim Ingham 803b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 804ebc09c36SJim Ingham public: 8057428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 806b9c1b51eSKate Stone : CommandObjectParsed( 807b9c1b51eSKate Stone interpreter, "command unalias", 808b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 809b9c1b51eSKate Stone nullptr) { 810405fe67fSCaroline Tice CommandArgumentEntry arg; 811405fe67fSCaroline Tice CommandArgumentData alias_arg; 812405fe67fSCaroline Tice 813405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 814405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 815405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 816405fe67fSCaroline Tice 817b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 818b9c1b51eSKate Stone // argument entry. 819405fe67fSCaroline Tice arg.push_back(alias_arg); 820405fe67fSCaroline Tice 821405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 822405fe67fSCaroline Tice m_arguments.push_back(arg); 823ebc09c36SJim Ingham } 824ebc09c36SJim Ingham 8256e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 826ebc09c36SJim Ingham 8275a988416SJim Ingham protected: 828b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 829ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 830ebc09c36SJim Ingham CommandObject *cmd_obj; 831ebc09c36SJim Ingham 83211eb9c64SZachary Turner if (args.empty()) { 83311eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 83411eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 83511eb9c64SZachary Turner return false; 83611eb9c64SZachary Turner } 83711eb9c64SZachary Turner 8384574a890SZachary Turner auto command_name = args[0].ref; 839a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 8404574a890SZachary Turner if (!cmd_obj) { 8414574a890SZachary Turner result.AppendErrorWithFormat( 8424574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 8434574a890SZachary Turner "current list of commands.\n", 844867e7d17SZachary Turner args[0].c_str()); 8454574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 8464574a890SZachary Turner return false; 8474574a890SZachary Turner } 8484574a890SZachary Turner 849b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 850b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 851b9c1b51eSKate Stone result.AppendErrorWithFormat( 852b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 853b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 854867e7d17SZachary Turner args[0].c_str()); 855b9c1b51eSKate Stone } else { 856b9c1b51eSKate Stone result.AppendErrorWithFormat( 857b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 858867e7d17SZachary Turner args[0].c_str()); 859b547278cSGreg Clayton } 860ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8614574a890SZachary Turner return false; 8624574a890SZachary Turner } 8634574a890SZachary Turner 864b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 865a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 866b9c1b51eSKate Stone result.AppendErrorWithFormat( 867867e7d17SZachary Turner "Error occurred while attempting to unalias '%s'.\n", 868867e7d17SZachary Turner args[0].c_str()); 869ebc09c36SJim Ingham else 870b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 871867e7d17SZachary Turner args[0].c_str()); 872ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8734574a890SZachary Turner return false; 874ebc09c36SJim Ingham } 875ebc09c36SJim Ingham 8764574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 877ebc09c36SJim Ingham return result.Succeeded(); 878ebc09c36SJim Ingham } 879ebc09c36SJim Ingham }; 880ebc09c36SJim Ingham 881b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 882b547278cSGreg Clayton //------------------------------------------------------------------------- 883b547278cSGreg Clayton // CommandObjectCommandsDelete 884b547278cSGreg Clayton //------------------------------------------------------------------------- 885b547278cSGreg Clayton 886b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 887b547278cSGreg Clayton public: 8887428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 889b9c1b51eSKate Stone : CommandObjectParsed( 890b9c1b51eSKate Stone interpreter, "command delete", 891b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 892b9c1b51eSKate Stone nullptr) { 893b547278cSGreg Clayton CommandArgumentEntry arg; 894b547278cSGreg Clayton CommandArgumentData alias_arg; 895b547278cSGreg Clayton 896b547278cSGreg Clayton // Define the first (and only) variant of this arg. 897b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 898b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 899b547278cSGreg Clayton 900b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 901b9c1b51eSKate Stone // argument entry. 902b547278cSGreg Clayton arg.push_back(alias_arg); 903b547278cSGreg Clayton 904b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 905b547278cSGreg Clayton m_arguments.push_back(arg); 906b547278cSGreg Clayton } 907b547278cSGreg Clayton 9086e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 909b547278cSGreg Clayton 910b547278cSGreg Clayton protected: 911b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 912b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 913b547278cSGreg Clayton 91411eb9c64SZachary Turner if (args.empty()) { 91511eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 91611eb9c64SZachary Turner "defined regular expression command names", 917a449698cSZachary Turner GetCommandName().str().c_str()); 91811eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 91911eb9c64SZachary Turner } 92011eb9c64SZachary Turner 9214574a890SZachary Turner auto command_name = args[0].ref; 9224574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 92346d4aa21SEnrico Granata StreamString error_msg_stream; 92446d4aa21SEnrico Granata const bool generate_apropos = true; 92546d4aa21SEnrico Granata const bool generate_type_lookup = false; 926b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 9274574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 9284574a890SZachary Turner generate_apropos, generate_type_lookup); 929c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 930b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 9314574a890SZachary Turner return false; 932b547278cSGreg Clayton } 933b547278cSGreg Clayton 9344574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 9354574a890SZachary Turner result.AppendErrorWithFormat( 9364574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 937867e7d17SZachary Turner args[0].c_str()); 9384574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 9394574a890SZachary Turner return false; 9404574a890SZachary Turner } 9414574a890SZachary Turner 9424574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 9434574a890SZachary Turner return true; 944b547278cSGreg Clayton } 945b547278cSGreg Clayton }; 946b547278cSGreg Clayton 947de164aaaSGreg Clayton //------------------------------------------------------------------------- 948de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 949de164aaaSGreg Clayton //------------------------------------------------------------------------- 9501f0f5b5bSZachary Turner 9511f0f5b5bSZachary Turner static OptionDefinition g_regex_options[] = { 9521f0f5b5bSZachary Turner // clang-format off 9531f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." }, 9541f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, 9551f0f5b5bSZachary Turner // clang-format on 9561f0f5b5bSZachary Turner }; 9571f0f5b5bSZachary Turner 9585a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 959de164aaaSGreg Clayton 960b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 961b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 962de164aaaSGreg Clayton public: 9637428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 964b9c1b51eSKate Stone : CommandObjectParsed( 965b9c1b51eSKate Stone interpreter, "command regex", "Define a custom command in terms of " 966b9c1b51eSKate Stone "existing commands by matching " 967b9c1b51eSKate Stone "regular expressions.", 9680e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 969b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 970b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 971b9c1b51eSKate Stone m_options() { 972b9c1b51eSKate Stone SetHelpLong( 973b9c1b51eSKate Stone R"( 974b9c1b51eSKate Stone )" 975b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 976ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 977b9c1b51eSKate Stone using the regular expression substitution format of:" 978b9c1b51eSKate Stone R"( 979ea671fbdSKate Stone 980ea671fbdSKate Stone s/<regex>/<subst>/ 981ea671fbdSKate Stone 982b9c1b51eSKate Stone )" 983b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 984ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 985b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 986b9c1b51eSKate Stone R"( 987ea671fbdSKate Stone 988b9c1b51eSKate Stone )" 989b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 990ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 991ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 992b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 993b9c1b51eSKate Stone R"( 994ea671fbdSKate Stone 995ea671fbdSKate Stone EXAMPLES 996ea671fbdSKate Stone 997b9c1b51eSKate Stone )" 998b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 999ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 1000b9c1b51eSKate Stone a number follows 'f':" 1001b9c1b51eSKate Stone R"( 1002ea671fbdSKate Stone 1003b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 1004de164aaaSGreg Clayton } 1005de164aaaSGreg Clayton 10066e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 1007de164aaaSGreg Clayton 10085a988416SJim Ingham protected: 1009b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 101044d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1011b9c1b51eSKate Stone if (output_sp) { 1012b9c1b51eSKate Stone output_sp->PutCString("Enter one of more sed substitution commands in " 1013b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 1014b9c1b51eSKate Stone "substitution list with an empty line.\n"); 101544d93782SGreg Clayton output_sp->Flush(); 101644d93782SGreg Clayton } 101744d93782SGreg Clayton } 101844d93782SGreg Clayton 1019b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1020b9c1b51eSKate Stone std::string &data) override { 102144d93782SGreg Clayton io_handler.SetIsDone(true); 1022b9c1b51eSKate Stone if (m_regex_cmd_ap) { 102344d93782SGreg Clayton StringList lines; 1024b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 102544d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 102644d93782SGreg Clayton bool check_only = false; 1027b9c1b51eSKate Stone for (size_t i = 0; i < num_lines; ++i) { 102844d93782SGreg Clayton llvm::StringRef bytes_strref(lines[i]); 102944d93782SGreg Clayton Error error = AppendRegexSubstitution(bytes_strref, check_only); 1030b9c1b51eSKate Stone if (error.Fail()) { 1031b9c1b51eSKate Stone if (!m_interpreter.GetDebugger() 1032b9c1b51eSKate Stone .GetCommandInterpreter() 1033b9c1b51eSKate Stone .GetBatchCommandMode()) { 1034b9c1b51eSKate Stone StreamSP out_stream = 1035b9c1b51eSKate Stone m_interpreter.GetDebugger().GetAsyncOutputStream(); 103644d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 103744d93782SGreg Clayton } 103844d93782SGreg Clayton } 103944d93782SGreg Clayton } 104044d93782SGreg Clayton } 1041b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 104244d93782SGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 104344d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 104444d93782SGreg Clayton } 104544d93782SGreg Clayton } 104644d93782SGreg Clayton } 104744d93782SGreg Clayton 1048b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 10495a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 1050b9c1b51eSKate Stone if (argc == 0) { 1051b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 1052b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 10530e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 105411eb9c64SZachary Turner return false; 105511eb9c64SZachary Turner } 105611eb9c64SZachary Turner 10570e5e5a79SGreg Clayton Error error; 10584574a890SZachary Turner auto name = command[0].ref; 10594574a890SZachary Turner m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>( 10604574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 10614574a890SZachary Turner true); 10620e5e5a79SGreg Clayton 1063b9c1b51eSKate Stone if (argc == 1) { 106444d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1065e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 106644d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 1067b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 1068b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 106973d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1070514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 1071514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 1072b9c1b51eSKate Stone multiple_lines, color_prompt, 1073f6913cd7SGreg Clayton 0, // Don't show line numbers 107444d93782SGreg Clayton *this)); 107544d93782SGreg Clayton 1076b9c1b51eSKate Stone if (io_handler_sp) { 107744d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1078de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 1079de164aaaSGreg Clayton } 1080b9c1b51eSKate Stone } else { 108197d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 108244d93782SGreg Clayton bool check_only = false; 108397d2c401SZachary Turner error = AppendRegexSubstitution(entry.ref, check_only); 10840e5e5a79SGreg Clayton if (error.Fail()) 10850e5e5a79SGreg Clayton break; 10860e5e5a79SGreg Clayton } 10870e5e5a79SGreg Clayton 1088b9c1b51eSKate Stone if (error.Success()) { 10890e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 10900e5e5a79SGreg Clayton } 10910e5e5a79SGreg Clayton } 1092b9c1b51eSKate Stone if (error.Fail()) { 10930e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 1094de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 1095de164aaaSGreg Clayton } 10960e5e5a79SGreg Clayton 1097de164aaaSGreg Clayton return result.Succeeded(); 1098de164aaaSGreg Clayton } 1099de164aaaSGreg Clayton 1100b9c1b51eSKate Stone Error AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 1101b9c1b51eSKate Stone bool check_only) { 11020e5e5a79SGreg Clayton Error error; 11030e5e5a79SGreg Clayton 1104b9c1b51eSKate Stone if (!m_regex_cmd_ap) { 1105b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1106b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 1107b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11080e5e5a79SGreg Clayton return error; 1109de164aaaSGreg Clayton } 11100e5e5a79SGreg Clayton 11110e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 11120e5e5a79SGreg Clayton 1113b9c1b51eSKate Stone if (regex_sed_size <= 1) { 1114b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1115b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 1116b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11170e5e5a79SGreg Clayton return error; 11180e5e5a79SGreg Clayton } 11190e5e5a79SGreg Clayton 1120b9c1b51eSKate Stone if (regex_sed[0] != 's') { 1121b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 1122b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 1123b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11240e5e5a79SGreg Clayton return error; 11250e5e5a79SGreg Clayton } 11260e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 11270e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 11280e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 11290e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 1130b9c1b51eSKate Stone const size_t second_separator_char_pos = 1131b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 11320e5e5a79SGreg Clayton 1133b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 1134b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1135b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 11360e5e5a79SGreg Clayton separator_char, 11370e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1138ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1139b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11400e5e5a79SGreg Clayton return error; 11410e5e5a79SGreg Clayton } 11420e5e5a79SGreg Clayton 1143b9c1b51eSKate Stone const size_t third_separator_char_pos = 1144b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 11450e5e5a79SGreg Clayton 1146b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 1147b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1148b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 11490e5e5a79SGreg Clayton separator_char, 11500e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1151ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1152b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11530e5e5a79SGreg Clayton return error; 11540e5e5a79SGreg Clayton } 11550e5e5a79SGreg Clayton 1156b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 11570e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 11580e5e5a79SGreg Clayton // separator char 1159b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 1160b9c1b51eSKate Stone third_separator_char_pos + 1) != 1161b9c1b51eSKate Stone std::string::npos) { 1162b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1163b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 1164b9c1b51eSKate Stone "string: '%.*s'", 1165b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 11660e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 11670e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 11680e5e5a79SGreg Clayton return error; 11690e5e5a79SGreg Clayton } 1170b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 1171b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1172b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1173b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11740e5e5a79SGreg Clayton regex_sed.data()); 11750e5e5a79SGreg Clayton return error; 1176b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 1177b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1178b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1179b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11800e5e5a79SGreg Clayton regex_sed.data()); 11810e5e5a79SGreg Clayton return error; 11820e5e5a79SGreg Clayton } 118344d93782SGreg Clayton 1184b9c1b51eSKate Stone if (!check_only) { 1185b9c1b51eSKate Stone std::string regex(regex_sed.substr(first_separator_char_pos + 1, 1186b9c1b51eSKate Stone second_separator_char_pos - 1187b9c1b51eSKate Stone first_separator_char_pos - 1)); 1188b9c1b51eSKate Stone std::string subst(regex_sed.substr(second_separator_char_pos + 1, 1189b9c1b51eSKate Stone third_separator_char_pos - 1190b9c1b51eSKate Stone second_separator_char_pos - 1)); 1191b9c1b51eSKate Stone m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str()); 119244d93782SGreg Clayton } 11930e5e5a79SGreg Clayton return error; 1194de164aaaSGreg Clayton } 1195de164aaaSGreg Clayton 1196b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 1197b9c1b51eSKate Stone if (m_regex_cmd_ap) { 1198b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 1199de164aaaSGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 1200de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1201de164aaaSGreg Clayton } 1202de164aaaSGreg Clayton } 1203de164aaaSGreg Clayton } 1204de164aaaSGreg Clayton 1205de164aaaSGreg Clayton private: 12067b0992d9SGreg Clayton std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1207de164aaaSGreg Clayton 1208b9c1b51eSKate Stone class CommandOptions : public Options { 1209de164aaaSGreg Clayton public: 1210b9c1b51eSKate Stone CommandOptions() : Options() {} 1211de164aaaSGreg Clayton 12126e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1213de164aaaSGreg Clayton 1214fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1215b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1216de164aaaSGreg Clayton Error error; 12173bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1218de164aaaSGreg Clayton 1219b9c1b51eSKate Stone switch (short_option) { 1220de164aaaSGreg Clayton case 'h': 1221de164aaaSGreg Clayton m_help.assign(option_arg); 1222de164aaaSGreg Clayton break; 1223de164aaaSGreg Clayton case 's': 1224de164aaaSGreg Clayton m_syntax.assign(option_arg); 1225de164aaaSGreg Clayton break; 1226de164aaaSGreg Clayton default: 1227b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1228b9c1b51eSKate Stone short_option); 1229de164aaaSGreg Clayton break; 1230de164aaaSGreg Clayton } 1231de164aaaSGreg Clayton 1232de164aaaSGreg Clayton return error; 1233de164aaaSGreg Clayton } 1234de164aaaSGreg Clayton 1235b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1236de164aaaSGreg Clayton m_help.clear(); 1237de164aaaSGreg Clayton m_syntax.clear(); 1238de164aaaSGreg Clayton } 1239de164aaaSGreg Clayton 12401f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 124170602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 12421f0f5b5bSZachary Turner } 1243de164aaaSGreg Clayton 124411eb9c64SZachary Turner // TODO: Convert these functions to return StringRefs. 1245b9c1b51eSKate Stone const char *GetHelp() { 12466e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1247de164aaaSGreg Clayton } 12486e3d8e7fSEugene Zelenko 1249b9c1b51eSKate Stone const char *GetSyntax() { 12506e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1251de164aaaSGreg Clayton } 12526e3d8e7fSEugene Zelenko 1253de164aaaSGreg Clayton protected: 12546e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 12556e3d8e7fSEugene Zelenko 1256de164aaaSGreg Clayton std::string m_help; 1257de164aaaSGreg Clayton std::string m_syntax; 1258de164aaaSGreg Clayton }; 1259de164aaaSGreg Clayton 1260b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1261de164aaaSGreg Clayton 12625a988416SJim Ingham CommandOptions m_options; 1263de164aaaSGreg Clayton }; 1264de164aaaSGreg Clayton 1265b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1266223383edSEnrico Granata public: 1267b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1268b9c1b51eSKate Stone std::string funct, std::string help, 1269b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1270a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1271b9c1b51eSKate Stone m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { 1272735152e3SEnrico Granata if (!help.empty()) 1273442f6530SZachary Turner SetHelp(help); 1274b9c1b51eSKate Stone else { 1275735152e3SEnrico Granata StreamString stream; 1276735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1277c156427dSZachary Turner SetHelp(stream.GetString()); 1278735152e3SEnrico Granata } 1279223383edSEnrico Granata } 1280223383edSEnrico Granata 12816e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1282223383edSEnrico Granata 1283b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 12845a988416SJim Ingham 1285b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 12865a988416SJim Ingham 1287b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 12885a988416SJim Ingham 1289442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1290442f6530SZachary Turner if (m_fetched_help_long) 1291442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1292442f6530SZachary Turner 1293fac939e9SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1294442f6530SZachary Turner if (!scripter) 1295442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1296442f6530SZachary Turner 1297fac939e9SEnrico Granata std::string docstring; 1298442f6530SZachary Turner m_fetched_help_long = 1299442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1300fac939e9SEnrico Granata if (!docstring.empty()) 1301442f6530SZachary Turner SetHelpLong(docstring); 1302fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1303fac939e9SEnrico Granata } 1304fac939e9SEnrico Granata 13055a988416SJim Ingham protected: 1306b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1307b9c1b51eSKate Stone CommandReturnObject &result) override { 1308223383edSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1309223383edSEnrico Granata 1310223383edSEnrico Granata Error error; 1311223383edSEnrico Granata 131270f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 131370f11f88SJim Ingham 1314b9c1b51eSKate Stone if (!scripter || 1315b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1316b9c1b51eSKate Stone raw_command_line, m_synchro, result, 1317b9c1b51eSKate Stone error, m_exe_ctx)) { 1318223383edSEnrico Granata result.AppendError(error.AsCString()); 1319223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1320b9c1b51eSKate Stone } else { 132170f11f88SJim Ingham // Don't change the status if the command already set it... 1322b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1323c156427dSZachary Turner if (result.GetOutputData().empty()) 1324223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 132570f11f88SJim Ingham else 132670f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 132770f11f88SJim Ingham } 132870f11f88SJim Ingham } 1329223383edSEnrico Granata 1330223383edSEnrico Granata return result.Succeeded(); 1331223383edSEnrico Granata } 1332223383edSEnrico Granata 13336e3d8e7fSEugene Zelenko private: 13346e3d8e7fSEugene Zelenko std::string m_function_name; 13356e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 13366e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1337223383edSEnrico Granata }; 1338223383edSEnrico Granata 1339b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 13409fe00e52SEnrico Granata public: 13419fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 13429fe00e52SEnrico Granata std::string name, 13430641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1344b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1345a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1346b9c1b51eSKate Stone m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), 1347b9c1b51eSKate Stone m_fetched_help_long(false) { 13489fe00e52SEnrico Granata StreamString stream; 13499fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1350c156427dSZachary Turner SetHelp(stream.GetString()); 1351e87764f2SEnrico Granata if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter()) 1352e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 13539fe00e52SEnrico Granata } 13549fe00e52SEnrico Granata 13556e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 13569fe00e52SEnrico Granata 1357b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 13589fe00e52SEnrico Granata 1359b9c1b51eSKate Stone StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } 13609fe00e52SEnrico Granata 1361b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 13629fe00e52SEnrico Granata 1363442f6530SZachary Turner llvm::StringRef GetHelp() override { 1364442f6530SZachary Turner if (m_fetched_help_short) 1365442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13666f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1367442f6530SZachary Turner if (!scripter) 1368442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13696f79bb2dSEnrico Granata std::string docstring; 1370b9c1b51eSKate Stone m_fetched_help_short = 1371b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 13726f79bb2dSEnrico Granata if (!docstring.empty()) 1373442f6530SZachary Turner SetHelp(docstring); 1374442f6530SZachary Turner 13756f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 13766f79bb2dSEnrico Granata } 13776f79bb2dSEnrico Granata 1378442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1379442f6530SZachary Turner if (m_fetched_help_long) 1380442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1381442f6530SZachary Turner 13826f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1383442f6530SZachary Turner if (!scripter) 1384442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1385442f6530SZachary Turner 13866f79bb2dSEnrico Granata std::string docstring; 1387b9c1b51eSKate Stone m_fetched_help_long = 1388b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 13896f79bb2dSEnrico Granata if (!docstring.empty()) 1390442f6530SZachary Turner SetHelpLong(docstring); 13919fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 13929fe00e52SEnrico Granata } 13939fe00e52SEnrico Granata 13949fe00e52SEnrico Granata protected: 1395b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1396b9c1b51eSKate Stone CommandReturnObject &result) override { 13979fe00e52SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 13989fe00e52SEnrico Granata 13999fe00e52SEnrico Granata Error error; 14009fe00e52SEnrico Granata 14019fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 14029fe00e52SEnrico Granata 1403b9c1b51eSKate Stone if (!scripter || 1404b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1405b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 14069fe00e52SEnrico Granata result.AppendError(error.AsCString()); 14079fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1408b9c1b51eSKate Stone } else { 14099fe00e52SEnrico Granata // Don't change the status if the command already set it... 1410b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1411c156427dSZachary Turner if (result.GetOutputData().empty()) 14129fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 14139fe00e52SEnrico Granata else 14149fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 14159fe00e52SEnrico Granata } 14169fe00e52SEnrico Granata } 14179fe00e52SEnrico Granata 14189fe00e52SEnrico Granata return result.Succeeded(); 14199fe00e52SEnrico Granata } 14209fe00e52SEnrico Granata 14216e3d8e7fSEugene Zelenko private: 14226e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 14236e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 14246e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 14256e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 14269fe00e52SEnrico Granata }; 14279fe00e52SEnrico Granata 1428a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1429a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1430a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1431a9dbf432SEnrico Granata 14321f0f5b5bSZachary Turner OptionDefinition g_script_import_options[] = { 14331f0f5b5bSZachary Turner // clang-format off 14341f0f5b5bSZachary 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." }, 14351f0f5b5bSZachary Turner // clang-format on 14361f0f5b5bSZachary Turner }; 14371f0f5b5bSZachary Turner 1438b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 14395a988416SJim Ingham public: 1440b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1441b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1442b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1443b9c1b51eSKate Stone m_options() { 14445a988416SJim Ingham CommandArgumentEntry arg1; 14455a988416SJim Ingham CommandArgumentData cmd_arg; 14465a988416SJim Ingham 14475a988416SJim Ingham // Define the first (and only) variant of this arg. 14485a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 14493b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 14505a988416SJim Ingham 1451b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1452b9c1b51eSKate Stone // argument entry. 14535a988416SJim Ingham arg1.push_back(cmd_arg); 14545a988416SJim Ingham 14555a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 14565a988416SJim Ingham m_arguments.push_back(arg1); 14575a988416SJim Ingham } 14585a988416SJim Ingham 14596e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 14605a988416SJim Ingham 1461b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 14625a988416SJim Ingham int &cursor_char_position, 14635a988416SJim Ingham OptionElementVector &opt_element_vector, 1464b9c1b51eSKate Stone int match_start_point, int max_return_elements, 14655a988416SJim Ingham bool &word_complete, 1466b9c1b51eSKate Stone StringList &matches) override { 1467d6a24757SZachary Turner llvm::StringRef completion_str = input[cursor_index].ref; 1468d6a24757SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 14695a988416SJim Ingham 1470b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1471b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1472d6a24757SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 1473b9c1b51eSKate Stone word_complete, matches); 14745a988416SJim Ingham return matches.GetSize(); 14755a988416SJim Ingham } 14765a988416SJim Ingham 1477b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14785a988416SJim Ingham 14795a988416SJim Ingham protected: 1480b9c1b51eSKate Stone class CommandOptions : public Options { 14810a305db7SEnrico Granata public: 1482b9c1b51eSKate Stone CommandOptions() : Options() {} 14830a305db7SEnrico Granata 14846e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 14850a305db7SEnrico Granata 1486fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1487b9c1b51eSKate Stone ExecutionContext *execution_context) override { 14880a305db7SEnrico Granata Error error; 14893bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14900a305db7SEnrico Granata 1491b9c1b51eSKate Stone switch (short_option) { 14920a305db7SEnrico Granata case 'r': 14930a305db7SEnrico Granata m_allow_reload = true; 14940a305db7SEnrico Granata break; 14950a305db7SEnrico Granata default: 1496b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1497b9c1b51eSKate Stone short_option); 14980a305db7SEnrico Granata break; 14990a305db7SEnrico Granata } 15000a305db7SEnrico Granata 15010a305db7SEnrico Granata return error; 15020a305db7SEnrico Granata } 15030a305db7SEnrico Granata 1504b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1505e0c70f1bSEnrico Granata m_allow_reload = true; 15060a305db7SEnrico Granata } 15070a305db7SEnrico Granata 15081f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 150970602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 15101f0f5b5bSZachary Turner } 15110a305db7SEnrico Granata 15120a305db7SEnrico Granata // Instance variables to hold the values for command options. 15130a305db7SEnrico Granata 15140a305db7SEnrico Granata bool m_allow_reload; 15150a305db7SEnrico Granata }; 15160a305db7SEnrico Granata 1517b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1518b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1519b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1520b9c1b51eSKate Stone result.AppendError("only scripting language supported for module " 1521b9c1b51eSKate Stone "importing is currently Python"); 1522a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1523a9dbf432SEnrico Granata return false; 1524a9dbf432SEnrico Granata } 1525a9dbf432SEnrico Granata 152611eb9c64SZachary Turner if (command.empty()) { 15273b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1528a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1529a9dbf432SEnrico Granata return false; 1530a9dbf432SEnrico Granata } 1531a9dbf432SEnrico Granata 153211eb9c64SZachary Turner for (auto &entry : command.entries()) { 1533a9dbf432SEnrico Granata Error error; 1534a9dbf432SEnrico Granata 1535c9d645d3SGreg Clayton const bool init_session = true; 1536b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 153711eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 153811eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 153911eb9c64SZachary Turner // script imports" in __lldb_init_module the real fix is to have recursive 154011eb9c64SZachary Turner // commands possible with a CommandInvocation object separate from the 154111eb9c64SZachary Turner // CommandObject itself, so that recursive command invocations won't stomp 154211eb9c64SZachary Turner // on each other (wrt to execution contents, options, and more) 1543078551c7SEnrico Granata m_exe_ctx.Clear(); 1544b9c1b51eSKate Stone if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule( 154511eb9c64SZachary Turner entry.c_str(), m_options.m_allow_reload, init_session, error)) { 1546a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1547b9c1b51eSKate Stone } else { 1548b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1549b9c1b51eSKate Stone error.AsCString()); 1550a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1551a9dbf432SEnrico Granata } 15523b00e35bSEnrico Granata } 1553a9dbf432SEnrico Granata 1554a9dbf432SEnrico Granata return result.Succeeded(); 1555a9dbf432SEnrico Granata } 15560a305db7SEnrico Granata 15575a988416SJim Ingham CommandOptions m_options; 1558a9dbf432SEnrico Granata }; 1559223383edSEnrico Granata 1560223383edSEnrico Granata //------------------------------------------------------------------------- 1561223383edSEnrico Granata // CommandObjectCommandsScriptAdd 1562223383edSEnrico Granata //------------------------------------------------------------------------- 1563223383edSEnrico Granata 15641f0f5b5bSZachary Turner static OptionEnumValueElement g_script_synchro_type[] = { 15651f0f5b5bSZachary Turner {eScriptedCommandSynchronicitySynchronous, "synchronous", 15661f0f5b5bSZachary Turner "Run synchronous"}, 15671f0f5b5bSZachary Turner {eScriptedCommandSynchronicityAsynchronous, "asynchronous", 15681f0f5b5bSZachary Turner "Run asynchronous"}, 15691f0f5b5bSZachary Turner {eScriptedCommandSynchronicityCurrentValue, "current", 15701f0f5b5bSZachary Turner "Do not alter current setting"}, 15711f0f5b5bSZachary Turner {0, nullptr, nullptr}}; 15721f0f5b5bSZachary Turner 15731f0f5b5bSZachary Turner static OptionDefinition g_script_add_options[] = { 15741f0f5b5bSZachary Turner // clang-format off 15751f0f5b5bSZachary 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." }, 15761f0f5b5bSZachary 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." }, 15771f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." }, 15781f0f5b5bSZachary 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." }, 15791f0f5b5bSZachary Turner // clang-format on 15801f0f5b5bSZachary Turner }; 15811f0f5b5bSZachary Turner 1582b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1583b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 15845a988416SJim Ingham public: 1585b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1586b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 15875a988416SJim Ingham "Add a scripted function as an LLDB command.", 15886e3d8e7fSEugene Zelenko nullptr), 1589b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 15905a988416SJim Ingham CommandArgumentEntry arg1; 15915a988416SJim Ingham CommandArgumentData cmd_arg; 15925a988416SJim Ingham 15935a988416SJim Ingham // Define the first (and only) variant of this arg. 15945a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 15955a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 15965a988416SJim Ingham 1597b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1598b9c1b51eSKate Stone // argument entry. 15995a988416SJim Ingham arg1.push_back(cmd_arg); 16005a988416SJim Ingham 16015a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 16025a988416SJim Ingham m_arguments.push_back(arg1); 16035a988416SJim Ingham } 16045a988416SJim Ingham 16056e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 16065a988416SJim Ingham 1607b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 16085a988416SJim Ingham 16095a988416SJim Ingham protected: 1610b9c1b51eSKate Stone class CommandOptions : public Options { 1611223383edSEnrico Granata public: 1612b9c1b51eSKate Stone CommandOptions() 1613b9c1b51eSKate Stone : Options(), m_class_name(), m_funct_name(), m_short_help(), 1614b9c1b51eSKate Stone m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1615223383edSEnrico Granata 16166e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1617223383edSEnrico Granata 1618fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1619b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1620223383edSEnrico Granata Error error; 16213bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1622223383edSEnrico Granata 1623b9c1b51eSKate Stone switch (short_option) { 1624223383edSEnrico Granata case 'f': 1625fe11483bSZachary Turner if (!option_arg.empty()) 1626fe11483bSZachary Turner m_funct_name = option_arg; 1627735152e3SEnrico Granata break; 16289fe00e52SEnrico Granata case 'c': 1629fe11483bSZachary Turner if (!option_arg.empty()) 1630fe11483bSZachary Turner m_class_name = option_arg; 16319fe00e52SEnrico Granata break; 1632735152e3SEnrico Granata case 'h': 1633fe11483bSZachary Turner if (!option_arg.empty()) 1634fe11483bSZachary Turner m_short_help = option_arg; 1635223383edSEnrico Granata break; 16360a305db7SEnrico Granata case 's': 1637b9c1b51eSKate Stone m_synchronicity = 1638b9c1b51eSKate Stone (ScriptedCommandSynchronicity)Args::StringToOptionEnum( 1639fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 16400a305db7SEnrico Granata if (!error.Success()) 1641b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1642fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1643fe11483bSZachary Turner option_arg.str().c_str()); 16440a305db7SEnrico Granata break; 1645223383edSEnrico Granata default: 1646b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1647b9c1b51eSKate Stone short_option); 1648223383edSEnrico Granata break; 1649223383edSEnrico Granata } 1650223383edSEnrico Granata 1651223383edSEnrico Granata return error; 1652223383edSEnrico Granata } 1653223383edSEnrico Granata 1654b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16559fe00e52SEnrico Granata m_class_name.clear(); 1656735152e3SEnrico Granata m_funct_name.clear(); 1657735152e3SEnrico Granata m_short_help.clear(); 165844d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1659223383edSEnrico Granata } 1660223383edSEnrico Granata 16611f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 166270602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 16631f0f5b5bSZachary Turner } 1664223383edSEnrico Granata 1665223383edSEnrico Granata // Instance variables to hold the values for command options. 1666223383edSEnrico Granata 16679fe00e52SEnrico Granata std::string m_class_name; 1668223383edSEnrico Granata std::string m_funct_name; 1669735152e3SEnrico Granata std::string m_short_help; 167044d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1671223383edSEnrico Granata }; 1672223383edSEnrico Granata 1673b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 167444d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1675b9c1b51eSKate Stone if (output_sp) { 167644d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 167744d93782SGreg Clayton output_sp->Flush(); 1678223383edSEnrico Granata } 1679223383edSEnrico Granata } 1680223383edSEnrico Granata 1681b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1682b9c1b51eSKate Stone std::string &data) override { 168344d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 168444d93782SGreg Clayton 168544d93782SGreg Clayton ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1686b9c1b51eSKate Stone if (interpreter) { 168744d93782SGreg Clayton 168844d93782SGreg Clayton StringList lines; 168944d93782SGreg Clayton lines.SplitIntoLines(data); 1690b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1691a73b7df7SEnrico Granata std::string funct_name_str; 1692b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1693b9c1b51eSKate Stone if (funct_name_str.empty()) { 1694b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1695b9c1b51eSKate Stone "add python command.\n"); 169644d93782SGreg Clayton error_sp->Flush(); 1697b9c1b51eSKate Stone } else { 1698223383edSEnrico Granata // everything should be fine now, let's add this alias 1699223383edSEnrico Granata 1700b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1701771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 170244d93782SGreg Clayton m_synchronicity)); 1703223383edSEnrico Granata 1704b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1705b9c1b51eSKate Stone true)) { 1706b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1707b9c1b51eSKate Stone "add python command.\n"); 170844d93782SGreg Clayton error_sp->Flush(); 1709223383edSEnrico Granata } 1710223383edSEnrico Granata } 1711b9c1b51eSKate Stone } else { 1712b9c1b51eSKate Stone error_sp->Printf( 1713b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 171444d93782SGreg Clayton error_sp->Flush(); 171544d93782SGreg Clayton } 1716b9c1b51eSKate Stone } else { 171744d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 171844d93782SGreg Clayton error_sp->Flush(); 171944d93782SGreg Clayton } 1720b9c1b51eSKate Stone } else { 1721b9c1b51eSKate Stone error_sp->Printf( 1722b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 172344d93782SGreg Clayton error_sp->Flush(); 172444d93782SGreg Clayton } 172544d93782SGreg Clayton 172644d93782SGreg Clayton io_handler.SetIsDone(true); 172744d93782SGreg Clayton } 1728223383edSEnrico Granata 17295a988416SJim Ingham protected: 1730b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1731b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1732b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1733b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1734b9c1b51eSKate Stone "commands is currently Python"); 173599f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 173699f0b8f9SEnrico Granata return false; 173799f0b8f9SEnrico Granata } 173899f0b8f9SEnrico Granata 173911eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1740223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1741223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1742223383edSEnrico Granata return false; 1743223383edSEnrico Granata } 1744223383edSEnrico Granata 1745735152e3SEnrico Granata // Store the options in case we get multi-line input 17464574a890SZachary Turner m_cmd_name = command[0].ref; 1747735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 174844d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1749223383edSEnrico Granata 1750b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1751b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1752b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1753b9c1b51eSKate Stone " ", // Prompt 175444d93782SGreg Clayton *this, // IOHandlerDelegate 175544d93782SGreg Clayton true, // Run IOHandler in async mode 1756b9c1b51eSKate Stone nullptr); // Baton for the "io_handler" that will be passed back 1757b9c1b51eSKate Stone // into our IOHandlerDelegate functions 1758b9c1b51eSKate Stone } else { 1759b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1760b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1761b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1762b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1763223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1764b9c1b51eSKate Stone } else { 1765223383edSEnrico Granata result.AppendError("cannot add command"); 1766223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1767223383edSEnrico Granata } 1768223383edSEnrico Granata } 1769b9c1b51eSKate Stone } else { 1770b9c1b51eSKate Stone ScriptInterpreter *interpreter = 1771b9c1b51eSKate Stone GetCommandInterpreter().GetScriptInterpreter(); 1772b9c1b51eSKate Stone if (!interpreter) { 17739fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 17749fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17759fe00e52SEnrico Granata return false; 17769fe00e52SEnrico Granata } 17779fe00e52SEnrico Granata 1778b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1779b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1780b9c1b51eSKate Stone if (!cmd_obj_sp) { 17819fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 17829fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17839fe00e52SEnrico Granata return false; 17849fe00e52SEnrico Granata } 17859fe00e52SEnrico Granata 1786b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1787b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1788b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 17899fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1790b9c1b51eSKate Stone } else { 17919fe00e52SEnrico Granata result.AppendError("cannot add command"); 17929fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17939fe00e52SEnrico Granata } 17949fe00e52SEnrico Granata } 1795223383edSEnrico Granata 1796223383edSEnrico Granata return result.Succeeded(); 1797223383edSEnrico Granata } 17985a988416SJim Ingham 17995a988416SJim Ingham CommandOptions m_options; 180044d93782SGreg Clayton std::string m_cmd_name; 1801735152e3SEnrico Granata std::string m_short_help; 180244d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1803223383edSEnrico Granata }; 1804223383edSEnrico Granata 1805223383edSEnrico Granata //------------------------------------------------------------------------- 1806223383edSEnrico Granata // CommandObjectCommandsScriptList 1807223383edSEnrico Granata //------------------------------------------------------------------------- 1808223383edSEnrico Granata 1809b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1810223383edSEnrico Granata public: 1811b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1812b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1813b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1814223383edSEnrico Granata 18156e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1816223383edSEnrico Granata 1817b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1818b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1819223383edSEnrico Granata 1820223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1821223383edSEnrico Granata 1822223383edSEnrico Granata return true; 1823223383edSEnrico Granata } 1824223383edSEnrico Granata }; 1825223383edSEnrico Granata 1826223383edSEnrico Granata //------------------------------------------------------------------------- 1827223383edSEnrico Granata // CommandObjectCommandsScriptClear 1828223383edSEnrico Granata //------------------------------------------------------------------------- 1829223383edSEnrico Granata 1830b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1831223383edSEnrico Granata public: 1832b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1833b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1834b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1835223383edSEnrico Granata 18366e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1837223383edSEnrico Granata 18385a988416SJim Ingham protected: 1839b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1840223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1841223383edSEnrico Granata 1842223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1843223383edSEnrico Granata 1844223383edSEnrico Granata return true; 1845223383edSEnrico Granata } 1846223383edSEnrico Granata }; 1847223383edSEnrico Granata 1848223383edSEnrico Granata //------------------------------------------------------------------------- 1849223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1850223383edSEnrico Granata //------------------------------------------------------------------------- 1851223383edSEnrico Granata 1852b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1853223383edSEnrico Granata public: 1854b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1855b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1856b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1857223383edSEnrico Granata CommandArgumentEntry arg1; 1858223383edSEnrico Granata CommandArgumentData cmd_arg; 1859223383edSEnrico Granata 1860223383edSEnrico Granata // Define the first (and only) variant of this arg. 1861223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1862223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1863223383edSEnrico Granata 1864b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1865b9c1b51eSKate Stone // argument entry. 1866223383edSEnrico Granata arg1.push_back(cmd_arg); 1867223383edSEnrico Granata 1868223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1869223383edSEnrico Granata m_arguments.push_back(arg1); 1870223383edSEnrico Granata } 1871223383edSEnrico Granata 18726e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1873223383edSEnrico Granata 18745a988416SJim Ingham protected: 1875b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1876223383edSEnrico Granata 187711eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1878223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1879223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1880223383edSEnrico Granata return false; 1881223383edSEnrico Granata } 1882223383edSEnrico Granata 18834574a890SZachary Turner auto cmd_name = command[0].ref; 1884223383edSEnrico Granata 18854574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 18864574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1887867e7d17SZachary Turner result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1888223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 18894574a890SZachary Turner return false; 1890223383edSEnrico Granata } 1891223383edSEnrico Granata 18924574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 18934574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 18944574a890SZachary Turner return true; 1895223383edSEnrico Granata } 1896223383edSEnrico Granata }; 1897223383edSEnrico Granata 1898223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1899223383edSEnrico Granata 1900223383edSEnrico Granata //------------------------------------------------------------------------- 1901223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1902223383edSEnrico Granata //------------------------------------------------------------------------- 1903223383edSEnrico Granata 1904b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1905223383edSEnrico Granata public: 19067428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1907b9c1b51eSKate Stone : CommandObjectMultiword( 1908b9c1b51eSKate Stone interpreter, "command script", "Commands for managing custom " 1909b9c1b51eSKate Stone "commands implemented by " 1910b9c1b51eSKate Stone "interpreter scripts.", 1911b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1912b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1913b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1914b9c1b51eSKate Stone LoadSubCommand( 1915b9c1b51eSKate Stone "delete", 1916b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1917b9c1b51eSKate Stone LoadSubCommand( 1918b9c1b51eSKate Stone "clear", 1919b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1920b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1921b9c1b51eSKate Stone interpreter))); 1922b9c1b51eSKate Stone LoadSubCommand( 1923b9c1b51eSKate Stone "import", 1924b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1925223383edSEnrico Granata } 1926223383edSEnrico Granata 19276e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1928223383edSEnrico Granata }; 1929223383edSEnrico Granata 1930ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1931ebc09c36SJim Ingham 1932ebc09c36SJim Ingham //------------------------------------------------------------------------- 1933ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1934ebc09c36SJim Ingham //------------------------------------------------------------------------- 1935ebc09c36SJim Ingham 1936b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1937b9c1b51eSKate Stone CommandInterpreter &interpreter) 1938b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1939b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1940b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1941b9c1b51eSKate Stone LoadSubCommand("source", 1942b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1943b9c1b51eSKate Stone LoadSubCommand("alias", 1944b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1945b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1946b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1947b9c1b51eSKate Stone LoadSubCommand("delete", 1948b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1949b9c1b51eSKate Stone LoadSubCommand( 1950b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1951b9c1b51eSKate Stone LoadSubCommand("history", CommandObjectSP( 1952b9c1b51eSKate Stone new CommandObjectCommandsHistory(interpreter))); 1953b9c1b51eSKate Stone LoadSubCommand( 1954b9c1b51eSKate Stone "script", 1955b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1956ebc09c36SJim Ingham } 1957ebc09c36SJim Ingham 19586e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1959