267 lines · cpp
1//===-- CommandObjectScripting.cpp ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "CommandObjectScripting.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/PluginManager.h"12#include "lldb/DataFormatters/DataVisualization.h"13#include "lldb/Host/Config.h"14#include "lldb/Host/OptionParser.h"15#include "lldb/Interpreter/CommandInterpreter.h"16#include "lldb/Interpreter/CommandOptionArgumentTable.h"17#include "lldb/Interpreter/CommandReturnObject.h"18#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"19#include "lldb/Interpreter/OptionArgParser.h"20#include "lldb/Interpreter/ScriptInterpreter.h"21#include "lldb/Utility/Args.h"22 23using namespace lldb;24using namespace lldb_private;25 26#define LLDB_OPTIONS_scripting_run27#include "CommandOptions.inc"28 29class CommandObjectScriptingRun : public CommandObjectRaw {30public:31 CommandObjectScriptingRun(CommandInterpreter &interpreter)32 : CommandObjectRaw(33 interpreter, "scripting run",34 "Invoke the script interpreter with provided code and display any "35 "results. Start the interactive interpreter if no code is "36 "supplied.",37 "scripting run [--language <scripting-language> --] "38 "[<script-code>]") {}39 40 ~CommandObjectScriptingRun() override = default;41 42 Options *GetOptions() override { return &m_options; }43 44 class CommandOptions : public Options {45 public:46 CommandOptions() = default;47 ~CommandOptions() override = default;48 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,49 ExecutionContext *execution_context) override {50 Status error;51 const int short_option = m_getopt_table[option_idx].val;52 53 switch (short_option) {54 case 'l':55 language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(56 option_arg, GetDefinitions()[option_idx].enum_values,57 eScriptLanguageNone, error);58 if (!error.Success())59 error = Status::FromErrorStringWithFormat(60 "unrecognized value for language '%s'", option_arg.str().c_str());61 break;62 default:63 llvm_unreachable("Unimplemented option");64 }65 66 return error;67 }68 69 void OptionParsingStarting(ExecutionContext *execution_context) override {70 language = lldb::eScriptLanguageNone;71 }72 73 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {74 return llvm::ArrayRef(g_scripting_run_options);75 }76 77 lldb::ScriptLanguage language = lldb::eScriptLanguageNone;78 };79 80protected:81 void DoExecute(llvm::StringRef command,82 CommandReturnObject &result) override {83 // Try parsing the language option but when the command contains a raw part84 // separated by the -- delimiter.85 OptionsWithRaw raw_args(command);86 if (raw_args.HasArgs()) {87 if (!ParseOptions(raw_args.GetArgs(), result))88 return;89 command = raw_args.GetRawPart();90 }91 92 lldb::ScriptLanguage language =93 (m_options.language == lldb::eScriptLanguageNone)94 ? m_interpreter.GetDebugger().GetScriptLanguage()95 : m_options.language;96 97 if (language == lldb::eScriptLanguageNone) {98 result.AppendError(99 "the script-lang setting is set to none - scripting not available");100 return;101 }102 103 ScriptInterpreter *script_interpreter =104 GetDebugger().GetScriptInterpreter(true, language);105 106 if (script_interpreter == nullptr) {107 result.AppendError("no script interpreter");108 return;109 }110 111 // Script might change Python code we use for formatting. Make sure we keep112 // up to date with it.113 DataVisualization::ForceUpdate();114 115 if (command.empty()) {116 script_interpreter->ExecuteInterpreterLoop();117 result.SetStatus(eReturnStatusSuccessFinishNoResult);118 return;119 }120 121 // We can do better when reporting the status of one-liner script execution.122 if (script_interpreter->ExecuteOneLine(command, &result))123 result.SetStatus(eReturnStatusSuccessFinishNoResult);124 else125 result.SetStatus(eReturnStatusFailed);126 }127 128private:129 CommandOptions m_options;130};131 132#define LLDB_OPTIONS_scripting_extension_list133#include "CommandOptions.inc"134 135class CommandObjectScriptingExtensionList : public CommandObjectParsed {136public:137 CommandObjectScriptingExtensionList(CommandInterpreter &interpreter)138 : CommandObjectParsed(139 interpreter, "scripting extension list",140 "List all the available scripting extension templates. ",141 "scripting template list [--language <scripting-language> --]") {}142 143 ~CommandObjectScriptingExtensionList() override = default;144 145 Options *GetOptions() override { return &m_options; }146 147 class CommandOptions : public Options {148 public:149 CommandOptions() = default;150 ~CommandOptions() override = default;151 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,152 ExecutionContext *execution_context) override {153 Status error;154 const int short_option = m_getopt_table[option_idx].val;155 156 switch (short_option) {157 case 'l':158 m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(159 option_arg, GetDefinitions()[option_idx].enum_values,160 eScriptLanguageNone, error);161 if (!error.Success())162 error = Status::FromErrorStringWithFormatv(163 "unrecognized value for language '{0}'", option_arg);164 break;165 default:166 llvm_unreachable("Unimplemented option");167 }168 169 return error;170 }171 172 void OptionParsingStarting(ExecutionContext *execution_context) override {173 m_language = lldb::eScriptLanguageDefault;174 }175 176 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {177 return llvm::ArrayRef(g_scripting_extension_list_options);178 }179 180 lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;181 };182 183protected:184 void DoExecute(Args &command, CommandReturnObject &result) override {185 Stream &s = result.GetOutputStream();186 s.Printf("Available scripted extension templates:");187 188 auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) {189 if (!value.empty()) {190 s.IndentMore();191 s.Indent();192 s << key << ": " << value << '\n';193 s.IndentLess();194 }195 };196 197 size_t num_listed_interface = 0;198 size_t num_extensions = PluginManager::GetNumScriptedInterfaces();199 for (size_t i = 0; i < num_extensions; i++) {200 llvm::StringRef plugin_name =201 PluginManager::GetScriptedInterfaceNameAtIndex(i);202 if (plugin_name.empty())203 break;204 205 lldb::ScriptLanguage lang =206 PluginManager::GetScriptedInterfaceLanguageAtIndex(i);207 if (lang != m_options.m_language)208 continue;209 210 if (!num_listed_interface)211 s.EOL();212 213 num_listed_interface++;214 215 llvm::StringRef desc =216 PluginManager::GetScriptedInterfaceDescriptionAtIndex(i);217 ScriptedInterfaceUsages usages =218 PluginManager::GetScriptedInterfaceUsagesAtIndex(i);219 220 print_field("Name", plugin_name);221 print_field("Language", ScriptInterpreter::LanguageToString(lang));222 print_field("Description", desc);223 usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API);224 usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter);225 226 if (i != num_extensions - 1)227 s.EOL();228 }229 230 if (!num_listed_interface)231 s << " None\n";232 }233 234private:235 CommandOptions m_options;236};237 238class CommandObjectMultiwordScriptingExtension : public CommandObjectMultiword {239public:240 CommandObjectMultiwordScriptingExtension(CommandInterpreter &interpreter)241 : CommandObjectMultiword(242 interpreter, "scripting extension",243 "Commands for operating on the scripting extensions.",244 "scripting extension [<subcommand-options>]") {245 LoadSubCommand(246 "list",247 CommandObjectSP(new CommandObjectScriptingExtensionList(interpreter)));248 }249 250 ~CommandObjectMultiwordScriptingExtension() override = default;251};252 253CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(254 CommandInterpreter &interpreter)255 : CommandObjectMultiword(256 interpreter, "scripting",257 "Commands for operating on the scripting functionalities.",258 "scripting <subcommand> [<subcommand-options>]") {259 LoadSubCommand("run",260 CommandObjectSP(new CommandObjectScriptingRun(interpreter)));261 LoadSubCommand("extension",262 CommandObjectSP(new CommandObjectMultiwordScriptingExtension(263 interpreter)));264}265 266CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;267