Index: lldb/source/Commands/CommandObjectScript.cpp =================================================================== --- lldb/source/Commands/CommandObjectScript.cpp +++ lldb/source/Commands/CommandObjectScript.cpp @@ -25,21 +25,63 @@ interpreter, "script", "Invoke the script interpreter with provided code and display any " "results. Start the interactive interpreter if no code is supplied.", - "script []") {} + "script [-l ] []") {} CommandObjectScript::~CommandObjectScript() {} +struct CommandParsed { + CommandParsed(llvm::StringRef command) + : language(llvm::None), command(command) {} + CommandParsed(llvm::Optional language, + llvm::StringRef command) + : language(language), command(command) {} + llvm::Optional language; + llvm::StringRef command; +}; + +/// Manually parse the -l or --language +/// argument from the command. This is necessary because CommandObjectScript is +/// an instance of CommandObjectRaw. We cannot use CommandObjectParsed because +/// it removes quotes and replace embedded script commands between backticks. +static CommandParsed ParseLanguageArgument(llvm::StringRef command) { + llvm::StringRef head; + llvm::StringRef tail = command; + + std::tie(head, tail) = tail.split(' '); + if (head != "-l" && head != "--language") + return CommandParsed(command); + + std::tie(head, tail) = tail.split(' '); + llvm::Optional language = + llvm::StringSwitch>(head.lower()) + .Case("lua", eScriptLanguageLua) + .Case("none", eScriptLanguageNone) + .Case("python", eScriptLanguagePython) + .Default(llvm::None); + + if (language) + return CommandParsed(language, tail.ltrim()); + + return CommandParsed(command); +} + bool CommandObjectScript::DoExecute(llvm::StringRef command, CommandReturnObject &result) { - if (m_interpreter.GetDebugger().GetScriptLanguage() == - lldb::eScriptLanguageNone) { + CommandParsed parsed = ParseLanguageArgument(command); + + ScriptLanguage language = + parsed.language ? *parsed.language + : m_interpreter.GetDebugger().GetScriptLanguage(); + + if (language == eScriptLanguageNone) { result.AppendError( "the script-lang setting is set to none - scripting not available"); result.SetStatus(eReturnStatusFailed); return false; } - ScriptInterpreter *script_interpreter = GetDebugger().GetScriptInterpreter(); + ScriptInterpreter *script_interpreter = + GetDebugger().GetScriptInterpreter(true, language); if (script_interpreter == nullptr) { result.AppendError("no script interpreter"); @@ -51,14 +93,14 @@ // up to date with it. DataVisualization::ForceUpdate(); - if (command.empty()) { + if (parsed.command.empty()) { script_interpreter->ExecuteInterpreterLoop(); result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } // We can do better when reporting the status of one-liner script execution. - if (script_interpreter->ExecuteOneLine(command, &result)) + if (script_interpreter->ExecuteOneLine(parsed.command, &result)) result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusFailed); Index: lldb/test/Shell/ScriptInterpreter/Lua/lua-python.test =================================================================== --- /dev/null +++ lldb/test/Shell/ScriptInterpreter/Lua/lua-python.test @@ -0,0 +1,17 @@ +# REQUIRES: lua +# REQUIRES: python +# UNSUPPORTED: lldb-repro + +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: echo "int main() { return 0; }" | %clang_host -x c - -o a.out +# RUN: cat %s | %lldb 2>&1 | FileCheck %s +script -l lua +target = lldb.debugger:CreateTarget("a.out") +print("target is valid:", tostring(target:IsValid())) +lldb.debugger:SetSelectedTarget(target) +quit +# CHECK: target is valid: true +script -l python +print("selected target: {}".format(lldb.debugger.GetSelectedTarget())) +# CHECK: selected target: a.out Index: lldb/test/Shell/ScriptInterpreter/Lua/lua.test =================================================================== --- lldb/test/Shell/ScriptInterpreter/Lua/lua.test +++ lldb/test/Shell/ScriptInterpreter/Lua/lua.test @@ -1,3 +1,5 @@ # REQUIRES: lua -# RUN: %lldb --script-language lua -o 'script print(1000+100+10+1)' 2>&1 | FileCheck %s +# RUN: %lldb --script-language lua -o 'script io.stdout:write(1000+100+10+1, "\n")' 2>&1 | FileCheck %s +# RUN: %lldb -o 'script -l lua io.stdout:write(1000+100+10+1, "\n")' 2>&1 | FileCheck %s +# RUN: %lldb -o 'script --language lua io.stdout:write(1000+100+10+1, "\n")' 2>&1 | FileCheck %s # CHECK: 1111 Index: lldb/test/Shell/ScriptInterpreter/None/none.test =================================================================== --- lldb/test/Shell/ScriptInterpreter/None/none.test +++ lldb/test/Shell/ScriptInterpreter/None/none.test @@ -1,2 +1,5 @@ # RUN: %lldb --script-language none -o 'script' 2>&1 | FileCheck %s # CHECK: error: the script-lang setting is set to none - scripting not available + +# RUN: %lldb -o 'script -l none foo' 2>&1 | FileCheck %s --check-prefix ERROR +# ERROR: error: the script-lang setting is set to none - scripting not available Index: lldb/test/Shell/ScriptInterpreter/Python/python.test =================================================================== --- /dev/null +++ lldb/test/Shell/ScriptInterpreter/Python/python.test @@ -0,0 +1,9 @@ +# REQUIRES: python +# RUN: %lldb --script-language python -o 'script print("{}".format(1000+100+10+1))' 2>&1 | FileCheck %s +# RUN: %lldb -o 'script -l python print("{}".format(1000+100+10+1))' 2>&1 | FileCheck %s +# RUN: %lldb -o 'script --language python print("{}".format(1000+100+10+1))' 2>&1 | FileCheck %s +# CHECK: 1111 + +# RUN: %lldb -o 'script --language invalid print("{}".format(1000+100+10+1))' 2>&1 | FileCheck %s --check-prefix INVALID +# INVALID: SyntaxError +# INVALID-NOT: 1111