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-exception 6 // 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 23 using namespace lldb; 24 using namespace lldb_private; 25 26 #define LLDB_OPTIONS_scripting_run 27 #include "CommandOptions.inc" 28 29 class CommandObjectScriptingRun : public CommandObjectRaw { 30 public: 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 80 protected: 81 void DoExecute(llvm::StringRef command, 82 CommandReturnObject &result) override { 83 // Try parsing the language option but when the command contains a raw part 84 // 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 keep 112 // 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 else 125 result.SetStatus(eReturnStatusFailed); 126 } 127 128 private: 129 CommandOptions m_options; 130 }; 131 132 #define LLDB_OPTIONS_scripting_extension_list 133 #include "CommandOptions.inc" 134 135 class CommandObjectScriptingExtensionList : public CommandObjectParsed { 136 public: 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 183 protected: 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 234 private: 235 CommandOptions m_options; 236 }; 237 238 class CommandObjectMultiwordScriptingExtension : public CommandObjectMultiword { 239 public: 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 253 CommandObjectMultiwordScripting::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 266 CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default; 267