summaryrefslogtreecommitdiff
path: root/indra/newview/llluamanager.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-09-20 15:13:43 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-09-20 15:13:43 -0400
commit6d29beb91b019e1995cdb7c4aaf7a043de4bf053 (patch)
treec4772496fd833a934d1b7e93028b107b0e36ed8f /indra/newview/llluamanager.cpp
parent50513bab2d6b1823f983c145553b8a6af44c2f28 (diff)
Add ability to pass command-line arguments to a Lua script.
Introduce `ScriptCommand` class that parses a command line into a script name and optional args, using bash-like quoting and escaping. `ScriptCommand` searches for a file with that script name on a passed list of directories; the directories may be specified relative to a particular base directory. `ScriptCommand` supports the special case of a script name containing unescaped spaces. It guarantees that either the returned script file exists, or its `error()` string is non-empty. Replace `LLLeap::create()` logic, from which `ScriptCommand` was partly derived, with a `ScriptCommand` instance. Make `LLLUAmanager::runScriptFile()` use a `ScriptCommand` instance to parse the passed command line. Subsume `LLAppViewer::init()` script-path-searching logic for `--luafile` into `ScriptCommand`. In fact that lambda now simply calls `LLLUAmanager::runScriptFile()`. Make `lluau::dostring()` accept an optional vector of script argument strings. Following PUC-Rio Lua convention, pass these arguments into a Lua script as the predefined global `arg`, and also as the script's `...` argument. `LuaState::expr()` also accepts and passes through script argument strings. Change the log tag for the Lua script interruption message: if we want it, we can still enable it, but we don't necessarily want it along with all other "Lua" DEBUG messages. Remove `LuaState::script_finished_fn`, which isn't used any more. Also remove the corresponding `LLLUAmanager::script_finished_fn`. This allows us to simplify `~LuaState()` slightly, as well as the parameter signatures for `LLLUAmanager::runScriptFile()` and `runScriptLine()`.
Diffstat (limited to 'indra/newview/llluamanager.cpp')
-rw-r--r--indra/newview/llluamanager.cpp83
1 files changed, 23 insertions, 60 deletions
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
index c4ce07e492..046526ac3c 100644
--- a/indra/newview/llluamanager.cpp
+++ b/indra/newview/llluamanager.cpp
@@ -186,75 +186,41 @@ LLLUAmanager::script_result LLLUAmanager::waitScriptFile(const std::string& file
}
void LLLUAmanager::runScriptFile(const std::string &filename, bool autorun,
- script_result_fn result_cb, script_finished_fn finished_cb)
+ script_result_fn result_cb)
{
// A script_result_fn will be called when LuaState::expr() completes.
- LLCoros::instance().launch(filename, [filename, autorun, result_cb, finished_cb]()
+ LLCoros::instance().launch(filename, [filename, autorun, result_cb]()
{
ScriptObserver observer(LLCoros::getName(), filename);
- // Use LLStringUtil::getTokens() to parse the script command line
- auto tokens = LLStringUtil::getTokens(filename,
- " \t\r\n", // drop_delims
- "", // no keep_delims
- "\"'", // either kind of quotes
- "\\"); // backslash escape
-
-#error Under construction
- // TODO:
- // - Move this either/or file existence logic to LuaCommand()
- // - Accept LuaCommand in all LLLUAmanager::mumbleScriptFile() methods
- // - Update all existing mumbleScriptFile() callers
-
- llifstream in_file;
- in_file.open(tokens[0]);
- if (in_file.is_open())
- {
- // The first token is in fact the script filename. Now that the
- // script file is open, we've consumed that token. The rest are
- // command-line arguments.
- tokens.erase(tokens.begin());
- }
- else
+ LLSD paths(gSavedSettings.getLLSD("LuaCommandPath"));
+ LL_DEBUGS("Lua") << "LuaCommandPath = " << paths << LL_ENDL;
+ // allow LuaCommandPath to be specified relative to install dir
+ ScriptCommand command(filename, paths, gDirUtilp->getAppRODataDir());
+ auto error = command.error();
+ if (! error.empty())
{
- // Parsing the command line produced a script file path we can't
- // open. Maybe that's because there are spaces in the original
- // pathname that were neither quoted nor escaped? See if we can
- // open the whole original command line string.
- in_file.open(filename);
- if (! in_file.is_open())
+ if (result_cb)
{
- std::ostringstream msgstream;
- msgstream << "Can't open script file " << std::quoted(tokens[0]);
- if (filename != tokens[0])
- {
- msgstream << " or " << std::quoted(filename);
- }
- auto msg = msgstream.str();
- LL_WARNS("Lua") << msg << LL_ENDL;
- if (result_cb)
- {
- result_cb(-1, msg);
- }
- return;
+ result_cb(-1, error);
}
- // Here we do have in_file open, using the whole input command
- // line as its pathname. Discard any parts of it we mistook for
- // command-line arguments.
- tokens.clear();
- }
+ return;
+ }
- // Here in_file is open.
+ llifstream in_file;
+ in_file.open(command.script);
+ // At this point, since ScriptCommand did not report an error, we
+ // should be able to assume that 'script' exists. If we can't open it,
+ // something else is wrong?!
+ llassert(in_file.is_open());
if (autorun)
{
sAutorunScriptCount++;
}
sScriptCount++;
- // A script_finished_fn is used to initialize the LuaState.
- // It will be called when the LuaState is destroyed.
- LuaState L(finished_cb);
+ LuaState L;
std::string text{std::istreambuf_iterator<char>(in_file), {}};
- auto [count, result] = L.expr(filename, text, tokens);
+ auto [count, result] = L.expr(command.script, text, command.args);
if (result_cb)
{
result_cb(count, result);
@@ -279,8 +245,7 @@ LLLUAmanager::script_result LLLUAmanager::waitScriptLine(const std::string& chun
return startScriptLine(chunk).get();
}
-void LLLUAmanager::runScriptLine(const std::string& chunk, script_result_fn result_cb,
- script_finished_fn finished_cb)
+void LLLUAmanager::runScriptLine(const std::string& chunk, script_result_fn result_cb)
{
// find a suitable abbreviation for the chunk string
std::string shortchunk{ chunk };
@@ -292,11 +257,9 @@ void LLLUAmanager::runScriptLine(const std::string& chunk, script_result_fn resu
shortchunk = stringize(shortchunk.substr(0, shortlen), "...");
std::string desc{ "lua: " + shortchunk };
- LLCoros::instance().launch(desc, [desc, chunk, result_cb, finished_cb]()
+ LLCoros::instance().launch(desc, [desc, chunk, result_cb]()
{
- // A script_finished_fn is used to initialize the LuaState.
- // It will be called when the LuaState is destroyed.
- LuaState L(finished_cb);
+ LuaState L;
auto [count, result] = L.expr(desc, chunk);
if (result_cb)
{