1696bd635SAlexander Shaposhnikov //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===// 2ebc09c36SJim Ingham // 3ebc09c36SJim Ingham // The LLVM Compiler Infrastructure 4ebc09c36SJim Ingham // 5ebc09c36SJim Ingham // This file is distributed under the University of Illinois Open Source 6ebc09c36SJim Ingham // License. See LICENSE.TXT for details. 7ebc09c36SJim Ingham // 8ebc09c36SJim Ingham //===----------------------------------------------------------------------===// 9ebc09c36SJim Ingham 10ebc09c36SJim Ingham // C Includes 11ebc09c36SJim Ingham // C++ Includes 12ebc09c36SJim Ingham // Other libraries and framework includes 130e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h" 140e5e5a79SGreg Clayton 15ebc09c36SJim Ingham // Project includes 166e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h" 1746d4aa21SEnrico Granata #include "CommandObjectHelp.h" 18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 1944d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 20be93a35aSEnrico Granata #include "lldb/Core/StringList.h" 21de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h" 227594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h" 23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 24de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h" 25ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 26012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h" 2745d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h" 287594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h" 29ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 3099f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h" 31ebc09c36SJim Ingham 32ebc09c36SJim Ingham using namespace lldb; 33ebc09c36SJim Ingham using namespace lldb_private; 34ebc09c36SJim Ingham 35ebc09c36SJim Ingham //------------------------------------------------------------------------- 36ebc09c36SJim Ingham // CommandObjectCommandsSource 37ebc09c36SJim Ingham //------------------------------------------------------------------------- 38ebc09c36SJim Ingham 391f0f5b5bSZachary Turner static OptionDefinition g_history_options[] = { 401f0f5b5bSZachary Turner // clang-format off 411f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, 421f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, 431f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, 441f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." }, 451f0f5b5bSZachary Turner // clang-format on 461f0f5b5bSZachary Turner }; 471f0f5b5bSZachary Turner 48b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed { 495a988416SJim Ingham public: 50b9c1b51eSKate Stone CommandObjectCommandsHistory(CommandInterpreter &interpreter) 51b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command history", 525a988416SJim Ingham "Dump the history of commands in this session.", 536e3d8e7fSEugene Zelenko nullptr), 54b9c1b51eSKate Stone m_options() {} 555a988416SJim Ingham 566e3d8e7fSEugene Zelenko ~CommandObjectCommandsHistory() override = default; 575a988416SJim Ingham 58b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 595a988416SJim Ingham 605a988416SJim Ingham protected: 61b9c1b51eSKate Stone class CommandOptions : public Options { 62a5a97ebeSJim Ingham public: 63b9c1b51eSKate Stone CommandOptions() 64b9c1b51eSKate Stone : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 65a5a97ebeSJim Ingham } 66a5a97ebeSJim Ingham 676e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 68a5a97ebeSJim Ingham 69fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 70b9c1b51eSKate Stone ExecutionContext *execution_context) override { 71a5a97ebeSJim Ingham Error error; 723bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 73a5a97ebeSJim Ingham 74b9c1b51eSKate Stone switch (short_option) { 75a5a97ebeSJim Ingham case 'c': 76fe11483bSZachary Turner error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 77a5a97ebeSJim Ingham break; 78a5a97ebeSJim Ingham case 's': 79fe11483bSZachary Turner if (option_arg == "end") { 807594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 817594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 82b9c1b51eSKate Stone } else 83fe11483bSZachary Turner error = m_start_idx.SetValueFromString(option_arg, 84b9c1b51eSKate Stone eVarSetOperationAssign); 857594f14fSEnrico Granata break; 867594f14fSEnrico Granata case 'e': 87fe11483bSZachary Turner error = 88fe11483bSZachary Turner m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 897594f14fSEnrico Granata break; 9063123b64SEnrico Granata case 'C': 9163123b64SEnrico Granata m_clear.SetCurrentValue(true); 9263123b64SEnrico Granata m_clear.SetOptionWasSet(); 93a5a97ebeSJim Ingham break; 94a5a97ebeSJim Ingham default: 95b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 96b9c1b51eSKate Stone short_option); 97a5a97ebeSJim Ingham break; 98a5a97ebeSJim Ingham } 99a5a97ebeSJim Ingham 100a5a97ebeSJim Ingham return error; 101a5a97ebeSJim Ingham } 102a5a97ebeSJim Ingham 103b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1047594f14fSEnrico Granata m_start_idx.Clear(); 1057594f14fSEnrico Granata m_stop_idx.Clear(); 1067594f14fSEnrico Granata m_count.Clear(); 10763123b64SEnrico Granata m_clear.Clear(); 108a5a97ebeSJim Ingham } 109a5a97ebeSJim Ingham 1101f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 11170602439SZachary Turner return llvm::makeArrayRef(g_history_options); 1121f0f5b5bSZachary Turner } 113a5a97ebeSJim Ingham 114a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 115a5a97ebeSJim Ingham 1167594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1177594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1187594f14fSEnrico Granata OptionValueUInt64 m_count; 11963123b64SEnrico Granata OptionValueBoolean m_clear; 120a5a97ebeSJim Ingham }; 121a5a97ebeSJim Ingham 122b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 123b9c1b51eSKate Stone if (m_options.m_clear.GetCurrentValue() && 124b9c1b51eSKate Stone m_options.m_clear.OptionWasSet()) { 1257594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1267594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 127b9c1b51eSKate Stone } else { 128b9c1b51eSKate Stone if (m_options.m_start_idx.OptionWasSet() && 129b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet() && 130b9c1b51eSKate Stone m_options.m_count.OptionWasSet()) { 131b9c1b51eSKate Stone result.AppendError("--count, --start-index and --end-index cannot be " 132b9c1b51eSKate Stone "all specified in the same invocation"); 1337594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 134b9c1b51eSKate Stone } else { 135b9c1b51eSKate Stone std::pair<bool, uint64_t> start_idx( 136b9c1b51eSKate Stone m_options.m_start_idx.OptionWasSet(), 137b9c1b51eSKate Stone m_options.m_start_idx.GetCurrentValue()); 138b9c1b51eSKate Stone std::pair<bool, uint64_t> stop_idx( 139b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet(), 140b9c1b51eSKate Stone m_options.m_stop_idx.GetCurrentValue()); 141b9c1b51eSKate Stone std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 142b9c1b51eSKate Stone m_options.m_count.GetCurrentValue()); 143a5a97ebeSJim Ingham 1447594f14fSEnrico Granata const CommandHistory &history(m_interpreter.GetCommandHistory()); 1457594f14fSEnrico Granata 146b9c1b51eSKate Stone if (start_idx.first && start_idx.second == UINT64_MAX) { 147b9c1b51eSKate Stone if (count.first) { 1487594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1497594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 150b9c1b51eSKate Stone } else if (stop_idx.first) { 1517594f14fSEnrico Granata start_idx.second = stop_idx.second; 1527594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 153b9c1b51eSKate Stone } else { 1547594f14fSEnrico Granata start_idx.second = 0; 1557594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1567594f14fSEnrico Granata } 157b9c1b51eSKate Stone } else { 158b9c1b51eSKate Stone if (!start_idx.first && !stop_idx.first && !count.first) { 1597594f14fSEnrico Granata start_idx.second = 0; 1607594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 161b9c1b51eSKate Stone } else if (start_idx.first) { 162b9c1b51eSKate Stone if (count.first) { 1637594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 164b9c1b51eSKate Stone } else if (!stop_idx.first) { 1657594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1667594f14fSEnrico Granata } 167b9c1b51eSKate Stone } else if (stop_idx.first) { 168b9c1b51eSKate Stone if (count.first) { 1697594f14fSEnrico Granata if (stop_idx.second >= count.second) 1707594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 1717594f14fSEnrico Granata else 1727594f14fSEnrico Granata start_idx.second = 0; 1737594f14fSEnrico Granata } 174b9c1b51eSKate Stone } else /* if (count.first) */ 1757594f14fSEnrico Granata { 1767594f14fSEnrico Granata start_idx.second = 0; 1777594f14fSEnrico Granata stop_idx.second = count.second - 1; 1787594f14fSEnrico Granata } 1797594f14fSEnrico Granata } 180b9c1b51eSKate Stone history.Dump(result.GetOutputStream(), start_idx.second, 181b9c1b51eSKate Stone stop_idx.second); 1827594f14fSEnrico Granata } 1837594f14fSEnrico Granata } 184a5a97ebeSJim Ingham return result.Succeeded(); 185a5a97ebeSJim Ingham } 1865a988416SJim Ingham 1875a988416SJim Ingham CommandOptions m_options; 188a5a97ebeSJim Ingham }; 189a5a97ebeSJim Ingham 190a5a97ebeSJim Ingham //------------------------------------------------------------------------- 191a5a97ebeSJim Ingham // CommandObjectCommandsSource 192a5a97ebeSJim Ingham //------------------------------------------------------------------------- 193a5a97ebeSJim Ingham 1941f0f5b5bSZachary Turner static OptionDefinition g_source_options[] = { 1951f0f5b5bSZachary Turner // clang-format off 1961f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, 1971f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, 1981f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, 1991f0f5b5bSZachary Turner // clang-format on 2001f0f5b5bSZachary Turner }; 2011f0f5b5bSZachary Turner 202b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed { 2035a988416SJim Ingham public: 2047428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 205b9c1b51eSKate Stone : CommandObjectParsed( 206b9c1b51eSKate Stone interpreter, "command source", 207b9c1b51eSKate Stone "Read and execute LLDB commands from the file <filename>.", 2086e3d8e7fSEugene Zelenko nullptr), 209b9c1b51eSKate Stone m_options() { 2105a988416SJim Ingham CommandArgumentEntry arg; 2115a988416SJim Ingham CommandArgumentData file_arg; 2125a988416SJim Ingham 2135a988416SJim Ingham // Define the first (and only) variant of this arg. 2145a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2155a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2165a988416SJim Ingham 217b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 218b9c1b51eSKate Stone // argument entry. 2195a988416SJim Ingham arg.push_back(file_arg); 2205a988416SJim Ingham 2215a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2225a988416SJim Ingham m_arguments.push_back(arg); 2235a988416SJim Ingham } 2245a988416SJim Ingham 2256e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2265a988416SJim Ingham 227b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 228b9c1b51eSKate Stone uint32_t index) override { 2295a988416SJim Ingham return ""; 2305a988416SJim Ingham } 2315a988416SJim Ingham 232b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 2335a988416SJim Ingham int &cursor_char_position, 2345a988416SJim Ingham OptionElementVector &opt_element_vector, 235b9c1b51eSKate Stone int match_start_point, int max_return_elements, 2365a988416SJim Ingham bool &word_complete, 237b9c1b51eSKate Stone StringList &matches) override { 2384574a890SZachary Turner auto completion_str = input[cursor_index].ref; 2394574a890SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 2405a988416SJim Ingham 241b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 242b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 2434574a890SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 244b9c1b51eSKate Stone word_complete, matches); 2455a988416SJim Ingham return matches.GetSize(); 2465a988416SJim Ingham } 2475a988416SJim Ingham 248b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 2495a988416SJim Ingham 2505a988416SJim Ingham protected: 251b9c1b51eSKate Stone class CommandOptions : public Options { 252e16c50a1SJim Ingham public: 253b9c1b51eSKate Stone CommandOptions() 254b9c1b51eSKate Stone : Options(), m_stop_on_error(true), m_silent_run(false), 255b9c1b51eSKate Stone m_stop_on_continue(true) {} 256e16c50a1SJim Ingham 2576e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 258e16c50a1SJim Ingham 259fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 260b9c1b51eSKate Stone ExecutionContext *execution_context) override { 261e16c50a1SJim Ingham Error error; 2623bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 263e16c50a1SJim Ingham 264b9c1b51eSKate Stone switch (short_option) { 265e16c50a1SJim Ingham case 'e': 266fe11483bSZachary Turner error = m_stop_on_error.SetValueFromString(option_arg); 267e16c50a1SJim Ingham break; 268340b0309SGreg Clayton 269e16c50a1SJim Ingham case 'c': 270fe11483bSZachary Turner error = m_stop_on_continue.SetValueFromString(option_arg); 271e16c50a1SJim Ingham break; 272340b0309SGreg Clayton 27360986174SMichael Sartain case 's': 274fe11483bSZachary Turner error = m_silent_run.SetValueFromString(option_arg); 27560986174SMichael Sartain break; 276340b0309SGreg Clayton 277e16c50a1SJim Ingham default: 278b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 279b9c1b51eSKate Stone short_option); 280e16c50a1SJim Ingham break; 281e16c50a1SJim Ingham } 282e16c50a1SJim Ingham 283e16c50a1SJim Ingham return error; 284e16c50a1SJim Ingham } 285e16c50a1SJim Ingham 286b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 287012d4fcaSEnrico Granata m_stop_on_error.Clear(); 288340b0309SGreg Clayton m_silent_run.Clear(); 289340b0309SGreg Clayton m_stop_on_continue.Clear(); 290e16c50a1SJim Ingham } 291e16c50a1SJim Ingham 2921f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 29370602439SZachary Turner return llvm::makeArrayRef(g_source_options); 2941f0f5b5bSZachary Turner } 295e16c50a1SJim Ingham 296e16c50a1SJim Ingham // Instance variables to hold the values for command options. 297e16c50a1SJim Ingham 298012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 299340b0309SGreg Clayton OptionValueBoolean m_silent_run; 300340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 301e16c50a1SJim Ingham }; 302e16c50a1SJim Ingham 303b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 3044574a890SZachary Turner if (command.GetArgumentCount() != 1) { 3054574a890SZachary Turner result.AppendErrorWithFormat( 3064574a890SZachary Turner "'%s' takes exactly one executable filename argument.\n", 3074574a890SZachary Turner GetCommandName().str().c_str()); 3084574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 3094574a890SZachary Turner return false; 3104574a890SZachary Turner } 311ebc09c36SJim Ingham 3124574a890SZachary Turner FileSpec cmd_file(command[0].ref, true); 3136e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 314ebc09c36SJim Ingham 315340b0309SGreg Clayton // If any options were set, then use them 316340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 317340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 318b9c1b51eSKate Stone m_options.m_stop_on_continue.OptionWasSet()) { 319340b0309SGreg Clayton // Use user set settings 32026c7bf93SJim Ingham CommandInterpreterRunOptions options; 3214574a890SZachary Turner options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 32226c7bf93SJim Ingham options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 3237d8555c4SJim Ingham options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue()); 3247d8555c4SJim Ingham options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue()); 32526c7bf93SJim Ingham 3264574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 327b9c1b51eSKate Stone } else { 328b9c1b51eSKate Stone // No options were set, inherit any settings from nested "command 329b9c1b51eSKate Stone // source" commands, 330340b0309SGreg Clayton // or set to sane default settings... 33126c7bf93SJim Ingham CommandInterpreterRunOptions options; 3324574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 333ebc09c36SJim Ingham } 334ebc09c36SJim Ingham return result.Succeeded(); 335ebc09c36SJim Ingham } 3366e3d8e7fSEugene Zelenko 3375a988416SJim Ingham CommandOptions m_options; 338ebc09c36SJim Ingham }; 339ebc09c36SJim Ingham 340ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 341ebc09c36SJim Ingham //------------------------------------------------------------------------- 342ebc09c36SJim Ingham // CommandObjectCommandsAlias 343ebc09c36SJim Ingham //------------------------------------------------------------------------- 344ebc09c36SJim Ingham 3451f0f5b5bSZachary Turner static OptionDefinition g_alias_options[] = { 3461f0f5b5bSZachary Turner // clang-format off 3471f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" }, 3481f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" }, 3491f0f5b5bSZachary Turner // clang-format on 3501f0f5b5bSZachary Turner }; 3511f0f5b5bSZachary Turner 352b9c1b51eSKate Stone static const char *g_python_command_instructions = 353b9c1b51eSKate Stone "Enter your Python command(s). Type 'DONE' to end.\n" 354be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 35544d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 356be93a35aSEnrico Granata 357b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw { 35845d0e238SEnrico Granata protected: 359b9c1b51eSKate Stone class CommandOptions : public OptionGroup { 360ebc09c36SJim Ingham public: 361b9c1b51eSKate Stone CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 36245d0e238SEnrico Granata 36345d0e238SEnrico Granata ~CommandOptions() override = default; 36445d0e238SEnrico Granata 3651f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 36670602439SZachary Turner return llvm::makeArrayRef(g_alias_options); 3671f0f5b5bSZachary Turner } 36845d0e238SEnrico Granata 3698cef4b0bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 370b9c1b51eSKate Stone ExecutionContext *execution_context) override { 37145d0e238SEnrico Granata Error error; 37245d0e238SEnrico Granata 3731f0f5b5bSZachary Turner const int short_option = GetDefinitions()[option_idx].short_option; 3748cef4b0bSZachary Turner std::string option_str(option_value); 37545d0e238SEnrico Granata 376b9c1b51eSKate Stone switch (short_option) { 37745d0e238SEnrico Granata case 'h': 3788cef4b0bSZachary Turner m_help.SetCurrentValue(option_str); 37945d0e238SEnrico Granata m_help.SetOptionWasSet(); 38045d0e238SEnrico Granata break; 38145d0e238SEnrico Granata 38245d0e238SEnrico Granata case 'H': 3838cef4b0bSZachary Turner m_long_help.SetCurrentValue(option_str); 38445d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 38545d0e238SEnrico Granata break; 38645d0e238SEnrico Granata 38745d0e238SEnrico Granata default: 388b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid short option character '%c'", 389b9c1b51eSKate Stone short_option); 39045d0e238SEnrico Granata break; 39145d0e238SEnrico Granata } 39245d0e238SEnrico Granata 39345d0e238SEnrico Granata return error; 39445d0e238SEnrico Granata } 39545d0e238SEnrico Granata 396b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 39745d0e238SEnrico Granata m_help.Clear(); 39845d0e238SEnrico Granata m_long_help.Clear(); 39945d0e238SEnrico Granata } 40045d0e238SEnrico Granata 40145d0e238SEnrico Granata OptionValueString m_help; 40245d0e238SEnrico Granata OptionValueString m_long_help; 40345d0e238SEnrico Granata }; 40445d0e238SEnrico Granata 40545d0e238SEnrico Granata OptionGroupOptions m_option_group; 40645d0e238SEnrico Granata CommandOptions m_command_options; 40745d0e238SEnrico Granata 40845d0e238SEnrico Granata public: 409b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 41045d0e238SEnrico Granata 4117428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 412b9c1b51eSKate Stone : CommandObjectRaw( 413b9c1b51eSKate Stone interpreter, "command alias", 414a449698cSZachary Turner "Define a custom command in terms of an existing command."), 415b9c1b51eSKate Stone m_option_group(), m_command_options() { 41645d0e238SEnrico Granata m_option_group.Append(&m_command_options); 41745d0e238SEnrico Granata m_option_group.Finalize(); 41845d0e238SEnrico Granata 419ebc09c36SJim Ingham SetHelpLong( 420ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 421ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 422b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:" 423b9c1b51eSKate Stone R"( 424ea671fbdSKate Stone 425ea671fbdSKate Stone (lldb) command alias sc script 426ea671fbdSKate Stone 427ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 428ea671fbdSKate Stone 429ea671fbdSKate Stone (lldb) command alias bp breakpoint 430ea671fbdSKate Stone 431b9c1b51eSKate Stone )" 432b9c1b51eSKate Stone " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 433ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 434b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 435b9c1b51eSKate Stone R"( 436ea671fbdSKate Stone 437ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 438ea671fbdSKate Stone 439ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 440ea671fbdSKate Stone 441b9c1b51eSKate Stone )" 442b9c1b51eSKate Stone "An alias can include some options for the command, with the values either \ 443ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 444ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 445b9c1b51eSKate Stone shows how to create aliases with options:" 446b9c1b51eSKate Stone R"( 447ea671fbdSKate Stone 448ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 449ea671fbdSKate Stone 450b9c1b51eSKate Stone )" 451b9c1b51eSKate Stone " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 452ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 453ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 454ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 455ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 456ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 457ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 458ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 459ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 460ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 461b9c1b51eSKate Stone launch' example below)." 462b9c1b51eSKate Stone R"( 463ea671fbdSKate Stone 464b9c1b51eSKate Stone )" 465b9c1b51eSKate Stone "Note: the positional arguments must substitute as whole words in the resultant \ 466ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 467b9c1b51eSKate Stone \".cpp\":" 468b9c1b51eSKate Stone R"( 469ea671fbdSKate Stone 470ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 471ea671fbdSKate Stone 472b9c1b51eSKate Stone )" 473b9c1b51eSKate Stone "For more complex aliasing, use the \"command regex\" command instead. In the \ 474ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 475ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 476b9c1b51eSKate Stone argument. The user would use this alias as follows:" 477b9c1b51eSKate Stone R"( 478ea671fbdSKate Stone 479ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 480ea671fbdSKate Stone (lldb) bfl my-file.c 137 481ea671fbdSKate Stone 482ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 483ea671fbdSKate Stone 484ea671fbdSKate Stone Another example: 485ea671fbdSKate Stone 486ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 487ea671fbdSKate Stone (lldb) pltty /dev/tty0 488ea671fbdSKate Stone 489ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 490ea671fbdSKate Stone 491b9c1b51eSKate Stone )" 492b9c1b51eSKate Stone "If the user always wanted to pass the same value to a particular option, the \ 493ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 494b9c1b51eSKate Stone rather than using a positional placeholder:" 495b9c1b51eSKate Stone R"( 496ea671fbdSKate Stone 497ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 498ea671fbdSKate Stone 499b9c1b51eSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)"); 500ebc09c36SJim Ingham 501405fe67fSCaroline Tice CommandArgumentEntry arg1; 502405fe67fSCaroline Tice CommandArgumentEntry arg2; 503405fe67fSCaroline Tice CommandArgumentEntry arg3; 504405fe67fSCaroline Tice CommandArgumentData alias_arg; 505405fe67fSCaroline Tice CommandArgumentData cmd_arg; 506405fe67fSCaroline Tice CommandArgumentData options_arg; 507405fe67fSCaroline Tice 508405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 509405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 510405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 511405fe67fSCaroline Tice 512b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 513b9c1b51eSKate Stone // argument entry. 514405fe67fSCaroline Tice arg1.push_back(alias_arg); 515405fe67fSCaroline Tice 516405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 517405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 518405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 519405fe67fSCaroline Tice 520b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 521b9c1b51eSKate Stone // argument entry. 522405fe67fSCaroline Tice arg2.push_back(cmd_arg); 523405fe67fSCaroline Tice 524405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 525405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 526405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 527405fe67fSCaroline Tice 528b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 529b9c1b51eSKate Stone // argument entry. 530405fe67fSCaroline Tice arg3.push_back(options_arg); 531405fe67fSCaroline Tice 532405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 533405fe67fSCaroline Tice m_arguments.push_back(arg1); 534405fe67fSCaroline Tice m_arguments.push_back(arg2); 535405fe67fSCaroline Tice m_arguments.push_back(arg3); 536ebc09c36SJim Ingham } 537ebc09c36SJim Ingham 5386e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 539ebc09c36SJim Ingham 5405a988416SJim Ingham protected: 541b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 542b9c1b51eSKate Stone CommandReturnObject &result) override { 543b9c1b51eSKate Stone if (!raw_command_line || !raw_command_line[0]) { 544d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 54545d0e238SEnrico Granata return false; 54645d0e238SEnrico Granata } 54745d0e238SEnrico Granata 548e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 549e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 55045d0e238SEnrico Granata 55145d0e238SEnrico Granata const char *remainder = nullptr; 55245d0e238SEnrico Granata 553b9c1b51eSKate Stone if (raw_command_line[0] == '-') { 55445d0e238SEnrico Granata // We have some options and these options MUST end with --. 55545d0e238SEnrico Granata const char *end_options = nullptr; 55645d0e238SEnrico Granata const char *s = raw_command_line; 557b9c1b51eSKate Stone while (s && s[0]) { 55845d0e238SEnrico Granata end_options = ::strstr(s, "--"); 559b9c1b51eSKate Stone if (end_options) { 56045d0e238SEnrico Granata end_options += 2; // Get past the "--" 561b9c1b51eSKate Stone if (::isspace(end_options[0])) { 56245d0e238SEnrico Granata remainder = end_options; 56345d0e238SEnrico Granata while (::isspace(*remainder)) 56445d0e238SEnrico Granata ++remainder; 56545d0e238SEnrico Granata break; 56645d0e238SEnrico Granata } 56745d0e238SEnrico Granata } 56845d0e238SEnrico Granata s = end_options; 56945d0e238SEnrico Granata } 57045d0e238SEnrico Granata 571b9c1b51eSKate Stone if (end_options) { 572b9c1b51eSKate Stone Args args( 573b9c1b51eSKate Stone llvm::StringRef(raw_command_line, end_options - raw_command_line)); 57445d0e238SEnrico Granata if (!ParseOptions(args, result)) 57545d0e238SEnrico Granata return false; 57645d0e238SEnrico Granata 577e1cfbc79STodd Fiala Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); 578b9c1b51eSKate Stone if (error.Fail()) { 57945d0e238SEnrico Granata result.AppendError(error.AsCString()); 58045d0e238SEnrico Granata result.SetStatus(eReturnStatusFailed); 58145d0e238SEnrico Granata return false; 58245d0e238SEnrico Granata } 58345d0e238SEnrico Granata } 58445d0e238SEnrico Granata } 58545d0e238SEnrico Granata if (nullptr == remainder) 58645d0e238SEnrico Granata remainder = raw_command_line; 58745d0e238SEnrico Granata 588a01bccdbSZachary Turner llvm::StringRef raw_command_string(remainder); 589a01bccdbSZachary Turner Args args(raw_command_string); 590844d2303SCaroline Tice 59111eb9c64SZachary Turner if (args.GetArgumentCount() < 2) { 592d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 593844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 594844d2303SCaroline Tice return false; 595844d2303SCaroline Tice } 596844d2303SCaroline Tice 597844d2303SCaroline Tice // Get the alias command. 598844d2303SCaroline Tice 5994574a890SZachary Turner auto alias_command = args[0].ref; 6004574a890SZachary Turner if (alias_command.startswith("-")) { 601d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 602b9c1b51eSKate Stone if (alias_command == "--help" || alias_command == "--long-help") { 603b9c1b51eSKate Stone result.AppendWarning("if trying to pass options to 'command alias' add " 604b9c1b51eSKate Stone "a -- at the end of the options"); 605d72e412fSEnrico Granata } 606d72e412fSEnrico Granata result.SetStatus(eReturnStatusFailed); 607d72e412fSEnrico Granata return false; 608d72e412fSEnrico Granata } 609844d2303SCaroline Tice 610b9c1b51eSKate Stone // Strip the new alias name off 'raw_command_string' (leave it on args, 611b9c1b51eSKate Stone // which gets passed to 'Execute', which 612844d2303SCaroline Tice // does the stripping itself. 613844d2303SCaroline Tice size_t pos = raw_command_string.find(alias_command); 614b9c1b51eSKate Stone if (pos == 0) { 615844d2303SCaroline Tice raw_command_string = raw_command_string.substr(alias_command.size()); 616844d2303SCaroline Tice pos = raw_command_string.find_first_not_of(' '); 617844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 618844d2303SCaroline Tice raw_command_string = raw_command_string.substr(pos); 619b9c1b51eSKate Stone } else { 620844d2303SCaroline Tice result.AppendError("Error parsing command string. No alias created."); 621844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 622844d2303SCaroline Tice return false; 623844d2303SCaroline Tice } 624844d2303SCaroline Tice 625844d2303SCaroline Tice // Verify that the command is alias-able. 626771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 627b9c1b51eSKate Stone result.AppendErrorWithFormat( 628b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 6294574a890SZachary Turner args[0].c_str()); 630844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 631844d2303SCaroline Tice return false; 632844d2303SCaroline Tice } 633844d2303SCaroline Tice 634b9c1b51eSKate Stone // Get CommandObject that is being aliased. The command name is read from 635a01bccdbSZachary Turner // the front of raw_command_string. raw_command_string is returned with the 636a01bccdbSZachary Turner // name of the command object stripped off the front. 637a01bccdbSZachary Turner llvm::StringRef original_raw_command_string = raw_command_string; 638b9c1b51eSKate Stone CommandObject *cmd_obj = 639b9c1b51eSKate Stone m_interpreter.GetCommandObjectForCommand(raw_command_string); 640844d2303SCaroline Tice 641b9c1b51eSKate Stone if (!cmd_obj) { 642b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command given to 'command alias'. " 643b9c1b51eSKate Stone "'%s' does not begin with a valid command." 644b9c1b51eSKate Stone " No alias created.", 645a01bccdbSZachary Turner original_raw_command_string.str().c_str()); 646844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 647844d2303SCaroline Tice return false; 648b9c1b51eSKate Stone } else if (!cmd_obj->WantsRawCommandString()) { 649b9c1b51eSKate Stone // Note that args was initialized with the original command, and has not 650b9c1b51eSKate Stone // been updated to this point. 651b9c1b51eSKate Stone // Therefore can we pass it to the version of Execute that does not 652b9c1b51eSKate Stone // need/expect raw input in the alias. 6535a988416SJim Ingham return HandleAliasingNormalCommand(args, result); 654b9c1b51eSKate Stone } else { 655b9c1b51eSKate Stone return HandleAliasingRawCommand(alias_command, raw_command_string, 656b9c1b51eSKate Stone *cmd_obj, result); 6575a988416SJim Ingham } 6585a988416SJim Ingham return result.Succeeded(); 6595a988416SJim Ingham } 6605a988416SJim Ingham 661a01bccdbSZachary Turner bool HandleAliasingRawCommand(llvm::StringRef alias_command, 662a01bccdbSZachary Turner llvm::StringRef raw_command_string, 663b9c1b51eSKate Stone CommandObject &cmd_obj, 664b9c1b51eSKate Stone CommandReturnObject &result) { 665844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 666844d2303SCaroline Tice 667b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 668b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 669844d2303SCaroline Tice 670b9c1b51eSKate Stone if (CommandObjectSP cmd_obj_sp = 671b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 672a01bccdbSZachary Turner if (m_interpreter.AliasExists(alias_command) || 673a01bccdbSZachary Turner m_interpreter.UserCommandExists(alias_command)) { 674b9c1b51eSKate Stone result.AppendWarningWithFormat( 675b9c1b51eSKate Stone "Overwriting existing definition for '%s'.\n", 676a01bccdbSZachary Turner alias_command.str().c_str()); 677844d2303SCaroline Tice } 678b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 679a01bccdbSZachary Turner alias_command, cmd_obj_sp, raw_command_string)) { 68045d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 68145d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 68245d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 68345d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 684844d2303SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 685b9c1b51eSKate Stone } else { 686472362e6SCaroline Tice result.AppendError("Unable to create requested alias.\n"); 687472362e6SCaroline Tice result.SetStatus(eReturnStatusFailed); 688472362e6SCaroline Tice } 689212130acSEnrico Granata 690b9c1b51eSKate Stone } else { 691212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 692212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 693212130acSEnrico Granata } 694212130acSEnrico Granata 695844d2303SCaroline Tice return result.Succeeded(); 696844d2303SCaroline Tice } 697ebc09c36SJim Ingham 698b9c1b51eSKate Stone bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 699867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 700ebc09c36SJim Ingham 701b9c1b51eSKate Stone if (argc < 2) { 702d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 703ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 704ebc09c36SJim Ingham return false; 705ebc09c36SJim Ingham } 706ebc09c36SJim Ingham 7074574a890SZachary Turner // Save these in std::strings since we're going to shift them off. 7084574a890SZachary Turner const std::string alias_command(args[0].ref); 7094574a890SZachary Turner const std::string actual_command(args[1].ref); 710ebc09c36SJim Ingham 711ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 712ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 713ebc09c36SJim Ingham 714b9c1b51eSKate Stone // Verify that the command is alias'able, and get the appropriate command 715b9c1b51eSKate Stone // object. 716ebc09c36SJim Ingham 717771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 718b9c1b51eSKate Stone result.AppendErrorWithFormat( 719b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 720ebc09c36SJim Ingham alias_command.c_str()); 721ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 7224574a890SZachary Turner return false; 7234574a890SZachary Turner } 7244574a890SZachary Turner 725b9c1b51eSKate Stone CommandObjectSP command_obj_sp( 726a449698cSZachary Turner m_interpreter.GetCommandSPExact(actual_command, true)); 727ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 728ebc09c36SJim Ingham bool use_subcommand = false; 7294574a890SZachary Turner if (!command_obj_sp) { 7304574a890SZachary Turner result.AppendErrorWithFormat("'%s' is not an existing command.\n", 7314574a890SZachary Turner actual_command.c_str()); 7324574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 7334574a890SZachary Turner return false; 7344574a890SZachary Turner } 735ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 7366e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 737b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 738b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 739ebc09c36SJim Ingham 74011eb9c64SZachary Turner while (cmd_obj->IsMultiwordObject() && !args.empty()) { 7414574a890SZachary Turner auto sub_command = args[0].ref; 74211eb9c64SZachary Turner assert(!sub_command.empty()); 7434574a890SZachary Turner subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 7444574a890SZachary Turner if (!subcommand_obj_sp) { 745b9c1b51eSKate Stone result.AppendErrorWithFormat( 746b9c1b51eSKate Stone "'%s' is not a valid sub-command of '%s'. " 747f415eeb4SCaroline Tice "Unable to create alias.\n", 7484574a890SZachary Turner args[0].c_str(), actual_command.c_str()); 749ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 750ebc09c36SJim Ingham return false; 751ebc09c36SJim Ingham } 7524574a890SZachary Turner 7534574a890SZachary Turner sub_cmd_obj = subcommand_obj_sp.get(); 7544574a890SZachary Turner use_subcommand = true; 7554574a890SZachary Turner args.Shift(); // Shift the sub_command word off the argument vector. 7564574a890SZachary Turner cmd_obj = sub_cmd_obj; 757ebc09c36SJim Ingham } 758ebc09c36SJim Ingham 759ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 760ebc09c36SJim Ingham 761212130acSEnrico Granata std::string args_string; 762212130acSEnrico Granata 76311eb9c64SZachary Turner if (!args.empty()) { 764b9c1b51eSKate Stone CommandObjectSP tmp_sp = 765b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 766ebc09c36SJim Ingham if (use_subcommand) 7674574a890SZachary Turner tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 7684574a890SZachary Turner false); 769ca90c47eSCaroline Tice 770ca90c47eSCaroline Tice args.GetCommandString(args_string); 771867b185dSCaroline Tice } 772ebc09c36SJim Ingham 773771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 774771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 775b9c1b51eSKate Stone result.AppendWarningWithFormat( 7764574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 777ebc09c36SJim Ingham } 778ebc09c36SJim Ingham 779b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 7804574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 781771ef6d4SMalcolm Parsons args_string)) { 78245d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 78345d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 78445d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 78545d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 786ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 787b9c1b51eSKate Stone } else { 788212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 789212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 790212130acSEnrico Granata return false; 791212130acSEnrico Granata } 792ebc09c36SJim Ingham 793ebc09c36SJim Ingham return result.Succeeded(); 794ebc09c36SJim Ingham } 795ebc09c36SJim Ingham }; 796ebc09c36SJim Ingham 797ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 798ebc09c36SJim Ingham //------------------------------------------------------------------------- 799ebc09c36SJim Ingham // CommandObjectCommandsUnalias 800ebc09c36SJim Ingham //------------------------------------------------------------------------- 801ebc09c36SJim Ingham 802b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 803ebc09c36SJim Ingham public: 8047428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 805b9c1b51eSKate Stone : CommandObjectParsed( 806b9c1b51eSKate Stone interpreter, "command unalias", 807b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 808b9c1b51eSKate Stone nullptr) { 809405fe67fSCaroline Tice CommandArgumentEntry arg; 810405fe67fSCaroline Tice CommandArgumentData alias_arg; 811405fe67fSCaroline Tice 812405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 813405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 814405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 815405fe67fSCaroline Tice 816b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 817b9c1b51eSKate Stone // argument entry. 818405fe67fSCaroline Tice arg.push_back(alias_arg); 819405fe67fSCaroline Tice 820405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 821405fe67fSCaroline Tice m_arguments.push_back(arg); 822ebc09c36SJim Ingham } 823ebc09c36SJim Ingham 8246e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 825ebc09c36SJim Ingham 8265a988416SJim Ingham protected: 827b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 828ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 829ebc09c36SJim Ingham CommandObject *cmd_obj; 830ebc09c36SJim Ingham 83111eb9c64SZachary Turner if (args.empty()) { 83211eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 83311eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 83411eb9c64SZachary Turner return false; 83511eb9c64SZachary Turner } 83611eb9c64SZachary Turner 8374574a890SZachary Turner auto command_name = args[0].ref; 838a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 8394574a890SZachary Turner if (!cmd_obj) { 8404574a890SZachary Turner result.AppendErrorWithFormat( 8414574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 8424574a890SZachary Turner "current list of commands.\n", 843*867e7d17SZachary Turner args[0].c_str()); 8444574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 8454574a890SZachary Turner return false; 8464574a890SZachary Turner } 8474574a890SZachary Turner 848b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 849b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 850b9c1b51eSKate Stone result.AppendErrorWithFormat( 851b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 852b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 853*867e7d17SZachary Turner args[0].c_str()); 854b9c1b51eSKate Stone } else { 855b9c1b51eSKate Stone result.AppendErrorWithFormat( 856b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 857*867e7d17SZachary Turner args[0].c_str()); 858b547278cSGreg Clayton } 859ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8604574a890SZachary Turner return false; 8614574a890SZachary Turner } 8624574a890SZachary Turner 863b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 864a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 865b9c1b51eSKate Stone result.AppendErrorWithFormat( 866*867e7d17SZachary Turner "Error occurred while attempting to unalias '%s'.\n", 867*867e7d17SZachary Turner args[0].c_str()); 868ebc09c36SJim Ingham else 869b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 870*867e7d17SZachary Turner args[0].c_str()); 871ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8724574a890SZachary Turner return false; 873ebc09c36SJim Ingham } 874ebc09c36SJim Ingham 8754574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 876ebc09c36SJim Ingham return result.Succeeded(); 877ebc09c36SJim Ingham } 878ebc09c36SJim Ingham }; 879ebc09c36SJim Ingham 880b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 881b547278cSGreg Clayton //------------------------------------------------------------------------- 882b547278cSGreg Clayton // CommandObjectCommandsDelete 883b547278cSGreg Clayton //------------------------------------------------------------------------- 884b547278cSGreg Clayton 885b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 886b547278cSGreg Clayton public: 8877428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 888b9c1b51eSKate Stone : CommandObjectParsed( 889b9c1b51eSKate Stone interpreter, "command delete", 890b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 891b9c1b51eSKate Stone nullptr) { 892b547278cSGreg Clayton CommandArgumentEntry arg; 893b547278cSGreg Clayton CommandArgumentData alias_arg; 894b547278cSGreg Clayton 895b547278cSGreg Clayton // Define the first (and only) variant of this arg. 896b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 897b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 898b547278cSGreg Clayton 899b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 900b9c1b51eSKate Stone // argument entry. 901b547278cSGreg Clayton arg.push_back(alias_arg); 902b547278cSGreg Clayton 903b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 904b547278cSGreg Clayton m_arguments.push_back(arg); 905b547278cSGreg Clayton } 906b547278cSGreg Clayton 9076e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 908b547278cSGreg Clayton 909b547278cSGreg Clayton protected: 910b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 911b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 912b547278cSGreg Clayton 91311eb9c64SZachary Turner if (args.empty()) { 91411eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 91511eb9c64SZachary Turner "defined regular expression command names", 916a449698cSZachary Turner GetCommandName().str().c_str()); 91711eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 91811eb9c64SZachary Turner } 91911eb9c64SZachary Turner 9204574a890SZachary Turner auto command_name = args[0].ref; 9214574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 92246d4aa21SEnrico Granata StreamString error_msg_stream; 92346d4aa21SEnrico Granata const bool generate_apropos = true; 92446d4aa21SEnrico Granata const bool generate_type_lookup = false; 925b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 9264574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 9274574a890SZachary Turner generate_apropos, generate_type_lookup); 928c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 929b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 9304574a890SZachary Turner return false; 931b547278cSGreg Clayton } 932b547278cSGreg Clayton 9334574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 9344574a890SZachary Turner result.AppendErrorWithFormat( 9354574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 936*867e7d17SZachary Turner args[0].c_str()); 9374574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 9384574a890SZachary Turner return false; 9394574a890SZachary Turner } 9404574a890SZachary Turner 9414574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 9424574a890SZachary Turner return true; 943b547278cSGreg Clayton } 944b547278cSGreg Clayton }; 945b547278cSGreg Clayton 946de164aaaSGreg Clayton //------------------------------------------------------------------------- 947de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 948de164aaaSGreg Clayton //------------------------------------------------------------------------- 9491f0f5b5bSZachary Turner 9501f0f5b5bSZachary Turner static OptionDefinition g_regex_options[] = { 9511f0f5b5bSZachary Turner // clang-format off 9521f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." }, 9531f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, 9541f0f5b5bSZachary Turner // clang-format on 9551f0f5b5bSZachary Turner }; 9561f0f5b5bSZachary Turner 9575a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 958de164aaaSGreg Clayton 959b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 960b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 961de164aaaSGreg Clayton public: 9627428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 963b9c1b51eSKate Stone : CommandObjectParsed( 964b9c1b51eSKate Stone interpreter, "command regex", "Define a custom command in terms of " 965b9c1b51eSKate Stone "existing commands by matching " 966b9c1b51eSKate Stone "regular expressions.", 9670e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 968b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 969b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 970b9c1b51eSKate Stone m_options() { 971b9c1b51eSKate Stone SetHelpLong( 972b9c1b51eSKate Stone R"( 973b9c1b51eSKate Stone )" 974b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 975ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 976b9c1b51eSKate Stone using the regular expression substitution format of:" 977b9c1b51eSKate Stone R"( 978ea671fbdSKate Stone 979ea671fbdSKate Stone s/<regex>/<subst>/ 980ea671fbdSKate Stone 981b9c1b51eSKate Stone )" 982b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 983ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 984b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 985b9c1b51eSKate Stone R"( 986ea671fbdSKate Stone 987b9c1b51eSKate Stone )" 988b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 989ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 990ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 991b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 992b9c1b51eSKate Stone R"( 993ea671fbdSKate Stone 994ea671fbdSKate Stone EXAMPLES 995ea671fbdSKate Stone 996b9c1b51eSKate Stone )" 997b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 998ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 999b9c1b51eSKate Stone a number follows 'f':" 1000b9c1b51eSKate Stone R"( 1001ea671fbdSKate Stone 1002b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 1003de164aaaSGreg Clayton } 1004de164aaaSGreg Clayton 10056e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 1006de164aaaSGreg Clayton 10075a988416SJim Ingham protected: 1008b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 100944d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1010b9c1b51eSKate Stone if (output_sp) { 1011b9c1b51eSKate Stone output_sp->PutCString("Enter one of more sed substitution commands in " 1012b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 1013b9c1b51eSKate Stone "substitution list with an empty line.\n"); 101444d93782SGreg Clayton output_sp->Flush(); 101544d93782SGreg Clayton } 101644d93782SGreg Clayton } 101744d93782SGreg Clayton 1018b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1019b9c1b51eSKate Stone std::string &data) override { 102044d93782SGreg Clayton io_handler.SetIsDone(true); 1021b9c1b51eSKate Stone if (m_regex_cmd_ap) { 102244d93782SGreg Clayton StringList lines; 1023b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 102444d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 102544d93782SGreg Clayton bool check_only = false; 1026b9c1b51eSKate Stone for (size_t i = 0; i < num_lines; ++i) { 102744d93782SGreg Clayton llvm::StringRef bytes_strref(lines[i]); 102844d93782SGreg Clayton Error error = AppendRegexSubstitution(bytes_strref, check_only); 1029b9c1b51eSKate Stone if (error.Fail()) { 1030b9c1b51eSKate Stone if (!m_interpreter.GetDebugger() 1031b9c1b51eSKate Stone .GetCommandInterpreter() 1032b9c1b51eSKate Stone .GetBatchCommandMode()) { 1033b9c1b51eSKate Stone StreamSP out_stream = 1034b9c1b51eSKate Stone m_interpreter.GetDebugger().GetAsyncOutputStream(); 103544d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 103644d93782SGreg Clayton } 103744d93782SGreg Clayton } 103844d93782SGreg Clayton } 103944d93782SGreg Clayton } 1040b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 104144d93782SGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 104244d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 104344d93782SGreg Clayton } 104444d93782SGreg Clayton } 104544d93782SGreg Clayton } 104644d93782SGreg Clayton 1047b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 10485a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 1049b9c1b51eSKate Stone if (argc == 0) { 1050b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 1051b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 10520e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 105311eb9c64SZachary Turner return false; 105411eb9c64SZachary Turner } 105511eb9c64SZachary Turner 10560e5e5a79SGreg Clayton Error error; 10574574a890SZachary Turner auto name = command[0].ref; 10584574a890SZachary Turner m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>( 10594574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 10604574a890SZachary Turner true); 10610e5e5a79SGreg Clayton 1062b9c1b51eSKate Stone if (argc == 1) { 106344d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1064e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 106544d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 1066b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 1067b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 106873d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1069514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 1070514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 1071b9c1b51eSKate Stone multiple_lines, color_prompt, 1072f6913cd7SGreg Clayton 0, // Don't show line numbers 107344d93782SGreg Clayton *this)); 107444d93782SGreg Clayton 1075b9c1b51eSKate Stone if (io_handler_sp) { 107644d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1077de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 1078de164aaaSGreg Clayton } 1079b9c1b51eSKate Stone } else { 108097d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 108144d93782SGreg Clayton bool check_only = false; 108297d2c401SZachary Turner error = AppendRegexSubstitution(entry.ref, check_only); 10830e5e5a79SGreg Clayton if (error.Fail()) 10840e5e5a79SGreg Clayton break; 10850e5e5a79SGreg Clayton } 10860e5e5a79SGreg Clayton 1087b9c1b51eSKate Stone if (error.Success()) { 10880e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 10890e5e5a79SGreg Clayton } 10900e5e5a79SGreg Clayton } 1091b9c1b51eSKate Stone if (error.Fail()) { 10920e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 1093de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 1094de164aaaSGreg Clayton } 10950e5e5a79SGreg Clayton 1096de164aaaSGreg Clayton return result.Succeeded(); 1097de164aaaSGreg Clayton } 1098de164aaaSGreg Clayton 1099b9c1b51eSKate Stone Error AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 1100b9c1b51eSKate Stone bool check_only) { 11010e5e5a79SGreg Clayton Error error; 11020e5e5a79SGreg Clayton 1103b9c1b51eSKate Stone if (!m_regex_cmd_ap) { 1104b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1105b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 1106b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11070e5e5a79SGreg Clayton return error; 1108de164aaaSGreg Clayton } 11090e5e5a79SGreg Clayton 11100e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 11110e5e5a79SGreg Clayton 1112b9c1b51eSKate Stone if (regex_sed_size <= 1) { 1113b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1114b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 1115b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11160e5e5a79SGreg Clayton return error; 11170e5e5a79SGreg Clayton } 11180e5e5a79SGreg Clayton 1119b9c1b51eSKate Stone if (regex_sed[0] != 's') { 1120b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 1121b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 1122b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11230e5e5a79SGreg Clayton return error; 11240e5e5a79SGreg Clayton } 11250e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 11260e5e5a79SGreg Clayton // use the char that follows 's' as the regex separator character 11270e5e5a79SGreg Clayton // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 11280e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 1129b9c1b51eSKate Stone const size_t second_separator_char_pos = 1130b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 11310e5e5a79SGreg Clayton 1132b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 1133b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1134b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 11350e5e5a79SGreg Clayton separator_char, 11360e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1137ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1138b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11390e5e5a79SGreg Clayton return error; 11400e5e5a79SGreg Clayton } 11410e5e5a79SGreg Clayton 1142b9c1b51eSKate Stone const size_t third_separator_char_pos = 1143b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 11440e5e5a79SGreg Clayton 1145b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 1146b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1147b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 11480e5e5a79SGreg Clayton separator_char, 11490e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1150ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1151b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11520e5e5a79SGreg Clayton return error; 11530e5e5a79SGreg Clayton } 11540e5e5a79SGreg Clayton 1155b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 11560e5e5a79SGreg Clayton // Make sure that everything that follows the last regex 11570e5e5a79SGreg Clayton // separator char 1158b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 1159b9c1b51eSKate Stone third_separator_char_pos + 1) != 1160b9c1b51eSKate Stone std::string::npos) { 1161b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1162b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 1163b9c1b51eSKate Stone "string: '%.*s'", 1164b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 11650e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 11660e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 11670e5e5a79SGreg Clayton return error; 11680e5e5a79SGreg Clayton } 1169b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 1170b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1171b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1172b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11730e5e5a79SGreg Clayton regex_sed.data()); 11740e5e5a79SGreg Clayton return error; 1175b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 1176b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1177b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1178b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11790e5e5a79SGreg Clayton regex_sed.data()); 11800e5e5a79SGreg Clayton return error; 11810e5e5a79SGreg Clayton } 118244d93782SGreg Clayton 1183b9c1b51eSKate Stone if (!check_only) { 1184b9c1b51eSKate Stone std::string regex(regex_sed.substr(first_separator_char_pos + 1, 1185b9c1b51eSKate Stone second_separator_char_pos - 1186b9c1b51eSKate Stone first_separator_char_pos - 1)); 1187b9c1b51eSKate Stone std::string subst(regex_sed.substr(second_separator_char_pos + 1, 1188b9c1b51eSKate Stone third_separator_char_pos - 1189b9c1b51eSKate Stone second_separator_char_pos - 1)); 1190b9c1b51eSKate Stone m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str()); 119144d93782SGreg Clayton } 11920e5e5a79SGreg Clayton return error; 1193de164aaaSGreg Clayton } 1194de164aaaSGreg Clayton 1195b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 1196b9c1b51eSKate Stone if (m_regex_cmd_ap) { 1197b9c1b51eSKate Stone if (m_regex_cmd_ap->HasRegexEntries()) { 1198de164aaaSGreg Clayton CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); 1199de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1200de164aaaSGreg Clayton } 1201de164aaaSGreg Clayton } 1202de164aaaSGreg Clayton } 1203de164aaaSGreg Clayton 1204de164aaaSGreg Clayton private: 12057b0992d9SGreg Clayton std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 1206de164aaaSGreg Clayton 1207b9c1b51eSKate Stone class CommandOptions : public Options { 1208de164aaaSGreg Clayton public: 1209b9c1b51eSKate Stone CommandOptions() : Options() {} 1210de164aaaSGreg Clayton 12116e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1212de164aaaSGreg Clayton 1213fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1214b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1215de164aaaSGreg Clayton Error error; 12163bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1217de164aaaSGreg Clayton 1218b9c1b51eSKate Stone switch (short_option) { 1219de164aaaSGreg Clayton case 'h': 1220de164aaaSGreg Clayton m_help.assign(option_arg); 1221de164aaaSGreg Clayton break; 1222de164aaaSGreg Clayton case 's': 1223de164aaaSGreg Clayton m_syntax.assign(option_arg); 1224de164aaaSGreg Clayton break; 1225de164aaaSGreg Clayton default: 1226b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1227b9c1b51eSKate Stone short_option); 1228de164aaaSGreg Clayton break; 1229de164aaaSGreg Clayton } 1230de164aaaSGreg Clayton 1231de164aaaSGreg Clayton return error; 1232de164aaaSGreg Clayton } 1233de164aaaSGreg Clayton 1234b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1235de164aaaSGreg Clayton m_help.clear(); 1236de164aaaSGreg Clayton m_syntax.clear(); 1237de164aaaSGreg Clayton } 1238de164aaaSGreg Clayton 12391f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 124070602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 12411f0f5b5bSZachary Turner } 1242de164aaaSGreg Clayton 124311eb9c64SZachary Turner // TODO: Convert these functions to return StringRefs. 1244b9c1b51eSKate Stone const char *GetHelp() { 12456e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1246de164aaaSGreg Clayton } 12476e3d8e7fSEugene Zelenko 1248b9c1b51eSKate Stone const char *GetSyntax() { 12496e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1250de164aaaSGreg Clayton } 12516e3d8e7fSEugene Zelenko 1252de164aaaSGreg Clayton protected: 12536e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 12546e3d8e7fSEugene Zelenko 1255de164aaaSGreg Clayton std::string m_help; 1256de164aaaSGreg Clayton std::string m_syntax; 1257de164aaaSGreg Clayton }; 1258de164aaaSGreg Clayton 1259b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1260de164aaaSGreg Clayton 12615a988416SJim Ingham CommandOptions m_options; 1262de164aaaSGreg Clayton }; 1263de164aaaSGreg Clayton 1264b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1265223383edSEnrico Granata public: 1266b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1267b9c1b51eSKate Stone std::string funct, std::string help, 1268b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1269a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1270b9c1b51eSKate Stone m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { 1271735152e3SEnrico Granata if (!help.empty()) 1272442f6530SZachary Turner SetHelp(help); 1273b9c1b51eSKate Stone else { 1274735152e3SEnrico Granata StreamString stream; 1275735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1276c156427dSZachary Turner SetHelp(stream.GetString()); 1277735152e3SEnrico Granata } 1278223383edSEnrico Granata } 1279223383edSEnrico Granata 12806e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1281223383edSEnrico Granata 1282b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 12835a988416SJim Ingham 1284b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 12855a988416SJim Ingham 1286b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 12875a988416SJim Ingham 1288442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1289442f6530SZachary Turner if (m_fetched_help_long) 1290442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1291442f6530SZachary Turner 1292fac939e9SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1293442f6530SZachary Turner if (!scripter) 1294442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1295442f6530SZachary Turner 1296fac939e9SEnrico Granata std::string docstring; 1297442f6530SZachary Turner m_fetched_help_long = 1298442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1299fac939e9SEnrico Granata if (!docstring.empty()) 1300442f6530SZachary Turner SetHelpLong(docstring); 1301fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1302fac939e9SEnrico Granata } 1303fac939e9SEnrico Granata 13045a988416SJim Ingham protected: 1305b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1306b9c1b51eSKate Stone CommandReturnObject &result) override { 1307223383edSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1308223383edSEnrico Granata 1309223383edSEnrico Granata Error error; 1310223383edSEnrico Granata 131170f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 131270f11f88SJim Ingham 1313b9c1b51eSKate Stone if (!scripter || 1314b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1315b9c1b51eSKate Stone raw_command_line, m_synchro, result, 1316b9c1b51eSKate Stone error, m_exe_ctx)) { 1317223383edSEnrico Granata result.AppendError(error.AsCString()); 1318223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1319b9c1b51eSKate Stone } else { 132070f11f88SJim Ingham // Don't change the status if the command already set it... 1321b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1322c156427dSZachary Turner if (result.GetOutputData().empty()) 1323223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 132470f11f88SJim Ingham else 132570f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 132670f11f88SJim Ingham } 132770f11f88SJim Ingham } 1328223383edSEnrico Granata 1329223383edSEnrico Granata return result.Succeeded(); 1330223383edSEnrico Granata } 1331223383edSEnrico Granata 13326e3d8e7fSEugene Zelenko private: 13336e3d8e7fSEugene Zelenko std::string m_function_name; 13346e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 13356e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1336223383edSEnrico Granata }; 1337223383edSEnrico Granata 1338b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 13399fe00e52SEnrico Granata public: 13409fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 13419fe00e52SEnrico Granata std::string name, 13420641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1343b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1344a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1345b9c1b51eSKate Stone m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), 1346b9c1b51eSKate Stone m_fetched_help_long(false) { 13479fe00e52SEnrico Granata StreamString stream; 13489fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1349c156427dSZachary Turner SetHelp(stream.GetString()); 1350e87764f2SEnrico Granata if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter()) 1351e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 13529fe00e52SEnrico Granata } 13539fe00e52SEnrico Granata 13546e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 13559fe00e52SEnrico Granata 1356b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 13579fe00e52SEnrico Granata 1358b9c1b51eSKate Stone StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } 13599fe00e52SEnrico Granata 1360b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 13619fe00e52SEnrico Granata 1362442f6530SZachary Turner llvm::StringRef GetHelp() override { 1363442f6530SZachary Turner if (m_fetched_help_short) 1364442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13656f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1366442f6530SZachary Turner if (!scripter) 1367442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13686f79bb2dSEnrico Granata std::string docstring; 1369b9c1b51eSKate Stone m_fetched_help_short = 1370b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 13716f79bb2dSEnrico Granata if (!docstring.empty()) 1372442f6530SZachary Turner SetHelp(docstring); 1373442f6530SZachary Turner 13746f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 13756f79bb2dSEnrico Granata } 13766f79bb2dSEnrico Granata 1377442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1378442f6530SZachary Turner if (m_fetched_help_long) 1379442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1380442f6530SZachary Turner 13816f79bb2dSEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 1382442f6530SZachary Turner if (!scripter) 1383442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1384442f6530SZachary Turner 13856f79bb2dSEnrico Granata std::string docstring; 1386b9c1b51eSKate Stone m_fetched_help_long = 1387b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 13886f79bb2dSEnrico Granata if (!docstring.empty()) 1389442f6530SZachary Turner SetHelpLong(docstring); 13909fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 13919fe00e52SEnrico Granata } 13929fe00e52SEnrico Granata 13939fe00e52SEnrico Granata protected: 1394b9c1b51eSKate Stone bool DoExecute(const char *raw_command_line, 1395b9c1b51eSKate Stone CommandReturnObject &result) override { 13969fe00e52SEnrico Granata ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); 13979fe00e52SEnrico Granata 13989fe00e52SEnrico Granata Error error; 13999fe00e52SEnrico Granata 14009fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 14019fe00e52SEnrico Granata 1402b9c1b51eSKate Stone if (!scripter || 1403b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1404b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 14059fe00e52SEnrico Granata result.AppendError(error.AsCString()); 14069fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1407b9c1b51eSKate Stone } else { 14089fe00e52SEnrico Granata // Don't change the status if the command already set it... 1409b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1410c156427dSZachary Turner if (result.GetOutputData().empty()) 14119fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 14129fe00e52SEnrico Granata else 14139fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 14149fe00e52SEnrico Granata } 14159fe00e52SEnrico Granata } 14169fe00e52SEnrico Granata 14179fe00e52SEnrico Granata return result.Succeeded(); 14189fe00e52SEnrico Granata } 14199fe00e52SEnrico Granata 14206e3d8e7fSEugene Zelenko private: 14216e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 14226e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 14236e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 14246e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 14259fe00e52SEnrico Granata }; 14269fe00e52SEnrico Granata 1427a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1428a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1429a9dbf432SEnrico Granata //------------------------------------------------------------------------- 1430a9dbf432SEnrico Granata 14311f0f5b5bSZachary Turner OptionDefinition g_script_import_options[] = { 14321f0f5b5bSZachary Turner // clang-format off 14331f0f5b5bSZachary 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." }, 14341f0f5b5bSZachary Turner // clang-format on 14351f0f5b5bSZachary Turner }; 14361f0f5b5bSZachary Turner 1437b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 14385a988416SJim Ingham public: 1439b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1440b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1441b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1442b9c1b51eSKate Stone m_options() { 14435a988416SJim Ingham CommandArgumentEntry arg1; 14445a988416SJim Ingham CommandArgumentData cmd_arg; 14455a988416SJim Ingham 14465a988416SJim Ingham // Define the first (and only) variant of this arg. 14475a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 14483b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 14495a988416SJim Ingham 1450b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1451b9c1b51eSKate Stone // argument entry. 14525a988416SJim Ingham arg1.push_back(cmd_arg); 14535a988416SJim Ingham 14545a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 14555a988416SJim Ingham m_arguments.push_back(arg1); 14565a988416SJim Ingham } 14575a988416SJim Ingham 14586e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 14595a988416SJim Ingham 1460b9c1b51eSKate Stone int HandleArgumentCompletion(Args &input, int &cursor_index, 14615a988416SJim Ingham int &cursor_char_position, 14625a988416SJim Ingham OptionElementVector &opt_element_vector, 1463b9c1b51eSKate Stone int match_start_point, int max_return_elements, 14645a988416SJim Ingham bool &word_complete, 1465b9c1b51eSKate Stone StringList &matches) override { 1466d6a24757SZachary Turner llvm::StringRef completion_str = input[cursor_index].ref; 1467d6a24757SZachary Turner completion_str = completion_str.take_front(cursor_char_position); 14685a988416SJim Ingham 1469b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1470b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1471d6a24757SZachary Turner completion_str, match_start_point, max_return_elements, nullptr, 1472b9c1b51eSKate Stone word_complete, matches); 14735a988416SJim Ingham return matches.GetSize(); 14745a988416SJim Ingham } 14755a988416SJim Ingham 1476b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14775a988416SJim Ingham 14785a988416SJim Ingham protected: 1479b9c1b51eSKate Stone class CommandOptions : public Options { 14800a305db7SEnrico Granata public: 1481b9c1b51eSKate Stone CommandOptions() : Options() {} 14820a305db7SEnrico Granata 14836e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 14840a305db7SEnrico Granata 1485fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1486b9c1b51eSKate Stone ExecutionContext *execution_context) override { 14870a305db7SEnrico Granata Error error; 14883bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14890a305db7SEnrico Granata 1490b9c1b51eSKate Stone switch (short_option) { 14910a305db7SEnrico Granata case 'r': 14920a305db7SEnrico Granata m_allow_reload = true; 14930a305db7SEnrico Granata break; 14940a305db7SEnrico Granata default: 1495b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1496b9c1b51eSKate Stone short_option); 14970a305db7SEnrico Granata break; 14980a305db7SEnrico Granata } 14990a305db7SEnrico Granata 15000a305db7SEnrico Granata return error; 15010a305db7SEnrico Granata } 15020a305db7SEnrico Granata 1503b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1504e0c70f1bSEnrico Granata m_allow_reload = true; 15050a305db7SEnrico Granata } 15060a305db7SEnrico Granata 15071f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 150870602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 15091f0f5b5bSZachary Turner } 15100a305db7SEnrico Granata 15110a305db7SEnrico Granata // Instance variables to hold the values for command options. 15120a305db7SEnrico Granata 15130a305db7SEnrico Granata bool m_allow_reload; 15140a305db7SEnrico Granata }; 15150a305db7SEnrico Granata 1516b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1517b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1518b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1519b9c1b51eSKate Stone result.AppendError("only scripting language supported for module " 1520b9c1b51eSKate Stone "importing is currently Python"); 1521a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1522a9dbf432SEnrico Granata return false; 1523a9dbf432SEnrico Granata } 1524a9dbf432SEnrico Granata 152511eb9c64SZachary Turner if (command.empty()) { 15263b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1527a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1528a9dbf432SEnrico Granata return false; 1529a9dbf432SEnrico Granata } 1530a9dbf432SEnrico Granata 153111eb9c64SZachary Turner for (auto &entry : command.entries()) { 1532a9dbf432SEnrico Granata Error error; 1533a9dbf432SEnrico Granata 1534c9d645d3SGreg Clayton const bool init_session = true; 1535b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 153611eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 153711eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 153811eb9c64SZachary Turner // script imports" in __lldb_init_module the real fix is to have recursive 153911eb9c64SZachary Turner // commands possible with a CommandInvocation object separate from the 154011eb9c64SZachary Turner // CommandObject itself, so that recursive command invocations won't stomp 154111eb9c64SZachary Turner // on each other (wrt to execution contents, options, and more) 1542078551c7SEnrico Granata m_exe_ctx.Clear(); 1543b9c1b51eSKate Stone if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule( 154411eb9c64SZachary Turner entry.c_str(), m_options.m_allow_reload, init_session, error)) { 1545a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1546b9c1b51eSKate Stone } else { 1547b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1548b9c1b51eSKate Stone error.AsCString()); 1549a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1550a9dbf432SEnrico Granata } 15513b00e35bSEnrico Granata } 1552a9dbf432SEnrico Granata 1553a9dbf432SEnrico Granata return result.Succeeded(); 1554a9dbf432SEnrico Granata } 15550a305db7SEnrico Granata 15565a988416SJim Ingham CommandOptions m_options; 1557a9dbf432SEnrico Granata }; 1558223383edSEnrico Granata 1559223383edSEnrico Granata //------------------------------------------------------------------------- 1560223383edSEnrico Granata // CommandObjectCommandsScriptAdd 1561223383edSEnrico Granata //------------------------------------------------------------------------- 1562223383edSEnrico Granata 15631f0f5b5bSZachary Turner static OptionEnumValueElement g_script_synchro_type[] = { 15641f0f5b5bSZachary Turner {eScriptedCommandSynchronicitySynchronous, "synchronous", 15651f0f5b5bSZachary Turner "Run synchronous"}, 15661f0f5b5bSZachary Turner {eScriptedCommandSynchronicityAsynchronous, "asynchronous", 15671f0f5b5bSZachary Turner "Run asynchronous"}, 15681f0f5b5bSZachary Turner {eScriptedCommandSynchronicityCurrentValue, "current", 15691f0f5b5bSZachary Turner "Do not alter current setting"}, 15701f0f5b5bSZachary Turner {0, nullptr, nullptr}}; 15711f0f5b5bSZachary Turner 15721f0f5b5bSZachary Turner static OptionDefinition g_script_add_options[] = { 15731f0f5b5bSZachary Turner // clang-format off 15741f0f5b5bSZachary 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." }, 15751f0f5b5bSZachary 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." }, 15761f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." }, 15771f0f5b5bSZachary 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." }, 15781f0f5b5bSZachary Turner // clang-format on 15791f0f5b5bSZachary Turner }; 15801f0f5b5bSZachary Turner 1581b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1582b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 15835a988416SJim Ingham public: 1584b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1585b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 15865a988416SJim Ingham "Add a scripted function as an LLDB command.", 15876e3d8e7fSEugene Zelenko nullptr), 1588b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 15895a988416SJim Ingham CommandArgumentEntry arg1; 15905a988416SJim Ingham CommandArgumentData cmd_arg; 15915a988416SJim Ingham 15925a988416SJim Ingham // Define the first (and only) variant of this arg. 15935a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 15945a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 15955a988416SJim Ingham 1596b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1597b9c1b51eSKate Stone // argument entry. 15985a988416SJim Ingham arg1.push_back(cmd_arg); 15995a988416SJim Ingham 16005a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 16015a988416SJim Ingham m_arguments.push_back(arg1); 16025a988416SJim Ingham } 16035a988416SJim Ingham 16046e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 16055a988416SJim Ingham 1606b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 16075a988416SJim Ingham 16085a988416SJim Ingham protected: 1609b9c1b51eSKate Stone class CommandOptions : public Options { 1610223383edSEnrico Granata public: 1611b9c1b51eSKate Stone CommandOptions() 1612b9c1b51eSKate Stone : Options(), m_class_name(), m_funct_name(), m_short_help(), 1613b9c1b51eSKate Stone m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1614223383edSEnrico Granata 16156e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1616223383edSEnrico Granata 1617fe11483bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1618b9c1b51eSKate Stone ExecutionContext *execution_context) override { 1619223383edSEnrico Granata Error error; 16203bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1621223383edSEnrico Granata 1622b9c1b51eSKate Stone switch (short_option) { 1623223383edSEnrico Granata case 'f': 1624fe11483bSZachary Turner if (!option_arg.empty()) 1625fe11483bSZachary Turner m_funct_name = option_arg; 1626735152e3SEnrico Granata break; 16279fe00e52SEnrico Granata case 'c': 1628fe11483bSZachary Turner if (!option_arg.empty()) 1629fe11483bSZachary Turner m_class_name = option_arg; 16309fe00e52SEnrico Granata break; 1631735152e3SEnrico Granata case 'h': 1632fe11483bSZachary Turner if (!option_arg.empty()) 1633fe11483bSZachary Turner m_short_help = option_arg; 1634223383edSEnrico Granata break; 16350a305db7SEnrico Granata case 's': 1636b9c1b51eSKate Stone m_synchronicity = 1637b9c1b51eSKate Stone (ScriptedCommandSynchronicity)Args::StringToOptionEnum( 1638fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 16390a305db7SEnrico Granata if (!error.Success()) 1640b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1641fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1642fe11483bSZachary Turner option_arg.str().c_str()); 16430a305db7SEnrico Granata break; 1644223383edSEnrico Granata default: 1645b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1646b9c1b51eSKate Stone short_option); 1647223383edSEnrico Granata break; 1648223383edSEnrico Granata } 1649223383edSEnrico Granata 1650223383edSEnrico Granata return error; 1651223383edSEnrico Granata } 1652223383edSEnrico Granata 1653b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16549fe00e52SEnrico Granata m_class_name.clear(); 1655735152e3SEnrico Granata m_funct_name.clear(); 1656735152e3SEnrico Granata m_short_help.clear(); 165744d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1658223383edSEnrico Granata } 1659223383edSEnrico Granata 16601f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 166170602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 16621f0f5b5bSZachary Turner } 1663223383edSEnrico Granata 1664223383edSEnrico Granata // Instance variables to hold the values for command options. 1665223383edSEnrico Granata 16669fe00e52SEnrico Granata std::string m_class_name; 1667223383edSEnrico Granata std::string m_funct_name; 1668735152e3SEnrico Granata std::string m_short_help; 166944d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1670223383edSEnrico Granata }; 1671223383edSEnrico Granata 1672b9c1b51eSKate Stone void IOHandlerActivated(IOHandler &io_handler) override { 167344d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1674b9c1b51eSKate Stone if (output_sp) { 167544d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 167644d93782SGreg Clayton output_sp->Flush(); 1677223383edSEnrico Granata } 1678223383edSEnrico Granata } 1679223383edSEnrico Granata 1680b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1681b9c1b51eSKate Stone std::string &data) override { 168244d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 168344d93782SGreg Clayton 168444d93782SGreg Clayton ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1685b9c1b51eSKate Stone if (interpreter) { 168644d93782SGreg Clayton 168744d93782SGreg Clayton StringList lines; 168844d93782SGreg Clayton lines.SplitIntoLines(data); 1689b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1690a73b7df7SEnrico Granata std::string funct_name_str; 1691b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1692b9c1b51eSKate Stone if (funct_name_str.empty()) { 1693b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1694b9c1b51eSKate Stone "add python command.\n"); 169544d93782SGreg Clayton error_sp->Flush(); 1696b9c1b51eSKate Stone } else { 1697223383edSEnrico Granata // everything should be fine now, let's add this alias 1698223383edSEnrico Granata 1699b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1700771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 170144d93782SGreg Clayton m_synchronicity)); 1702223383edSEnrico Granata 1703b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1704b9c1b51eSKate Stone true)) { 1705b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1706b9c1b51eSKate Stone "add python command.\n"); 170744d93782SGreg Clayton error_sp->Flush(); 1708223383edSEnrico Granata } 1709223383edSEnrico Granata } 1710b9c1b51eSKate Stone } else { 1711b9c1b51eSKate Stone error_sp->Printf( 1712b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 171344d93782SGreg Clayton error_sp->Flush(); 171444d93782SGreg Clayton } 1715b9c1b51eSKate Stone } else { 171644d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 171744d93782SGreg Clayton error_sp->Flush(); 171844d93782SGreg Clayton } 1719b9c1b51eSKate Stone } else { 1720b9c1b51eSKate Stone error_sp->Printf( 1721b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 172244d93782SGreg Clayton error_sp->Flush(); 172344d93782SGreg Clayton } 172444d93782SGreg Clayton 172544d93782SGreg Clayton io_handler.SetIsDone(true); 172644d93782SGreg Clayton } 1727223383edSEnrico Granata 17285a988416SJim Ingham protected: 1729b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1730b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1731b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1732b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1733b9c1b51eSKate Stone "commands is currently Python"); 173499f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 173599f0b8f9SEnrico Granata return false; 173699f0b8f9SEnrico Granata } 173799f0b8f9SEnrico Granata 173811eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1739223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1740223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1741223383edSEnrico Granata return false; 1742223383edSEnrico Granata } 1743223383edSEnrico Granata 1744735152e3SEnrico Granata // Store the options in case we get multi-line input 17454574a890SZachary Turner m_cmd_name = command[0].ref; 1746735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 174744d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1748223383edSEnrico Granata 1749b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1750b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1751b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1752b9c1b51eSKate Stone " ", // Prompt 175344d93782SGreg Clayton *this, // IOHandlerDelegate 175444d93782SGreg Clayton true, // Run IOHandler in async mode 1755b9c1b51eSKate Stone nullptr); // Baton for the "io_handler" that will be passed back 1756b9c1b51eSKate Stone // into our IOHandlerDelegate functions 1757b9c1b51eSKate Stone } else { 1758b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1759b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1760b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1761b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1762223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1763b9c1b51eSKate Stone } else { 1764223383edSEnrico Granata result.AppendError("cannot add command"); 1765223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1766223383edSEnrico Granata } 1767223383edSEnrico Granata } 1768b9c1b51eSKate Stone } else { 1769b9c1b51eSKate Stone ScriptInterpreter *interpreter = 1770b9c1b51eSKate Stone GetCommandInterpreter().GetScriptInterpreter(); 1771b9c1b51eSKate Stone if (!interpreter) { 17729fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 17739fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17749fe00e52SEnrico Granata return false; 17759fe00e52SEnrico Granata } 17769fe00e52SEnrico Granata 1777b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1778b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1779b9c1b51eSKate Stone if (!cmd_obj_sp) { 17809fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 17819fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17829fe00e52SEnrico Granata return false; 17839fe00e52SEnrico Granata } 17849fe00e52SEnrico Granata 1785b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1786b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1787b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 17889fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1789b9c1b51eSKate Stone } else { 17909fe00e52SEnrico Granata result.AppendError("cannot add command"); 17919fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17929fe00e52SEnrico Granata } 17939fe00e52SEnrico Granata } 1794223383edSEnrico Granata 1795223383edSEnrico Granata return result.Succeeded(); 1796223383edSEnrico Granata } 17975a988416SJim Ingham 17985a988416SJim Ingham CommandOptions m_options; 179944d93782SGreg Clayton std::string m_cmd_name; 1800735152e3SEnrico Granata std::string m_short_help; 180144d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1802223383edSEnrico Granata }; 1803223383edSEnrico Granata 1804223383edSEnrico Granata //------------------------------------------------------------------------- 1805223383edSEnrico Granata // CommandObjectCommandsScriptList 1806223383edSEnrico Granata //------------------------------------------------------------------------- 1807223383edSEnrico Granata 1808b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1809223383edSEnrico Granata public: 1810b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1811b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1812b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1813223383edSEnrico Granata 18146e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1815223383edSEnrico Granata 1816b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1817b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1818223383edSEnrico Granata 1819223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1820223383edSEnrico Granata 1821223383edSEnrico Granata return true; 1822223383edSEnrico Granata } 1823223383edSEnrico Granata }; 1824223383edSEnrico Granata 1825223383edSEnrico Granata //------------------------------------------------------------------------- 1826223383edSEnrico Granata // CommandObjectCommandsScriptClear 1827223383edSEnrico Granata //------------------------------------------------------------------------- 1828223383edSEnrico Granata 1829b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1830223383edSEnrico Granata public: 1831b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1832b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1833b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1834223383edSEnrico Granata 18356e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1836223383edSEnrico Granata 18375a988416SJim Ingham protected: 1838b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1839223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1840223383edSEnrico Granata 1841223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1842223383edSEnrico Granata 1843223383edSEnrico Granata return true; 1844223383edSEnrico Granata } 1845223383edSEnrico Granata }; 1846223383edSEnrico Granata 1847223383edSEnrico Granata //------------------------------------------------------------------------- 1848223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1849223383edSEnrico Granata //------------------------------------------------------------------------- 1850223383edSEnrico Granata 1851b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1852223383edSEnrico Granata public: 1853b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1854b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1855b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1856223383edSEnrico Granata CommandArgumentEntry arg1; 1857223383edSEnrico Granata CommandArgumentData cmd_arg; 1858223383edSEnrico Granata 1859223383edSEnrico Granata // Define the first (and only) variant of this arg. 1860223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1861223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1862223383edSEnrico Granata 1863b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1864b9c1b51eSKate Stone // argument entry. 1865223383edSEnrico Granata arg1.push_back(cmd_arg); 1866223383edSEnrico Granata 1867223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1868223383edSEnrico Granata m_arguments.push_back(arg1); 1869223383edSEnrico Granata } 1870223383edSEnrico Granata 18716e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1872223383edSEnrico Granata 18735a988416SJim Ingham protected: 1874b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1875223383edSEnrico Granata 187611eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1877223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1878223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1879223383edSEnrico Granata return false; 1880223383edSEnrico Granata } 1881223383edSEnrico Granata 18824574a890SZachary Turner auto cmd_name = command[0].ref; 1883223383edSEnrico Granata 18844574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 18854574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1886*867e7d17SZachary Turner result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1887223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 18884574a890SZachary Turner return false; 1889223383edSEnrico Granata } 1890223383edSEnrico Granata 18914574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 18924574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 18934574a890SZachary Turner return true; 1894223383edSEnrico Granata } 1895223383edSEnrico Granata }; 1896223383edSEnrico Granata 1897223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1898223383edSEnrico Granata 1899223383edSEnrico Granata //------------------------------------------------------------------------- 1900223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1901223383edSEnrico Granata //------------------------------------------------------------------------- 1902223383edSEnrico Granata 1903b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1904223383edSEnrico Granata public: 19057428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1906b9c1b51eSKate Stone : CommandObjectMultiword( 1907b9c1b51eSKate Stone interpreter, "command script", "Commands for managing custom " 1908b9c1b51eSKate Stone "commands implemented by " 1909b9c1b51eSKate Stone "interpreter scripts.", 1910b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1911b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1912b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1913b9c1b51eSKate Stone LoadSubCommand( 1914b9c1b51eSKate Stone "delete", 1915b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1916b9c1b51eSKate Stone LoadSubCommand( 1917b9c1b51eSKate Stone "clear", 1918b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1919b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1920b9c1b51eSKate Stone interpreter))); 1921b9c1b51eSKate Stone LoadSubCommand( 1922b9c1b51eSKate Stone "import", 1923b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1924223383edSEnrico Granata } 1925223383edSEnrico Granata 19266e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1927223383edSEnrico Granata }; 1928223383edSEnrico Granata 1929ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1930ebc09c36SJim Ingham 1931ebc09c36SJim Ingham //------------------------------------------------------------------------- 1932ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1933ebc09c36SJim Ingham //------------------------------------------------------------------------- 1934ebc09c36SJim Ingham 1935b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1936b9c1b51eSKate Stone CommandInterpreter &interpreter) 1937b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1938b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1939b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1940b9c1b51eSKate Stone LoadSubCommand("source", 1941b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1942b9c1b51eSKate Stone LoadSubCommand("alias", 1943b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1944b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1945b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1946b9c1b51eSKate Stone LoadSubCommand("delete", 1947b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1948b9c1b51eSKate Stone LoadSubCommand( 1949b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1950b9c1b51eSKate Stone LoadSubCommand("history", CommandObjectSP( 1951b9c1b51eSKate Stone new CommandObjectCommandsHistory(interpreter))); 1952b9c1b51eSKate Stone LoadSubCommand( 1953b9c1b51eSKate Stone "script", 1954b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1955ebc09c36SJim Ingham } 1956ebc09c36SJim Ingham 19576e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1958