xref: /freebsd/contrib/llvm-project/lldb/source/Commands/CommandObjectScripting.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/DataFormatters/DataVisualization.h"
12 #include "lldb/Host/Config.h"
13 #include "lldb/Host/OptionParser.h"
14 #include "lldb/Interpreter/CommandInterpreter.h"
15 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
16 #include "lldb/Interpreter/CommandReturnObject.h"
17 #include "lldb/Interpreter/OptionArgParser.h"
18 #include "lldb/Interpreter/ScriptInterpreter.h"
19 #include "lldb/Utility/Args.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 #define LLDB_OPTIONS_scripting_run
25 #include "CommandOptions.inc"
26 
27 class CommandObjectScriptingRun : public CommandObjectRaw {
28 public:
CommandObjectScriptingRun(CommandInterpreter & interpreter)29   CommandObjectScriptingRun(CommandInterpreter &interpreter)
30       : CommandObjectRaw(
31             interpreter, "scripting run",
32             "Invoke the script interpreter with provided code and display any "
33             "results.  Start the interactive interpreter if no code is "
34             "supplied.",
35             "scripting run [--language <scripting-language> --] "
36             "[<script-code>]") {}
37 
38   ~CommandObjectScriptingRun() override = default;
39 
GetOptions()40   Options *GetOptions() override { return &m_options; }
41 
42   class CommandOptions : public Options {
43   public:
44     CommandOptions() = default;
45     ~CommandOptions() override = default;
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)46     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
47                           ExecutionContext *execution_context) override {
48       Status error;
49       const int short_option = m_getopt_table[option_idx].val;
50 
51       switch (short_option) {
52       case 'l':
53         language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
54             option_arg, GetDefinitions()[option_idx].enum_values,
55             eScriptLanguageNone, error);
56         if (!error.Success())
57           error.SetErrorStringWithFormat("unrecognized value for language '%s'",
58                                          option_arg.str().c_str());
59         break;
60       default:
61         llvm_unreachable("Unimplemented option");
62       }
63 
64       return error;
65     }
66 
OptionParsingStarting(ExecutionContext * execution_context)67     void OptionParsingStarting(ExecutionContext *execution_context) override {
68       language = lldb::eScriptLanguageNone;
69     }
70 
GetDefinitions()71     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
72       return llvm::ArrayRef(g_scripting_run_options);
73     }
74 
75     lldb::ScriptLanguage language = lldb::eScriptLanguageNone;
76   };
77 
78 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)79   void DoExecute(llvm::StringRef command,
80                  CommandReturnObject &result) override {
81     // Try parsing the language option but when the command contains a raw part
82     // separated by the -- delimiter.
83     OptionsWithRaw raw_args(command);
84     if (raw_args.HasArgs()) {
85       if (!ParseOptions(raw_args.GetArgs(), result))
86         return;
87       command = raw_args.GetRawPart();
88     }
89 
90     lldb::ScriptLanguage language =
91         (m_options.language == lldb::eScriptLanguageNone)
92             ? m_interpreter.GetDebugger().GetScriptLanguage()
93             : m_options.language;
94 
95     if (language == lldb::eScriptLanguageNone) {
96       result.AppendError(
97           "the script-lang setting is set to none - scripting not available");
98       return;
99     }
100 
101     ScriptInterpreter *script_interpreter =
102         GetDebugger().GetScriptInterpreter(true, language);
103 
104     if (script_interpreter == nullptr) {
105       result.AppendError("no script interpreter");
106       return;
107     }
108 
109     // Script might change Python code we use for formatting. Make sure we keep
110     // up to date with it.
111     DataVisualization::ForceUpdate();
112 
113     if (command.empty()) {
114       script_interpreter->ExecuteInterpreterLoop();
115       result.SetStatus(eReturnStatusSuccessFinishNoResult);
116       return;
117     }
118 
119     // We can do better when reporting the status of one-liner script execution.
120     if (script_interpreter->ExecuteOneLine(command, &result))
121       result.SetStatus(eReturnStatusSuccessFinishNoResult);
122     else
123       result.SetStatus(eReturnStatusFailed);
124   }
125 
126 private:
127   CommandOptions m_options;
128 };
129 
130 #pragma mark CommandObjectMultiwordScripting
131 
132 // CommandObjectMultiwordScripting
133 
CommandObjectMultiwordScripting(CommandInterpreter & interpreter)134 CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
135     CommandInterpreter &interpreter)
136     : CommandObjectMultiword(
137           interpreter, "scripting",
138           "Commands for operating on the scripting functionnalities.",
139           "scripting <subcommand> [<subcommand-options>]") {
140   LoadSubCommand("run",
141                  CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
142 }
143 
144 CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;
145