mirror of
https://github.com/opentx/opentx.git
synced 2025-07-17 13:25:20 +03:00
Fixes #1643 - Thanks to projectkk2glider for his help on this one
Conflicts: radio/src/lua.cpp radio/src/opentx.cpp
This commit is contained in:
parent
04f9eb5c0f
commit
500602e8cc
8 changed files with 417 additions and 219 deletions
|
@ -289,6 +289,10 @@ USB = JOYSTICK
|
||||||
# NO - normal behaviour, show real channel values
|
# NO - normal behaviour, show real channel values
|
||||||
CHANNELS_MONITOR_INV_HIDE = NO
|
CHANNELS_MONITOR_INV_HIDE = NO
|
||||||
|
|
||||||
|
# Use newlib-nano
|
||||||
|
# Values = NO, YES
|
||||||
|
NANO = YES
|
||||||
|
|
||||||
#------- END BUILD OPTIONS ---------------------------
|
#------- END BUILD OPTIONS ---------------------------
|
||||||
|
|
||||||
# Define programs and commands.
|
# Define programs and commands.
|
||||||
|
@ -1116,6 +1120,12 @@ MATH_LIB = -lm
|
||||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||||
LDFLAGS += $(MATH_LIB)
|
LDFLAGS += $(MATH_LIB)
|
||||||
|
|
||||||
|
ifeq ($(NANO), YES)
|
||||||
|
# use newlib-nano for linking
|
||||||
|
NEWLIB_NANO_FLAGS = --specs=nano.specs -u _printf_float
|
||||||
|
CPPDEFS += -DNANO
|
||||||
|
endif
|
||||||
|
|
||||||
# Define Messages
|
# Define Messages
|
||||||
# English
|
# English
|
||||||
MSG_BEGIN = -------- begin --------
|
MSG_BEGIN = -------- begin --------
|
||||||
|
@ -1324,7 +1334,7 @@ FOXLIB=-L/usr/local/lib \
|
||||||
-Wl,-rpath,$(FOXPATH)/src/.libs
|
-Wl,-rpath,$(FOXPATH)/src/.libs
|
||||||
|
|
||||||
simu: $(LUADEP) stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin
|
simu: $(LUADEP) stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin
|
||||||
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions
|
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -DLUA_USE_APICHECK -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions
|
||||||
|
|
||||||
eeprom.bin:
|
eeprom.bin:
|
||||||
dd if=/dev/zero of=$@ bs=1 count=2048
|
dd if=/dev/zero of=$@ bs=1 count=2048
|
||||||
|
@ -1390,7 +1400,7 @@ OBJS = $(TMP:.s=.o)
|
||||||
@echo
|
@echo
|
||||||
@echo $(MSG_COMPILING) $@
|
@echo $(MSG_COMPILING) $@
|
||||||
$(CC) $(ARMCPPFLAGS) $< -o allsrc.o
|
$(CC) $(ARMCPPFLAGS) $< -o allsrc.o
|
||||||
$(CC) $(OBJS) allsrc.o -mcpu=cortex-m3 -mthumb -nostartfiles -lm -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch,--gc-sections -o $@
|
$(CC) $(OBJS) allsrc.o -mcpu=cortex-m3 -mthumb -nostartfiles -lm -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref,--no-warn-mismatch,--gc-sections $(NEWLIB_NANO_FLAGS) -o $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Target: clean project.
|
# Target: clean project.
|
||||||
|
|
|
@ -76,6 +76,19 @@ uint16_t maxLuaDuration = 0;
|
||||||
#define SCRIPTS_MAX_HEAP 50
|
#define SCRIPTS_MAX_HEAP 50
|
||||||
#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x))
|
#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x))
|
||||||
|
|
||||||
|
struct our_longjmp * global_lj = 0;
|
||||||
|
|
||||||
|
/* custom panic handler */
|
||||||
|
static int custom_lua_atpanic(lua_State *lua)
|
||||||
|
{
|
||||||
|
TRACE("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
|
||||||
|
if (global_lj) {
|
||||||
|
longjmp(global_lj->b, 1);
|
||||||
|
/* will never return */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int instructionsPercent = 0;
|
static int instructionsPercent = 0;
|
||||||
void hook(lua_State* L, lua_Debug *ar)
|
void hook(lua_State* L, lua_Debug *ar)
|
||||||
{
|
{
|
||||||
|
@ -268,9 +281,10 @@ static int luaPlayFile(lua_State *L)
|
||||||
strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file));
|
strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file));
|
||||||
file[AUDIO_FILENAME_MAXLEN] = 0;
|
file[AUDIO_FILENAME_MAXLEN] = 0;
|
||||||
PLAY_FILE(file, 0, 0);
|
PLAY_FILE(file, 0, 0);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
PLAY_FILE(filename, 0, 0);
|
else {
|
||||||
|
PLAY_FILE(filename, 0, 0);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,14 +1372,29 @@ static const luaL_Reg lcdLib[] = {
|
||||||
{ NULL, NULL } /* sentinel */
|
{ NULL, NULL } /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
void luaInit()
|
void luaDisable()
|
||||||
|
{
|
||||||
|
POPUP_WARNING("Lua disabled!");
|
||||||
|
luaState = INTERPRETER_PANIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaClose()
|
||||||
{
|
{
|
||||||
if (L) {
|
if (L) {
|
||||||
lua_close(L);
|
PROTECT_LUA() {
|
||||||
|
lua_close(L); // this should not panic, but we make sure anyway
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we can only disable Lua for the rest of the session
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
L = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
L = luaL_newstate();
|
void luaRegisterAll()
|
||||||
|
{
|
||||||
// Init lua
|
// Init lua
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
|
|
||||||
|
@ -1441,13 +1470,50 @@ void luaInit()
|
||||||
lua_registerint(L, "TIMEHOUR", TIMEHOUR);
|
lua_registerint(L, "TIMEHOUR", TIMEHOUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void luaInit()
|
||||||
|
{
|
||||||
|
luaClose();
|
||||||
|
if (luaState != INTERPRETER_PANIC) {
|
||||||
|
L = luaL_newstate();
|
||||||
|
if (L) {
|
||||||
|
// install our panic handler
|
||||||
|
lua_atpanic(L, &custom_lua_atpanic);
|
||||||
|
|
||||||
|
// protect libs and constants registration
|
||||||
|
PROTECT_LUA() {
|
||||||
|
luaRegisterAll();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if we got panic during registration
|
||||||
|
// we disable Lua for this session
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* log error and return */
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void luaFree(ScriptInternalData & sid)
|
void luaFree(ScriptInternalData & sid)
|
||||||
{
|
{
|
||||||
if (sid.run) {
|
PROTECT_LUA() {
|
||||||
luaL_unref(L, LUA_REGISTRYINDEX, sid.run);
|
if (sid.run) {
|
||||||
sid.run = 0;
|
luaL_unref(L, LUA_REGISTRYINDEX, sid.run);
|
||||||
|
sid.run = 0;
|
||||||
|
}
|
||||||
|
if (sid.background) {
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, sid.background);
|
||||||
|
sid.background = 0;
|
||||||
|
}
|
||||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
}
|
}
|
||||||
|
|
||||||
int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL)
|
int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL)
|
||||||
|
@ -1461,47 +1527,55 @@ int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs
|
||||||
|
|
||||||
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
|
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
|
||||||
|
|
||||||
if (luaL_loadfile(L, filename) == 0 &&
|
PROTECT_LUA() {
|
||||||
lua_pcall(L, 0, 1, 0) == 0 &&
|
if (luaL_loadfile(L, filename) == 0 &&
|
||||||
lua_istable(L, -1)) {
|
lua_pcall(L, 0, 1, 0) == 0 &&
|
||||||
|
lua_istable(L, -1)) {
|
||||||
|
|
||||||
luaL_checktype(L, -1, LUA_TTABLE);
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
|
|
||||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||||
const char *key = lua_tostring(L, -2);
|
const char *key = lua_tostring(L, -2);
|
||||||
if (!strcmp(key, "init")) {
|
if (!strcmp(key, "init")) {
|
||||||
init = luaL_ref(L, LUA_REGISTRYINDEX);
|
init = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "run")) {
|
||||||
|
sid.run = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "background")) {
|
||||||
|
sid.background = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
else if (sio && !strcmp(key, "input")) {
|
||||||
|
luaGetInputs(*sio);
|
||||||
|
}
|
||||||
|
else if (sio && !strcmp(key, "output")) {
|
||||||
|
luaGetOutputs(*sio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(key, "run")) {
|
|
||||||
sid.run = luaL_ref(L, LUA_REGISTRYINDEX);
|
if (init) {
|
||||||
lua_pushnil(L);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, init);
|
||||||
}
|
if (lua_pcall(L, 0, 0, 0) != 0) {
|
||||||
else if (!strcmp(key, "background")) {
|
TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1));
|
||||||
sid.background = luaL_ref(L, LUA_REGISTRYINDEX);
|
sid.state = SCRIPT_SYNTAX_ERROR;
|
||||||
lua_pushnil(L);
|
}
|
||||||
}
|
luaL_unref(L, LUA_REGISTRYINDEX, init);
|
||||||
else if (sio && !strcmp(key, "input")) {
|
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||||
luaGetInputs(*sio);
|
|
||||||
}
|
|
||||||
else if (sio && !strcmp(key, "output")) {
|
|
||||||
luaGetOutputs(*sio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if (init) {
|
TRACE("Error in script %s: %s", filename, lua_tostring(L, -1));
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, init);
|
sid.state = SCRIPT_SYNTAX_ERROR;
|
||||||
luaL_unref(L, LUA_REGISTRYINDEX, init);
|
|
||||||
if (lua_pcall(L, 0, 0, 0) != 0) {
|
|
||||||
TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1));
|
|
||||||
sid.state = SCRIPT_SYNTAX_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TRACE("Error in script %s: %s", filename, lua_tostring(L, -1));
|
TRACE("Panic in script %s: %s", filename, lua_tostring(L, -1));
|
||||||
sid.state = SCRIPT_SYNTAX_ERROR;
|
sid.state = SCRIPT_PANIC;
|
||||||
}
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
|
||||||
if (sid.state != SCRIPT_OK) {
|
if (sid.state != SCRIPT_OK) {
|
||||||
luaFree(sid);
|
luaFree(sid);
|
||||||
|
@ -1663,6 +1737,9 @@ void luaError(uint8_t error)
|
||||||
case SCRIPT_KILLED:
|
case SCRIPT_KILLED:
|
||||||
msg = "Script killed";
|
msg = "Script killed";
|
||||||
break;
|
break;
|
||||||
|
case SCRIPT_PANIC:
|
||||||
|
msg = "Script panic";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
POPUP_WARNING(msg);
|
POPUP_WARNING(msg);
|
||||||
}
|
}
|
||||||
|
@ -1670,22 +1747,198 @@ void luaError(uint8_t error)
|
||||||
|
|
||||||
void luaExec(const char *filename)
|
void luaExec(const char *filename)
|
||||||
{
|
{
|
||||||
LUA_RESET();
|
luaInit();
|
||||||
|
|
||||||
standaloneScript.state = SCRIPT_NOFILE;
|
standaloneScript.state = SCRIPT_NOFILE;
|
||||||
int result = luaLoad(filename, standaloneScript);
|
int result = luaLoad(filename, standaloneScript);
|
||||||
// TODO the same with run ...
|
// TODO the same with run ...
|
||||||
if (result == SCRIPT_OK) {
|
if (result == SCRIPT_OK) {
|
||||||
luaState = LUASTATE_STANDALONE_SCRIPT_RUNNING;
|
luaState = INTERPRETER_RUNNING_STANDALONE_SCRIPT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
luaError(result);
|
luaError(result);
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void luaDoOneRunStandalone(uint8_t evt)
|
||||||
|
{
|
||||||
|
static uint8_t luaDisplayStatistics = false;
|
||||||
|
|
||||||
|
if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) {
|
||||||
|
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run);
|
||||||
|
lua_pushinteger(L, evt);
|
||||||
|
if (lua_pcall(L, 1, 1, 0) == 0) {
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
if (instructionsPercent > 100) {
|
||||||
|
TRACE("Script killed");
|
||||||
|
standaloneScript.state = SCRIPT_KILLED;
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
else if (lua_isstring(L, -1)) {
|
||||||
|
char nextScript[_MAX_LFN+1];
|
||||||
|
strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN);
|
||||||
|
nextScript[_MAX_LFN] = '\0';
|
||||||
|
luaExec(nextScript);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("Script error");
|
||||||
|
standaloneScript.state = SCRIPT_SYNTAX_ERROR;
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int scriptResult = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1); /* pop returned value */
|
||||||
|
if (scriptResult != 0) {
|
||||||
|
TRACE("Script finished with status %d", scriptResult);
|
||||||
|
standaloneScript.state = SCRIPT_NOFILE;
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
else if (luaDisplayStatistics) {
|
||||||
|
lcd_hline(0, 7*FH-1, lcdLastPos+FW, ERASE);
|
||||||
|
lcd_puts(0, 7*FH, "GV Use: ");
|
||||||
|
lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT);
|
||||||
|
lcd_putc(lcdLastPos, 7*FH, 'b');
|
||||||
|
lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE);
|
||||||
|
lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("Script error: %s", lua_tostring(L, -1));
|
||||||
|
standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (standaloneScript.state != SCRIPT_OK) {
|
||||||
|
luaError(standaloneScript.state);
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt == EVT_KEY_LONG(KEY_EXIT)) {
|
||||||
|
TRACE("Script force exit");
|
||||||
|
killEvents(evt);
|
||||||
|
standaloneScript.state = SCRIPT_NOFILE;
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
else if (evt == EVT_KEY_LONG(KEY_MENU)) {
|
||||||
|
killEvents(evt);
|
||||||
|
luaDisplayStatistics = !luaDisplayStatistics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaDoOneRunPermanentScript(uint8_t evt, int i)
|
||||||
|
{
|
||||||
|
ScriptInternalData & sid = scriptInternalData[i];
|
||||||
|
if (sid.state == SCRIPT_OK) {
|
||||||
|
SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS);
|
||||||
|
int inputsCount = 0;
|
||||||
|
#if defined(SIMU) || defined(DEBUG)
|
||||||
|
const char *filename;
|
||||||
|
#endif
|
||||||
|
ScriptInputsOutputs * sio = NULL;
|
||||||
|
if (sid.reference >= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST) {
|
||||||
|
ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST];
|
||||||
|
sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST];
|
||||||
|
inputsCount = sio->inputsCount;
|
||||||
|
#if defined(SIMU) || defined(DEBUG)
|
||||||
|
filename = sd.file;
|
||||||
|
#endif
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
||||||
|
for (int j=0; j<sio->inputsCount; j++) {
|
||||||
|
if (sio->inputs[j].type == 1)
|
||||||
|
luaGetValueAndPush((uint8_t)sd.inputs[j]);
|
||||||
|
else
|
||||||
|
lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) {
|
||||||
|
CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST];
|
||||||
|
if (!getSwitch(fn.swtch)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(SIMU) || defined(DEBUG)
|
||||||
|
filename = fn.play.name;
|
||||||
|
#endif
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#if defined(SIMU) || defined(DEBUG)
|
||||||
|
filename = "[telem]";
|
||||||
|
#endif
|
||||||
|
if (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view) {
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
||||||
|
lua_pushinteger(L, evt);
|
||||||
|
inputsCount = 1;
|
||||||
|
}
|
||||||
|
else if (sid.background) {
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
|
||||||
|
if (sio) {
|
||||||
|
for (int j=sio->outputsCount-1; j>=0; j--) {
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
|
||||||
|
TRACE("Script %8s disabled", filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sio->outputs[j].value = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (instructionsPercent > 100) {
|
||||||
|
TRACE("Script %8s killed", filename);
|
||||||
|
sid.state = SCRIPT_KILLED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("Script %8s error: %s", filename, lua_tostring(L, -1));
|
||||||
|
sid.state = SCRIPT_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sid.state != SCRIPT_OK) {
|
||||||
|
luaFree(sid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (instructionsPercent > sid.instructions) {
|
||||||
|
sid.instructions = instructionsPercent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaDoGc()
|
||||||
|
{
|
||||||
|
PROTECT_LUA() {
|
||||||
|
lua_gc(L, LUA_GCSTEP /*LUA_GCCOLLECT*/, 0); // LUA_GCSTEP is enough
|
||||||
|
#if defined(SIMU) || defined(DEBUG)
|
||||||
|
static int lastgc = 0;
|
||||||
|
int gc = luaGetMemUsed();
|
||||||
|
if (gc != lastgc) {
|
||||||
|
lastgc = gc;
|
||||||
|
TRACE("GC Use: %dbytes", gc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we disable Lua for the rest of the session
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
}
|
||||||
|
|
||||||
void luaTask(uint8_t evt)
|
void luaTask(uint8_t evt)
|
||||||
{
|
{
|
||||||
lcd_locked = false;
|
lcd_locked = false;
|
||||||
static uint8_t luaDisplayStatistics = false;
|
|
||||||
|
|
||||||
uint32_t t0 = get_tmr10ms();
|
uint32_t t0 = get_tmr10ms();
|
||||||
static uint32_t lastLuaTime = 0;
|
static uint32_t lastLuaTime = 0;
|
||||||
|
@ -1695,176 +1948,40 @@ void luaTask(uint8_t evt)
|
||||||
maxLuaInterval = interval;
|
maxLuaInterval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (luaState & LUASTATE_STANDALONE_SCRIPT_RUNNING) {
|
if (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) {
|
||||||
// standalone script
|
PROTECT_LUA() {
|
||||||
if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) {
|
luaDoOneRunStandalone(evt);
|
||||||
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run);
|
|
||||||
lua_pushinteger(L, evt);
|
|
||||||
if (lua_pcall(L, 1, 1, 0) == 0) {
|
|
||||||
if (!lua_isnumber(L, -1)) {
|
|
||||||
if (instructionsPercent > 100) {
|
|
||||||
TRACE("Script killed");
|
|
||||||
standaloneScript.state = SCRIPT_KILLED;
|
|
||||||
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS;
|
|
||||||
}
|
|
||||||
else if (lua_isstring(L, -1)) {
|
|
||||||
char nextScript[_MAX_LFN+1];
|
|
||||||
strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN);
|
|
||||||
nextScript[_MAX_LFN] = '\0';
|
|
||||||
luaExec(nextScript);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TRACE("Script error");
|
|
||||||
standaloneScript.state = SCRIPT_SYNTAX_ERROR;
|
|
||||||
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int scriptResult = lua_tointeger(L, -1);
|
|
||||||
lua_pop(L, 1); /* pop returned value */
|
|
||||||
if (scriptResult != 0) {
|
|
||||||
TRACE("Script finished with status %d", scriptResult);
|
|
||||||
standaloneScript.state = SCRIPT_NOFILE;
|
|
||||||
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS;
|
|
||||||
}
|
|
||||||
else if (luaDisplayStatistics) {
|
|
||||||
int gc = 1000*lua_gc(L, LUA_GCCOUNT, 0) + lua_gc(L, LUA_GCCOUNTB, 0);
|
|
||||||
lcd_hline(0, 7*FH-1, lcdLastPos+FW, ERASE);
|
|
||||||
lcd_puts(0, 7*FH, "GV Use: ");
|
|
||||||
lcd_outdezAtt(lcdLastPos, 7*FH, gc, LEFT);
|
|
||||||
lcd_putc(lcdLastPos, 7*FH, 'b');
|
|
||||||
lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE);
|
|
||||||
lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TRACE("Script error: %s", lua_tostring(L, -1));
|
|
||||||
standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
|
|
||||||
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (standaloneScript.state != SCRIPT_OK) {
|
|
||||||
luaError(standaloneScript.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evt == EVT_KEY_LONG(KEY_EXIT)) {
|
|
||||||
TRACE("Script force exit");
|
|
||||||
killEvents(evt);
|
|
||||||
standaloneScript.state = SCRIPT_NOFILE;
|
|
||||||
luaState = LUASTATE_RELOAD_MODEL_SCRIPTS;
|
|
||||||
}
|
|
||||||
else if (evt == EVT_KEY_LONG(KEY_MENU)) {
|
|
||||||
killEvents(evt);
|
|
||||||
luaDisplayStatistics = !luaDisplayStatistics;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
POPUP_WARNING("Script Panic!");
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// model scripts
|
// model scripts
|
||||||
if (luaState & LUASTATE_RELOAD_MODEL_SCRIPTS) {
|
if (luaState & INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
|
||||||
luaState = 0;
|
luaState = 0;
|
||||||
LUA_RESET();
|
luaInit();
|
||||||
|
if (!L) return;
|
||||||
luaLoadPermanentScripts();
|
luaLoadPermanentScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<luaScriptsCount; i++) {
|
for (int i=0; i<luaScriptsCount; i++) {
|
||||||
ScriptInternalData & sid = scriptInternalData[i];
|
PROTECT_LUA() {
|
||||||
if (sid.state == SCRIPT_OK) {
|
luaDoOneRunPermanentScript(evt, i);
|
||||||
SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS);
|
|
||||||
int inputsCount = 0;
|
|
||||||
#if defined(SIMU) || defined(DEBUG)
|
|
||||||
const char *filename;
|
|
||||||
#endif
|
|
||||||
ScriptInputsOutputs * sio = NULL;
|
|
||||||
if (sid.reference >= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST) {
|
|
||||||
ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST];
|
|
||||||
sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST];
|
|
||||||
inputsCount = sio->inputsCount;
|
|
||||||
#if defined(SIMU) || defined(DEBUG)
|
|
||||||
filename = sd.file;
|
|
||||||
#endif
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
|
||||||
for (int j=0; j<sio->inputsCount; j++) {
|
|
||||||
if (sio->inputs[j].type == 1)
|
|
||||||
luaGetValueAndPush((uint8_t)sd.inputs[j]);
|
|
||||||
else
|
|
||||||
lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) {
|
|
||||||
CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST];
|
|
||||||
if (!getSwitch(fn.swtch)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#if defined(SIMU) || defined(DEBUG)
|
|
||||||
filename = fn.play.name;
|
|
||||||
#endif
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if defined(SIMU) || defined(DEBUG)
|
|
||||||
filename = "[telem]";
|
|
||||||
#endif
|
|
||||||
if (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view) {
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
|
||||||
lua_pushinteger(L, evt);
|
|
||||||
inputsCount = 1;
|
|
||||||
}
|
|
||||||
else if (sid.background) {
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
|
|
||||||
if (sio) {
|
|
||||||
for (int j=sio->outputsCount-1; j>=0; j--) {
|
|
||||||
if (!lua_isnumber(L, -1)) {
|
|
||||||
sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
|
|
||||||
TRACE("Script %8s disabled", filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sio->outputs[j].value = lua_tointeger(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (instructionsPercent > 100) {
|
|
||||||
TRACE("Script %8s killed", filename);
|
|
||||||
sid.state = SCRIPT_KILLED;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TRACE("Script %8s error: %s", filename, lua_tostring(L, -1));
|
|
||||||
sid.state = SCRIPT_SYNTAX_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sid.state != SCRIPT_OK) {
|
|
||||||
luaFree(sid);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (instructionsPercent > sid.instructions) {
|
|
||||||
sid.instructions = instructionsPercent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// we disable this script for the rest of the session
|
||||||
|
ScriptInternalData & sid = scriptInternalData[i];
|
||||||
|
sid.state = SCRIPT_PANIC;
|
||||||
|
luaFree(sid);
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
luaDoGc();
|
||||||
|
|
||||||
#if defined(SIMU) || defined(DEBUG)
|
|
||||||
static int lastgc = 0;
|
|
||||||
int gc = luaGetMemUsed();
|
|
||||||
if (gc != lastgc) {
|
|
||||||
lastgc = gc;
|
|
||||||
TRACE("GC Use: %dbytes", gc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
t0 = get_tmr10ms() - t0;
|
t0 = get_tmr10ms() - t0;
|
||||||
if (t0 > maxLuaDuration) {
|
if (t0 > maxLuaDuration) {
|
||||||
|
@ -1874,5 +1991,5 @@ void luaTask(uint8_t evt)
|
||||||
|
|
||||||
int luaGetMemUsed()
|
int luaGetMemUsed()
|
||||||
{
|
{
|
||||||
return 1000*lua_gc(L, LUA_GCCOUNT, 0) + lua_gc(L, LUA_GCCOUNTB, 0);
|
return (lua_gc(L, LUA_GCCOUNT, 0) << 10) + lua_gc(L, LUA_GCCOUNTB, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2505,6 +2505,10 @@ void opentxClose()
|
||||||
// TODO needed? telemetryEnd();
|
// TODO needed? telemetryEnd();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(LUA)
|
||||||
|
luaClose();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(SDCARD)
|
#if defined(SDCARD)
|
||||||
closeLogs();
|
closeLogs();
|
||||||
sdDone();
|
sdDone();
|
||||||
|
@ -3352,8 +3356,6 @@ void opentxInit(OPENTX_INIT_ARGS)
|
||||||
rtcInit();
|
rtcInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LUA_INIT();
|
|
||||||
|
|
||||||
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
|
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
|
||||||
|
|
||||||
if (UNEXPECTED_SHUTDOWN()) {
|
if (UNEXPECTED_SHUTDOWN()) {
|
||||||
|
|
|
@ -1475,7 +1475,8 @@ enum AUDIO_SOUNDS {
|
||||||
SCRIPT_OK,
|
SCRIPT_OK,
|
||||||
SCRIPT_NOFILE,
|
SCRIPT_NOFILE,
|
||||||
SCRIPT_SYNTAX_ERROR,
|
SCRIPT_SYNTAX_ERROR,
|
||||||
SCRIPT_KILLED
|
SCRIPT_PANIC,
|
||||||
|
SCRIPT_KILLED,
|
||||||
};
|
};
|
||||||
enum ScriptReference {
|
enum ScriptReference {
|
||||||
SCRIPT_MIX_FIRST,
|
SCRIPT_MIX_FIRST,
|
||||||
|
@ -1498,13 +1499,18 @@ enum AUDIO_SOUNDS {
|
||||||
uint8_t outputsCount;
|
uint8_t outputsCount;
|
||||||
ScriptOutput outputs[MAX_SCRIPT_OUTPUTS];
|
ScriptOutput outputs[MAX_SCRIPT_OUTPUTS];
|
||||||
};
|
};
|
||||||
#define LUASTATE_STANDALONE_SCRIPT_RUNNING 1
|
enum InterpreterState {
|
||||||
#define LUASTATE_RELOAD_MODEL_SCRIPTS 2
|
INTERPRETER_RUNNING_PERMANENT_SCRIPTS,
|
||||||
|
INTERPRETER_RUNNING_STANDALONE_SCRIPT,
|
||||||
|
INTERPRETER_RELOAD_PERMANENT_SCRIPTS,
|
||||||
|
INTERPRETER_PANIC,
|
||||||
|
};
|
||||||
extern uint8_t luaState;
|
extern uint8_t luaState;
|
||||||
extern uint8_t luaScriptsCount;
|
extern uint8_t luaScriptsCount;
|
||||||
extern ScriptInternalData standaloneScript;
|
extern ScriptInternalData standaloneScript;
|
||||||
extern ScriptInternalData scriptInternalData[MAX_SCRIPTS];
|
extern ScriptInternalData scriptInternalData[MAX_SCRIPTS];
|
||||||
extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS];
|
extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS];
|
||||||
|
void luaClose();
|
||||||
void luaInit();
|
void luaInit();
|
||||||
void luaTask(uint8_t evt);
|
void luaTask(uint8_t evt);
|
||||||
void luaExec(const char *filename);
|
void luaExec(const char *filename);
|
||||||
|
@ -1513,13 +1519,23 @@ enum AUDIO_SOUNDS {
|
||||||
int luaGetMemUsed();
|
int luaGetMemUsed();
|
||||||
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
||||||
bool isTelemetryScriptAvailable(uint8_t index);
|
bool isTelemetryScriptAvailable(uint8_t index);
|
||||||
#define LUA_INIT()
|
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||||
#define LUA_RESET() luaInit()
|
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||||
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS
|
|
||||||
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS
|
// Lua PROTECT/UNPROTECT
|
||||||
|
#include <setjmp.h>
|
||||||
|
struct our_longjmp {
|
||||||
|
struct our_longjmp *previous;
|
||||||
|
jmp_buf b;
|
||||||
|
volatile int status; /* error code */
|
||||||
|
};
|
||||||
|
extern struct our_longjmp * global_lj;
|
||||||
|
#define PROTECT_LUA() { struct our_longjmp lj; \
|
||||||
|
lj.previous = global_lj; /* chain new error handler */ \
|
||||||
|
global_lj = &lj; \
|
||||||
|
if (setjmp(lj.b) == 0)
|
||||||
|
#define UNPROTECT_LUA() global_lj = lj.previous; } /* restore old error handler */
|
||||||
#else
|
#else
|
||||||
#define LUA_INIT()
|
|
||||||
#define LUA_RESET()
|
|
||||||
#define LUA_LOAD_MODEL_SCRIPTS()
|
#define LUA_LOAD_MODEL_SCRIPTS()
|
||||||
#define LUA_LOAD_MODEL_SCRIPT(idx)
|
#define LUA_LOAD_MODEL_SCRIPT(idx)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -309,8 +309,6 @@ void *main_thread(void *)
|
||||||
|
|
||||||
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
|
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
|
||||||
|
|
||||||
LUA_INIT();
|
|
||||||
|
|
||||||
if (main_thread_running == 1) {
|
if (main_thread_running == 1) {
|
||||||
opentxStart();
|
opentxStart();
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,13 @@ uint32_t stack_free(uint32_t tid)
|
||||||
stack = audioStack;
|
stack = audioStack;
|
||||||
size = AUDIO_STACK_SIZE;
|
size = AUDIO_STACK_SIZE;
|
||||||
break;
|
break;
|
||||||
|
#if defined(PCBTARANIS)
|
||||||
|
case 255:
|
||||||
|
// main stack
|
||||||
|
stack = (OS_STK *)&_main_stack_start;
|
||||||
|
size = ((unsigned char *)&_estack - (unsigned char *)&_main_stack_start) / 4;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +114,7 @@ uint32_t stack_free(uint32_t tid)
|
||||||
for (; i<size; i++)
|
for (; i<size; i++)
|
||||||
if (stack[i] != 0x55555555)
|
if (stack[i] != 0x55555555)
|
||||||
break;
|
break;
|
||||||
return i;
|
return i*4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixerTask(void * pdata)
|
void mixerTask(void * pdata)
|
||||||
|
|
|
@ -183,7 +183,6 @@ int main(int argc, char **argv)
|
||||||
StartEepromThread(NULL);
|
StartEepromThread(NULL);
|
||||||
g_menuStackPtr = 0;
|
g_menuStackPtr = 0;
|
||||||
g_menuStack[0] = menuMainView;
|
g_menuStack[0] = menuMainView;
|
||||||
LUA_RESET();
|
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@ extern const char * zchar2string(const char * zstring, int size);
|
||||||
void luaExecStr(const char * str)
|
void luaExecStr(const char * str)
|
||||||
{
|
{
|
||||||
extern lua_State * L;
|
extern lua_State * L;
|
||||||
|
if (!L) luaInit();
|
||||||
|
if (!L) FAIL() << "No Lua state!";
|
||||||
if (luaL_dostring(L, str)) {
|
if (luaL_dostring(L, str)) {
|
||||||
FAIL() << "lua error: " << lua_tostring(L, -1);
|
FAIL() << "lua error: " << lua_tostring(L, -1);
|
||||||
}
|
}
|
||||||
|
@ -98,4 +100,51 @@ TEST(Lua, testSetTelemetryChannel)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Lua, testPanicProtection)
|
||||||
|
{
|
||||||
|
bool passed = false;
|
||||||
|
PROTECT_LUA() {
|
||||||
|
PROTECT_LUA() {
|
||||||
|
//simulate panic
|
||||||
|
longjmp(global_lj->b, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//we should come here
|
||||||
|
passed = true;
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// an not here
|
||||||
|
// TRACE("testLuaProtection: test 1 FAILED");
|
||||||
|
FAIL() << "Failed test 1";
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA()
|
||||||
|
|
||||||
|
EXPECT_EQ(passed, true);
|
||||||
|
|
||||||
|
passed = false;
|
||||||
|
|
||||||
|
PROTECT_LUA() {
|
||||||
|
PROTECT_LUA() {
|
||||||
|
int a = 5;
|
||||||
|
a = a; // avoids the warning
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//we should not come here
|
||||||
|
// TRACE("testLuaProtection: test 2 FAILED");
|
||||||
|
FAIL() << "Failed test 2";
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA()
|
||||||
|
//simulate panic
|
||||||
|
longjmp(global_lj->b, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we should come here
|
||||||
|
passed = true;
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA()
|
||||||
|
|
||||||
|
EXPECT_EQ(passed, true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue