1410de0c8SMed Ismail Bennani //===-- CommandObjectScripting.cpp ----------------------------------------===// 2410de0c8SMed Ismail Bennani // 3410de0c8SMed Ismail Bennani // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4410de0c8SMed Ismail Bennani // See https://llvm.org/LICENSE.txt for license information. 5410de0c8SMed Ismail Bennani // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6410de0c8SMed Ismail Bennani // 7410de0c8SMed Ismail Bennani //===----------------------------------------------------------------------===// 8410de0c8SMed Ismail Bennani 9410de0c8SMed Ismail Bennani #include "CommandObjectScripting.h" 10410de0c8SMed Ismail Bennani #include "lldb/Core/Debugger.h" 11bccff3baSMed Ismail Bennani #include "lldb/Core/PluginManager.h" 12410de0c8SMed Ismail Bennani #include "lldb/DataFormatters/DataVisualization.h" 13410de0c8SMed Ismail Bennani #include "lldb/Host/Config.h" 14410de0c8SMed Ismail Bennani #include "lldb/Host/OptionParser.h" 15410de0c8SMed Ismail Bennani #include "lldb/Interpreter/CommandInterpreter.h" 16410de0c8SMed Ismail Bennani #include "lldb/Interpreter/CommandOptionArgumentTable.h" 17410de0c8SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h" 18bccff3baSMed Ismail Bennani #include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h" 19410de0c8SMed Ismail Bennani #include "lldb/Interpreter/OptionArgParser.h" 20410de0c8SMed Ismail Bennani #include "lldb/Interpreter/ScriptInterpreter.h" 21410de0c8SMed Ismail Bennani #include "lldb/Utility/Args.h" 22410de0c8SMed Ismail Bennani 23410de0c8SMed Ismail Bennani using namespace lldb; 24410de0c8SMed Ismail Bennani using namespace lldb_private; 25410de0c8SMed Ismail Bennani 26410de0c8SMed Ismail Bennani #define LLDB_OPTIONS_scripting_run 27410de0c8SMed Ismail Bennani #include "CommandOptions.inc" 28410de0c8SMed Ismail Bennani 29410de0c8SMed Ismail Bennani class CommandObjectScriptingRun : public CommandObjectRaw { 30410de0c8SMed Ismail Bennani public: 31410de0c8SMed Ismail Bennani CommandObjectScriptingRun(CommandInterpreter &interpreter) 32410de0c8SMed Ismail Bennani : CommandObjectRaw( 33410de0c8SMed Ismail Bennani interpreter, "scripting run", 34410de0c8SMed Ismail Bennani "Invoke the script interpreter with provided code and display any " 35410de0c8SMed Ismail Bennani "results. Start the interactive interpreter if no code is " 36410de0c8SMed Ismail Bennani "supplied.", 37410de0c8SMed Ismail Bennani "scripting run [--language <scripting-language> --] " 38410de0c8SMed Ismail Bennani "[<script-code>]") {} 39410de0c8SMed Ismail Bennani 40410de0c8SMed Ismail Bennani ~CommandObjectScriptingRun() override = default; 41410de0c8SMed Ismail Bennani 42410de0c8SMed Ismail Bennani Options *GetOptions() override { return &m_options; } 43410de0c8SMed Ismail Bennani 44410de0c8SMed Ismail Bennani class CommandOptions : public Options { 45410de0c8SMed Ismail Bennani public: 46410de0c8SMed Ismail Bennani CommandOptions() = default; 47410de0c8SMed Ismail Bennani ~CommandOptions() override = default; 48410de0c8SMed Ismail Bennani Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 49410de0c8SMed Ismail Bennani ExecutionContext *execution_context) override { 50410de0c8SMed Ismail Bennani Status error; 51410de0c8SMed Ismail Bennani const int short_option = m_getopt_table[option_idx].val; 52410de0c8SMed Ismail Bennani 53410de0c8SMed Ismail Bennani switch (short_option) { 54410de0c8SMed Ismail Bennani case 'l': 55410de0c8SMed Ismail Bennani language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( 56410de0c8SMed Ismail Bennani option_arg, GetDefinitions()[option_idx].enum_values, 57410de0c8SMed Ismail Bennani eScriptLanguageNone, error); 58410de0c8SMed Ismail Bennani if (!error.Success()) 590642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 600642cd76SAdrian Prantl "unrecognized value for language '%s'", option_arg.str().c_str()); 61410de0c8SMed Ismail Bennani break; 62410de0c8SMed Ismail Bennani default: 63410de0c8SMed Ismail Bennani llvm_unreachable("Unimplemented option"); 64410de0c8SMed Ismail Bennani } 65410de0c8SMed Ismail Bennani 66410de0c8SMed Ismail Bennani return error; 67410de0c8SMed Ismail Bennani } 68410de0c8SMed Ismail Bennani 69410de0c8SMed Ismail Bennani void OptionParsingStarting(ExecutionContext *execution_context) override { 70410de0c8SMed Ismail Bennani language = lldb::eScriptLanguageNone; 71410de0c8SMed Ismail Bennani } 72410de0c8SMed Ismail Bennani 73410de0c8SMed Ismail Bennani llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 74410de0c8SMed Ismail Bennani return llvm::ArrayRef(g_scripting_run_options); 75410de0c8SMed Ismail Bennani } 76410de0c8SMed Ismail Bennani 77410de0c8SMed Ismail Bennani lldb::ScriptLanguage language = lldb::eScriptLanguageNone; 78410de0c8SMed Ismail Bennani }; 79410de0c8SMed Ismail Bennani 80410de0c8SMed Ismail Bennani protected: 81410de0c8SMed Ismail Bennani void DoExecute(llvm::StringRef command, 82410de0c8SMed Ismail Bennani CommandReturnObject &result) override { 83410de0c8SMed Ismail Bennani // Try parsing the language option but when the command contains a raw part 84410de0c8SMed Ismail Bennani // separated by the -- delimiter. 85410de0c8SMed Ismail Bennani OptionsWithRaw raw_args(command); 86410de0c8SMed Ismail Bennani if (raw_args.HasArgs()) { 87410de0c8SMed Ismail Bennani if (!ParseOptions(raw_args.GetArgs(), result)) 88410de0c8SMed Ismail Bennani return; 89410de0c8SMed Ismail Bennani command = raw_args.GetRawPart(); 90410de0c8SMed Ismail Bennani } 91410de0c8SMed Ismail Bennani 92410de0c8SMed Ismail Bennani lldb::ScriptLanguage language = 93410de0c8SMed Ismail Bennani (m_options.language == lldb::eScriptLanguageNone) 94410de0c8SMed Ismail Bennani ? m_interpreter.GetDebugger().GetScriptLanguage() 95410de0c8SMed Ismail Bennani : m_options.language; 96410de0c8SMed Ismail Bennani 97410de0c8SMed Ismail Bennani if (language == lldb::eScriptLanguageNone) { 98410de0c8SMed Ismail Bennani result.AppendError( 99410de0c8SMed Ismail Bennani "the script-lang setting is set to none - scripting not available"); 100410de0c8SMed Ismail Bennani return; 101410de0c8SMed Ismail Bennani } 102410de0c8SMed Ismail Bennani 103410de0c8SMed Ismail Bennani ScriptInterpreter *script_interpreter = 104410de0c8SMed Ismail Bennani GetDebugger().GetScriptInterpreter(true, language); 105410de0c8SMed Ismail Bennani 106410de0c8SMed Ismail Bennani if (script_interpreter == nullptr) { 107410de0c8SMed Ismail Bennani result.AppendError("no script interpreter"); 108410de0c8SMed Ismail Bennani return; 109410de0c8SMed Ismail Bennani } 110410de0c8SMed Ismail Bennani 111410de0c8SMed Ismail Bennani // Script might change Python code we use for formatting. Make sure we keep 112410de0c8SMed Ismail Bennani // up to date with it. 113410de0c8SMed Ismail Bennani DataVisualization::ForceUpdate(); 114410de0c8SMed Ismail Bennani 115410de0c8SMed Ismail Bennani if (command.empty()) { 116410de0c8SMed Ismail Bennani script_interpreter->ExecuteInterpreterLoop(); 117410de0c8SMed Ismail Bennani result.SetStatus(eReturnStatusSuccessFinishNoResult); 118410de0c8SMed Ismail Bennani return; 119410de0c8SMed Ismail Bennani } 120410de0c8SMed Ismail Bennani 121410de0c8SMed Ismail Bennani // We can do better when reporting the status of one-liner script execution. 122410de0c8SMed Ismail Bennani if (script_interpreter->ExecuteOneLine(command, &result)) 123410de0c8SMed Ismail Bennani result.SetStatus(eReturnStatusSuccessFinishNoResult); 124410de0c8SMed Ismail Bennani else 125410de0c8SMed Ismail Bennani result.SetStatus(eReturnStatusFailed); 126410de0c8SMed Ismail Bennani } 127410de0c8SMed Ismail Bennani 128410de0c8SMed Ismail Bennani private: 129410de0c8SMed Ismail Bennani CommandOptions m_options; 130410de0c8SMed Ismail Bennani }; 131410de0c8SMed Ismail Bennani 1325689ccceSMed Ismail Bennani #define LLDB_OPTIONS_scripting_extension_list 133bccff3baSMed Ismail Bennani #include "CommandOptions.inc" 134410de0c8SMed Ismail Bennani 1355689ccceSMed Ismail Bennani class CommandObjectScriptingExtensionList : public CommandObjectParsed { 136bccff3baSMed Ismail Bennani public: 1375689ccceSMed Ismail Bennani CommandObjectScriptingExtensionList(CommandInterpreter &interpreter) 138bccff3baSMed Ismail Bennani : CommandObjectParsed( 1395689ccceSMed Ismail Bennani interpreter, "scripting extension list", 140bccff3baSMed Ismail Bennani "List all the available scripting extension templates. ", 141bccff3baSMed Ismail Bennani "scripting template list [--language <scripting-language> --]") {} 142bccff3baSMed Ismail Bennani 1435689ccceSMed Ismail Bennani ~CommandObjectScriptingExtensionList() override = default; 144bccff3baSMed Ismail Bennani 145bccff3baSMed Ismail Bennani Options *GetOptions() override { return &m_options; } 146bccff3baSMed Ismail Bennani 147bccff3baSMed Ismail Bennani class CommandOptions : public Options { 148bccff3baSMed Ismail Bennani public: 149bccff3baSMed Ismail Bennani CommandOptions() = default; 150bccff3baSMed Ismail Bennani ~CommandOptions() override = default; 151bccff3baSMed Ismail Bennani Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 152bccff3baSMed Ismail Bennani ExecutionContext *execution_context) override { 153bccff3baSMed Ismail Bennani Status error; 154bccff3baSMed Ismail Bennani const int short_option = m_getopt_table[option_idx].val; 155bccff3baSMed Ismail Bennani 156bccff3baSMed Ismail Bennani switch (short_option) { 157bccff3baSMed Ismail Bennani case 'l': 158bccff3baSMed Ismail Bennani m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( 159bccff3baSMed Ismail Bennani option_arg, GetDefinitions()[option_idx].enum_values, 160bccff3baSMed Ismail Bennani eScriptLanguageNone, error); 161bccff3baSMed Ismail Bennani if (!error.Success()) 1620642cd76SAdrian Prantl error = Status::FromErrorStringWithFormatv( 163bccff3baSMed Ismail Bennani "unrecognized value for language '{0}'", option_arg); 164bccff3baSMed Ismail Bennani break; 165bccff3baSMed Ismail Bennani default: 166bccff3baSMed Ismail Bennani llvm_unreachable("Unimplemented option"); 167bccff3baSMed Ismail Bennani } 168bccff3baSMed Ismail Bennani 169bccff3baSMed Ismail Bennani return error; 170bccff3baSMed Ismail Bennani } 171bccff3baSMed Ismail Bennani 172bccff3baSMed Ismail Bennani void OptionParsingStarting(ExecutionContext *execution_context) override { 173bccff3baSMed Ismail Bennani m_language = lldb::eScriptLanguageDefault; 174bccff3baSMed Ismail Bennani } 175bccff3baSMed Ismail Bennani 176bccff3baSMed Ismail Bennani llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1775689ccceSMed Ismail Bennani return llvm::ArrayRef(g_scripting_extension_list_options); 178bccff3baSMed Ismail Bennani } 179bccff3baSMed Ismail Bennani 180bccff3baSMed Ismail Bennani lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault; 181bccff3baSMed Ismail Bennani }; 182bccff3baSMed Ismail Bennani 183bccff3baSMed Ismail Bennani protected: 184bccff3baSMed Ismail Bennani void DoExecute(Args &command, CommandReturnObject &result) override { 185bccff3baSMed Ismail Bennani Stream &s = result.GetOutputStream(); 186bccff3baSMed Ismail Bennani s.Printf("Available scripted extension templates:"); 187bccff3baSMed Ismail Bennani 188bccff3baSMed Ismail Bennani auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) { 189bccff3baSMed Ismail Bennani if (!value.empty()) { 190bccff3baSMed Ismail Bennani s.IndentMore(); 191bccff3baSMed Ismail Bennani s.Indent(); 192bccff3baSMed Ismail Bennani s << key << ": " << value << '\n'; 193bccff3baSMed Ismail Bennani s.IndentLess(); 194bccff3baSMed Ismail Bennani } 195bccff3baSMed Ismail Bennani }; 196bccff3baSMed Ismail Bennani 197bccff3baSMed Ismail Bennani size_t num_listed_interface = 0; 1985689ccceSMed Ismail Bennani size_t num_extensions = PluginManager::GetNumScriptedInterfaces(); 1995689ccceSMed Ismail Bennani for (size_t i = 0; i < num_extensions; i++) { 200bccff3baSMed Ismail Bennani llvm::StringRef plugin_name = 201bccff3baSMed Ismail Bennani PluginManager::GetScriptedInterfaceNameAtIndex(i); 202bccff3baSMed Ismail Bennani if (plugin_name.empty()) 203bccff3baSMed Ismail Bennani break; 204bccff3baSMed Ismail Bennani 205bccff3baSMed Ismail Bennani lldb::ScriptLanguage lang = 206bccff3baSMed Ismail Bennani PluginManager::GetScriptedInterfaceLanguageAtIndex(i); 207bccff3baSMed Ismail Bennani if (lang != m_options.m_language) 208bccff3baSMed Ismail Bennani continue; 209bccff3baSMed Ismail Bennani 210bccff3baSMed Ismail Bennani if (!num_listed_interface) 211bccff3baSMed Ismail Bennani s.EOL(); 212bccff3baSMed Ismail Bennani 213bccff3baSMed Ismail Bennani num_listed_interface++; 214bccff3baSMed Ismail Bennani 215bccff3baSMed Ismail Bennani llvm::StringRef desc = 216bccff3baSMed Ismail Bennani PluginManager::GetScriptedInterfaceDescriptionAtIndex(i); 217bccff3baSMed Ismail Bennani ScriptedInterfaceUsages usages = 218bccff3baSMed Ismail Bennani PluginManager::GetScriptedInterfaceUsagesAtIndex(i); 219bccff3baSMed Ismail Bennani 220bccff3baSMed Ismail Bennani print_field("Name", plugin_name); 221bccff3baSMed Ismail Bennani print_field("Language", ScriptInterpreter::LanguageToString(lang)); 222bccff3baSMed Ismail Bennani print_field("Description", desc); 223bccff3baSMed Ismail Bennani usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API); 224bccff3baSMed Ismail Bennani usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter); 225bccff3baSMed Ismail Bennani 2265689ccceSMed Ismail Bennani if (i != num_extensions - 1) 227bccff3baSMed Ismail Bennani s.EOL(); 228bccff3baSMed Ismail Bennani } 229bccff3baSMed Ismail Bennani 230bccff3baSMed Ismail Bennani if (!num_listed_interface) 231bccff3baSMed Ismail Bennani s << " None\n"; 232bccff3baSMed Ismail Bennani } 233bccff3baSMed Ismail Bennani 234bccff3baSMed Ismail Bennani private: 235bccff3baSMed Ismail Bennani CommandOptions m_options; 236bccff3baSMed Ismail Bennani }; 237bccff3baSMed Ismail Bennani 2385689ccceSMed Ismail Bennani class CommandObjectMultiwordScriptingExtension : public CommandObjectMultiword { 239bccff3baSMed Ismail Bennani public: 2405689ccceSMed Ismail Bennani CommandObjectMultiwordScriptingExtension(CommandInterpreter &interpreter) 241bccff3baSMed Ismail Bennani : CommandObjectMultiword( 2425689ccceSMed Ismail Bennani interpreter, "scripting extension", 2435689ccceSMed Ismail Bennani "Commands for operating on the scripting extensions.", 2445689ccceSMed Ismail Bennani "scripting extension [<subcommand-options>]") { 245bccff3baSMed Ismail Bennani LoadSubCommand( 246bccff3baSMed Ismail Bennani "list", 2475689ccceSMed Ismail Bennani CommandObjectSP(new CommandObjectScriptingExtensionList(interpreter))); 248bccff3baSMed Ismail Bennani } 249bccff3baSMed Ismail Bennani 2505689ccceSMed Ismail Bennani ~CommandObjectMultiwordScriptingExtension() override = default; 251bccff3baSMed Ismail Bennani }; 252410de0c8SMed Ismail Bennani 253410de0c8SMed Ismail Bennani CommandObjectMultiwordScripting::CommandObjectMultiwordScripting( 254410de0c8SMed Ismail Bennani CommandInterpreter &interpreter) 255410de0c8SMed Ismail Bennani : CommandObjectMultiword( 256410de0c8SMed Ismail Bennani interpreter, "scripting", 257*4494c543SRyan Mansfield "Commands for operating on the scripting functionalities.", 258410de0c8SMed Ismail Bennani "scripting <subcommand> [<subcommand-options>]") { 259410de0c8SMed Ismail Bennani LoadSubCommand("run", 260410de0c8SMed Ismail Bennani CommandObjectSP(new CommandObjectScriptingRun(interpreter))); 2615689ccceSMed Ismail Bennani LoadSubCommand("extension", 2625689ccceSMed Ismail Bennani CommandObjectSP(new CommandObjectMultiwordScriptingExtension( 2635689ccceSMed Ismail Bennani interpreter))); 264410de0c8SMed Ismail Bennani } 265410de0c8SMed Ismail Bennani 266410de0c8SMed Ismail Bennani CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default; 267