summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lua_function.cpp37
-rw-r--r--indra/llcommon/lua_function.h30
2 files changed, 53 insertions, 14 deletions
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index f6db4eafe1..5466e0058e 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -407,8 +407,7 @@ void lua_pushllsd(lua_State* L, const LLSD& data)
}
}
-LuaState::LuaState(const std::string_view& desc, script_finished_fn cb):
- mDesc(desc),
+LuaState::LuaState(script_finished_fn cb):
mCallback(cb),
mState(luaL_newstate())
{
@@ -450,19 +449,49 @@ LuaState::~LuaState()
}
}
-bool LuaState::checkLua(int r)
+bool LuaState::checkLua(const std::string& desc, int r)
{
if (r != LUA_OK)
{
mError = lua_tostring(mState, -1);
lua_pop(mState, 1);
- LL_WARNS() << mDesc << ": " << mError << LL_ENDL;
+ LL_WARNS() << desc << ": " << mError << LL_ENDL;
return false;
}
return true;
}
+std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string& text)
+{
+ if (! checkLua(desc, lluau::dostring(mState, desc, text)))
+ return { -1, mError };
+
+ // here we believe there was no error -- did the Lua fragment leave
+ // anything on the stack?
+ std::pair<int, LLSD> result{ lua_gettop(mState), {} };
+ if (! result.first)
+ return result;
+
+ // aha, at least one entry on the stack!
+ if (result.first == 1)
+ {
+ result.second = lua_tollsd(mState, 1);
+ // pop the result we claimed
+ lua_settop(mState, 0);
+ return result;
+ }
+
+ // multiple entries on the stack
+ for (int index = 1; index <= result.first; ++index)
+ {
+ result.second.append(lua_tollsd(mState, index));
+ }
+ // pop everything
+ lua_settop(mState, 0);
+ return result;
+}
+
LuaPopper::~LuaPopper()
{
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
index e2bd58e80a..ea9f2ebdf8 100644
--- a/indra/llcommon/lua_function.h
+++ b/indra/llcommon/lua_function.h
@@ -17,6 +17,7 @@
#include "luau/luaconf.h"
#include "luau/lualib.h"
#include "stringize.h"
+#include <utility> // std::pair
#define lua_register(L, n, f) (lua_pushcfunction(L, (f), n), lua_setglobal(L, (n)))
#define lua_rawlen lua_objlen
@@ -55,19 +56,28 @@ class LuaState
public:
typedef std::function<void(std::string msg)> script_finished_fn;
- LuaState(const std::string_view& desc, script_finished_fn cb);
+ LuaState(script_finished_fn cb={});
LuaState(const LuaState&) = delete;
LuaState& operator=(const LuaState&) = delete;
~LuaState();
- bool checkLua(int r);
+ bool checkLua(const std::string& desc, int r);
+
+ // expr() is for when we want to capture any results left on the stack
+ // by a Lua expression, possibly including multiple return values.
+ // int < 0 means error, and LLSD::asString() is the error message.
+ // int == 0 with LLSD::isUndefined() means the Lua expression returned no
+ // results.
+ // int == 1 means the Lua expression returned one result.
+ // int > 1 with LLSD::isArray() means the Lua expression returned
+ // multiple results, represented as the entries of the array.
+ std::pair<int, LLSD> expr(const std::string& desc, const std::string& text);
operator lua_State*() const { return mState; }
private:
- std::string mDesc;
script_finished_fn mCallback;
lua_State* mState;
std::string mError;
@@ -129,13 +139,13 @@ private:
* call() method definition header, to be followed by a method body enclosed
* in curly braces as usual.
*/
-#define lua_function(name) \
-static struct name##_ : public LuaFunction \
-{ \
- name##_(): LuaFunction(#name, &call) {} \
- static int call(lua_State* L); \
-} name; \
-int name##_::call(lua_State* L)
+#define lua_function(name) \
+static struct name##_luadecl : public LuaFunction \
+{ \
+ name##_luadecl(): LuaFunction(#name, &call) {} \
+ static int call(lua_State* L); \
+} name##_luadef; \
+int name##_luadecl::call(lua_State* L)
// {
// ... supply method body here, referencing 'L' ...
// }