mirror of https://github.com/mgba-emu/mgba.git
Scripting: Add error reporting
This commit is contained in:
parent
66142ab4dc
commit
b9f88061ca
|
@ -41,6 +41,7 @@ struct mScriptEngineContext {
|
||||||
|
|
||||||
bool (*load)(struct mScriptEngineContext*, struct VFile*, const char** error);
|
bool (*load)(struct mScriptEngineContext*, struct VFile*, const char** error);
|
||||||
bool (*run)(struct mScriptEngineContext*);
|
bool (*run)(struct mScriptEngineContext*);
|
||||||
|
const char* (*getError)(struct mScriptEngineContext*);
|
||||||
};
|
};
|
||||||
|
|
||||||
void mScriptContextInit(struct mScriptContext*);
|
void mScriptContextInit(struct mScriptContext*);
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include <mgba/internal/script/lua.h>
|
#include <mgba/internal/script/lua.h>
|
||||||
|
|
||||||
|
#include <mgba-util/string.h>
|
||||||
|
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
@ -14,6 +17,7 @@ static struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext*, const ch
|
||||||
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
static bool _luaSetGlobal(struct mScriptEngineContext*, const char* name, struct mScriptValue*);
|
||||||
static bool _luaLoad(struct mScriptEngineContext*, struct VFile*, const char** error);
|
static bool _luaLoad(struct mScriptEngineContext*, struct VFile*, const char** error);
|
||||||
static bool _luaRun(struct mScriptEngineContext*);
|
static bool _luaRun(struct mScriptEngineContext*);
|
||||||
|
static const char* _luaGetError(struct mScriptEngineContext*);
|
||||||
|
|
||||||
static bool _luaCall(struct mScriptFrame*, void* context);
|
static bool _luaCall(struct mScriptFrame*, void* context);
|
||||||
|
|
||||||
|
@ -61,6 +65,7 @@ struct mScriptEngineContextLua {
|
||||||
struct mScriptEngineContext d;
|
struct mScriptEngineContext d;
|
||||||
lua_State* lua;
|
lua_State* lua;
|
||||||
int func;
|
int func;
|
||||||
|
char* lastError;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mScriptEngineContextLuaRef {
|
struct mScriptEngineContextLuaRef {
|
||||||
|
@ -97,7 +102,8 @@ struct mScriptEngineContext* _luaCreate(struct mScriptEngine2* engine, struct mS
|
||||||
.getGlobal = _luaGetGlobal,
|
.getGlobal = _luaGetGlobal,
|
||||||
.setGlobal = _luaSetGlobal,
|
.setGlobal = _luaSetGlobal,
|
||||||
.load = _luaLoad,
|
.load = _luaLoad,
|
||||||
.run = _luaRun
|
.run = _luaRun,
|
||||||
|
.getError = _luaGetError
|
||||||
};
|
};
|
||||||
luaContext->lua = luaL_newstate();
|
luaContext->lua = luaL_newstate();
|
||||||
luaContext->func = -1;
|
luaContext->func = -1;
|
||||||
|
@ -117,6 +123,10 @@ struct mScriptEngineContext* _luaCreate(struct mScriptEngine2* engine, struct mS
|
||||||
|
|
||||||
void _luaDestroy(struct mScriptEngineContext* ctx) {
|
void _luaDestroy(struct mScriptEngineContext* ctx) {
|
||||||
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
|
||||||
|
if (luaContext->lastError) {
|
||||||
|
free(luaContext->lastError);
|
||||||
|
luaContext->lastError = NULL;
|
||||||
|
}
|
||||||
if (luaContext->func > 0) {
|
if (luaContext->func > 0) {
|
||||||
luaL_unref(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func);
|
luaL_unref(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func);
|
||||||
}
|
}
|
||||||
|
@ -298,6 +308,11 @@ bool _luaRun(struct mScriptEngineContext* context) {
|
||||||
return _luaInvoke(luaContext, NULL);
|
return _luaInvoke(luaContext, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* _luaGetError(struct mScriptEngineContext* context) {
|
||||||
|
struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) context;
|
||||||
|
return luaContext->lastError;
|
||||||
|
}
|
||||||
|
|
||||||
bool _luaPushFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList* frame) {
|
bool _luaPushFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList* frame) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (frame) {
|
if (frame) {
|
||||||
|
@ -360,6 +375,11 @@ bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame*
|
||||||
nargs = mScriptListSize(&frame->arguments);
|
nargs = mScriptListSize(&frame->arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (luaContext->lastError) {
|
||||||
|
free(luaContext->lastError);
|
||||||
|
luaContext->lastError = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame && !_luaPushFrame(luaContext, &frame->arguments)) {
|
if (frame && !_luaPushFrame(luaContext, &frame->arguments)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -373,6 +393,7 @@ bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame*
|
||||||
lua_rawset(luaContext->lua, LUA_REGISTRYINDEX);
|
lua_rawset(luaContext->lua, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
if (ret == LUA_ERRRUN) {
|
if (ret == LUA_ERRRUN) {
|
||||||
|
luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1));
|
||||||
lua_pop(luaContext->lua, 1);
|
lua_pop(luaContext->lua, 1);
|
||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -516,6 +516,26 @@ M_TEST_DEFINE(globalStructMethods) {
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(errorReporting) {
|
||||||
|
SETUP_LUA;
|
||||||
|
|
||||||
|
assert_null(lua->getError(lua));
|
||||||
|
|
||||||
|
LOAD_PROGRAM("assert(false)");
|
||||||
|
|
||||||
|
assert_false(lua->run(lua));
|
||||||
|
const char* errorBuffer = lua->getError(lua);
|
||||||
|
assert_non_null(errorBuffer);
|
||||||
|
assert_non_null(strstr(errorBuffer, "assertion failed"));
|
||||||
|
|
||||||
|
LOAD_PROGRAM("assert(true)");
|
||||||
|
|
||||||
|
assert_true(lua->run(lua));
|
||||||
|
assert_null(lua->getError(lua));
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||||
cmocka_unit_test(create),
|
cmocka_unit_test(create),
|
||||||
cmocka_unit_test(loadGood),
|
cmocka_unit_test(loadGood),
|
||||||
|
@ -527,4 +547,6 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||||
cmocka_unit_test(callCFunc),
|
cmocka_unit_test(callCFunc),
|
||||||
cmocka_unit_test(globalStructFieldGet),
|
cmocka_unit_test(globalStructFieldGet),
|
||||||
cmocka_unit_test(globalStructFieldSet),
|
cmocka_unit_test(globalStructFieldSet),
|
||||||
cmocka_unit_test(globalStructMethods))
|
cmocka_unit_test(globalStructMethods),
|
||||||
|
cmocka_unit_test(errorReporting),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue