1696bd635SAlexander Shaposhnikov //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===// 2ebc09c36SJim Ingham // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ebc09c36SJim Ingham // 7ebc09c36SJim Ingham //===----------------------------------------------------------------------===// 8ebc09c36SJim Ingham 90e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h" 100e5e5a79SGreg Clayton 116e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h" 1246d4aa21SEnrico Granata #include "CommandObjectHelp.h" 13ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 1444d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 153eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 167594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h" 17ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 18de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h" 19ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 2047cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 21012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h" 2245d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h" 237594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h" 24ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 2599f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h" 26145d95c9SPavel Labath #include "lldb/Utility/Args.h" 27573ab909SZachary Turner #include "lldb/Utility/StringList.h" 28ebc09c36SJim Ingham 29ebc09c36SJim Ingham using namespace lldb; 30ebc09c36SJim Ingham using namespace lldb_private; 31ebc09c36SJim Ingham 32ebc09c36SJim Ingham // CommandObjectCommandsSource 33ebc09c36SJim Ingham 348fe53c49STatyana Krasnukha static constexpr OptionDefinition g_history_options[] = { 351f0f5b5bSZachary Turner // clang-format off 368fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, 378fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, 388fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, 398fe53c49STatyana Krasnukha { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." }, 401f0f5b5bSZachary Turner // clang-format on 411f0f5b5bSZachary Turner }; 421f0f5b5bSZachary Turner 43b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed { 445a988416SJim Ingham public: 45b9c1b51eSKate Stone CommandObjectCommandsHistory(CommandInterpreter &interpreter) 46b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command history", 47aab5be05SJim Ingham "Dump the history of commands in this session.\n" 48aab5be05SJim Ingham "Commands in the history list can be run again " 49aab5be05SJim Ingham "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " 50aab5be05SJim Ingham "the command that is <OFFSET> commands from the end" 51aab5be05SJim Ingham " of the list (counting the current command).", 526e3d8e7fSEugene Zelenko nullptr), 53b9c1b51eSKate Stone m_options() {} 545a988416SJim Ingham 556e3d8e7fSEugene Zelenko ~CommandObjectCommandsHistory() override = default; 565a988416SJim Ingham 57b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 585a988416SJim Ingham 595a988416SJim Ingham protected: 60b9c1b51eSKate Stone class CommandOptions : public Options { 61a5a97ebeSJim Ingham public: 62b9c1b51eSKate Stone CommandOptions() 63b9c1b51eSKate Stone : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 64a5a97ebeSJim Ingham } 65a5a97ebeSJim Ingham 666e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 67a5a97ebeSJim Ingham 6897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 69b9c1b51eSKate Stone ExecutionContext *execution_context) override { 7097206d57SZachary Turner Status error; 713bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 72a5a97ebeSJim Ingham 73b9c1b51eSKate Stone switch (short_option) { 74a5a97ebeSJim Ingham case 'c': 75fe11483bSZachary Turner error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 76a5a97ebeSJim Ingham break; 77a5a97ebeSJim Ingham case 's': 78fe11483bSZachary Turner if (option_arg == "end") { 797594f14fSEnrico Granata m_start_idx.SetCurrentValue(UINT64_MAX); 807594f14fSEnrico Granata m_start_idx.SetOptionWasSet(); 81b9c1b51eSKate Stone } else 82fe11483bSZachary Turner error = m_start_idx.SetValueFromString(option_arg, 83b9c1b51eSKate Stone eVarSetOperationAssign); 847594f14fSEnrico Granata break; 857594f14fSEnrico Granata case 'e': 86fe11483bSZachary Turner error = 87fe11483bSZachary Turner m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 887594f14fSEnrico Granata break; 8963123b64SEnrico Granata case 'C': 9063123b64SEnrico Granata m_clear.SetCurrentValue(true); 9163123b64SEnrico Granata m_clear.SetOptionWasSet(); 92a5a97ebeSJim Ingham break; 93a5a97ebeSJim Ingham default: 94b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 95b9c1b51eSKate Stone short_option); 96a5a97ebeSJim Ingham break; 97a5a97ebeSJim Ingham } 98a5a97ebeSJim Ingham 99a5a97ebeSJim Ingham return error; 100a5a97ebeSJim Ingham } 101a5a97ebeSJim Ingham 102b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1037594f14fSEnrico Granata m_start_idx.Clear(); 1047594f14fSEnrico Granata m_stop_idx.Clear(); 1057594f14fSEnrico Granata m_count.Clear(); 10663123b64SEnrico Granata m_clear.Clear(); 107a5a97ebeSJim Ingham } 108a5a97ebeSJim Ingham 1091f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 11070602439SZachary Turner return llvm::makeArrayRef(g_history_options); 1111f0f5b5bSZachary Turner } 112a5a97ebeSJim Ingham 113a5a97ebeSJim Ingham // Instance variables to hold the values for command options. 114a5a97ebeSJim Ingham 1157594f14fSEnrico Granata OptionValueUInt64 m_start_idx; 1167594f14fSEnrico Granata OptionValueUInt64 m_stop_idx; 1177594f14fSEnrico Granata OptionValueUInt64 m_count; 11863123b64SEnrico Granata OptionValueBoolean m_clear; 119a5a97ebeSJim Ingham }; 120a5a97ebeSJim Ingham 121b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 122b9c1b51eSKate Stone if (m_options.m_clear.GetCurrentValue() && 123b9c1b51eSKate Stone m_options.m_clear.OptionWasSet()) { 1247594f14fSEnrico Granata m_interpreter.GetCommandHistory().Clear(); 1257594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 126b9c1b51eSKate Stone } else { 127b9c1b51eSKate Stone if (m_options.m_start_idx.OptionWasSet() && 128b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet() && 129b9c1b51eSKate Stone m_options.m_count.OptionWasSet()) { 130b9c1b51eSKate Stone result.AppendError("--count, --start-index and --end-index cannot be " 131b9c1b51eSKate Stone "all specified in the same invocation"); 1327594f14fSEnrico Granata result.SetStatus(lldb::eReturnStatusFailed); 133b9c1b51eSKate Stone } else { 134b9c1b51eSKate Stone std::pair<bool, uint64_t> start_idx( 135b9c1b51eSKate Stone m_options.m_start_idx.OptionWasSet(), 136b9c1b51eSKate Stone m_options.m_start_idx.GetCurrentValue()); 137b9c1b51eSKate Stone std::pair<bool, uint64_t> stop_idx( 138b9c1b51eSKate Stone m_options.m_stop_idx.OptionWasSet(), 139b9c1b51eSKate Stone m_options.m_stop_idx.GetCurrentValue()); 140b9c1b51eSKate Stone std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 141b9c1b51eSKate Stone m_options.m_count.GetCurrentValue()); 142a5a97ebeSJim Ingham 1437594f14fSEnrico Granata const CommandHistory &history(m_interpreter.GetCommandHistory()); 1447594f14fSEnrico Granata 145b9c1b51eSKate Stone if (start_idx.first && start_idx.second == UINT64_MAX) { 146b9c1b51eSKate Stone if (count.first) { 1477594f14fSEnrico Granata start_idx.second = history.GetSize() - count.second; 1487594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 149b9c1b51eSKate Stone } else if (stop_idx.first) { 1507594f14fSEnrico Granata start_idx.second = stop_idx.second; 1517594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 152b9c1b51eSKate Stone } else { 1537594f14fSEnrico Granata start_idx.second = 0; 1547594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1557594f14fSEnrico Granata } 156b9c1b51eSKate Stone } else { 157b9c1b51eSKate Stone if (!start_idx.first && !stop_idx.first && !count.first) { 1587594f14fSEnrico Granata start_idx.second = 0; 1597594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 160b9c1b51eSKate Stone } else if (start_idx.first) { 161b9c1b51eSKate Stone if (count.first) { 1627594f14fSEnrico Granata stop_idx.second = start_idx.second + count.second - 1; 163b9c1b51eSKate Stone } else if (!stop_idx.first) { 1647594f14fSEnrico Granata stop_idx.second = history.GetSize() - 1; 1657594f14fSEnrico Granata } 166b9c1b51eSKate Stone } else if (stop_idx.first) { 167b9c1b51eSKate Stone if (count.first) { 1687594f14fSEnrico Granata if (stop_idx.second >= count.second) 1697594f14fSEnrico Granata start_idx.second = stop_idx.second - count.second + 1; 1707594f14fSEnrico Granata else 1717594f14fSEnrico Granata start_idx.second = 0; 1727594f14fSEnrico Granata } 173b9c1b51eSKate Stone } else /* if (count.first) */ 1747594f14fSEnrico Granata { 1757594f14fSEnrico Granata start_idx.second = 0; 1767594f14fSEnrico Granata stop_idx.second = count.second - 1; 1777594f14fSEnrico Granata } 1787594f14fSEnrico Granata } 179b9c1b51eSKate Stone history.Dump(result.GetOutputStream(), start_idx.second, 180b9c1b51eSKate Stone stop_idx.second); 1817594f14fSEnrico Granata } 1827594f14fSEnrico Granata } 183a5a97ebeSJim Ingham return result.Succeeded(); 184a5a97ebeSJim Ingham } 1855a988416SJim Ingham 1865a988416SJim Ingham CommandOptions m_options; 187a5a97ebeSJim Ingham }; 188a5a97ebeSJim Ingham 189a5a97ebeSJim Ingham // CommandObjectCommandsSource 190a5a97ebeSJim Ingham 1918fe53c49STatyana Krasnukha static constexpr OptionDefinition g_source_options[] = { 1921f0f5b5bSZachary Turner // clang-format off 1938fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, 1948fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, 1958fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, 1961f0f5b5bSZachary Turner // clang-format on 1971f0f5b5bSZachary Turner }; 1981f0f5b5bSZachary Turner 199b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed { 2005a988416SJim Ingham public: 2017428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 202b9c1b51eSKate Stone : CommandObjectParsed( 203b9c1b51eSKate Stone interpreter, "command source", 204b9c1b51eSKate Stone "Read and execute LLDB commands from the file <filename>.", 2056e3d8e7fSEugene Zelenko nullptr), 206b9c1b51eSKate Stone m_options() { 2075a988416SJim Ingham CommandArgumentEntry arg; 2085a988416SJim Ingham CommandArgumentData file_arg; 2095a988416SJim Ingham 2105a988416SJim Ingham // Define the first (and only) variant of this arg. 2115a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 2125a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 2135a988416SJim Ingham 214b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 215b9c1b51eSKate Stone // argument entry. 2165a988416SJim Ingham arg.push_back(file_arg); 2175a988416SJim Ingham 2185a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 2195a988416SJim Ingham m_arguments.push_back(arg); 2205a988416SJim Ingham } 2215a988416SJim Ingham 2226e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 2235a988416SJim Ingham 224b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 225b9c1b51eSKate Stone uint32_t index) override { 2265a988416SJim Ingham return ""; 2275a988416SJim Ingham } 2285a988416SJim Ingham 2292443bbd4SRaphael Isemann int HandleArgumentCompletion( 2302443bbd4SRaphael Isemann CompletionRequest &request, 2312443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 232b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 233b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 234a2e76c0bSRaphael Isemann request, nullptr); 2351a6d7ab5SRaphael Isemann return request.GetNumberOfMatches(); 2365a988416SJim Ingham } 2375a988416SJim Ingham 238b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 2395a988416SJim Ingham 2405a988416SJim Ingham protected: 241b9c1b51eSKate Stone class CommandOptions : public Options { 242e16c50a1SJim Ingham public: 243b9c1b51eSKate Stone CommandOptions() 244b9c1b51eSKate Stone : Options(), m_stop_on_error(true), m_silent_run(false), 245b9c1b51eSKate Stone m_stop_on_continue(true) {} 246e16c50a1SJim Ingham 2476e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 248e16c50a1SJim Ingham 24997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 250b9c1b51eSKate Stone ExecutionContext *execution_context) override { 25197206d57SZachary Turner Status error; 2523bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 253e16c50a1SJim Ingham 254b9c1b51eSKate Stone switch (short_option) { 255e16c50a1SJim Ingham case 'e': 256fe11483bSZachary Turner error = m_stop_on_error.SetValueFromString(option_arg); 257e16c50a1SJim Ingham break; 258340b0309SGreg Clayton 259e16c50a1SJim Ingham case 'c': 260fe11483bSZachary Turner error = m_stop_on_continue.SetValueFromString(option_arg); 261e16c50a1SJim Ingham break; 262340b0309SGreg Clayton 26360986174SMichael Sartain case 's': 264fe11483bSZachary Turner error = m_silent_run.SetValueFromString(option_arg); 26560986174SMichael Sartain break; 266340b0309SGreg Clayton 267e16c50a1SJim Ingham default: 268b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 269b9c1b51eSKate Stone short_option); 270e16c50a1SJim Ingham break; 271e16c50a1SJim Ingham } 272e16c50a1SJim Ingham 273e16c50a1SJim Ingham return error; 274e16c50a1SJim Ingham } 275e16c50a1SJim Ingham 276b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 277012d4fcaSEnrico Granata m_stop_on_error.Clear(); 278340b0309SGreg Clayton m_silent_run.Clear(); 279340b0309SGreg Clayton m_stop_on_continue.Clear(); 280e16c50a1SJim Ingham } 281e16c50a1SJim Ingham 2821f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 28370602439SZachary Turner return llvm::makeArrayRef(g_source_options); 2841f0f5b5bSZachary Turner } 285e16c50a1SJim Ingham 286e16c50a1SJim Ingham // Instance variables to hold the values for command options. 287e16c50a1SJim Ingham 288012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 289340b0309SGreg Clayton OptionValueBoolean m_silent_run; 290340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 291e16c50a1SJim Ingham }; 292e16c50a1SJim Ingham 293b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2944574a890SZachary Turner if (command.GetArgumentCount() != 1) { 2954574a890SZachary Turner result.AppendErrorWithFormat( 2964574a890SZachary Turner "'%s' takes exactly one executable filename argument.\n", 2974574a890SZachary Turner GetCommandName().str().c_str()); 2984574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 2994574a890SZachary Turner return false; 3004574a890SZachary Turner } 301ebc09c36SJim Ingham 3028f3be7a3SJonas Devlieghere FileSpec cmd_file(command[0].ref); 3038f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(cmd_file); 3046e3d8e7fSEugene Zelenko ExecutionContext *exe_ctx = nullptr; // Just use the default context. 305ebc09c36SJim Ingham 306340b0309SGreg Clayton // If any options were set, then use them 307340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 308340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 309b9c1b51eSKate Stone m_options.m_stop_on_continue.OptionWasSet()) { 310340b0309SGreg Clayton // Use user set settings 31126c7bf93SJim Ingham CommandInterpreterRunOptions options; 3124574a890SZachary Turner options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); 31326c7bf93SJim Ingham options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 314c678ed77SStefan Granitz 315c678ed77SStefan Granitz // Individual silent setting is override for global command echo settings. 316c678ed77SStefan Granitz if (m_options.m_silent_run.GetCurrentValue()) { 317c678ed77SStefan Granitz options.SetSilent(true); 318c678ed77SStefan Granitz } else { 319c678ed77SStefan Granitz options.SetPrintResults(true); 320c678ed77SStefan Granitz options.SetEchoCommands(m_interpreter.GetEchoCommands()); 321c678ed77SStefan Granitz options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands()); 322c678ed77SStefan Granitz } 32326c7bf93SJim Ingham 3244574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 325b9c1b51eSKate Stone } else { 32605097246SAdrian Prantl // No options were set, inherit any settings from nested "command source" 32705097246SAdrian Prantl // commands, or set to sane default settings... 32826c7bf93SJim Ingham CommandInterpreterRunOptions options; 3294574a890SZachary Turner m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 330ebc09c36SJim Ingham } 331ebc09c36SJim Ingham return result.Succeeded(); 332ebc09c36SJim Ingham } 3336e3d8e7fSEugene Zelenko 3345a988416SJim Ingham CommandOptions m_options; 335ebc09c36SJim Ingham }; 336ebc09c36SJim Ingham 337ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 338ebc09c36SJim Ingham // CommandObjectCommandsAlias 339ebc09c36SJim Ingham 3408fe53c49STatyana Krasnukha static constexpr OptionDefinition g_alias_options[] = { 3411f0f5b5bSZachary Turner // clang-format off 3428fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" }, 3438fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" }, 3441f0f5b5bSZachary Turner // clang-format on 3451f0f5b5bSZachary Turner }; 3461f0f5b5bSZachary Turner 347b9c1b51eSKate Stone static const char *g_python_command_instructions = 348b9c1b51eSKate Stone "Enter your Python command(s). Type 'DONE' to end.\n" 349be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 35044d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 351be93a35aSEnrico Granata 352b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw { 35345d0e238SEnrico Granata protected: 354b9c1b51eSKate Stone class CommandOptions : public OptionGroup { 355ebc09c36SJim Ingham public: 356b9c1b51eSKate Stone CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 35745d0e238SEnrico Granata 35845d0e238SEnrico Granata ~CommandOptions() override = default; 35945d0e238SEnrico Granata 3601f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 36170602439SZachary Turner return llvm::makeArrayRef(g_alias_options); 3621f0f5b5bSZachary Turner } 36345d0e238SEnrico Granata 36497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 365b9c1b51eSKate Stone ExecutionContext *execution_context) override { 36697206d57SZachary Turner Status error; 36745d0e238SEnrico Granata 3681f0f5b5bSZachary Turner const int short_option = GetDefinitions()[option_idx].short_option; 3698cef4b0bSZachary Turner std::string option_str(option_value); 37045d0e238SEnrico Granata 371b9c1b51eSKate Stone switch (short_option) { 37245d0e238SEnrico Granata case 'h': 3738cef4b0bSZachary Turner m_help.SetCurrentValue(option_str); 37445d0e238SEnrico Granata m_help.SetOptionWasSet(); 37545d0e238SEnrico Granata break; 37645d0e238SEnrico Granata 37745d0e238SEnrico Granata case 'H': 3788cef4b0bSZachary Turner m_long_help.SetCurrentValue(option_str); 37945d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 38045d0e238SEnrico Granata break; 38145d0e238SEnrico Granata 38245d0e238SEnrico Granata default: 383b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid short option character '%c'", 384b9c1b51eSKate Stone short_option); 38545d0e238SEnrico Granata break; 38645d0e238SEnrico Granata } 38745d0e238SEnrico Granata 38845d0e238SEnrico Granata return error; 38945d0e238SEnrico Granata } 39045d0e238SEnrico Granata 391b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 39245d0e238SEnrico Granata m_help.Clear(); 39345d0e238SEnrico Granata m_long_help.Clear(); 39445d0e238SEnrico Granata } 39545d0e238SEnrico Granata 39645d0e238SEnrico Granata OptionValueString m_help; 39745d0e238SEnrico Granata OptionValueString m_long_help; 39845d0e238SEnrico Granata }; 39945d0e238SEnrico Granata 40045d0e238SEnrico Granata OptionGroupOptions m_option_group; 40145d0e238SEnrico Granata CommandOptions m_command_options; 40245d0e238SEnrico Granata 40345d0e238SEnrico Granata public: 404b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 40545d0e238SEnrico Granata 4067428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 407b9c1b51eSKate Stone : CommandObjectRaw( 408b9c1b51eSKate Stone interpreter, "command alias", 409a449698cSZachary Turner "Define a custom command in terms of an existing command."), 410b9c1b51eSKate Stone m_option_group(), m_command_options() { 41145d0e238SEnrico Granata m_option_group.Append(&m_command_options); 41245d0e238SEnrico Granata m_option_group.Finalize(); 41345d0e238SEnrico Granata 414ebc09c36SJim Ingham SetHelpLong( 415ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 416ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 417b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:" 418b9c1b51eSKate Stone R"( 419ea671fbdSKate Stone 420ea671fbdSKate Stone (lldb) command alias sc script 421ea671fbdSKate Stone 422ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 423ea671fbdSKate Stone 424ea671fbdSKate Stone (lldb) command alias bp breakpoint 425ea671fbdSKate Stone 426b9c1b51eSKate Stone )" 427b9c1b51eSKate Stone " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 428ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 429b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 430b9c1b51eSKate Stone R"( 431ea671fbdSKate Stone 432ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 433ea671fbdSKate Stone 434ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 435ea671fbdSKate Stone 436b9c1b51eSKate Stone )" 437b9c1b51eSKate Stone "An alias can include some options for the command, with the values either \ 438ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 439ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 440b9c1b51eSKate Stone shows how to create aliases with options:" 441b9c1b51eSKate Stone R"( 442ea671fbdSKate Stone 443ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 444ea671fbdSKate Stone 445b9c1b51eSKate Stone )" 446b9c1b51eSKate Stone " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 447ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 448ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 449ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 450ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 451ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 452ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 453ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 454ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 455ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 456b9c1b51eSKate Stone launch' example below)." 457b9c1b51eSKate Stone R"( 458ea671fbdSKate Stone 459b9c1b51eSKate Stone )" 460b9c1b51eSKate Stone "Note: the positional arguments must substitute as whole words in the resultant \ 461ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 462b9c1b51eSKate Stone \".cpp\":" 463b9c1b51eSKate Stone R"( 464ea671fbdSKate Stone 465ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 466ea671fbdSKate Stone 467b9c1b51eSKate Stone )" 468b9c1b51eSKate Stone "For more complex aliasing, use the \"command regex\" command instead. In the \ 469ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 470ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 471b9c1b51eSKate Stone argument. The user would use this alias as follows:" 472b9c1b51eSKate Stone R"( 473ea671fbdSKate Stone 474ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 475ea671fbdSKate Stone (lldb) bfl my-file.c 137 476ea671fbdSKate Stone 477ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 478ea671fbdSKate Stone 479ea671fbdSKate Stone Another example: 480ea671fbdSKate Stone 481ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 482ea671fbdSKate Stone (lldb) pltty /dev/tty0 483ea671fbdSKate Stone 484ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 485ea671fbdSKate Stone 486b9c1b51eSKate Stone )" 487b9c1b51eSKate Stone "If the user always wanted to pass the same value to a particular option, the \ 488ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 489b9c1b51eSKate Stone rather than using a positional placeholder:" 490b9c1b51eSKate Stone R"( 491ea671fbdSKate Stone 492ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 493ea671fbdSKate Stone 494b9c1b51eSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)"); 495ebc09c36SJim Ingham 496405fe67fSCaroline Tice CommandArgumentEntry arg1; 497405fe67fSCaroline Tice CommandArgumentEntry arg2; 498405fe67fSCaroline Tice CommandArgumentEntry arg3; 499405fe67fSCaroline Tice CommandArgumentData alias_arg; 500405fe67fSCaroline Tice CommandArgumentData cmd_arg; 501405fe67fSCaroline Tice CommandArgumentData options_arg; 502405fe67fSCaroline Tice 503405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 504405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 505405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 506405fe67fSCaroline Tice 507b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 508b9c1b51eSKate Stone // argument entry. 509405fe67fSCaroline Tice arg1.push_back(alias_arg); 510405fe67fSCaroline Tice 511405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 512405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 513405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 514405fe67fSCaroline Tice 515b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 516b9c1b51eSKate Stone // argument entry. 517405fe67fSCaroline Tice arg2.push_back(cmd_arg); 518405fe67fSCaroline Tice 519405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 520405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 521405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 522405fe67fSCaroline Tice 523b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 524b9c1b51eSKate Stone // argument entry. 525405fe67fSCaroline Tice arg3.push_back(options_arg); 526405fe67fSCaroline Tice 527405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 528405fe67fSCaroline Tice m_arguments.push_back(arg1); 529405fe67fSCaroline Tice m_arguments.push_back(arg2); 530405fe67fSCaroline Tice m_arguments.push_back(arg3); 531ebc09c36SJim Ingham } 532ebc09c36SJim Ingham 5336e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 534ebc09c36SJim Ingham 5355a988416SJim Ingham protected: 5364d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 537b9c1b51eSKate Stone CommandReturnObject &result) override { 5384d51a902SRaphael Isemann if (raw_command_line.empty()) { 539d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 54045d0e238SEnrico Granata return false; 54145d0e238SEnrico Granata } 54245d0e238SEnrico Granata 543e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 544e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 54545d0e238SEnrico Granata 5463a0e1270SRaphael Isemann OptionsWithRaw args_with_suffix(raw_command_line); 5473a0e1270SRaphael Isemann const char *remainder = args_with_suffix.GetRawPart().c_str(); 54845d0e238SEnrico Granata 5493a0e1270SRaphael Isemann if (args_with_suffix.HasArgs()) 5503a0e1270SRaphael Isemann if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result, 5513a0e1270SRaphael Isemann m_option_group, exe_ctx)) 55245d0e238SEnrico Granata return false; 55345d0e238SEnrico Granata 554a01bccdbSZachary Turner llvm::StringRef raw_command_string(remainder); 555a01bccdbSZachary Turner Args args(raw_command_string); 556844d2303SCaroline Tice 55711eb9c64SZachary Turner if (args.GetArgumentCount() < 2) { 558d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 559844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 560844d2303SCaroline Tice return false; 561844d2303SCaroline Tice } 562844d2303SCaroline Tice 563844d2303SCaroline Tice // Get the alias command. 564844d2303SCaroline Tice 5654574a890SZachary Turner auto alias_command = args[0].ref; 5664574a890SZachary Turner if (alias_command.startswith("-")) { 567d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 568b9c1b51eSKate Stone if (alias_command == "--help" || alias_command == "--long-help") { 569b9c1b51eSKate Stone result.AppendWarning("if trying to pass options to 'command alias' add " 570b9c1b51eSKate Stone "a -- at the end of the options"); 571d72e412fSEnrico Granata } 572d72e412fSEnrico Granata result.SetStatus(eReturnStatusFailed); 573d72e412fSEnrico Granata return false; 574d72e412fSEnrico Granata } 575844d2303SCaroline Tice 576b9c1b51eSKate Stone // Strip the new alias name off 'raw_command_string' (leave it on args, 57705097246SAdrian Prantl // which gets passed to 'Execute', which does the stripping itself. 578844d2303SCaroline Tice size_t pos = raw_command_string.find(alias_command); 579b9c1b51eSKate Stone if (pos == 0) { 580844d2303SCaroline Tice raw_command_string = raw_command_string.substr(alias_command.size()); 581844d2303SCaroline Tice pos = raw_command_string.find_first_not_of(' '); 582844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 583844d2303SCaroline Tice raw_command_string = raw_command_string.substr(pos); 584b9c1b51eSKate Stone } else { 585844d2303SCaroline Tice result.AppendError("Error parsing command string. No alias created."); 586844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 587844d2303SCaroline Tice return false; 588844d2303SCaroline Tice } 589844d2303SCaroline Tice 590844d2303SCaroline Tice // Verify that the command is alias-able. 591771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 592b9c1b51eSKate Stone result.AppendErrorWithFormat( 593b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 5944574a890SZachary Turner args[0].c_str()); 595844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 596844d2303SCaroline Tice return false; 597844d2303SCaroline Tice } 598844d2303SCaroline Tice 599b9c1b51eSKate Stone // Get CommandObject that is being aliased. The command name is read from 600a01bccdbSZachary Turner // the front of raw_command_string. raw_command_string is returned with the 601a01bccdbSZachary Turner // name of the command object stripped off the front. 602a01bccdbSZachary Turner llvm::StringRef original_raw_command_string = raw_command_string; 603b9c1b51eSKate Stone CommandObject *cmd_obj = 604b9c1b51eSKate Stone m_interpreter.GetCommandObjectForCommand(raw_command_string); 605844d2303SCaroline Tice 606b9c1b51eSKate Stone if (!cmd_obj) { 607b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command given to 'command alias'. " 608b9c1b51eSKate Stone "'%s' does not begin with a valid command." 609b9c1b51eSKate Stone " No alias created.", 610a01bccdbSZachary Turner original_raw_command_string.str().c_str()); 611844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 612844d2303SCaroline Tice return false; 613b9c1b51eSKate Stone } else if (!cmd_obj->WantsRawCommandString()) { 614b9c1b51eSKate Stone // Note that args was initialized with the original command, and has not 61505097246SAdrian Prantl // been updated to this point. Therefore can we pass it to the version of 61605097246SAdrian Prantl // Execute that does not need/expect raw input in the alias. 6175a988416SJim Ingham return HandleAliasingNormalCommand(args, result); 618b9c1b51eSKate Stone } else { 619b9c1b51eSKate Stone return HandleAliasingRawCommand(alias_command, raw_command_string, 620b9c1b51eSKate Stone *cmd_obj, result); 6215a988416SJim Ingham } 6225a988416SJim Ingham return result.Succeeded(); 6235a988416SJim Ingham } 6245a988416SJim Ingham 625a01bccdbSZachary Turner bool HandleAliasingRawCommand(llvm::StringRef alias_command, 626a01bccdbSZachary Turner llvm::StringRef raw_command_string, 627b9c1b51eSKate Stone CommandObject &cmd_obj, 628b9c1b51eSKate Stone CommandReturnObject &result) { 629844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 630844d2303SCaroline Tice 631b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 632b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 633844d2303SCaroline Tice 634b9c1b51eSKate Stone if (CommandObjectSP cmd_obj_sp = 635b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 636a01bccdbSZachary Turner if (m_interpreter.AliasExists(alias_command) || 637a01bccdbSZachary Turner m_interpreter.UserCommandExists(alias_command)) { 638b9c1b51eSKate Stone result.AppendWarningWithFormat( 639b9c1b51eSKate Stone "Overwriting existing definition for '%s'.\n", 640a01bccdbSZachary Turner alias_command.str().c_str()); 641844d2303SCaroline Tice } 642b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 643a01bccdbSZachary Turner alias_command, cmd_obj_sp, raw_command_string)) { 64445d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 64545d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 64645d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 64745d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 648844d2303SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 649b9c1b51eSKate Stone } else { 650472362e6SCaroline Tice result.AppendError("Unable to create requested alias.\n"); 651472362e6SCaroline Tice result.SetStatus(eReturnStatusFailed); 652472362e6SCaroline Tice } 653212130acSEnrico Granata 654b9c1b51eSKate Stone } else { 655212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 656212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 657212130acSEnrico Granata } 658212130acSEnrico Granata 659844d2303SCaroline Tice return result.Succeeded(); 660844d2303SCaroline Tice } 661ebc09c36SJim Ingham 662b9c1b51eSKate Stone bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 663867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 664ebc09c36SJim Ingham 665b9c1b51eSKate Stone if (argc < 2) { 666d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 667ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 668ebc09c36SJim Ingham return false; 669ebc09c36SJim Ingham } 670ebc09c36SJim Ingham 6714574a890SZachary Turner // Save these in std::strings since we're going to shift them off. 6724574a890SZachary Turner const std::string alias_command(args[0].ref); 6734574a890SZachary Turner const std::string actual_command(args[1].ref); 674ebc09c36SJim Ingham 675ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 676ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 677ebc09c36SJim Ingham 678b9c1b51eSKate Stone // Verify that the command is alias'able, and get the appropriate command 679b9c1b51eSKate Stone // object. 680ebc09c36SJim Ingham 681771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 682b9c1b51eSKate Stone result.AppendErrorWithFormat( 683b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 684ebc09c36SJim Ingham alias_command.c_str()); 685ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 6864574a890SZachary Turner return false; 6874574a890SZachary Turner } 6884574a890SZachary Turner 689b9c1b51eSKate Stone CommandObjectSP command_obj_sp( 690a449698cSZachary Turner m_interpreter.GetCommandSPExact(actual_command, true)); 691ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 692ebc09c36SJim Ingham bool use_subcommand = false; 6934574a890SZachary Turner if (!command_obj_sp) { 6944574a890SZachary Turner result.AppendErrorWithFormat("'%s' is not an existing command.\n", 6954574a890SZachary Turner actual_command.c_str()); 6964574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 6974574a890SZachary Turner return false; 6984574a890SZachary Turner } 699ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 7006e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 701b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 702b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 703ebc09c36SJim Ingham 70411eb9c64SZachary Turner while (cmd_obj->IsMultiwordObject() && !args.empty()) { 7054574a890SZachary Turner auto sub_command = args[0].ref; 70611eb9c64SZachary Turner assert(!sub_command.empty()); 7074574a890SZachary Turner subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 7084574a890SZachary Turner if (!subcommand_obj_sp) { 709b9c1b51eSKate Stone result.AppendErrorWithFormat( 710b9c1b51eSKate Stone "'%s' is not a valid sub-command of '%s'. " 711f415eeb4SCaroline Tice "Unable to create alias.\n", 7124574a890SZachary Turner args[0].c_str(), actual_command.c_str()); 713ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 714ebc09c36SJim Ingham return false; 715ebc09c36SJim Ingham } 7164574a890SZachary Turner 7174574a890SZachary Turner sub_cmd_obj = subcommand_obj_sp.get(); 7184574a890SZachary Turner use_subcommand = true; 7194574a890SZachary Turner args.Shift(); // Shift the sub_command word off the argument vector. 7204574a890SZachary Turner cmd_obj = sub_cmd_obj; 721ebc09c36SJim Ingham } 722ebc09c36SJim Ingham 723ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 724ebc09c36SJim Ingham 725212130acSEnrico Granata std::string args_string; 726212130acSEnrico Granata 72711eb9c64SZachary Turner if (!args.empty()) { 728b9c1b51eSKate Stone CommandObjectSP tmp_sp = 729b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 730ebc09c36SJim Ingham if (use_subcommand) 7314574a890SZachary Turner tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 7324574a890SZachary Turner false); 733ca90c47eSCaroline Tice 734ca90c47eSCaroline Tice args.GetCommandString(args_string); 735867b185dSCaroline Tice } 736ebc09c36SJim Ingham 737771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 738771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 739b9c1b51eSKate Stone result.AppendWarningWithFormat( 7404574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 741ebc09c36SJim Ingham } 742ebc09c36SJim Ingham 743b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 7444574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 745771ef6d4SMalcolm Parsons args_string)) { 74645d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 74745d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 74845d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 74945d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 750ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 751b9c1b51eSKate Stone } else { 752212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 753212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 754212130acSEnrico Granata return false; 755212130acSEnrico Granata } 756ebc09c36SJim Ingham 757ebc09c36SJim Ingham return result.Succeeded(); 758ebc09c36SJim Ingham } 759ebc09c36SJim Ingham }; 760ebc09c36SJim Ingham 761ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 762ebc09c36SJim Ingham // CommandObjectCommandsUnalias 763ebc09c36SJim Ingham 764b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 765ebc09c36SJim Ingham public: 7667428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 767b9c1b51eSKate Stone : CommandObjectParsed( 768b9c1b51eSKate Stone interpreter, "command unalias", 769b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 770b9c1b51eSKate Stone nullptr) { 771405fe67fSCaroline Tice CommandArgumentEntry arg; 772405fe67fSCaroline Tice CommandArgumentData alias_arg; 773405fe67fSCaroline Tice 774405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 775405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 776405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 777405fe67fSCaroline Tice 778b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 779b9c1b51eSKate Stone // argument entry. 780405fe67fSCaroline Tice arg.push_back(alias_arg); 781405fe67fSCaroline Tice 782405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 783405fe67fSCaroline Tice m_arguments.push_back(arg); 784ebc09c36SJim Ingham } 785ebc09c36SJim Ingham 7866e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 787ebc09c36SJim Ingham 7885a988416SJim Ingham protected: 789b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 790ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 791ebc09c36SJim Ingham CommandObject *cmd_obj; 792ebc09c36SJim Ingham 79311eb9c64SZachary Turner if (args.empty()) { 79411eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 79511eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 79611eb9c64SZachary Turner return false; 79711eb9c64SZachary Turner } 79811eb9c64SZachary Turner 7994574a890SZachary Turner auto command_name = args[0].ref; 800a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 8014574a890SZachary Turner if (!cmd_obj) { 8024574a890SZachary Turner result.AppendErrorWithFormat( 8034574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 8044574a890SZachary Turner "current list of commands.\n", 805867e7d17SZachary Turner args[0].c_str()); 8064574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 8074574a890SZachary Turner return false; 8084574a890SZachary Turner } 8094574a890SZachary Turner 810b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 811b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 812b9c1b51eSKate Stone result.AppendErrorWithFormat( 813b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 814b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 815867e7d17SZachary Turner args[0].c_str()); 816b9c1b51eSKate Stone } else { 817b9c1b51eSKate Stone result.AppendErrorWithFormat( 818b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 819867e7d17SZachary Turner args[0].c_str()); 820b547278cSGreg Clayton } 821ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8224574a890SZachary Turner return false; 8234574a890SZachary Turner } 8244574a890SZachary Turner 825b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 826a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 827b9c1b51eSKate Stone result.AppendErrorWithFormat( 828867e7d17SZachary Turner "Error occurred while attempting to unalias '%s'.\n", 829867e7d17SZachary Turner args[0].c_str()); 830ebc09c36SJim Ingham else 831b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 832867e7d17SZachary Turner args[0].c_str()); 833ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 8344574a890SZachary Turner return false; 835ebc09c36SJim Ingham } 836ebc09c36SJim Ingham 8374574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 838ebc09c36SJim Ingham return result.Succeeded(); 839ebc09c36SJim Ingham } 840ebc09c36SJim Ingham }; 841ebc09c36SJim Ingham 842b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 843b547278cSGreg Clayton // CommandObjectCommandsDelete 844b547278cSGreg Clayton 845b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 846b547278cSGreg Clayton public: 8477428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 848b9c1b51eSKate Stone : CommandObjectParsed( 849b9c1b51eSKate Stone interpreter, "command delete", 850b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 851b9c1b51eSKate Stone nullptr) { 852b547278cSGreg Clayton CommandArgumentEntry arg; 853b547278cSGreg Clayton CommandArgumentData alias_arg; 854b547278cSGreg Clayton 855b547278cSGreg Clayton // Define the first (and only) variant of this arg. 856b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 857b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 858b547278cSGreg Clayton 859b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 860b9c1b51eSKate Stone // argument entry. 861b547278cSGreg Clayton arg.push_back(alias_arg); 862b547278cSGreg Clayton 863b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 864b547278cSGreg Clayton m_arguments.push_back(arg); 865b547278cSGreg Clayton } 866b547278cSGreg Clayton 8676e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 868b547278cSGreg Clayton 869b547278cSGreg Clayton protected: 870b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 871b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 872b547278cSGreg Clayton 87311eb9c64SZachary Turner if (args.empty()) { 87411eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 87511eb9c64SZachary Turner "defined regular expression command names", 876a449698cSZachary Turner GetCommandName().str().c_str()); 87711eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 87811eb9c64SZachary Turner } 87911eb9c64SZachary Turner 8804574a890SZachary Turner auto command_name = args[0].ref; 8814574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 88246d4aa21SEnrico Granata StreamString error_msg_stream; 883d5b44036SJonas Devlieghere const bool generate_upropos = true; 88446d4aa21SEnrico Granata const bool generate_type_lookup = false; 885b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 8864574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 887d5b44036SJonas Devlieghere generate_upropos, generate_type_lookup); 888c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 889b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 8904574a890SZachary Turner return false; 891b547278cSGreg Clayton } 892b547278cSGreg Clayton 8934574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 8944574a890SZachary Turner result.AppendErrorWithFormat( 8954574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 896867e7d17SZachary Turner args[0].c_str()); 8974574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 8984574a890SZachary Turner return false; 8994574a890SZachary Turner } 9004574a890SZachary Turner 9014574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 9024574a890SZachary Turner return true; 903b547278cSGreg Clayton } 904b547278cSGreg Clayton }; 905b547278cSGreg Clayton 906de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 9071f0f5b5bSZachary Turner 9088fe53c49STatyana Krasnukha static constexpr OptionDefinition g_regex_options[] = { 9091f0f5b5bSZachary Turner // clang-format off 9108fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." }, 9118fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, 9121f0f5b5bSZachary Turner // clang-format on 9131f0f5b5bSZachary Turner }; 9141f0f5b5bSZachary Turner 9155a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 916de164aaaSGreg Clayton 917b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 918b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 919de164aaaSGreg Clayton public: 9207428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 921b9c1b51eSKate Stone : CommandObjectParsed( 922b9c1b51eSKate Stone interpreter, "command regex", "Define a custom command in terms of " 923b9c1b51eSKate Stone "existing commands by matching " 924b9c1b51eSKate Stone "regular expressions.", 9250e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 926b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 927b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 928b9c1b51eSKate Stone m_options() { 929b9c1b51eSKate Stone SetHelpLong( 930b9c1b51eSKate Stone R"( 931b9c1b51eSKate Stone )" 932b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 933ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 934b9c1b51eSKate Stone using the regular expression substitution format of:" 935b9c1b51eSKate Stone R"( 936ea671fbdSKate Stone 937ea671fbdSKate Stone s/<regex>/<subst>/ 938ea671fbdSKate Stone 939b9c1b51eSKate Stone )" 940b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 941ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 942b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 943b9c1b51eSKate Stone R"( 944ea671fbdSKate Stone 945b9c1b51eSKate Stone )" 946b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 947ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 948ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 949b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 950b9c1b51eSKate Stone R"( 951ea671fbdSKate Stone 952ea671fbdSKate Stone EXAMPLES 953ea671fbdSKate Stone 954b9c1b51eSKate Stone )" 955b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 956ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 957b9c1b51eSKate Stone a number follows 'f':" 958b9c1b51eSKate Stone R"( 959ea671fbdSKate Stone 960b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 961de164aaaSGreg Clayton } 962de164aaaSGreg Clayton 9636e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 964de164aaaSGreg Clayton 9655a988416SJim Ingham protected: 9660affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 96744d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 9680affb582SDave Lee if (output_sp && interactive) { 9690affb582SDave Lee output_sp->PutCString("Enter one or more sed substitution commands in " 970b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 971b9c1b51eSKate Stone "substitution list with an empty line.\n"); 97244d93782SGreg Clayton output_sp->Flush(); 97344d93782SGreg Clayton } 97444d93782SGreg Clayton } 97544d93782SGreg Clayton 976b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 977b9c1b51eSKate Stone std::string &data) override { 97844d93782SGreg Clayton io_handler.SetIsDone(true); 979d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 98044d93782SGreg Clayton StringList lines; 981b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 98244d93782SGreg Clayton const size_t num_lines = lines.GetSize(); 98344d93782SGreg Clayton bool check_only = false; 984b9c1b51eSKate Stone for (size_t i = 0; i < num_lines; ++i) { 98544d93782SGreg Clayton llvm::StringRef bytes_strref(lines[i]); 98697206d57SZachary Turner Status error = AppendRegexSubstitution(bytes_strref, check_only); 987b9c1b51eSKate Stone if (error.Fail()) { 988b9c1b51eSKate Stone if (!m_interpreter.GetDebugger() 989b9c1b51eSKate Stone .GetCommandInterpreter() 990b9c1b51eSKate Stone .GetBatchCommandMode()) { 991b9c1b51eSKate Stone StreamSP out_stream = 992b9c1b51eSKate Stone m_interpreter.GetDebugger().GetAsyncOutputStream(); 99344d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 99444d93782SGreg Clayton } 99544d93782SGreg Clayton } 99644d93782SGreg Clayton } 99744d93782SGreg Clayton } 998d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 999d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 100044d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 100144d93782SGreg Clayton } 100244d93782SGreg Clayton } 100344d93782SGreg Clayton } 100444d93782SGreg Clayton 1005b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 10065a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 1007b9c1b51eSKate Stone if (argc == 0) { 1008b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 1009b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 10100e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 101111eb9c64SZachary Turner return false; 101211eb9c64SZachary Turner } 101311eb9c64SZachary Turner 101497206d57SZachary Turner Status error; 10154574a890SZachary Turner auto name = command[0].ref; 1016d5b44036SJonas Devlieghere m_regex_cmd_up = llvm::make_unique<CommandObjectRegexCommand>( 10174574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 10184574a890SZachary Turner true); 10190e5e5a79SGreg Clayton 1020b9c1b51eSKate Stone if (argc == 1) { 102144d93782SGreg Clayton Debugger &debugger = m_interpreter.GetDebugger(); 1022e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 102344d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 1024b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 1025b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 102673d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 1027514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 1028514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 1029b9c1b51eSKate Stone multiple_lines, color_prompt, 1030f6913cd7SGreg Clayton 0, // Don't show line numbers 1031d77c2e09SJonas Devlieghere *this, nullptr)); 103244d93782SGreg Clayton 1033b9c1b51eSKate Stone if (io_handler_sp) { 103444d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 1035de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 1036de164aaaSGreg Clayton } 1037b9c1b51eSKate Stone } else { 103897d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 103944d93782SGreg Clayton bool check_only = false; 104097d2c401SZachary Turner error = AppendRegexSubstitution(entry.ref, check_only); 10410e5e5a79SGreg Clayton if (error.Fail()) 10420e5e5a79SGreg Clayton break; 10430e5e5a79SGreg Clayton } 10440e5e5a79SGreg Clayton 1045b9c1b51eSKate Stone if (error.Success()) { 10460e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 10470e5e5a79SGreg Clayton } 10480e5e5a79SGreg Clayton } 1049b9c1b51eSKate Stone if (error.Fail()) { 10500e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 1051de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 1052de164aaaSGreg Clayton } 10530e5e5a79SGreg Clayton 1054de164aaaSGreg Clayton return result.Succeeded(); 1055de164aaaSGreg Clayton } 1056de164aaaSGreg Clayton 105797206d57SZachary Turner Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 1058b9c1b51eSKate Stone bool check_only) { 105997206d57SZachary Turner Status error; 10600e5e5a79SGreg Clayton 1061d5b44036SJonas Devlieghere if (!m_regex_cmd_up) { 1062b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1063b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 1064b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 10650e5e5a79SGreg Clayton return error; 1066de164aaaSGreg Clayton } 10670e5e5a79SGreg Clayton 10680e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 10690e5e5a79SGreg Clayton 1070b9c1b51eSKate Stone if (regex_sed_size <= 1) { 1071b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1072b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 1073b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 10740e5e5a79SGreg Clayton return error; 10750e5e5a79SGreg Clayton } 10760e5e5a79SGreg Clayton 1077b9c1b51eSKate Stone if (regex_sed[0] != 's') { 1078b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 1079b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 1080b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 10810e5e5a79SGreg Clayton return error; 10820e5e5a79SGreg Clayton } 10830e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 108405097246SAdrian Prantl // use the char that follows 's' as the regex separator character so we can 108505097246SAdrian Prantl // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 10860e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 1087b9c1b51eSKate Stone const size_t second_separator_char_pos = 1088b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 10890e5e5a79SGreg Clayton 1090b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 1091b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1092b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 10930e5e5a79SGreg Clayton separator_char, 10940e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 1095ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 1096b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 10970e5e5a79SGreg Clayton return error; 10980e5e5a79SGreg Clayton } 10990e5e5a79SGreg Clayton 1100b9c1b51eSKate Stone const size_t third_separator_char_pos = 1101b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 11020e5e5a79SGreg Clayton 1103b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 1104b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1105b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 11060e5e5a79SGreg Clayton separator_char, 11070e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 1108ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 1109b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 11100e5e5a79SGreg Clayton return error; 11110e5e5a79SGreg Clayton } 11120e5e5a79SGreg Clayton 1113b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 111405097246SAdrian Prantl // Make sure that everything that follows the last regex separator char 1115b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 1116b9c1b51eSKate Stone third_separator_char_pos + 1) != 1117b9c1b51eSKate Stone std::string::npos) { 1118b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1119b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 1120b9c1b51eSKate Stone "string: '%.*s'", 1121b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 11220e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 11230e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 11240e5e5a79SGreg Clayton return error; 11250e5e5a79SGreg Clayton } 1126b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 1127b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1128b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1129b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11300e5e5a79SGreg Clayton regex_sed.data()); 11310e5e5a79SGreg Clayton return error; 1132b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 1133b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1134b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1135b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 11360e5e5a79SGreg Clayton regex_sed.data()); 11370e5e5a79SGreg Clayton return error; 11380e5e5a79SGreg Clayton } 113944d93782SGreg Clayton 1140b9c1b51eSKate Stone if (!check_only) { 1141b9c1b51eSKate Stone std::string regex(regex_sed.substr(first_separator_char_pos + 1, 1142b9c1b51eSKate Stone second_separator_char_pos - 1143b9c1b51eSKate Stone first_separator_char_pos - 1)); 1144b9c1b51eSKate Stone std::string subst(regex_sed.substr(second_separator_char_pos + 1, 1145b9c1b51eSKate Stone third_separator_char_pos - 1146b9c1b51eSKate Stone second_separator_char_pos - 1)); 1147d5b44036SJonas Devlieghere m_regex_cmd_up->AddRegexCommand(regex.c_str(), subst.c_str()); 114844d93782SGreg Clayton } 11490e5e5a79SGreg Clayton return error; 1150de164aaaSGreg Clayton } 1151de164aaaSGreg Clayton 1152b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 1153d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 1154d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 1155d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 1156de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1157de164aaaSGreg Clayton } 1158de164aaaSGreg Clayton } 1159de164aaaSGreg Clayton } 1160de164aaaSGreg Clayton 1161de164aaaSGreg Clayton private: 1162d5b44036SJonas Devlieghere std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up; 1163de164aaaSGreg Clayton 1164b9c1b51eSKate Stone class CommandOptions : public Options { 1165de164aaaSGreg Clayton public: 1166b9c1b51eSKate Stone CommandOptions() : Options() {} 1167de164aaaSGreg Clayton 11686e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1169de164aaaSGreg Clayton 117097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1171b9c1b51eSKate Stone ExecutionContext *execution_context) override { 117297206d57SZachary Turner Status error; 11733bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1174de164aaaSGreg Clayton 1175b9c1b51eSKate Stone switch (short_option) { 1176de164aaaSGreg Clayton case 'h': 1177de164aaaSGreg Clayton m_help.assign(option_arg); 1178de164aaaSGreg Clayton break; 1179de164aaaSGreg Clayton case 's': 1180de164aaaSGreg Clayton m_syntax.assign(option_arg); 1181de164aaaSGreg Clayton break; 1182de164aaaSGreg Clayton default: 1183b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1184b9c1b51eSKate Stone short_option); 1185de164aaaSGreg Clayton break; 1186de164aaaSGreg Clayton } 1187de164aaaSGreg Clayton 1188de164aaaSGreg Clayton return error; 1189de164aaaSGreg Clayton } 1190de164aaaSGreg Clayton 1191b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1192de164aaaSGreg Clayton m_help.clear(); 1193de164aaaSGreg Clayton m_syntax.clear(); 1194de164aaaSGreg Clayton } 1195de164aaaSGreg Clayton 11961f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 119770602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 11981f0f5b5bSZachary Turner } 1199de164aaaSGreg Clayton 120011eb9c64SZachary Turner // TODO: Convert these functions to return StringRefs. 1201b9c1b51eSKate Stone const char *GetHelp() { 12026e3d8e7fSEugene Zelenko return (m_help.empty() ? nullptr : m_help.c_str()); 1203de164aaaSGreg Clayton } 12046e3d8e7fSEugene Zelenko 1205b9c1b51eSKate Stone const char *GetSyntax() { 12066e3d8e7fSEugene Zelenko return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1207de164aaaSGreg Clayton } 12086e3d8e7fSEugene Zelenko 1209de164aaaSGreg Clayton protected: 12106e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 12116e3d8e7fSEugene Zelenko 1212de164aaaSGreg Clayton std::string m_help; 1213de164aaaSGreg Clayton std::string m_syntax; 1214de164aaaSGreg Clayton }; 1215de164aaaSGreg Clayton 1216b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1217de164aaaSGreg Clayton 12185a988416SJim Ingham CommandOptions m_options; 1219de164aaaSGreg Clayton }; 1220de164aaaSGreg Clayton 1221b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1222223383edSEnrico Granata public: 1223b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1224b9c1b51eSKate Stone std::string funct, std::string help, 1225b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1226a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1227b9c1b51eSKate Stone m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { 1228735152e3SEnrico Granata if (!help.empty()) 1229442f6530SZachary Turner SetHelp(help); 1230b9c1b51eSKate Stone else { 1231735152e3SEnrico Granata StreamString stream; 1232735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1233c156427dSZachary Turner SetHelp(stream.GetString()); 1234735152e3SEnrico Granata } 1235223383edSEnrico Granata } 1236223383edSEnrico Granata 12376e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1238223383edSEnrico Granata 1239b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 12405a988416SJim Ingham 1241b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 12425a988416SJim Ingham 1243b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 12445a988416SJim Ingham 1245442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1246442f6530SZachary Turner if (m_fetched_help_long) 1247442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1248442f6530SZachary Turner 1249*2b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1250442f6530SZachary Turner if (!scripter) 1251442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1252442f6530SZachary Turner 1253fac939e9SEnrico Granata std::string docstring; 1254442f6530SZachary Turner m_fetched_help_long = 1255442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1256fac939e9SEnrico Granata if (!docstring.empty()) 1257442f6530SZachary Turner SetHelpLong(docstring); 1258fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1259fac939e9SEnrico Granata } 1260fac939e9SEnrico Granata 12615a988416SJim Ingham protected: 12624d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1263b9c1b51eSKate Stone CommandReturnObject &result) override { 1264*2b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1265223383edSEnrico Granata 126697206d57SZachary Turner Status error; 1267223383edSEnrico Granata 126870f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 126970f11f88SJim Ingham 1270b9c1b51eSKate Stone if (!scripter || 1271b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1272b9c1b51eSKate Stone raw_command_line, m_synchro, result, 1273b9c1b51eSKate Stone error, m_exe_ctx)) { 1274223383edSEnrico Granata result.AppendError(error.AsCString()); 1275223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1276b9c1b51eSKate Stone } else { 127770f11f88SJim Ingham // Don't change the status if the command already set it... 1278b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1279c156427dSZachary Turner if (result.GetOutputData().empty()) 1280223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 128170f11f88SJim Ingham else 128270f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 128370f11f88SJim Ingham } 128470f11f88SJim Ingham } 1285223383edSEnrico Granata 1286223383edSEnrico Granata return result.Succeeded(); 1287223383edSEnrico Granata } 1288223383edSEnrico Granata 12896e3d8e7fSEugene Zelenko private: 12906e3d8e7fSEugene Zelenko std::string m_function_name; 12916e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 12926e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1293223383edSEnrico Granata }; 1294223383edSEnrico Granata 1295b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 12969fe00e52SEnrico Granata public: 12979fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 12989fe00e52SEnrico Granata std::string name, 12990641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1300b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1301a449698cSZachary Turner : CommandObjectRaw(interpreter, name), 1302b9c1b51eSKate Stone m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), 1303b9c1b51eSKate Stone m_fetched_help_long(false) { 13049fe00e52SEnrico Granata StreamString stream; 13059fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1306c156427dSZachary Turner SetHelp(stream.GetString()); 1307*2b29b432SJonas Devlieghere if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) 1308e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 13099fe00e52SEnrico Granata } 13109fe00e52SEnrico Granata 13116e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 13129fe00e52SEnrico Granata 1313b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 13149fe00e52SEnrico Granata 1315b9c1b51eSKate Stone StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } 13169fe00e52SEnrico Granata 1317b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 13189fe00e52SEnrico Granata 1319442f6530SZachary Turner llvm::StringRef GetHelp() override { 1320442f6530SZachary Turner if (m_fetched_help_short) 1321442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 1322*2b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1323442f6530SZachary Turner if (!scripter) 1324442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 13256f79bb2dSEnrico Granata std::string docstring; 1326b9c1b51eSKate Stone m_fetched_help_short = 1327b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 13286f79bb2dSEnrico Granata if (!docstring.empty()) 1329442f6530SZachary Turner SetHelp(docstring); 1330442f6530SZachary Turner 13316f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 13326f79bb2dSEnrico Granata } 13336f79bb2dSEnrico Granata 1334442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1335442f6530SZachary Turner if (m_fetched_help_long) 1336442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1337442f6530SZachary Turner 1338*2b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1339442f6530SZachary Turner if (!scripter) 1340442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1341442f6530SZachary Turner 13426f79bb2dSEnrico Granata std::string docstring; 1343b9c1b51eSKate Stone m_fetched_help_long = 1344b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 13456f79bb2dSEnrico Granata if (!docstring.empty()) 1346442f6530SZachary Turner SetHelpLong(docstring); 13479fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 13489fe00e52SEnrico Granata } 13499fe00e52SEnrico Granata 13509fe00e52SEnrico Granata protected: 13514d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1352b9c1b51eSKate Stone CommandReturnObject &result) override { 1353*2b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 13549fe00e52SEnrico Granata 135597206d57SZachary Turner Status error; 13569fe00e52SEnrico Granata 13579fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 13589fe00e52SEnrico Granata 1359b9c1b51eSKate Stone if (!scripter || 1360b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1361b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 13629fe00e52SEnrico Granata result.AppendError(error.AsCString()); 13639fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1364b9c1b51eSKate Stone } else { 13659fe00e52SEnrico Granata // Don't change the status if the command already set it... 1366b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1367c156427dSZachary Turner if (result.GetOutputData().empty()) 13689fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 13699fe00e52SEnrico Granata else 13709fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 13719fe00e52SEnrico Granata } 13729fe00e52SEnrico Granata } 13739fe00e52SEnrico Granata 13749fe00e52SEnrico Granata return result.Succeeded(); 13759fe00e52SEnrico Granata } 13769fe00e52SEnrico Granata 13776e3d8e7fSEugene Zelenko private: 13786e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 13796e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 13806e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 13816e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 13829fe00e52SEnrico Granata }; 13839fe00e52SEnrico Granata 1384a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 1385a9dbf432SEnrico Granata 13868fe53c49STatyana Krasnukha static constexpr OptionDefinition g_script_import_options[] = { 13871f0f5b5bSZachary Turner // clang-format off 13888fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, 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." }, 13891f0f5b5bSZachary Turner // clang-format on 13901f0f5b5bSZachary Turner }; 13911f0f5b5bSZachary Turner 1392b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 13935a988416SJim Ingham public: 1394b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1395b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1396b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1397b9c1b51eSKate Stone m_options() { 13985a988416SJim Ingham CommandArgumentEntry arg1; 13995a988416SJim Ingham CommandArgumentData cmd_arg; 14005a988416SJim Ingham 14015a988416SJim Ingham // Define the first (and only) variant of this arg. 14025a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 14033b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 14045a988416SJim Ingham 1405b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1406b9c1b51eSKate Stone // argument entry. 14075a988416SJim Ingham arg1.push_back(cmd_arg); 14085a988416SJim Ingham 14095a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 14105a988416SJim Ingham m_arguments.push_back(arg1); 14115a988416SJim Ingham } 14125a988416SJim Ingham 14136e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 14145a988416SJim Ingham 14152443bbd4SRaphael Isemann int HandleArgumentCompletion( 14162443bbd4SRaphael Isemann CompletionRequest &request, 14172443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 1418b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1419b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1420a2e76c0bSRaphael Isemann request, nullptr); 14211a6d7ab5SRaphael Isemann return request.GetNumberOfMatches(); 14225a988416SJim Ingham } 14235a988416SJim Ingham 1424b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14255a988416SJim Ingham 14265a988416SJim Ingham protected: 1427b9c1b51eSKate Stone class CommandOptions : public Options { 14280a305db7SEnrico Granata public: 1429b9c1b51eSKate Stone CommandOptions() : Options() {} 14300a305db7SEnrico Granata 14316e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 14320a305db7SEnrico Granata 143397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1434b9c1b51eSKate Stone ExecutionContext *execution_context) override { 143597206d57SZachary Turner Status error; 14363bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14370a305db7SEnrico Granata 1438b9c1b51eSKate Stone switch (short_option) { 14390a305db7SEnrico Granata case 'r': 14400a305db7SEnrico Granata m_allow_reload = true; 14410a305db7SEnrico Granata break; 14420a305db7SEnrico Granata default: 1443b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1444b9c1b51eSKate Stone short_option); 14450a305db7SEnrico Granata break; 14460a305db7SEnrico Granata } 14470a305db7SEnrico Granata 14480a305db7SEnrico Granata return error; 14490a305db7SEnrico Granata } 14500a305db7SEnrico Granata 1451b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1452e0c70f1bSEnrico Granata m_allow_reload = true; 14530a305db7SEnrico Granata } 14540a305db7SEnrico Granata 14551f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 145670602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 14571f0f5b5bSZachary Turner } 14580a305db7SEnrico Granata 14590a305db7SEnrico Granata // Instance variables to hold the values for command options. 14600a305db7SEnrico Granata 14610a305db7SEnrico Granata bool m_allow_reload; 14620a305db7SEnrico Granata }; 14630a305db7SEnrico Granata 1464b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1465b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1466b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1467b9c1b51eSKate Stone result.AppendError("only scripting language supported for module " 1468b9c1b51eSKate Stone "importing is currently Python"); 1469a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1470a9dbf432SEnrico Granata return false; 1471a9dbf432SEnrico Granata } 1472a9dbf432SEnrico Granata 147311eb9c64SZachary Turner if (command.empty()) { 14743b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1475a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1476a9dbf432SEnrico Granata return false; 1477a9dbf432SEnrico Granata } 1478a9dbf432SEnrico Granata 147911eb9c64SZachary Turner for (auto &entry : command.entries()) { 148097206d57SZachary Turner Status error; 1481a9dbf432SEnrico Granata 1482c9d645d3SGreg Clayton const bool init_session = true; 1483b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 148411eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 148511eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 148605097246SAdrian Prantl // script imports" in __lldb_init_module the real fix is to have 148705097246SAdrian Prantl // recursive commands possible with a CommandInvocation object separate 148805097246SAdrian Prantl // from the CommandObject itself, so that recursive command invocations 148905097246SAdrian Prantl // won't stomp on each other (wrt to execution contents, options, and 149005097246SAdrian Prantl // more) 1491078551c7SEnrico Granata m_exe_ctx.Clear(); 1492*2b29b432SJonas Devlieghere if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule( 149311eb9c64SZachary Turner entry.c_str(), m_options.m_allow_reload, init_session, error)) { 1494a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1495b9c1b51eSKate Stone } else { 1496b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1497b9c1b51eSKate Stone error.AsCString()); 1498a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1499a9dbf432SEnrico Granata } 15003b00e35bSEnrico Granata } 1501a9dbf432SEnrico Granata 1502a9dbf432SEnrico Granata return result.Succeeded(); 1503a9dbf432SEnrico Granata } 15040a305db7SEnrico Granata 15055a988416SJim Ingham CommandOptions m_options; 1506a9dbf432SEnrico Granata }; 1507223383edSEnrico Granata 1508223383edSEnrico Granata // CommandObjectCommandsScriptAdd 15098fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_script_synchro_type[] = { 15101f0f5b5bSZachary Turner {eScriptedCommandSynchronicitySynchronous, "synchronous", 15111f0f5b5bSZachary Turner "Run synchronous"}, 15121f0f5b5bSZachary Turner {eScriptedCommandSynchronicityAsynchronous, "asynchronous", 15131f0f5b5bSZachary Turner "Run asynchronous"}, 15141f0f5b5bSZachary Turner {eScriptedCommandSynchronicityCurrentValue, "current", 15158fe53c49STatyana Krasnukha "Do not alter current setting"} }; 15161f0f5b5bSZachary Turner 15178fe53c49STatyana Krasnukha static constexpr OptionEnumValues ScriptSynchroType() { 15188fe53c49STatyana Krasnukha return OptionEnumValues(g_script_synchro_type); 15198fe53c49STatyana Krasnukha } 15208fe53c49STatyana Krasnukha 15218fe53c49STatyana Krasnukha static constexpr OptionDefinition g_script_add_options[] = { 15221f0f5b5bSZachary Turner // clang-format off 15238fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, 15248fe53c49STatyana Krasnukha { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, 15258fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." }, 15268fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, 15271f0f5b5bSZachary Turner // clang-format on 15281f0f5b5bSZachary Turner }; 15291f0f5b5bSZachary Turner 1530b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1531b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 15325a988416SJim Ingham public: 1533b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1534b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 15355a988416SJim Ingham "Add a scripted function as an LLDB command.", 15366e3d8e7fSEugene Zelenko nullptr), 1537b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 15385a988416SJim Ingham CommandArgumentEntry arg1; 15395a988416SJim Ingham CommandArgumentData cmd_arg; 15405a988416SJim Ingham 15415a988416SJim Ingham // Define the first (and only) variant of this arg. 15425a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 15435a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 15445a988416SJim Ingham 1545b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1546b9c1b51eSKate Stone // argument entry. 15475a988416SJim Ingham arg1.push_back(cmd_arg); 15485a988416SJim Ingham 15495a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 15505a988416SJim Ingham m_arguments.push_back(arg1); 15515a988416SJim Ingham } 15525a988416SJim Ingham 15536e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 15545a988416SJim Ingham 1555b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 15565a988416SJim Ingham 15575a988416SJim Ingham protected: 1558b9c1b51eSKate Stone class CommandOptions : public Options { 1559223383edSEnrico Granata public: 1560b9c1b51eSKate Stone CommandOptions() 1561b9c1b51eSKate Stone : Options(), m_class_name(), m_funct_name(), m_short_help(), 1562b9c1b51eSKate Stone m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1563223383edSEnrico Granata 15646e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1565223383edSEnrico Granata 156697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1567b9c1b51eSKate Stone ExecutionContext *execution_context) override { 156897206d57SZachary Turner Status error; 15693bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1570223383edSEnrico Granata 1571b9c1b51eSKate Stone switch (short_option) { 1572223383edSEnrico Granata case 'f': 1573fe11483bSZachary Turner if (!option_arg.empty()) 1574fe11483bSZachary Turner m_funct_name = option_arg; 1575735152e3SEnrico Granata break; 15769fe00e52SEnrico Granata case 'c': 1577fe11483bSZachary Turner if (!option_arg.empty()) 1578fe11483bSZachary Turner m_class_name = option_arg; 15799fe00e52SEnrico Granata break; 1580735152e3SEnrico Granata case 'h': 1581fe11483bSZachary Turner if (!option_arg.empty()) 1582fe11483bSZachary Turner m_short_help = option_arg; 1583223383edSEnrico Granata break; 15840a305db7SEnrico Granata case 's': 1585b9c1b51eSKate Stone m_synchronicity = 158647cbf4a0SPavel Labath (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum( 1587fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 15880a305db7SEnrico Granata if (!error.Success()) 1589b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1590fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1591fe11483bSZachary Turner option_arg.str().c_str()); 15920a305db7SEnrico Granata break; 1593223383edSEnrico Granata default: 1594b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1595b9c1b51eSKate Stone short_option); 1596223383edSEnrico Granata break; 1597223383edSEnrico Granata } 1598223383edSEnrico Granata 1599223383edSEnrico Granata return error; 1600223383edSEnrico Granata } 1601223383edSEnrico Granata 1602b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16039fe00e52SEnrico Granata m_class_name.clear(); 1604735152e3SEnrico Granata m_funct_name.clear(); 1605735152e3SEnrico Granata m_short_help.clear(); 160644d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1607223383edSEnrico Granata } 1608223383edSEnrico Granata 16091f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 161070602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 16111f0f5b5bSZachary Turner } 1612223383edSEnrico Granata 1613223383edSEnrico Granata // Instance variables to hold the values for command options. 1614223383edSEnrico Granata 16159fe00e52SEnrico Granata std::string m_class_name; 1616223383edSEnrico Granata std::string m_funct_name; 1617735152e3SEnrico Granata std::string m_short_help; 161844d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1619223383edSEnrico Granata }; 1620223383edSEnrico Granata 16210affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 162244d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 16230affb582SDave Lee if (output_sp && interactive) { 162444d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 162544d93782SGreg Clayton output_sp->Flush(); 1626223383edSEnrico Granata } 1627223383edSEnrico Granata } 1628223383edSEnrico Granata 1629b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1630b9c1b51eSKate Stone std::string &data) override { 163144d93782SGreg Clayton StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 163244d93782SGreg Clayton 1633*2b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1634b9c1b51eSKate Stone if (interpreter) { 163544d93782SGreg Clayton 163644d93782SGreg Clayton StringList lines; 163744d93782SGreg Clayton lines.SplitIntoLines(data); 1638b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1639a73b7df7SEnrico Granata std::string funct_name_str; 1640b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1641b9c1b51eSKate Stone if (funct_name_str.empty()) { 1642b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1643b9c1b51eSKate Stone "add python command.\n"); 164444d93782SGreg Clayton error_sp->Flush(); 1645b9c1b51eSKate Stone } else { 1646223383edSEnrico Granata // everything should be fine now, let's add this alias 1647223383edSEnrico Granata 1648b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1649771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 165044d93782SGreg Clayton m_synchronicity)); 1651223383edSEnrico Granata 1652b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1653b9c1b51eSKate Stone true)) { 1654b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1655b9c1b51eSKate Stone "add python command.\n"); 165644d93782SGreg Clayton error_sp->Flush(); 1657223383edSEnrico Granata } 1658223383edSEnrico Granata } 1659b9c1b51eSKate Stone } else { 1660b9c1b51eSKate Stone error_sp->Printf( 1661b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 166244d93782SGreg Clayton error_sp->Flush(); 166344d93782SGreg Clayton } 1664b9c1b51eSKate Stone } else { 166544d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 166644d93782SGreg Clayton error_sp->Flush(); 166744d93782SGreg Clayton } 1668b9c1b51eSKate Stone } else { 1669b9c1b51eSKate Stone error_sp->Printf( 1670b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 167144d93782SGreg Clayton error_sp->Flush(); 167244d93782SGreg Clayton } 167344d93782SGreg Clayton 167444d93782SGreg Clayton io_handler.SetIsDone(true); 167544d93782SGreg Clayton } 1676223383edSEnrico Granata 16775a988416SJim Ingham protected: 1678b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1679b9c1b51eSKate Stone if (m_interpreter.GetDebugger().GetScriptLanguage() != 1680b9c1b51eSKate Stone lldb::eScriptLanguagePython) { 1681b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1682b9c1b51eSKate Stone "commands is currently Python"); 168399f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 168499f0b8f9SEnrico Granata return false; 168599f0b8f9SEnrico Granata } 168699f0b8f9SEnrico Granata 168711eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1688223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1689223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1690223383edSEnrico Granata return false; 1691223383edSEnrico Granata } 1692223383edSEnrico Granata 1693735152e3SEnrico Granata // Store the options in case we get multi-line input 16944574a890SZachary Turner m_cmd_name = command[0].ref; 1695735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 169644d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1697223383edSEnrico Granata 1698b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1699b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1700b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1701b9c1b51eSKate Stone " ", // Prompt 170244d93782SGreg Clayton *this, // IOHandlerDelegate 170344d93782SGreg Clayton true, // Run IOHandler in async mode 1704b9c1b51eSKate Stone nullptr); // Baton for the "io_handler" that will be passed back 1705b9c1b51eSKate Stone // into our IOHandlerDelegate functions 1706b9c1b51eSKate Stone } else { 1707b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1708b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1709b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1710b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1711223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1712b9c1b51eSKate Stone } else { 1713223383edSEnrico Granata result.AppendError("cannot add command"); 1714223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1715223383edSEnrico Granata } 1716223383edSEnrico Granata } 1717b9c1b51eSKate Stone } else { 1718*2b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1719b9c1b51eSKate Stone if (!interpreter) { 17209fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 17219fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17229fe00e52SEnrico Granata return false; 17239fe00e52SEnrico Granata } 17249fe00e52SEnrico Granata 1725b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1726b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1727b9c1b51eSKate Stone if (!cmd_obj_sp) { 17289fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 17299fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17309fe00e52SEnrico Granata return false; 17319fe00e52SEnrico Granata } 17329fe00e52SEnrico Granata 1733b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1734b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1735b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 17369fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1737b9c1b51eSKate Stone } else { 17389fe00e52SEnrico Granata result.AppendError("cannot add command"); 17399fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 17409fe00e52SEnrico Granata } 17419fe00e52SEnrico Granata } 1742223383edSEnrico Granata 1743223383edSEnrico Granata return result.Succeeded(); 1744223383edSEnrico Granata } 17455a988416SJim Ingham 17465a988416SJim Ingham CommandOptions m_options; 174744d93782SGreg Clayton std::string m_cmd_name; 1748735152e3SEnrico Granata std::string m_short_help; 174944d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1750223383edSEnrico Granata }; 1751223383edSEnrico Granata 1752223383edSEnrico Granata // CommandObjectCommandsScriptList 1753223383edSEnrico Granata 1754b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1755223383edSEnrico Granata public: 1756b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1757b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1758b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1759223383edSEnrico Granata 17606e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1761223383edSEnrico Granata 1762b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1763b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1764223383edSEnrico Granata 1765223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1766223383edSEnrico Granata 1767223383edSEnrico Granata return true; 1768223383edSEnrico Granata } 1769223383edSEnrico Granata }; 1770223383edSEnrico Granata 1771223383edSEnrico Granata // CommandObjectCommandsScriptClear 1772223383edSEnrico Granata 1773b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1774223383edSEnrico Granata public: 1775b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1776b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1777b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1778223383edSEnrico Granata 17796e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1780223383edSEnrico Granata 17815a988416SJim Ingham protected: 1782b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1783223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1784223383edSEnrico Granata 1785223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1786223383edSEnrico Granata 1787223383edSEnrico Granata return true; 1788223383edSEnrico Granata } 1789223383edSEnrico Granata }; 1790223383edSEnrico Granata 1791223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1792223383edSEnrico Granata 1793b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1794223383edSEnrico Granata public: 1795b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1796b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1797b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1798223383edSEnrico Granata CommandArgumentEntry arg1; 1799223383edSEnrico Granata CommandArgumentData cmd_arg; 1800223383edSEnrico Granata 1801223383edSEnrico Granata // Define the first (and only) variant of this arg. 1802223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1803223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1804223383edSEnrico Granata 1805b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1806b9c1b51eSKate Stone // argument entry. 1807223383edSEnrico Granata arg1.push_back(cmd_arg); 1808223383edSEnrico Granata 1809223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1810223383edSEnrico Granata m_arguments.push_back(arg1); 1811223383edSEnrico Granata } 1812223383edSEnrico Granata 18136e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1814223383edSEnrico Granata 18155a988416SJim Ingham protected: 1816b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1817223383edSEnrico Granata 181811eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1819223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1820223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1821223383edSEnrico Granata return false; 1822223383edSEnrico Granata } 1823223383edSEnrico Granata 18244574a890SZachary Turner auto cmd_name = command[0].ref; 1825223383edSEnrico Granata 18264574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 18274574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1828867e7d17SZachary Turner result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1829223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 18304574a890SZachary Turner return false; 1831223383edSEnrico Granata } 1832223383edSEnrico Granata 18334574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 18344574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 18354574a890SZachary Turner return true; 1836223383edSEnrico Granata } 1837223383edSEnrico Granata }; 1838223383edSEnrico Granata 1839223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1840223383edSEnrico Granata 1841223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1842223383edSEnrico Granata 1843b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1844223383edSEnrico Granata public: 18457428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1846b9c1b51eSKate Stone : CommandObjectMultiword( 1847b9c1b51eSKate Stone interpreter, "command script", "Commands for managing custom " 1848b9c1b51eSKate Stone "commands implemented by " 1849b9c1b51eSKate Stone "interpreter scripts.", 1850b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1851b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1852b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1853b9c1b51eSKate Stone LoadSubCommand( 1854b9c1b51eSKate Stone "delete", 1855b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1856b9c1b51eSKate Stone LoadSubCommand( 1857b9c1b51eSKate Stone "clear", 1858b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1859b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1860b9c1b51eSKate Stone interpreter))); 1861b9c1b51eSKate Stone LoadSubCommand( 1862b9c1b51eSKate Stone "import", 1863b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1864223383edSEnrico Granata } 1865223383edSEnrico Granata 18666e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1867223383edSEnrico Granata }; 1868223383edSEnrico Granata 1869ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1870ebc09c36SJim Ingham 1871ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1872ebc09c36SJim Ingham 1873b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1874b9c1b51eSKate Stone CommandInterpreter &interpreter) 1875b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1876b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1877b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1878b9c1b51eSKate Stone LoadSubCommand("source", 1879b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1880b9c1b51eSKate Stone LoadSubCommand("alias", 1881b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1882b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1883b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1884b9c1b51eSKate Stone LoadSubCommand("delete", 1885b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1886b9c1b51eSKate Stone LoadSubCommand( 1887b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1888b9c1b51eSKate Stone LoadSubCommand("history", CommandObjectSP( 1889b9c1b51eSKate Stone new CommandObjectCommandsHistory(interpreter))); 1890b9c1b51eSKate Stone LoadSubCommand( 1891b9c1b51eSKate Stone "script", 1892b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1893ebc09c36SJim Ingham } 1894ebc09c36SJim Ingham 18956e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1896