From ea122610efe0c015251169ff91253ba9088bc059 Mon Sep 17 00:00:00 2001 From: bsongis Date: Sat, 13 Sep 2014 15:41:52 +0200 Subject: [PATCH] LTR patch (modified) applied. Saves around 8-10k RAM during the interpreter initialization Conflicts: radio/src/Makefile radio/src/lua.cpp radio/src/lua/src/linit.c --- radio/src/Makefile | 2 +- radio/src/lua.cpp | 148 +++++++++++++------------- radio/src/lua/src/lapi.c | 29 +++-- radio/src/lua/src/lauxlib.h | 6 ++ radio/src/lua/src/lbaselib.c | 25 ++--- radio/src/lua/src/lbitlib.c | 10 +- radio/src/lua/src/ldo.c | 5 +- radio/src/lua/src/linit.c | 18 +++- radio/src/lua/src/lmathlib.c | 20 ++-- radio/src/lua/src/lobject.h | 14 ++- radio/src/lua/src/lrotable.c | 86 +++++++++++++++ radio/src/lua/src/lrotable.h | 37 +++++++ radio/src/lua/src/ltable.c | 2 +- radio/src/lua/src/ltm.c | 3 +- radio/src/lua/src/lua.h | 20 ++-- radio/src/lua/src/luaconf.h | 2 +- radio/src/lua/src/lvm.c | 200 ++++++++++++++++++++++++++--------- 17 files changed, 444 insertions(+), 183 deletions(-) create mode 100644 radio/src/lua/src/lrotable.c create mode 100644 radio/src/lua/src/lrotable.h diff --git a/radio/src/Makefile b/radio/src/Makefile index 47118c158..06d2a6f53 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -727,7 +727,7 @@ ifeq ($(PCB), TARANIS) CPPSRC += lua.cpp LUASRC = lua/src/lapi.c lua/src/lcode.c lua/src/lctype.c lua/src/ldebug.c lua/src/ldo.c lua/src/ldump.c lua/src/lfunc.c lua/src/lgc.c lua/src/llex.c lua/src/lmem.c \ lua/src/lobject.c lua/src/lopcodes.c lua/src/lparser.c lua/src/lstate.c lua/src/lstring.c lua/src/ltable.c lua/src/ltm.c lua/src/lundump.c lua/src/lvm.c lua/src/lzio.c \ - lua/src/lbaselib.c lua/src/linit.c lua/src/lmathlib.c lua/src/loadlib.c lua/src/lauxlib.c lua/src/ltablib.c lua/src/lcorolib.c lua/src/lbitlib.c + lua/src/lbaselib.c lua/src/linit.c lua/src/lmathlib.c lua/src/lbitlib.c lua/src/loadlib.c lua/src/lauxlib.c lua/src/ltablib.c lua/src/lcorolib.c SRC += $(LUASRC) LUADEP = lua_exports.cpp endif diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index 224f1b88f..212ab49f8 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -45,6 +45,7 @@ extern "C" { #include #include #include + #include #if !defined(SIMU) } #endif @@ -1322,7 +1323,77 @@ int luaGetOutputs(ScriptInputsOutputs & sid) return 0; } -static const luaL_Reg modelLib[] = { +const luaL_Reg opentxLib[] = { + { "getTime", luaGetTime }, + { "getVersion", luaGetVersion }, + { "getGeneralSettings", luaGetGeneralSettings }, + { "getValue", luaGetValue }, + { "getFieldInfo", luaGetFieldInfo }, + { "playFile", luaPlayFile }, + { "playNumber", luaPlayNumber }, + { "playDuration", luaPlayDuration }, + { "playTone", luaPlayTone }, + { "popupInput", luaPopupInput }, + { "defaultStick", luaDefaultStick }, + { "defaultChannel", luaDefaultChannel }, + { "killEvents", luaKillEvents }, + { NULL, NULL } /* sentinel */ +}; + +const luaR_value_entry opentxConstants[] = { + { "FULLSCALE", RESX }, + { "XXLSIZE", XXLSIZE }, + { "DBLSIZE", DBLSIZE }, + { "MIDSIZE", MIDSIZE }, + { "SMLSIZE", SMLSIZE }, + { "INVERS", INVERS }, + { "LEFT", LEFT }, + { "PREC1", PREC1 }, + { "PREC2", PREC2 }, + { "BLINK", BLINK }, + { "VALUE", 0 }, + { "SOURCE", 1 }, + { "REPLACE", MLTPX_REP }, + { "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT }, + { "MIXSRC_Rud", MIXSRC_Rud }, + { "MIXSRC_Ele", MIXSRC_Ele }, + { "MIXSRC_Thr", MIXSRC_Thr }, + { "MIXSRC_Ail", MIXSRC_Ail }, + { "MIXSRC_SA", MIXSRC_SA }, + { "MIXSRC_SB", MIXSRC_SB }, + { "MIXSRC_SC", MIXSRC_SC }, + { "MIXSRC_SD", MIXSRC_SD }, + { "MIXSRC_SE", MIXSRC_SE }, + { "MIXSRC_SF", MIXSRC_SF }, + { "MIXSRC_SG", MIXSRC_SG }, + { "MIXSRC_SH", MIXSRC_SH }, + { "MIXSRC_CH1", MIXSRC_CH1 }, + { "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH }, + { "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU) }, + { "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE) }, + { "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE) }, + { "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER) }, + { "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, + { "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT) }, + { "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS) }, + { "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS) }, + { "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS) }, + { "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS) }, + { "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS) }, + { "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS) }, + { "FILL_WHITE", FILL_WHITE }, + { "GREY_DEFAULT", GREY_DEFAULT }, + { "SOLID", SOLID }, + { "DOTTED", DOTTED }, + { "LCD_W", LCD_W }, + { "LCD_H", LCD_H }, + { "PLAY_NOW", PLAY_NOW }, + { "PLAY_BACKGROUND", PLAY_BACKGROUND }, + { "TIMEHOUR", TIMEHOUR }, + { NULL, 0 } /* sentinel */ +}; + +const luaL_Reg modelLib[] = { { "getInfo", luaModelGetInfo }, { "setInfo", luaModelSetInfo }, { "getTimer", luaModelGetTimer }, @@ -1351,7 +1422,7 @@ static const luaL_Reg modelLib[] = { { NULL, NULL } /* sentinel */ }; -static const luaL_Reg lcdLib[] = { +const luaL_Reg lcdLib[] = { { "lock", luaLcdLock }, { "clear", luaLcdClear }, { "getLastPos", luaLcdGetLastPos }, @@ -1397,77 +1468,6 @@ void luaRegisterAll() { // Init lua luaL_openlibs(L); - - // Push OpenTX libs - lua_registerlib(L, "model", modelLib); - lua_registerlib(L, "lcd", lcdLib); - - // Push OpenTX functions - lua_register(L, "getTime", luaGetTime); - lua_register(L, "getVersion", luaGetVersion); - lua_register(L, "getGeneralSettings", luaGetGeneralSettings); - lua_register(L, "getValue", luaGetValue); - lua_register(L, "getFieldInfo", luaGetFieldInfo); - - lua_register(L, "playFile", luaPlayFile); - lua_register(L, "playNumber", luaPlayNumber); - lua_register(L, "playDuration", luaPlayDuration); - lua_register(L, "playTone", luaPlayTone); - lua_register(L, "popupInput", luaPopupInput); - lua_register(L, "defaultStick", luaDefaultStick); - lua_register(L, "defaultChannel", luaDefaultChannel); - lua_register(L, "killEvents", luaKillEvents); - - // Push OpenTX constants - lua_registerint(L, "FULLSCALE", RESX); - lua_registerint(L, "XXLSIZE", XXLSIZE); - lua_registerint(L, "DBLSIZE", DBLSIZE); - lua_registerint(L, "MIDSIZE", MIDSIZE); - lua_registerint(L, "SMLSIZE", SMLSIZE); - lua_registerint(L, "INVERS", INVERS); - lua_registerint(L, "LEFT", LEFT); - lua_registerint(L, "PREC1", PREC1); - lua_registerint(L, "PREC2", PREC2); - lua_registerint(L, "BLINK", BLINK); - lua_registerint(L, "VALUE", 0); - lua_registerint(L, "SOURCE", 1); - lua_registerint(L, "REPLACE", MLTPX_REP); - lua_registerint(L, "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT); - lua_registerint(L, "MIXSRC_Rud", MIXSRC_Rud); - lua_registerint(L, "MIXSRC_Ele", MIXSRC_Ele); - lua_registerint(L, "MIXSRC_Thr", MIXSRC_Thr); - lua_registerint(L, "MIXSRC_Ail", MIXSRC_Ail); - lua_registerint(L, "MIXSRC_SA", MIXSRC_SA); - lua_registerint(L, "MIXSRC_SB", MIXSRC_SB); - lua_registerint(L, "MIXSRC_SC", MIXSRC_SC); - lua_registerint(L, "MIXSRC_SD", MIXSRC_SD); - lua_registerint(L, "MIXSRC_SE", MIXSRC_SE); - lua_registerint(L, "MIXSRC_SF", MIXSRC_SF); - lua_registerint(L, "MIXSRC_SG", MIXSRC_SG); - lua_registerint(L, "MIXSRC_SH", MIXSRC_SH); - lua_registerint(L, "MIXSRC_CH1", MIXSRC_CH1); - lua_registerint(L, "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH); - lua_registerint(L, "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU)); - lua_registerint(L, "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE)); - lua_registerint(L, "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE)); - lua_registerint(L, "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER)); - lua_registerint(L, "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER)); - lua_registerint(L, "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT)); - lua_registerint(L, "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS)); - lua_registerint(L, "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS)); - lua_registerint(L, "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS)); - lua_registerint(L, "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS)); - lua_registerint(L, "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS)); - lua_registerint(L, "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS)); - lua_registerint(L, "FILL_WHITE", FILL_WHITE); - lua_registerint(L, "GREY_DEFAULT", GREY_DEFAULT); - lua_registerint(L, "SOLID", SOLID); - lua_registerint(L, "DOTTED", DOTTED); - lua_registerint(L, "LCD_W", LCD_W); - lua_registerint(L, "LCD_H", LCD_H); - lua_registerint(L, "PLAY_NOW", PLAY_NOW); - lua_registerint(L, "PLAY_BACKGROUND", PLAY_BACKGROUND); - lua_registerint(L, "TIMEHOUR", TIMEHOUR); } void luaInit() @@ -1963,7 +1963,7 @@ void luaTask(uint8_t evt) } if (luaState == INTERPRETER_PANIC) { - return; + return; } if (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) { diff --git a/radio/src/lua/src/lapi.c b/radio/src/lua/src/lapi.c index 791d85454..353018f88 100644 --- a/radio/src/lua/src/lapi.c +++ b/radio/src/lua/src/lapi.c @@ -260,7 +260,7 @@ LUA_API const char *lua_typename (lua_State *L, int t) { LUA_API int lua_iscfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); + return (ttislcf(o) || ttislightfunction(o) || (ttisCclosure(o))); } @@ -417,7 +417,7 @@ LUA_API size_t lua_rawlen (lua_State *L, int idx) { LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); - if (ttislcf(o)) return fvalue(o); + if (ttislcf(o)) return lcfvalue(o); else if (ttisCclosure(o)) return clCvalue(o)->f; else return NULL; /* not a C function */ @@ -446,11 +446,14 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { case LUA_TTABLE: return hvalue(o); case LUA_TLCL: return clLvalue(o); case LUA_TCCL: return clCvalue(o); - case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); + case LUA_TLCF: return cast(void *, cast(size_t, lcfvalue(o))); case LUA_TTHREAD: return thvalue(o); case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: return lua_touserdata(L, idx); + case LUA_TROTABLE: + case LUA_TLIGHTFUNCTION: + return pvalue(o); default: return NULL; } } @@ -551,11 +554,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { return ret; } - LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { - setfvalue(L->top, fn); + setlcfvalue(L->top, fn); } else { Closure *cl; @@ -573,7 +575,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_unlock(L); } - LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ @@ -589,6 +590,19 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_unlock(L); } +LUA_API void lua_pushrotable (lua_State *L, void *p) { + lua_lock(L); + setrvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + +LUA_API void lua_pushlightfunction(lua_State *L, void *p) { + lua_lock(L); + setlfvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); @@ -598,8 +612,6 @@ LUA_API int lua_pushthread (lua_State *L) { return (G(L)->mainthread == L); } - - /* ** get functions (Lua -> stack) */ @@ -1008,7 +1020,6 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { return status; } - LUA_API int lua_status (lua_State *L) { return L->status; } diff --git a/radio/src/lua/src/lauxlib.h b/radio/src/lua/src/lauxlib.h index d66471b0b..bb2ba5e97 100644 --- a/radio/src/lua/src/lauxlib.h +++ b/radio/src/lua/src/lauxlib.h @@ -24,6 +24,12 @@ typedef struct luaL_Reg { lua_CFunction func; } luaL_Reg; +extern const luaL_Reg baselib[]; +extern const luaL_Reg mathlib[]; +extern const luaL_Reg opentxLib[]; +extern const luaL_Reg bitlib[]; +extern const luaL_Reg lcdLib[]; +extern const luaL_Reg modelLib[]; LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); #define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) diff --git a/radio/src/lua/src/lbaselib.c b/radio/src/lua/src/lbaselib.c index a9521e536..806c8e0b5 100644 --- a/radio/src/lua/src/lbaselib.c +++ b/radio/src/lua/src/lbaselib.c @@ -16,7 +16,7 @@ #include "lauxlib.h" #include "lualib.h" - +#include "lrotable.h" static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ @@ -411,8 +411,7 @@ static int luaB_tostring (lua_State *L) { return 1; } - -static const luaL_Reg base_funcs[] = { +const luaL_Reg baselib[] = { {"assert", luaB_assert}, {"collectgarbage", luaB_collectgarbage}, {"dofile", luaB_dofile}, @@ -441,16 +440,10 @@ static const luaL_Reg base_funcs[] = { {NULL, NULL} }; - -LUAMOD_API int luaopen_base (lua_State *L) { - /* set global _G */ - lua_pushglobaltable(L); - lua_pushglobaltable(L); - lua_setfield(L, -2, "_G"); - /* open lib into global table */ - luaL_setfuncs(L, base_funcs, 0); - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ - return 1; -} - +#if 0 +// TODO +const luaR_value_entry baselib_vals[] = { + {"_VERSION", LUA_VERSION}, + {NULL, 0} +}; +#endif diff --git a/radio/src/lua/src/lbitlib.c b/radio/src/lua/src/lbitlib.c index 5910f135d..4862af712 100644 --- a/radio/src/lua/src/lbitlib.c +++ b/radio/src/lua/src/lbitlib.c @@ -11,6 +11,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lrotable.h" /* number of bits to consider in a number */ #if !defined(LUA_NBITS) @@ -185,7 +186,7 @@ static int b_replace (lua_State *L) { } -static const luaL_Reg bitlib[] = { +const luaL_Reg bitlib[] = { {"arshift", b_arshift}, {"band", b_and}, {"bnot", b_not}, @@ -201,10 +202,11 @@ static const luaL_Reg bitlib[] = { {NULL, NULL} }; - +const luaR_value_entry bitlib_vals[] = { + {NULL, 0} +}; LUAMOD_API int luaopen_bit32 (lua_State *L) { - luaL_newlib(L, bitlib); - return 1; + return 0; } diff --git a/radio/src/lua/src/ldo.c b/radio/src/lua/src/ldo.c index aafa3dca2..32d6e5ed4 100644 --- a/radio/src/lua/src/ldo.c +++ b/radio/src/lua/src/ldo.c @@ -299,7 +299,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { ptrdiff_t funcr = savestack(L, func); switch (ttype(func)) { case LUA_TLCF: /* light C function */ - f = fvalue(func); + f = lcfvalue(func); + goto Cfunc; + case LUA_TLIGHTFUNCTION: + f = check_exp(ttislightfunction(func), val_(func).f); goto Cfunc; case LUA_TCCL: { /* C closure */ f = clCvalue(func)->f; diff --git a/radio/src/lua/src/linit.c b/radio/src/lua/src/linit.c index e4a465e40..23596a6dc 100644 --- a/radio/src/lua/src/linit.c +++ b/radio/src/lua/src/linit.c @@ -20,25 +20,37 @@ #include "lualib.h" #include "lauxlib.h" +#include "lrotable.h" /* ** these libs are loaded by lua.c and are readily available to any Lua ** program */ static const luaL_Reg loadedlibs[] = { - {"_G", luaopen_base}, + // {"_G", luaopen_base}, // {LUA_LOADLIBNAME, luaopen_package}, // {LUA_COLIBNAME, luaopen_coroutine}, // {LUA_TABLIBNAME, luaopen_table}, // {LUA_IOLIBNAME, luaopen_io}, // {LUA_OSLIBNAME, luaopen_os}, // {LUA_STRLIBNAME, luaopen_string}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_MATHLIBNAME, luaopen_math}, + // {LUA_BITLIBNAME, luaopen_bit32}, + // {LUA_MATHLIBNAME, luaopen_math}, // {LUA_DBLIBNAME, luaopen_debug}, {NULL, NULL} }; +/* The read-only tables are defined here */ +const luaR_table lua_rotable[] = +{ + {LUA_MATHLIBNAME, mathlib, mathlib_vals}, + {LUA_BITLIBNAME, bitlib, NULL}, + {"lcd", lcdLib, NULL}, + {"model", modelLib, NULL}, + {"__baselib", baselib, NULL}, + {"__opentx", opentxLib, opentxConstants}, + {NULL, NULL, NULL} +}; /* ** these libs are preloaded and must be required before used diff --git a/radio/src/lua/src/lmathlib.c b/radio/src/lua/src/lmathlib.c index 20292d720..75ad5f2a8 100644 --- a/radio/src/lua/src/lmathlib.c +++ b/radio/src/lua/src/lmathlib.c @@ -15,6 +15,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lrotable.h" #undef PI #define PI ((lua_Number)(3.1415926535897932384626433832795)) @@ -228,20 +229,19 @@ static int math_randomseed (lua_State *L) { return 0; } - -static const luaL_Reg mathlib[] = { +const luaL_Reg mathlib[] = { {"abs", math_abs}, {"acos", math_acos}, {"asin", math_asin}, {"atan2", math_atan2}, {"atan", math_atan}, {"ceil", math_ceil}, - {"cosh", math_cosh}, + {"cosh", math_cosh}, {"cos", math_cos}, {"deg", math_deg}, {"exp", math_exp}, {"floor", math_floor}, - {"fmod", math_fmod}, + {"fmod", math_fmod}, {"frexp", math_frexp}, {"ldexp", math_ldexp}, #if defined(LUA_COMPAT_LOG10) @@ -263,16 +263,16 @@ static const luaL_Reg mathlib[] = { {NULL, NULL} }; +const luaR_value_entry mathlib_vals[] = { + {"pi", PI}, + {"huge", HUGE_VAL}, + {NULL, 0} +}; /* ** Open math library */ LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); - return 1; + return 0; } diff --git a/radio/src/lua/src/lobject.h b/radio/src/lua/src/lobject.h index 7ee7ef9fa..4a0375464 100644 --- a/radio/src/lua/src/lobject.h +++ b/radio/src/lua/src/lobject.h @@ -137,6 +137,8 @@ typedef union Value Value; #define ttisnil(o) checktag((o), LUA_TNIL) #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisrotable(o) checktag((o), LUA_TROTABLE) +#define ttislightfunction(o) checktag((o), LUA_TLIGHTFUNCTION) #define ttisstring(o) checktype((o), LUA_TSTRING) #define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) #define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) @@ -156,6 +158,8 @@ typedef union Value Value; #define nvalue(o) check_exp(ttisnumber(o), num_(o)) #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define rvalue(o) check_exp(ttisrotable(o), val_(o).p) +#define lfvalue(o) check_exp(ttislightfunction(o), val_(o).p) #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) #define tsvalue(o) (&rawtsvalue(o)->tsv) #define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) @@ -163,7 +167,7 @@ typedef union Value Value; #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) #define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define lcfvalue(o) check_exp(ttislcf(o), val_(o).f) #define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) #define bvalue(o) check_exp(ttisboolean(o), val_(o).b) #define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) @@ -192,12 +196,18 @@ typedef union Value Value; #define setnilvalue(obj) settt_(obj, LUA_TNIL) -#define setfvalue(obj,x) \ +#define setlcfvalue(obj,x) \ { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } #define setpvalue(obj,x) \ { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } +#define setrvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TROTABLE); } + +#define setlfvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTFUNCTION); } + #define setbvalue(obj,x) \ { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } diff --git a/radio/src/lua/src/lrotable.c b/radio/src/lua/src/lrotable.c new file mode 100644 index 000000000..d64f4d14a --- /dev/null +++ b/radio/src/lua/src/lrotable.c @@ -0,0 +1,86 @@ +/* Read-only tables for Lua */ + +#include +#include "lua.h" +#include "lauxlib.h" +#include "lrotable.h" + +/* Local defines */ +#define LUAR_FINDFUNCTION 0 +#define LUAR_FINDVALUE 1 + +/* Utility function: find a key in a given table (of functions or constants) */ +static luaR_result luaR_findkey(const void *where, const char *key, int type, int *found) { + const char *pname; + const luaL_Reg *pf = (luaL_Reg*)where; + const luaR_value_entry *pv = (luaR_value_entry*)where; + int isfunction = type == LUAR_FINDFUNCTION; + *found = 0; + if(!where) + return 0; + while(1) { + if (!(pname = isfunction ? pf->name : pv->name)) + break; + if (!strcmp(pname, key)) { + *found = 1; + return isfunction ? (luaR_result)(size_t)pf->func : (luaR_result)pv->value; + } + pf ++; pv ++; + } + return 0; +} + +/* Find a global "read only table" in the constant lua_rotable array */ +luaR_result luaR_findglobal(const char *name, lu_byte *ptype) { + unsigned i; + *ptype = LUA_TNIL; + if (strlen(name) > LUA_MAX_ROTABLE_NAME) + return 0; + for (i=0; lua_rotable[i].name; i++) { + if (!strcmp(lua_rotable[i].name, name)) { + *ptype = LUA_TROTABLE; + return i+1; + } + if (!strncmp(lua_rotable[i].name, "__", 2)) { + int result = luaR_findentry((void *)(size_t)(i+1), name, ptype); + if (result != 0) { + return result; + } + } + } + return 0; +} + + +int luaR_findfunction(lua_State *L, const luaL_Reg *ptable) { + int found; + const char *key = luaL_checkstring(L, 2); + luaR_result res = luaR_findkey(ptable, key, LUAR_FINDFUNCTION, &found); + if (found) + lua_pushlightfunction(L, (void*)(size_t)res); + else + lua_pushnil(L); + return 1; +} + +luaR_result luaR_findentry(void *data, const char *key, lu_byte *ptype) { + int found; + unsigned idx = (unsigned)(size_t)data - 1; + luaR_result res; + *ptype = LUA_TNIL; + /* First look at the functions */ + res = luaR_findkey(lua_rotable[idx].pfuncs, key, LUAR_FINDFUNCTION, &found); + if (found) { + *ptype = LUA_TLIGHTFUNCTION; + return res; + } + else { + /* Then at the values */ + res = luaR_findkey(lua_rotable[idx].pvalues, key, LUAR_FINDVALUE, &found); + if(found) { + *ptype = LUA_TNUMBER; + return res; + } + } + return 0; +} diff --git a/radio/src/lua/src/lrotable.h b/radio/src/lua/src/lrotable.h new file mode 100644 index 000000000..cd6129466 --- /dev/null +++ b/radio/src/lua/src/lrotable.h @@ -0,0 +1,37 @@ +// Read-only tables for Lua + +#ifndef lrotable_h +#define lrotable_h + +#include "lua.h" +#include "llimits.h" +#include "lauxlib.h" + +typedef lua_Number luaR_result; + +// A number entry in the read only table +typedef struct +{ + const char *name; + lua_Number value; +} luaR_value_entry; + +extern const luaR_value_entry baselib_vals[]; +extern const luaR_value_entry mathlib_vals[]; +extern const luaR_value_entry opentxConstants[]; + +// A mapping between table name and its entries +typedef struct +{ + const char *name; + const luaL_Reg *pfuncs; + const luaR_value_entry *pvalues; +} luaR_table; + +extern const luaR_table lua_rotable[]; + +luaR_result luaR_findglobal(const char *key, lu_byte *ptype); +int luaR_findfunction(lua_State *L, const luaL_Reg *ptable); +luaR_result luaR_findentry(void *data, const char *key, lu_byte *ptype); + +#endif diff --git a/radio/src/lua/src/ltable.c b/radio/src/lua/src/ltable.c index 9ef8af5df..6cea6e5e2 100644 --- a/radio/src/lua/src/ltable.c +++ b/radio/src/lua/src/ltable.c @@ -113,7 +113,7 @@ static Node *mainposition (const Table *t, const TValue *key) { case LUA_TLIGHTUSERDATA: return hashpointer(t, pvalue(key)); case LUA_TLCF: - return hashpointer(t, fvalue(key)); + return hashpointer(t, lcfvalue(key)); default: return hashpointer(t, gcvalue(key)); } diff --git a/radio/src/lua/src/ltm.c b/radio/src/lua/src/ltm.c index e70006dd7..a06cb79e4 100644 --- a/radio/src/lua/src/ltm.c +++ b/radio/src/lua/src/ltm.c @@ -23,12 +23,11 @@ static const char udatatypename[] = "userdata"; LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { "no value", - "nil", "boolean", udatatypename, "number", + "nil", "boolean", "rotable", "lightfunction", udatatypename, "number", "string", "table", "function", udatatypename, "thread", "proto", "upval" /* these last two cases are used for tests only */ }; - void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", diff --git a/radio/src/lua/src/lua.h b/radio/src/lua/src/lua.h index d9ae5c9ea..5dc0db202 100644 --- a/radio/src/lua/src/lua.h +++ b/radio/src/lua/src/lua.h @@ -77,15 +77,17 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 +#define LUA_TROTABLE 2 +#define LUA_TLIGHTFUNCTION 3 +#define LUA_TLIGHTUSERDATA 4 +#define LUA_TNUMBER 5 +#define LUA_TSTRING 6 +#define LUA_TTABLE 7 +#define LUA_TFUNCTION 8 +#define LUA_TUSERDATA 9 +#define LUA_TTHREAD 10 -#define LUA_NUMTAGS 9 +#define LUA_NUMTAGS 11 @@ -214,6 +216,8 @@ LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); LUA_API void (lua_pushboolean) (lua_State *L, int b); LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API void (lua_pushlightfunction) (lua_State *L, void *p); +LUA_API void (lua_pushrotable) (lua_State *L, void *p); LUA_API int (lua_pushthread) (lua_State *L); diff --git a/radio/src/lua/src/luaconf.h b/radio/src/lua/src/luaconf.h index 89524b1b8..4d96f2c77 100644 --- a/radio/src/lua/src/luaconf.h +++ b/radio/src/lua/src/luaconf.h @@ -558,7 +558,7 @@ ** without modifying the main part of the file. */ - +#define LUA_MAX_ROTABLE_NAME 20 #endif diff --git a/radio/src/lua/src/lvm.c b/radio/src/lua/src/lvm.c index 657d5c456..6b049bcf1 100644 --- a/radio/src/lua/src/lvm.c +++ b/radio/src/lua/src/lvm.c @@ -25,7 +25,7 @@ #include "ltable.h" #include "ltm.h" #include "lvm.h" - +#include "lrotable.h" /* limit for table tag-method chains (to avoid loops) */ @@ -106,9 +106,31 @@ static void callTM (lua_State *L, const TValue *f, const TValue *p1, } } +static void lua_getcstr(char *dest, const TString *src, size_t maxsize) { + if (src->tsv.len+1 > maxsize) + dest[0] = '\0'; + else { + memcpy(dest, getstr(src), src->tsv.len); + dest[src->tsv.len] = '\0'; + } +} void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; + if (ttisrotable(t)) { + setnilvalue(val); + if (ttisstring(key)) { + char keyname[LUA_MAX_ROTABLE_NAME + 1]; + lu_byte keytype; + lua_getcstr(keyname, rawtsvalue(key), LUA_MAX_ROTABLE_NAME); + luaR_result res = luaR_findentry(rvalue(t), keyname, &keytype); + if (keytype == LUA_TLIGHTFUNCTION) + setlfvalue(val, (void*)(size_t)res) + else if (keytype == LUA_TNUMBER) + setnvalue(val, (lua_Number)res) + } + return; + } for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ @@ -123,7 +145,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { + if (ttisfunction(tm) || ttislightfunction(tm)) { callTM(L, tm, t, key, val, 1); return; } @@ -264,8 +286,11 @@ int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { case LUA_TNIL: return 1; case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TLIGHTUSERDATA: + case LUA_TROTABLE: + case LUA_TLIGHTFUNCTION: + return pvalue(t1) == pvalue(t2); + case LUA_TLCF: return lcfvalue(t1) == lcfvalue(t2); case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); case LUA_TUSERDATA: { @@ -554,53 +579,97 @@ void luaV_execute (lua_State *L) { lua_assert(base == ci->u.l.base); lua_assert(base <= L->top && L->top < L->stack + L->stacksize); vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE, + case OP_MOVE: setobjs2s(L, ra, RB(i)); - ) - vmcase(OP_LOADK, + break; + + case OP_LOADK: + { TValue *rb = k + GETARG_Bx(i); setobj2s(L, ra, rb); - ) - vmcase(OP_LOADKX, + } + break; + + case OP_LOADKX: + { TValue *rb; lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); rb = k + GETARG_Ax(*ci->u.l.savedpc++); setobj2s(L, ra, rb); - ) - vmcase(OP_LOADBOOL, + } + break; + + case OP_LOADBOOL: setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ - ) - vmcase(OP_LOADNIL, + break; + + case OP_LOADNIL: + { int b = GETARG_B(i); do { setnilvalue(ra++); } while (b--); - ) - vmcase(OP_GETUPVAL, + } + break; + + case OP_GETUPVAL: + { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); - ) - vmcase(OP_GETTABUP, + } + break; + + case OP_GETTABUP: + { int b = GETARG_B(i); - Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); - ) - vmcase(OP_GETTABLE, + if (ttisstring(RKC(i))) { + char keyname[LUA_MAX_ROTABLE_NAME + 1]; + lu_byte keytype; + lua_getcstr(keyname, rawtsvalue(RKC(i)), LUA_MAX_ROTABLE_NAME); + luaR_result res = luaR_findglobal(keyname, &keytype); + if (keytype == LUA_TROTABLE) { + setrvalue(ra, (void*)(size_t)res) + } + else if (keytype == LUA_TLIGHTFUNCTION) + setlfvalue(ra, (void*)(size_t)res) + else if (keytype == LUA_TNUMBER) + setnvalue(ra, (lua_Number)res) + else + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + } + else { + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + } + } + break; + + case OP_GETTABLE: + /* First try to look for a rotable with this name */ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - ) - vmcase(OP_SETTABUP, + break; + + case OP_SETTABUP: + { int a = GETARG_A(i); Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); - ) - vmcase(OP_SETUPVAL, + } + break; + + case OP_SETUPVAL: + { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); - ) - vmcase(OP_SETTABLE, + } + break; + + case OP_SETTABLE: Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - ) - vmcase(OP_NEWTABLE, + break; + + case OP_NEWTABLE: + { int b = GETARG_B(i); int c = GETARG_C(i); Table *t = luaH_new(L); @@ -608,31 +677,43 @@ void luaV_execute (lua_State *L) { if (b != 0 || c != 0) luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); checkGC(L, ra + 1); - ) - vmcase(OP_SELF, + } + break; + + case OP_SELF: + { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); - ) - vmcase(OP_ADD, + } + break; + + case OP_ADD: arith_op(luai_numadd, TM_ADD); - ) - vmcase(OP_SUB, + break; + + case OP_SUB: arith_op(luai_numsub, TM_SUB); - ) - vmcase(OP_MUL, + break; + + case OP_MUL: arith_op(luai_nummul, TM_MUL); - ) - vmcase(OP_DIV, + break; + + case OP_DIV: arith_op(luai_numdiv, TM_DIV); - ) - vmcase(OP_MOD, + break; + + case OP_MOD: arith_op(luai_nummod, TM_MOD); - ) - vmcase(OP_POW, + break; + + case OP_POW: arith_op(luai_numpow, TM_POW); - ) - vmcase(OP_UNM, + break; + + case OP_UNM: + { TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); @@ -641,15 +722,19 @@ void luaV_execute (lua_State *L) { else { Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); } - ) + } + break; + vmcase(OP_NOT, TValue *rb = RB(i); int res = l_isfalse(rb); /* next assignment may change this value */ setbvalue(ra, res); ) + vmcase(OP_LEN, Protect(luaV_objlen(L, ra, RB(i))); ) + vmcase(OP_CONCAT, int b = GETARG_B(i); int c = GETARG_C(i); @@ -662,9 +747,11 @@ void luaV_execute (lua_State *L) { checkGC(L, (ra >= rb ? ra + 1 : rb)); L->top = ci->top; /* restore top */ ) + vmcase(OP_JMP, dojump(ci, i, 0); ) + vmcase(OP_EQ, TValue *rb = RKB(i); TValue *rc = RKC(i); @@ -675,6 +762,7 @@ void luaV_execute (lua_State *L) { donextjump(ci); ) ) + vmcase(OP_LT, Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) @@ -706,7 +794,9 @@ void luaV_execute (lua_State *L) { donextjump(ci); } ) - vmcase(OP_CALL, + + case OP_CALL: + { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ @@ -719,8 +809,11 @@ void luaV_execute (lua_State *L) { ci->callstatus |= CIST_REENTRY; goto newframe; /* restart luaV_execute over new Lua function */ } - ) - vmcase(OP_TAILCALL, + } + break; + + case OP_TAILCALL: + { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); @@ -748,7 +841,8 @@ void luaV_execute (lua_State *L) { lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); goto newframe; /* restart luaV_execute over new Lua function */ } - ) + } + vmcasenb(OP_RETURN, int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; @@ -764,7 +858,9 @@ void luaV_execute (lua_State *L) { goto newframe; /* restart luaV_execute over new Lua function */ } ) - vmcase(OP_FORLOOP, + + case OP_FORLOOP: + { lua_Number step = nvalue(ra+2); lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ lua_Number limit = nvalue(ra+1); @@ -774,7 +870,9 @@ void luaV_execute (lua_State *L) { setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ } - ) + } + break; + vmcase(OP_FORPREP, const TValue *init = ra; const TValue *plimit = ra+1;