1 //===-- CommandObjectScript.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 "CommandObjectScript.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_script
25 #include "CommandOptions.inc"
26 
27 Status CommandObjectScript::CommandOptions::SetOptionValue(
28     uint32_t option_idx, llvm::StringRef option_arg,
29     ExecutionContext *execution_context) {
30   Status error;
31   const int short_option = m_getopt_table[option_idx].val;
32 
33   switch (short_option) {
34   case 'l':
35     language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
36         option_arg, GetDefinitions()[option_idx].enum_values,
37         eScriptLanguageNone, error);
38     if (!error.Success())
39       error.SetErrorStringWithFormat("unrecognized value for language '%s'",
40                                      option_arg.str().c_str());
41     break;
42   default:
43     llvm_unreachable("Unimplemented option");
44   }
45 
46   return error;
47 }
48 
49 void CommandObjectScript::CommandOptions::OptionParsingStarting(
50     ExecutionContext *execution_context) {
51   language = lldb::eScriptLanguageNone;
52 }
53 
54 llvm::ArrayRef<OptionDefinition>
55 CommandObjectScript::CommandOptions::GetDefinitions() {
56   return llvm::makeArrayRef(g_script_options);
57 }
58 
59 CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter)
60     : CommandObjectRaw(
61           interpreter, "script",
62           "Invoke the script interpreter with provided code and display any "
63           "results.  Start the interactive interpreter if no code is supplied.",
64           "script [--language <scripting-language> --] [<script-code>]") {}
65 
66 CommandObjectScript::~CommandObjectScript() = default;
67 
68 bool CommandObjectScript::DoExecute(llvm::StringRef command,
69                                     CommandReturnObject &result) {
70   // Try parsing the language option but when the command contains a raw part
71   // separated by the -- delimiter.
72   OptionsWithRaw raw_args(command);
73   if (raw_args.HasArgs()) {
74     if (!ParseOptions(raw_args.GetArgs(), result))
75       return false;
76     command = raw_args.GetRawPart();
77   }
78 
79   lldb::ScriptLanguage language =
80       (m_options.language == lldb::eScriptLanguageNone)
81           ? m_interpreter.GetDebugger().GetScriptLanguage()
82           : m_options.language;
83 
84   if (language == lldb::eScriptLanguageNone) {
85     result.AppendError(
86         "the script-lang setting is set to none - scripting not available");
87     return false;
88   }
89 
90   ScriptInterpreter *script_interpreter =
91       GetDebugger().GetScriptInterpreter(true, language);
92 
93   if (script_interpreter == nullptr) {
94     result.AppendError("no script interpreter");
95     return false;
96   }
97 
98   // Script might change Python code we use for formatting. Make sure we keep
99   // up to date with it.
100   DataVisualization::ForceUpdate();
101 
102   if (command.empty()) {
103     script_interpreter->ExecuteInterpreterLoop();
104     result.SetStatus(eReturnStatusSuccessFinishNoResult);
105     return result.Succeeded();
106   }
107 
108   // We can do better when reporting the status of one-liner script execution.
109   if (script_interpreter->ExecuteOneLine(command, &result))
110     result.SetStatus(eReturnStatusSuccessFinishNoResult);
111   else
112     result.SetStatus(eReturnStatusFailed);
113 
114   return result.Succeeded();
115 }
116