From 8f08a61d121ef58757dd86a34ec51912bd787abe Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 5 Dec 2013 11:13:07 +0100 Subject: [PATCH 01/10] Lua interpreter introduced --- radio/src/Makefile | 20 +- radio/src/lua.cpp | 1112 +++ radio/src/lua/Makefile | 114 + radio/src/lua/README | 6 + radio/src/lua/doc/contents.html | 533 + radio/src/lua/doc/logo.gif | Bin 0 -> 4232 bytes radio/src/lua/doc/lua.1 | 116 + radio/src/lua/doc/lua.css | 83 + radio/src/lua/doc/luac.1 | 118 + radio/src/lua/doc/manual.css | 26 + radio/src/lua/doc/manual.html | 10507 ++++++++++++++++++++ radio/src/lua/doc/osi-certified-72x60.png | Bin 0 -> 3774 bytes radio/src/lua/doc/readme.html | 412 + radio/src/lua/src/Makefile | 187 + radio/src/lua/src/lapi.c | 1284 +++ radio/src/lua/src/lapi.h | 24 + radio/src/lua/src/lauxlib.c | 997 ++ radio/src/lua/src/lauxlib.h | 215 + radio/src/lua/src/lbaselib.c | 456 + radio/src/lua/src/lbitlib.c | 210 + radio/src/lua/src/lcode.c | 881 ++ radio/src/lua/src/lcode.h | 83 + radio/src/lua/src/lcorolib.c | 154 + radio/src/lua/src/lctype.c | 52 + radio/src/lua/src/lctype.h | 95 + radio/src/lua/src/ldblib.c | 396 + radio/src/lua/src/ldebug.c | 580 ++ radio/src/lua/src/ldebug.h | 34 + radio/src/lua/src/ldo.c | 673 ++ radio/src/lua/src/ldo.h | 46 + radio/src/lua/src/ldump.c | 173 + radio/src/lua/src/lfunc.c | 161 + radio/src/lua/src/lfunc.h | 33 + radio/src/lua/src/lgc.c | 1213 +++ radio/src/lua/src/lgc.h | 157 + radio/src/lua/src/linit.c | 66 + radio/src/lua/src/liolib.c | 663 ++ radio/src/lua/src/llex.c | 527 + radio/src/lua/src/llex.h | 78 + radio/src/lua/src/llimits.h | 309 + radio/src/lua/src/lmathlib.c | 278 + radio/src/lua/src/lmem.c | 98 + radio/src/lua/src/lmem.h | 57 + radio/src/lua/src/loadlib.c | 731 ++ radio/src/lua/src/lobject.c | 287 + radio/src/lua/src/lobject.h | 607 ++ radio/src/lua/src/lopcodes.c | 107 + radio/src/lua/src/lopcodes.h | 288 + radio/src/lua/src/loslib.c | 322 + radio/src/lua/src/lparser.c | 1638 +++ radio/src/lua/src/lparser.h | 119 + radio/src/lua/src/lstate.c | 322 + radio/src/lua/src/lstate.h | 228 + radio/src/lua/src/lstring.c | 185 + radio/src/lua/src/lstring.h | 46 + radio/src/lua/src/lstrlib.c | 1017 ++ radio/src/lua/src/ltable.c | 589 ++ radio/src/lua/src/ltable.h | 41 + radio/src/lua/src/ltablib.c | 282 + radio/src/lua/src/ltm.c | 77 + radio/src/lua/src/ltm.h | 57 + radio/src/lua/src/lua.c | 496 + radio/src/lua/src/lua.h | 455 + radio/src/lua/src/lua.hpp | 9 + radio/src/lua/src/luac.c | 431 + radio/src/lua/src/luaconf.h | 563 ++ radio/src/lua/src/lualib.h | 55 + radio/src/lua/src/lundump.c | 258 + radio/src/lua/src/lundump.h | 28 + radio/src/lua/src/lvm.c | 867 ++ radio/src/lua/src/lvm.h | 44 + radio/src/lua/src/lzio.c | 76 + radio/src/lua/src/lzio.h | 65 + 73 files changed, 33516 insertions(+), 1 deletion(-) create mode 100644 radio/src/lua.cpp create mode 100644 radio/src/lua/Makefile create mode 100644 radio/src/lua/README create mode 100644 radio/src/lua/doc/contents.html create mode 100644 radio/src/lua/doc/logo.gif create mode 100644 radio/src/lua/doc/lua.1 create mode 100644 radio/src/lua/doc/lua.css create mode 100644 radio/src/lua/doc/luac.1 create mode 100644 radio/src/lua/doc/manual.css create mode 100644 radio/src/lua/doc/manual.html create mode 100644 radio/src/lua/doc/osi-certified-72x60.png create mode 100644 radio/src/lua/doc/readme.html create mode 100644 radio/src/lua/src/Makefile create mode 100644 radio/src/lua/src/lapi.c create mode 100644 radio/src/lua/src/lapi.h create mode 100644 radio/src/lua/src/lauxlib.c create mode 100644 radio/src/lua/src/lauxlib.h create mode 100644 radio/src/lua/src/lbaselib.c create mode 100644 radio/src/lua/src/lbitlib.c create mode 100644 radio/src/lua/src/lcode.c create mode 100644 radio/src/lua/src/lcode.h create mode 100644 radio/src/lua/src/lcorolib.c create mode 100644 radio/src/lua/src/lctype.c create mode 100644 radio/src/lua/src/lctype.h create mode 100644 radio/src/lua/src/ldblib.c create mode 100644 radio/src/lua/src/ldebug.c create mode 100644 radio/src/lua/src/ldebug.h create mode 100644 radio/src/lua/src/ldo.c create mode 100644 radio/src/lua/src/ldo.h create mode 100644 radio/src/lua/src/ldump.c create mode 100644 radio/src/lua/src/lfunc.c create mode 100644 radio/src/lua/src/lfunc.h create mode 100644 radio/src/lua/src/lgc.c create mode 100644 radio/src/lua/src/lgc.h create mode 100644 radio/src/lua/src/linit.c create mode 100644 radio/src/lua/src/liolib.c create mode 100644 radio/src/lua/src/llex.c create mode 100644 radio/src/lua/src/llex.h create mode 100644 radio/src/lua/src/llimits.h create mode 100644 radio/src/lua/src/lmathlib.c create mode 100644 radio/src/lua/src/lmem.c create mode 100644 radio/src/lua/src/lmem.h create mode 100644 radio/src/lua/src/loadlib.c create mode 100644 radio/src/lua/src/lobject.c create mode 100644 radio/src/lua/src/lobject.h create mode 100644 radio/src/lua/src/lopcodes.c create mode 100644 radio/src/lua/src/lopcodes.h create mode 100644 radio/src/lua/src/loslib.c create mode 100644 radio/src/lua/src/lparser.c create mode 100644 radio/src/lua/src/lparser.h create mode 100644 radio/src/lua/src/lstate.c create mode 100644 radio/src/lua/src/lstate.h create mode 100644 radio/src/lua/src/lstring.c create mode 100644 radio/src/lua/src/lstring.h create mode 100644 radio/src/lua/src/lstrlib.c create mode 100644 radio/src/lua/src/ltable.c create mode 100644 radio/src/lua/src/ltable.h create mode 100644 radio/src/lua/src/ltablib.c create mode 100644 radio/src/lua/src/ltm.c create mode 100644 radio/src/lua/src/ltm.h create mode 100644 radio/src/lua/src/lua.c create mode 100644 radio/src/lua/src/lua.h create mode 100644 radio/src/lua/src/lua.hpp create mode 100644 radio/src/lua/src/luac.c create mode 100644 radio/src/lua/src/luaconf.h create mode 100644 radio/src/lua/src/lualib.h create mode 100644 radio/src/lua/src/lundump.c create mode 100644 radio/src/lua/src/lundump.h create mode 100644 radio/src/lua/src/lvm.c create mode 100644 radio/src/lua/src/lvm.h create mode 100644 radio/src/lua/src/lzio.c create mode 100644 radio/src/lua/src/lzio.h diff --git a/radio/src/Makefile b/radio/src/Makefile index 12fb145b1..d21c55513 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -250,6 +250,10 @@ GVARS = NO # Values = NO, POT1, POT2, POT3, 3POS = NO +# Lua interpreter embedded +# Values = NO, NO_MODEL_SCRIPTS, YES +# LUA = NO + # Menu Lock modes # Values = NO, READONLY, NOMENUS MENUS_LOCK == NO @@ -647,6 +651,20 @@ ifeq ($(PCB), TARANIS) EXTRABOARDSRC += targets/taranis/usbd_usr.cpp targets/taranis/usbd_storage_msd.cpp SRC += targets/sky9x/syscalls.c + ifneq ($(LUA), NO) + ifeq ($(LUA), YES) + CPPDEFS += -DLUA_MODEL_SCRIPTS + endif + CPPDEFS += -DLUA + INCDIRS += lua/src + 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/loslib.c lua/src/lbitlib.c lua/src/lstrlib.c lua/src/liolib.c lua/src/ldblib.c + SRC += $(LUASRC) + endif + ifeq ($(SDCARD), YES) EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp CPPDEFS += -DVOICE @@ -1208,7 +1226,7 @@ FOXLIB=-L/usr/local/lib \ -Wl,-rpath,$(FOXPATH)/src/.libs simu: stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp simpgmspace.cpp *.h tra lbm eeprom.bin - g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions + g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions eeprom.bin: dd if=/dev/zero of=$@ bs=1 count=2048 diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp new file mode 100644 index 000000000..88c58af85 --- /dev/null +++ b/radio/src/lua.cpp @@ -0,0 +1,1112 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "opentx.h" + +#if !defined(SIMU) +extern "C" { +#endif + #include + #include + #include +#if !defined(SIMU) +} +#endif + +#define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n))) +#define lua_pushtablenil(L, k) (lua_pushstring(L, (k)), lua_pushnil(L), lua_settable(L, -3)) +#define lua_pushtableboolean(L, k, v) (lua_pushstring(L, (k)), lua_pushboolean(L, (v)), lua_settable(L, -3)) +#define lua_pushtablenumber(L, k, v) (lua_pushstring(L, (k)), lua_pushinteger(L, (v)), lua_settable(L, -3)) +#define lua_pushtablestring(L, k, v) (lua_pushstring(L, (k)), lua_pushstring(L, (v)), lua_settable(L, -3)) +#define lua_pushtablezstring(L, k, v) { char _zz[sizeof(v)+1]; zchar2str(_zz, (v), sizeof(v)); lua_pushstring(L, (k)); lua_pushstring(L, _zz); lua_settable(L, -3); } +#define lua_registerlib(L, name, tab) (luaL_newmetatable(L, name), luaL_setfuncs(L, tab, 0), lua_setglobal(L, name)) + +lua_State *L = NULL; +uint8_t luaState = 0; +ScriptInternalData scriptInternalData[MAX_SCRIPTS] = { { SCRIPT_NOFILE, 0 } }; +ScriptInternalData standaloneScript = { SCRIPT_NOFILE, 0 }; + +#define PERMANENT_SCRIPTS_MAX_INSTRUCTIONS (1000/100) +#define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (10000/100) +#define SCRIPTS_MAX_HEAP 50 +#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x)) + +static int instructionsPercent = 0; +void hook(lua_State* L, lua_Debug *ar) +{ + instructionsPercent++; + if (instructionsPercent > 100) { + // From now on, as soon as a line is executed, error + // keep erroring until you're script reaches the top + lua_sethook(L, hook, LUA_MASKLINE, 0); + luaL_error(L, ""); + } +} + +static int luaGetTime(lua_State *L) +{ + lua_pushunsigned(L, get_tmr10ms()); + return 1; +} + +static int luaGetValue(lua_State *L) +{ + if (lua_isnumber(L, 1)) { + int src = luaL_checkinteger(L, 1); + lua_pushinteger(L, getValue(src)); + return 1; + } + else { + const char *what = luaL_checkstring(L, 1); + if (!strcmp(what, "altitude")) { + lua_pushnumber(L, double(frskyData.hub.baroAltitude)/100); + return 1; + } + else if (!strcmp(what, "latitude")) { + if (frskyData.hub.gpsFix) + lua_pushnumber(L, gpsToDouble(frskyData.hub.gpsLatitudeNS=='S', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap)); + else + lua_pushnil(L); + return 1; + } + else if (!strcmp(what, "longitude")) { + if (frskyData.hub.gpsFix) + lua_pushnumber(L, gpsToDouble(frskyData.hub.gpsLongitudeEW=='W', frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap)); + else + lua_pushnil(L); + return 1; + } + else if (!strcmp(what, "pilot latitude")) { + if (frskyData.hub.gpsFix) + lua_pushnumber(L, pilotLatitude); + else + lua_pushnil(L); + return 1; + } + else if (!strcmp(what, "pilot longitude")) { + if (frskyData.hub.gpsFix) + lua_pushnumber(L, pilotLongitude); + else + lua_pushnil(L); + return 1; + } + } + + return 0; +} + +static int luaPlayFile(lua_State *L) +{ + const char * filename = luaL_checkstring(L, 1); + PLAY_FILE(filename, 0, 0); + return 0; +} + +static int luaLcdLock(lua_State *L) +{ + lcd_locked = true; + return 0; +} + +static int luaLcdClear(lua_State *L) +{ + lcd_clear(); + return 0; +} + +static int luaLcdDrawPoint(lua_State *L) +{ + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + lcd_plot(x, y); + return 0; +} + +static int luaLcdDrawLine(lua_State *L) +{ + int x1 = luaL_checkinteger(L, 1); + int y1 = luaL_checkinteger(L, 2); + int x2 = luaL_checkinteger(L, 3); + int y2 = luaL_checkinteger(L, 4); + lcd_line(x1, y1, x2, y2); + return 0; +} + +static int luaLcdDrawRectangle(lua_State *L) +{ + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int w = luaL_checkinteger(L, 3); + int h = luaL_checkinteger(L, 4); + lcd_rect(x, y, w, h, 0xff, 0); + return 0; +} + +static int luaLcdDrawText(lua_State *L) +{ + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + const char * s = luaL_checkstring(L, 3); + int att = luaL_checkinteger(L, 4); + lcd_putsAtt(x, y, s, att); + return 0; +} + +static int luaLcdDrawSwitch(lua_State *L) +{ + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int s = luaL_checkinteger(L, 3); + int att = luaL_checkinteger(L, 4); + putsSwitches(x, y, s, att); + return 0; +} + +static int luaLcdDrawPixmap(lua_State *L) +{ + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + const char * filename = luaL_checkstring(L, 3); + // TODO int att = luaL_checkinteger(L, 4); + bmp_ptr_t bitmap = 0; + const pm_char * error = bmpLoad(bitmap, filename, LCD_W, LCD_H); + if (bitmap && !error) { + lcd_bmp(x, y, bitmap); + // free(bitmap); + } + return 0; +} + +static int luaLcdDrawScreenTitle(lua_State *L) +{ + const char * str = luaL_checkstring(L, 1); + int idx = luaL_checkinteger(L, 2); + int cnt = luaL_checkinteger(L, 3); + + displayScreenIndex(idx-1, cnt, 0); + lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); + title(str); + + return 0; +} + +static int luaModelGetTimer(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < MAX_TIMERS) { + TimerData & timer = g_model.timers[idx]; + lua_newtable(L); + lua_pushtablenumber(L, "mode", timer.mode); + lua_pushtablenumber(L, "start", timer.start); + lua_pushtablenumber(L, "value", timersStates[idx].val); + lua_pushtablenumber(L, "countdownBeep", timer.countdownBeep); + lua_pushtableboolean(L, "minuteBeep", timer.minuteBeep); + lua_pushtableboolean(L, "persistent", timer.persistent); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelSetTimer(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + + if (idx < MAX_TIMERS) { + TimerData & timer = g_model.timers[idx]; + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "mode")) { + timer.mode = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "start")) { + timer.start = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "value")) { + timersStates[idx].val = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "countdownBeep")) { + timer.countdownBeep = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "minuteBeep")) { + timer.minuteBeep = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "persistent")) { + timer.persistent = luaL_checkinteger(L, -1); + } + } + eeDirty(EE_MODEL); + } + return 0; +} + +static int getFirstInput(int chn) +{ + for (int i=0; isrcRaw || expo->chn>chn) break; + if (expo->chn == chn) { + return i; + } + } + return -1; +} + +static int getInputsCountFromFirst(int chn, int first) +{ + int count = 0; + if (first >= 0) { + for (int i=first; isrcRaw || expo->chn!=chn) break; + count++; + } + } + return count; +} + +static int getInputsCount(int chn) +{ + int first = getFirstInput(chn); + return getInputsCountFromFirst(chn, first); +} + +static int luaModelGetInputsCount(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int count = getInputsCount(chn); + lua_pushinteger(L, count); + return 1; +} + +static int luaModelGetInput(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + int first = getFirstInput(chn); + int count = getInputsCountFromFirst(chn, first); + if (first>=0 && idxname); + lua_pushtablenumber(L, "source", expo->srcRaw); + lua_pushtablenumber(L, "weight", expo->weight); + lua_pushtablenumber(L, "offset", expo->offset); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelInsertInput(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + + int first = getFirstInput(chn); + int count = getInputsCountFromFirst(chn, first); + + if (chnname, name, sizeof(expo->name)); + } + else if (!strcmp(key, "source")) { + expo->srcRaw = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "weight")) { + expo->weight = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "offset")) { + expo->offset = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "switch")) { + expo->swtch = luaL_checkinteger(L, -1); + } + } + } + + return 0; +} + +static int luaModelDeleteInput(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + + int first = getFirstInput(chn); + int count = getInputsCountFromFirst(chn, first); + + if (first>=0 && idxsrcRaw || mix->destCh>chn) break; + if (mix->destCh == chn) { + return i; + } + } + return -1; +} + +static int getMixesCountFromFirst(int chn, int first) +{ + int count = 0; + if (first >= 0) { + for (int i=first; isrcRaw || mix->destCh!=chn) break; + count++; + } + } + return count; +} + +static int getMixesCount(int chn) +{ + int first = getFirstMix(chn); + return getMixesCountFromFirst(chn, first); +} + +static int luaModelGetMixesCount(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int count = getMixesCount(chn); + lua_pushinteger(L, count); + return 1; +} + +static int luaModelGetMix(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + int first = getFirstMix(chn); + int count = getMixesCountFromFirst(chn, first); + if (first>=0 && idxname); + lua_pushtablenumber(L, "source", mix->srcRaw); + lua_pushtablenumber(L, "weight", mix->weight); + lua_pushtablenumber(L, "offset", mix->offset); + lua_pushtablenumber(L, "switch", mix->swtch); + lua_pushtablenumber(L, "multiplex", mix->mltpx); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelInsertMix(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + + int first = getFirstMix(chn); + int count = getMixesCountFromFirst(chn, first); + + if (chnname, name, sizeof(mix->name)); + } + else if (!strcmp(key, "source")) { + mix->srcRaw = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "weight")) { + mix->weight = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "offset")) { + mix->offset = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "switch")) { + mix->swtch = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "multiplex")) { + mix->mltpx = luaL_checkinteger(L, -1); + } + } + } + + return 0; +} + +static int luaModelDeleteMix(lua_State *L) +{ + int chn = luaL_checkunsigned(L, 1); + int idx = luaL_checkunsigned(L, 2); + + int first = getFirstMix(chn); + int count = getMixesCountFromFirst(chn, first); + + if (first>=0 && idxfunc); + lua_pushtablenumber(L, "v1", csw->v1); + lua_pushtablenumber(L, "v2", csw->v2); + lua_pushtablenumber(L, "and", csw->andsw); + lua_pushtablenumber(L, "delay", csw->delay); + lua_pushtablenumber(L, "duration", csw->duration); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelSetCustomSwitch(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < NUM_CSW) { + CustomSwData * csw = cswAddress(idx); + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "function")) { + csw->func = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "v1")) { + csw->v1 = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "v2")) { + csw->v2 = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "and")) { + csw->andsw = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "delay")) { + csw->delay = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "duration")) { + csw->duration = luaL_checkinteger(L, -1); + } + } + } + + return 0; +} + +static int luaModelGetCustomFunction(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < NUM_CFN) { + CustomFnData * cfn = &g_model.funcSw[idx]; + lua_newtable(L); + lua_pushtablenumber(L, "switch", cfn->swtch); + lua_pushtablenumber(L, "function", cfn->func); + lua_pushtablezstring(L, "name", cfn->param.name); + lua_pushtablenumber(L, "value", cfn->param.composite.val); + lua_pushtablenumber(L, "mode", cfn->mode); + lua_pushtablenumber(L, "active", cfn->active); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelSetCustomFunction(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < NUM_CFN) { + CustomFnData * cfn = &g_model.funcSw[idx]; + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "switch")) { + cfn->swtch = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "function")) { + cfn->func = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "name")) { + const char * name = luaL_checkstring(L, -1); + str2zchar(cfn->param.name, name, sizeof(cfn->param.name)); + } + else if (!strcmp(key, "value")) { + cfn->param.composite.val = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "mode")) { + cfn->mode = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "active")) { + cfn->active = luaL_checkinteger(L, -1); + } + } + } + + return 0; +} + +static int luaModelGetOutput(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < NUM_CHNOUT) { + LimitData * limit = limitAddress(idx); + lua_newtable(L); + lua_pushtablezstring(L, "name", limit->name); + lua_pushtablenumber(L, "min", limit->min); + lua_pushtablenumber(L, "max", limit->min); + lua_pushtablenumber(L, "offset", limit->offset); + lua_pushtablenumber(L, "ppmCenter", limit->ppmCenter); + lua_pushtableboolean(L, "symetrical", limit->symetrical); + lua_pushtableboolean(L, "revert", limit->revert); + if (limit->curve) + lua_pushtablenil(L, "curve"); + else + lua_pushtablenumber(L, "curve", limit->curve-1); + } + else { + lua_pushnil(L); + } + return 1; +} + +static int luaModelSetOutput(lua_State *L) +{ + int idx = luaL_checkunsigned(L, 1); + if (idx < NUM_CHNOUT) { + LimitData * limit = limitAddress(idx); + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "name")) { + const char * name = luaL_checkstring(L, -1); + str2zchar(limit->name, name, sizeof(limit->name)); + } + else if (!strcmp(key, "min")) { + limit->min = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "max")) { + limit->max = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "offset")) { + limit->offset = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "ppmCenter")) { + limit->ppmCenter = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "symetrical")) { + limit->symetrical = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "revert")) { + limit->revert = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "curve")) { + if (lua_isnil(L, -1)) + limit->curve = 0; + else + limit->curve = luaL_checkinteger(L, -1) + 1; + } + } + } + + return 0; +} +static int luaPopupInput(lua_State *L) +{ + uint8_t event = luaL_checkinteger(L, 2); + s_warning_input_value = luaL_checkinteger(L, 3); + s_warning_input_min = luaL_checkinteger(L, 4); + s_warning_input_max = luaL_checkinteger(L, 5); + s_warning = luaL_checkstring(L, 1); + s_warning_type = WARNING_TYPE_INPUT; + displayWarning(event); + if (s_warning_result) { + s_warning_result = 0; + lua_pushstring(L, "OK"); + } + else if (!s_warning) { + lua_pushstring(L, "CANCEL"); + } + else { + lua_pushinteger(L, s_warning_input_value); + } + s_warning = NULL; + return 1; +} + +int luaGetInputs(ScriptInternalData & sid) +{ + if (!lua_istable(L, -1)) + return -1; + + sid.inputsCount = 0; + for (lua_pushnil(L); lua_next(L, -2) && sid.inputsCount100) { + TRACE("Script killed"); + standaloneScript.state = SCRIPT_KILLED; + } + 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) { + if (lua_gc(L, LUA_GCCOUNT, 0) > SCRIPTS_MAX_HEAP) { + TRACE("Script memory leak"); + standaloneScript.state = SCRIPT_LEAK; + luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; + } + } + else { + TRACE("Script finished with status %d", scriptResult); + standaloneScript.state = SCRIPT_NOFILE; + luaState = LUASTATE_RELOAD_MODEL_SCRIPTS; + } + } + } + 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); + } + + } + } + else { + // model scripts + if (luaState & LUASTATE_RELOAD_MODEL_SCRIPTS) { + luaState = 0; + LUA_RESET(); + luaLoadModelScripts(); + } + + for (int i=0; i 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); + TRACE("Script %10s disabled", sd.file); + break; + } + sid.outputs[j].value = lua_tointeger(L, -1); + lua_pop(L, 1); + } + } + else { + if (instructionsPercent > 100) { + TRACE("Script %10s killed", sd.file); + sid.state = SCRIPT_KILLED; + } + else { + TRACE("Script %10s error: %s", sd.file, lua_tostring(L, -1)); + sid.state = SCRIPT_SYNTAX_ERROR; + } + } + + if (sid.state != SCRIPT_OK) { + luaFree(sid); + } + else { + sid.memory += lua_gc(L, LUA_GCCOUNT, 0) - prev_mem; + if (instructionsPercent > sid.instructions) { + sid.instructions = instructionsPercent; + } + } + } + } + + // TRACE("gc=%d", lua_gc(L, LUA_GCCOUNT, 0)); + + if (lua_gc(L, LUA_GCCOUNT, 0) > SCRIPTS_MAX_HEAP) { + uint8_t max_memory = 0; + int8_t max_idx = -1; + for (int i=0; i max_memory && sid.memory > 15) { + max_idx = i; + } + } + if (max_idx >= 0) { + ScriptInternalData & sid = scriptInternalData[max_idx]; + TRACE("Script %d killed", max_idx); + sid.state = SCRIPT_LEAK; + luaFree(sid); + } + } + } +} diff --git a/radio/src/lua/Makefile b/radio/src/lua/Makefile new file mode 100644 index 000000000..bd9515fd8 --- /dev/null +++ b/radio/src/lua/Makefile @@ -0,0 +1,114 @@ +# Makefile for installing Lua +# See doc/readme.html for installation and customization instructions. + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +# Where to install. The installation starts in the src and doc directories, +# so take care if INSTALL_TOP is not an absolute path. See the local target. +# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with +# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. +INSTALL_TOP= /usr/local +INSTALL_BIN= $(INSTALL_TOP)/bin +INSTALL_INC= $(INSTALL_TOP)/include +INSTALL_LIB= $(INSTALL_TOP)/lib +INSTALL_MAN= $(INSTALL_TOP)/man/man1 +INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V +INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V + +# How to install. If your install program does not support "-p", then +# you may have to run ranlib on the installed liblua.a. +INSTALL= install -p +INSTALL_EXEC= $(INSTALL) -m 0755 +INSTALL_DATA= $(INSTALL) -m 0644 +# +# If you don't have "install" you can use "cp" instead. +# INSTALL= cp -p +# INSTALL_EXEC= $(INSTALL) +# INSTALL_DATA= $(INSTALL) + +# Other utilities. +MKDIR= mkdir -p +RM= rm -f + +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= + +# Convenience platforms targets. +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +# What to install. +TO_BIN= lua luac +TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp +TO_LIB= liblua.a +TO_MAN= lua.1 luac.1 + +# Lua version and release. +V= 5.2 +R= $V.1 + +# Targets start here. +all: $(PLAT) + +$(PLATS) clean: + cd src && $(MAKE) $@ + +test: dummy + src/lua -v + +install: dummy + cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + +uninstall: + cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) + cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) + cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) + cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) + +local: + $(MAKE) install INSTALL_TOP=../install + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + @echo "See doc/readme.html for complete instructions." + +# make may get confused with test/ and install/ +dummy: + +# echo config parameters +echo: + @cd src && $(MAKE) -s echo + @echo "PLAT= $(PLAT)" + @echo "V= $V" + @echo "R= $R" + @echo "TO_BIN= $(TO_BIN)" + @echo "TO_INC= $(TO_INC)" + @echo "TO_LIB= $(TO_LIB)" + @echo "TO_MAN= $(TO_MAN)" + @echo "INSTALL_TOP= $(INSTALL_TOP)" + @echo "INSTALL_BIN= $(INSTALL_BIN)" + @echo "INSTALL_INC= $(INSTALL_INC)" + @echo "INSTALL_LIB= $(INSTALL_LIB)" + @echo "INSTALL_MAN= $(INSTALL_MAN)" + @echo "INSTALL_LMOD= $(INSTALL_LMOD)" + @echo "INSTALL_CMOD= $(INSTALL_CMOD)" + @echo "INSTALL_EXEC= $(INSTALL_EXEC)" + @echo "INSTALL_DATA= $(INSTALL_DATA)" + +# echo pkg-config data +pc: + @echo "version=$R" + @echo "prefix=$(INSTALL_TOP)" + @echo "libdir=$(INSTALL_LIB)" + @echo "includedir=$(INSTALL_INC)" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho + +# (end of Makefile) diff --git a/radio/src/lua/README b/radio/src/lua/README new file mode 100644 index 000000000..6e2aee6ce --- /dev/null +++ b/radio/src/lua/README @@ -0,0 +1,6 @@ + +This is Lua 5.2.2, released on 21 Mar 2013. + +For installation instructions, license details, and +further information about Lua, see doc/readme.html. + diff --git a/radio/src/lua/doc/contents.html b/radio/src/lua/doc/contents.html new file mode 100644 index 000000000..0ce297da1 --- /dev/null +++ b/radio/src/lua/doc/contents.html @@ -0,0 +1,533 @@ + + + +Lua 5.2 Reference Manual - contents + + + + + + + +
+

+ +Lua 5.2 Reference Manual +

+ +

+The reference manual is the official definition of the Lua language. +For a complete introduction to Lua programming, see the book +Programming in Lua. + +

+start +· +contents +· +index +


+ +Copyright © 2011–2013 Lua.org, PUC-Rio. +Freely available under the terms of the +Lua license. + + +

Contents

+ + +

Index

+ + + + + + + +
+

Lua functions

+

+_G
+_VERSION
+ +

+assert
+collectgarbage
+dofile
+error
+getmetatable
+ipairs
+load
+loadfile
+next
+pairs
+pcall
+print
+rawequal
+rawget
+rawlen
+rawset
+require
+select
+setmetatable
+tonumber
+tostring
+type
+xpcall
+ +

+bit32.arshift
+bit32.band
+bit32.bnot
+bit32.bor
+bit32.btest
+bit32.bxor
+bit32.extract
+bit32.lrotate
+bit32.lshift
+bit32.replace
+bit32.rrotate
+bit32.rshift
+ +

+coroutine.create
+coroutine.resume
+coroutine.running
+coroutine.status
+coroutine.wrap
+coroutine.yield
+ +

+debug.debug
+debug.getuservalue
+debug.gethook
+debug.getinfo
+debug.getlocal
+debug.getmetatable
+debug.getregistry
+debug.getupvalue
+debug.setuservalue
+debug.sethook
+debug.setlocal
+debug.setmetatable
+debug.setupvalue
+debug.traceback
+debug.upvalueid
+debug.upvaluejoin
+ +

+file:close
+file:flush
+file:lines
+file:read
+file:seek
+file:setvbuf
+file:write
+ +

+io.close
+io.flush
+io.input
+io.lines
+io.open
+io.output
+io.popen
+io.read
+io.stderr
+io.stdin
+io.stdout
+io.tmpfile
+io.type
+io.write
+ +

+

 

+

+math.abs
+math.acos
+math.asin
+math.atan
+math.atan2
+math.ceil
+math.cos
+math.cosh
+math.deg
+math.exp
+math.floor
+math.fmod
+math.frexp
+math.huge
+math.ldexp
+math.log
+math.max
+math.min
+math.modf
+math.pi
+math.pow
+math.rad
+math.random
+math.randomseed
+math.sin
+math.sinh
+math.sqrt
+math.tan
+math.tanh
+ +

+os.clock
+os.date
+os.difftime
+os.execute
+os.exit
+os.getenv
+os.remove
+os.rename
+os.setlocale
+os.time
+os.tmpname
+ +

+package.config
+package.cpath
+package.loaded
+package.loadlib
+package.path
+package.preload
+package.searchers
+package.searchpath
+ +

+string.byte
+string.char
+string.dump
+string.find
+string.format
+string.gmatch
+string.gsub
+string.len
+string.lower
+string.match
+string.rep
+string.reverse
+string.sub
+string.upper
+ +

+table.concat
+table.insert
+table.pack
+table.remove
+table.sort
+table.unpack
+ +

+

C API

+

+lua_Alloc
+lua_CFunction
+lua_Debug
+lua_Hook
+lua_Integer
+lua_Number
+lua_Reader
+lua_State
+lua_Unsigned
+lua_Writer
+ +

+lua_absindex
+lua_arith
+lua_atpanic
+lua_call
+lua_callk
+lua_checkstack
+lua_close
+lua_compare
+lua_concat
+lua_copy
+lua_createtable
+lua_dump
+lua_error
+lua_gc
+lua_getallocf
+lua_getctx
+lua_getfield
+lua_getglobal
+lua_gethook
+lua_gethookcount
+lua_gethookmask
+lua_getinfo
+lua_getlocal
+lua_getmetatable
+lua_getstack
+lua_gettable
+lua_gettop
+lua_getupvalue
+lua_getuservalue
+lua_insert
+lua_isboolean
+lua_iscfunction
+lua_isfunction
+lua_islightuserdata
+lua_isnil
+lua_isnone
+lua_isnoneornil
+lua_isnumber
+lua_isstring
+lua_istable
+lua_isthread
+lua_isuserdata
+lua_len
+lua_load
+lua_newstate
+lua_newtable
+lua_newthread
+lua_newuserdata
+lua_next
+lua_pcall
+lua_pcallk
+lua_pop
+lua_pushboolean
+lua_pushcclosure
+lua_pushcfunction
+lua_pushfstring
+lua_pushglobaltable
+lua_pushinteger
+lua_pushlightuserdata
+lua_pushliteral
+lua_pushlstring
+lua_pushnil
+lua_pushnumber
+lua_pushstring
+lua_pushthread
+lua_pushunsigned
+lua_pushvalue
+lua_pushvfstring
+lua_rawequal
+lua_rawget
+lua_rawgeti
+lua_rawgetp
+lua_rawlen
+lua_rawset
+lua_rawseti
+lua_rawsetp
+lua_register
+lua_remove
+lua_replace
+lua_resume
+lua_setallocf
+lua_setfield
+lua_setglobal
+lua_sethook
+lua_setlocal
+lua_setmetatable
+lua_settable
+lua_settop
+lua_setupvalue
+lua_setuservalue
+lua_status
+lua_toboolean
+lua_tocfunction
+lua_tointeger
+lua_tointegerx
+lua_tolstring
+lua_tonumber
+lua_tonumberx
+lua_topointer
+lua_tostring
+lua_tothread
+lua_tounsigned
+lua_tounsignedx
+lua_touserdata
+lua_type
+lua_typename
+lua_upvalueid
+lua_upvalueindex
+lua_upvaluejoin
+lua_version
+lua_xmove
+lua_yield
+lua_yieldk
+ +

+

auxiliary library

+

+luaL_Buffer
+luaL_Reg
+ +

+luaL_addchar
+luaL_addlstring
+luaL_addsize
+luaL_addstring
+luaL_addvalue
+luaL_argcheck
+luaL_argerror
+luaL_buffinit
+luaL_buffinitsize
+luaL_callmeta
+luaL_checkany
+luaL_checkint
+luaL_checkinteger
+luaL_checklong
+luaL_checklstring
+luaL_checknumber
+luaL_checkoption
+luaL_checkstack
+luaL_checkstring
+luaL_checktype
+luaL_checkudata
+luaL_checkunsigned
+luaL_checkversion
+luaL_dofile
+luaL_dostring
+luaL_error
+luaL_execresult
+luaL_fileresult
+luaL_getmetafield
+luaL_getmetatable
+luaL_getsubtable
+luaL_gsub
+luaL_len
+luaL_loadbuffer
+luaL_loadbufferx
+luaL_loadfile
+luaL_loadfilex
+luaL_loadstring
+luaL_newlib
+luaL_newlibtable
+luaL_newmetatable
+luaL_newstate
+luaL_openlibs
+luaL_optint
+luaL_optinteger
+luaL_optlong
+luaL_optlstring
+luaL_optnumber
+luaL_optstring
+luaL_optunsigned
+luaL_prepbuffer
+luaL_prepbuffsize
+luaL_pushresult
+luaL_pushresultsize
+luaL_ref
+luaL_requiref
+luaL_setfuncs
+luaL_setmetatable
+luaL_testudata
+luaL_tolstring
+luaL_traceback
+luaL_typename
+luaL_unref
+luaL_where
+ +

+ +
+ +Last update: +Tue Mar 12 11:22:18 BRT 2013 + + + + + diff --git a/radio/src/lua/doc/logo.gif b/radio/src/lua/doc/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f5e4ac2e742fbb7675e739879211553758aea9c GIT binary patch literal 4232 zcmeH``9G8i;K!fm@ywWE@XWZzZ5SF?A>^uN#>^O6HI%DVL*tw8h1>$H%uPC0$QQ=txe!o}PX)Ev+jn>*nFZ-TC=<^76WcLZL(=DJm)| zEiIKwrInSHXU?3duCC_u@5try#>U2`rlw1mF15F}U%!66tE;QKyIUmcDJ<+QF77*W zFJd#&)VAl)kJ6K zi<>tmZ{3>g>+2gB7#JQNe(>OdLh;A=`1q42PbMZNCMPF*dXxhLZw3aYhlZwyhu@Bj z%#4n{d-Q1b$&i4QMce4L#8^!oMdw{PDnm4D66&3*dxX=-YIX6DQL_g`jbzkd4k zZDCoLf=%jL&vIeE zO=XcZ9fxt`f}-DQ^%H*PHMUs(JN%UWkI|Y8h9#6~I$Cw@{RqzO4&P-x;jHCPJ6Ks2 zoU%foi)nXd_sdkiuJa@@5J4RrreKfWSnz5>eMa5yTP=)16uu)TIdx~Fhho))6jZl) z($*i>QrIX4u}u3>m{WSn_ehkUGQ& zs})aUlTH1Cj1g3ZE3=MPXsSniEwJ{e6C3N#HjD=B4`8rWIsz!a7ecYpec?WuH+y?Wsm18^$cS4WmHhH3_=r zh*ILlm*X1dB^E5($KVl&zT524%l}vpHg%;Y+LezV_&TAJCmH`idhuj-n$4FZ)UE|jXLayXa-&O3Q z?Iyo!x*$5hD_HfFnDfGYj-RD|eIb7I?%>Y_kf%}Nbd`BXb4l1(Pc+}zoUR|9%_!7f zum2T;wbx&pohtI+&@~wm3nH9xLbOYkg*`phY~TK5iC#3tZNXo9s`cahx+8j2)rh5C zQgZh6D7Ekgib|hpdhxYf{r!PTJc z!vsYG@{hA}l5kL)g)0N_)(nC<*L0qdUi*3fD5<0sn58>zklX@6Tyv3*X^}m=Cqc40 zQ6GfjG@kd1mFIm`qaubWunm_?P>WUZ`9|f_z%gGHi{n|uu(N8!L=aw5(qAcDj$-QK zu;D#j6e42OXTQD>)i zlvM$LX`$n9EEjxM$_QDF&a z7cme_rat}aXmiN&7`6Q98}dh4Z@8L_uAb#nK&GQiZOOUnA9kAEVb-csuN1AWL=sXt z{z9GCN%%l0N9QvJM;tl1nf?rrhT{*sE%4WqR?{0~aIrfCcCPxf4eh_*jjQ=`$p53Y z@_|Rsx2i}|3dNFetMQQ5y8agTK-E0D&7;@3-LUxfvZ7 z7~!p@&mFe^oca2^F|CBt+4Ly?^ViUVSAhAH>JH1GN{^TQb3QnM*x0ZiZgDyNI@_c3 z@{}(WH4*e3T~}n_^0}da4ElIxAf9B!IaL7z9X0Icvj@cIkE*~W--17&WN`Ea5)Gn> z#gpfRb#44;jVTOS{FuaZgd(-ZD848=fQzgST2MxR>wSLc1P=2HDvByz$B$IsNCC6L zCM?nK*OHj6JA9gz4|b<~2%RqelN^1Y)jIqnRs!mDKV^BQTfo@hOtz7*Ug}Ee^cbsj zNNlumRgAmt`1$b5MO;&X#5-EP<}AaY;52ihIpem&MTea$?3!DrwbYa?V`NjEfWF3z zUq5JY8Ch;L{kx&J<1K&Fe_Vn;8gk{%c;n?nA2(%(f%DCRHko3uT~VI7RE^JWEqaCq z)i|%nfj(*4|V*XhY3W%M# z*yn6SN4eUOHFxAD7B&9E_PO`G5bqgs^@J{9bk>&;PlUAiqo`j3rjQDgD!}mqLUtb` zCB}ZD@m@s#pf7bV4jreOC*JVfHZ|hyHkX!rauVdd_I9FL45d{gWH!DNYu;i(|8wVx z!)eLY6YXxZ2{Coae0xuTnxo1ACb5wtED?VJAz&@114$Ao6uG9YSy*!K;m5_mj=0^j zw%?b%AOs}ql@$TGC-!^^*_#RT5+y_kTzQG9?LPPZNAtt6cJ%d2$q(I)ws21*?xF%p zN+NeGnWRQ<5w70Rc(bl|S0Xr&5@WrmdurS|IgPB|EyuZO#=tf!35)G!HJ`E1jh^lH zTBu~rL#DhQO*XAWtBt}JHH$lc>3%r0yD|maW_(W=B_J+y164F>O4dO|@&@N3Z3p=B zmVl{|^Z&#atHY|9n&la)SBo}=3AFIF=_~LDJk6MTlA73CXtX+4bnn+c!}N}IPa5pp zwyqbqIkN|I3j_3vD6$zlu{Ps(N-J|*qzEt<$5Soh;s^AuKv_ z-Tz+O1_~6*9CJh4r}`}mbUtjbf#fX58RIIkP6&@*y9kI|5fK*_eZ%jv3U$5*x<>D_ za2M(TV8?XY+9xy>0En#Te<6X4$0&dbyd(go$~eq4u(u)EA2msyF<5ssLZ zDP|I}=~Bi_q)whWv=Ri~L1TYaNrR;5cMB@s78HF1{w&r(6GJ;_2@bD?#1p&P4n_?n0#9Vx~$qjMX=Lk?*!@aKo8m&$iPO7S{g3sFUwr`*<53(68xx7?z`2xf# zGSicy_zI(PJ|%qc2VxT+6bOE--a{k&aq7$<<= zFt)C<@|TPs`+eycPGoGL1Wn9|Ed&a2JyAmjnkm3DQBECX&`bt~odH9cUPq4M{#$-q?G3!)qO-it*&YHw+j-O* zYy78V*`4Q=kQ@^Yz*b6Tal4(Me7BGeS^;phWAW8+L^5A(=D)t?k!rLIwVAKtq=f7h z&^n&VX1-T$ScvN~639QLZ^d@niMaS{C-Q)8oHHBhwD*r~-1Ze#Q)GFOFptW32a-uF z;M@ux%i%a25NwIgXt*=GHX$3~aZfwovGL!}sf?j9TsVo^cn(%&a<--0mIXYqGe>c PWz_J}_#7St0k8iB@FZjZ literal 0 HcmV?d00001 diff --git a/radio/src/lua/doc/lua.1 b/radio/src/lua/doc/lua.1 new file mode 100644 index 000000000..1dbf04366 --- /dev/null +++ b/radio/src/lua/doc/lua.1 @@ -0,0 +1,116 @@ +.\" $Id: lua.man,v 1.13 2011/11/16 17:16:53 lhf Exp $ +.TH LUA 1 "$Date: 2011/11/16 17:16:53 $" +.SH NAME +lua \- Lua interpreter +.SH SYNOPSIS +.B lua +[ +.I options +] +[ +.I script +[ +.I args +] +] +.SH DESCRIPTION +.B lua +is the standalone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +.BR luac , +the Lua compiler.) +.B lua +can be used as a batch interpreter and also interactively. +.LP +The given +.I options +are handled in order and then +the Lua program in file +.I script +is loaded and executed. +The given +.I args +are available to +.I script +as strings in a global table named +.BR arg . +If no options or arguments are given, +then +.B "\-v \-i" +is assumed when the standard input is a terminal; +otherwise, +.B "\-" +is assumed. +.LP +In interactive mode, +.B lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +If a line starts with +.BR '=' , +then +.B lua +evaluates and displays +the values of the expressions in the remainder of the line. +.LP +At the very start, +before even handling the command line, +.B lua +checks the contents of the environment variables +.B LUA_INIT_5_2 +or +.BR LUA_INIT , +in that order. +If the contents is of the form +.RI '@ filename ', +then +.I filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +.SH OPTIONS +.TP +.BI \-e " stat" +execute statement +.IR stat . +.TP +.B \-i +enter interactive mode after executing +.IR script . +.TP +.BI \-l " name" +execute the equivalent of +.IB name =require(' name ') +before executing +.IR script . +.TP +.B \-v +show version information. +.TP +.B \-E +ignore environment variables. +.TP +.B \-\- +stop handling options. +.TP +.B \- +stop handling options and execute the standard input as a file. +.SH "SEE ALSO" +.BR luac (1) +.br +The documentation at lua.org, +especially section 7 of the reference manual. +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +R. Ierusalimschy, +L. H. de Figueiredo, +W. Celes +.\" EOF diff --git a/radio/src/lua/doc/lua.css b/radio/src/lua/doc/lua.css new file mode 100644 index 000000000..240e85eb8 --- /dev/null +++ b/radio/src/lua/doc/lua.css @@ -0,0 +1,83 @@ +body { + color: #000000 ; + background-color: #FFFFFF ; + font-family: Helvetica, Arial, sans-serif ; + text-align: justify ; + margin-right: 30px ; + margin-left: 30px ; +} + +h1, h2, h3, h4 { + font-family: Verdana, Geneva, sans-serif ; + font-weight: normal ; + font-style: italic ; +} + +h2 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 1em ; + padding-right: 1em ; + background-color: #E0E0FF ; + border-radius: 8px ; +} + +h3 { + padding-left: 0.5em ; + border-left: solid #E0E0FF 1em ; +} + +table h3 { + padding-left: 0px ; + border-left: none ; +} + +a:link { + color: #000080 ; + background-color: inherit ; + text-decoration: none ; +} + +a:visited { + background-color: inherit ; + text-decoration: none ; +} + +a:link:hover, a:visited:hover { + color: #000080 ; + background-color: #E0E0FF ; +} + +a:link:active, a:visited:active { + color: #FF0000 ; +} + +hr { + border: 0 ; + height: 1px ; + color: #a0a0a0 ; + background-color: #a0a0a0 ; +} + +:target { + background-color: #F8F8F8 ; + padding: 8px ; + border: solid #a0a0a0 2px ; +} + +.footer { + color: gray ; + font-size: small ; +} + +input[type=text] { + border: solid #a0a0a0 2px ; + border-radius: 2em ; + -moz-border-radius: 2em ; + background-image: url('images/search.png') ; + background-repeat: no-repeat; + background-position: 4px center ; + padding-left: 20px ; + height: 2em ; +} + diff --git a/radio/src/lua/doc/luac.1 b/radio/src/lua/doc/luac.1 new file mode 100644 index 000000000..33a4ed00a --- /dev/null +++ b/radio/src/lua/doc/luac.1 @@ -0,0 +1,118 @@ +.\" $Id: luac.man,v 1.29 2011/11/16 13:53:40 lhf Exp $ +.TH LUAC 1 "$Date: 2011/11/16 13:53:40 $" +.SH NAME +luac \- Lua compiler +.SH SYNOPSIS +.B luac +[ +.I options +] [ +.I filenames +] +.SH DESCRIPTION +.B luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files containing precompiled chunks +that can be later loaded and executed. +.LP +The main advantages of precompiling chunks are: +faster loading, +protecting source code from accidental user changes, +and +off-line syntax checking. +Precompiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +.B luac +simply allows those bytecodes to be saved in a file for later execution. +Precompiled chunks are not necessarily smaller than the corresponding source. +The main goal in precompiling is faster loading. +.LP +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +.B luac +produces a single output file containing the combined bytecodes +for all files given. +Executing the combined file is equivalent to executing the given files. +By default, +the output file is named +.BR luac.out , +but you can change this with the +.B \-o +option. +.LP +Precompiled chunks are +.I not +portable across different architectures. +Moreover, +the internal format of precompiled chunks +is likely to change when a new version of Lua is released. +Make sure you save the source files of all Lua programs that you precompile. +.LP +.SH OPTIONS +.TP +.B \-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +.B luac +loads +.B luac.out +and lists its contents. +Use +.B \-l \-l +for a full listing. +.TP +.BI \-o " file" +output to +.IR file , +instead of the default +.BR luac.out . +(You can use +.B "'\-'" +for standard output, +but not on platforms that open standard output in text mode.) +The output file may be one of the given files because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +.TP +.B \-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +If no files are given, then +.B luac +loads +.B luac.out +and tests its contents. +No messages are displayed if the file loads without errors. +.TP +.B \-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running a stripped chunk, +then the error messages may not contain the full information they usually do. +In particular, +line numbers and names of local variables are lost. +.TP +.B \-v +show version information. +.TP +.B \-\- +stop handling options. +.TP +.B \- +stop handling options and process standard input. +.SH "SEE ALSO" +.BR lua (1) +.br +The documentation at lua.org. +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +R. Ierusalimschy, +L. H. de Figueiredo, +W. Celes +.\" EOF diff --git a/radio/src/lua/doc/manual.css b/radio/src/lua/doc/manual.css new file mode 100644 index 000000000..269bd4358 --- /dev/null +++ b/radio/src/lua/doc/manual.css @@ -0,0 +1,26 @@ +h3 code { + font-family: inherit ; + font-size: inherit ; +} + +pre, code { + font-size: 12pt ; +} + +span.apii { + float: right ; + font-family: inherit ; + font-style: normal ; + font-size: small ; + color: gray ; +} + +p+h1, ul+h1 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 24px ; + margin-left: -24px ; + background-color: #E0E0FF ; + border-radius: 8px ; +} + diff --git a/radio/src/lua/doc/manual.html b/radio/src/lua/doc/manual.html new file mode 100644 index 000000000..85365363f --- /dev/null +++ b/radio/src/lua/doc/manual.html @@ -0,0 +1,10507 @@ + + + + +Lua 5.2 Reference Manual + + + + + + + +
+

+ +Lua 5.2 Reference Manual +

+ +by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes +

+ +Copyright © 2011–2013 Lua.org, PUC-Rio. +Freely available under the terms of the +Lua license. + +


+

+ +contents +· +index + + +

+ + + + + + +

1 – Introduction

+ +

+Lua is an extension programming language designed to support +general procedural programming with data description +facilities. +It also offers good support for object-oriented programming, +functional programming, and data-driven programming. +Lua is intended to be used as a powerful, lightweight, +embeddable scripting language for any program that needs one. +Lua is implemented as a library, written in clean C, +the common subset of Standard C and C++. + + +

+Being an extension language, Lua has no notion of a "main" program: +it only works embedded in a host client, +called the embedding program or simply the host. +The host program can invoke functions to execute a piece of Lua code, +can write and read Lua variables, +and can register C functions to be called by Lua code. +Through the use of C functions, Lua can be augmented to cope with +a wide range of different domains, +thus creating customized programming languages sharing a syntactical framework. +The Lua distribution includes a sample host program called lua, +which uses the Lua library to offer a complete, standalone Lua interpreter, +for interactive or batch use. + + +

+Lua is free software, +and is provided as usual with no guarantees, +as stated in its license. +The implementation described in this manual is available +at Lua's official web site, www.lua.org. + + +

+Like any other reference manual, +this document is dry in places. +For a discussion of the decisions behind the design of Lua, +see the technical papers available at Lua's web site. +For a detailed introduction to programming in Lua, +see Roberto's book, Programming in Lua. + + + +

2 – Basic Concepts

+ +

+This section describes the basic concepts of the language. + + + +

2.1 – Values and Types

+ +

+Lua is a dynamically typed language. +This means that +variables do not have types; only values do. +There are no type definitions in the language. +All values carry their own type. + + +

+All values in Lua are first-class values. +This means that all values can be stored in variables, +passed as arguments to other functions, and returned as results. + + +

+There are eight basic types in Lua: +nil, boolean, number, +string, function, userdata, +thread, and table. +Nil is the type of the value nil, +whose main property is to be different from any other value; +it usually represents the absence of a useful value. +Boolean is the type of the values false and true. +Both nil and false make a condition false; +any other value makes it true. +Number represents real (double-precision floating-point) numbers. +Operations on numbers follow the same rules of +the underlying C implementation, +which, in turn, usually follows the IEEE 754 standard. +(It is easy to build Lua interpreters that use other +internal representations for numbers, +such as single-precision floats or long integers; +see file luaconf.h.) +String represents immutable sequences of bytes. + +Lua is 8-bit clean: +strings can contain any 8-bit value, +including embedded zeros ('\0'). + + +

+Lua can call (and manipulate) functions written in Lua and +functions written in C +(see §3.4.9). + + +

+The type userdata is provided to allow arbitrary C data to +be stored in Lua variables. +A userdata value is a pointer to a block of raw memory. +There are two kinds of userdata: +full userdata, where the block of memory is managed by Lua, +and light userdata, where the block of memory is managed by the host. +Userdata has no predefined operations in Lua, +except assignment and identity test. +By using metatables, +the programmer can define operations for full userdata values +(see §2.4). +Userdata values cannot be created or modified in Lua, +only through the C API. +This guarantees the integrity of data owned by the host program. + + +

+The type thread represents independent threads of execution +and it is used to implement coroutines (see §2.6). +Do not confuse Lua threads with operating-system threads. +Lua supports coroutines on all systems, +even those that do not support threads. + + +

+The type table implements associative arrays, +that is, arrays that can be indexed not only with numbers, +but with any Lua value except nil and NaN +(Not a Number, a special numeric value used to represent +undefined or unrepresentable results, such as 0/0). +Tables can be heterogeneous; +that is, they can contain values of all types (except nil). +Any key with value nil is not considered part of the table. +Conversely, any key that is not part of a table has +an associated value nil. + + +

+Tables are the sole data structuring mechanism in Lua; +they can be used to represent ordinary arrays, sequences, +symbol tables, sets, records, graphs, trees, etc. +To represent records, Lua uses the field name as an index. +The language supports this representation by +providing a.name as syntactic sugar for a["name"]. +There are several convenient ways to create tables in Lua +(see §3.4.8). + + +

+We use the term sequence to denote a table where +the set of all positive numeric keys is equal to {1..n} +for some integer n, +which is called the length of the sequence (see §3.4.6). + + +

+Like indices, +the values of table fields can be of any type. +In particular, +because functions are first-class values, +table fields can contain functions. +Thus tables can also carry methods (see §3.4.10). + + +

+The indexing of tables follows +the definition of raw equality in the language. +The expressions a[i] and a[j] +denote the same table element +if and only if i and j are raw equal +(that is, equal without metamethods). + + +

+Tables, functions, threads, and (full) userdata values are objects: +variables do not actually contain these values, +only references to them. +Assignment, parameter passing, and function returns +always manipulate references to such values; +these operations do not imply any kind of copy. + + +

+The library function type returns a string describing the type +of a given value (see §6.1). + + + + + +

2.2 – Environments and the Global Environment

+ +

+As will be discussed in §3.2 and §3.3.3, +any reference to a global name var is syntactically translated +to _ENV.var. +Moreover, every chunk is compiled in the scope of +an external local variable called _ENV (see §3.3.2), +so _ENV itself is never a global name in a chunk. + + +

+Despite the existence of this external _ENV variable and +the translation of global names, +_ENV is a completely regular name. +In particular, +you can define new variables and parameters with that name. +Each reference to a global name uses the _ENV that is +visible at that point in the program, +following the usual visibility rules of Lua (see §3.5). + + +

+Any table used as the value of _ENV is called an environment. + + +

+Lua keeps a distinguished environment called the global environment. +This value is kept at a special index in the C registry (see §4.5). +In Lua, the variable _G is initialized with this same value. + + +

+When Lua compiles a chunk, +it initializes the value of its _ENV upvalue +with the global environment (see load). +Therefore, by default, +global variables in Lua code refer to entries in the global environment. +Moreover, all standard libraries are loaded in the global environment +and several functions there operate on that environment. +You can use load (or loadfile) +to load a chunk with a different environment. +(In C, you have to load the chunk and then change the value +of its first upvalue.) + + +

+If you change the global environment in the registry +(through C code or the debug library), +all chunks loaded after the change will get the new environment. +Previously loaded chunks are not affected, however, +as each has its own reference to the environment in its _ENV variable. +Moreover, the variable _G +(which is stored in the original global environment) +is never updated by Lua. + + + + + +

2.3 – Error Handling

+ +

+Because Lua is an embedded extension language, +all Lua actions start from C code in the host program +calling a function from the Lua library (see lua_pcall). +Whenever an error occurs during +the compilation or execution of a Lua chunk, +control returns to the host, +which can take appropriate measures +(such as printing an error message). + + +

+Lua code can explicitly generate an error by calling the +error function. +If you need to catch errors in Lua, +you can use pcall or xpcall +to call a given function in protected mode. + + +

+Whenever there is an error, +an error object (also called an error message) +is propagated with information about the error. +Lua itself only generates errors where the error object is a string, +but programs may generate errors with +any value for the error object. + + +

+When you use xpcall or lua_pcall, +you may give a message handler +to be called in case of errors. +This function is called with the original error message +and returns a new error message. +It is called before the error unwinds the stack, +so that it can gather more information about the error, +for instance by inspecting the stack and creating a stack traceback. +This message handler is still protected by the protected call; +so, an error inside the message handler +will call the message handler again. +If this loop goes on, Lua breaks it and returns an appropriate message. + + + + + +

2.4 – Metatables and Metamethods

+ +

+Every value in Lua can have a metatable. +This metatable is an ordinary Lua table +that defines the behavior of the original value +under certain special operations. +You can change several aspects of the behavior +of operations over a value by setting specific fields in its metatable. +For instance, when a non-numeric value is the operand of an addition, +Lua checks for a function in the field "__add" of the value's metatable. +If it finds one, +Lua calls this function to perform the addition. + + +

+The keys in a metatable are derived from the event names; +the corresponding values are called metamethods. +In the previous example, the event is "add" +and the metamethod is the function that performs the addition. + + +

+You can query the metatable of any value +using the getmetatable function. + + +

+You can replace the metatable of tables +using the setmetatable function. +You cannot change the metatable of other types from Lua +(except by using the debug library); +you must use the C API for that. + + +

+Tables and full userdata have individual metatables +(although multiple tables and userdata can share their metatables). +Values of all other types share one single metatable per type; +that is, there is one single metatable for all numbers, +one for all strings, etc. +By default, a value has no metatable, +but the string library sets a metatable for the string type (see §6.4). + + +

+A metatable controls how an object behaves in arithmetic operations, +order comparisons, concatenation, length operation, and indexing. +A metatable also can define a function to be called +when a userdata or a table is garbage collected. +When Lua performs one of these operations over a value, +it checks whether this value has a metatable with the corresponding event. +If so, the value associated with that key (the metamethod) +controls how Lua will perform the operation. + + +

+Metatables control the operations listed next. +Each operation is identified by its corresponding name. +The key for each operation is a string with its name prefixed by +two underscores, '__'; +for instance, the key for operation "add" is the +string "__add". + + +

+The semantics of these operations is better explained by a Lua function +describing how the interpreter executes the operation. +The code shown here in Lua is only illustrative; +the real behavior is hard coded in the interpreter +and it is much more efficient than this simulation. +All functions used in these descriptions +(rawget, tonumber, etc.) +are described in §6.1. +In particular, to retrieve the metamethod of a given object, +we use the expression + +

+     metatable(obj)[event]
+

+This should be read as + +

+     rawget(getmetatable(obj) or {}, event)
+

+This means that the access to a metamethod does not invoke other metamethods, +and access to objects with no metatables does not fail +(it simply results in nil). + + +

+For the unary - and # operators, +the metamethod is called with a dummy second argument. +This extra argument is only to simplify Lua's internals; +it may be removed in future versions and therefore it is not present +in the following code. +(For most uses this extra argument is irrelevant.) + + + +

    + +
  • "add": +the + operation. + + + +

    +The function getbinhandler below defines how Lua chooses a handler +for a binary operation. +First, Lua tries the first operand. +If its type does not define a handler for the operation, +then Lua tries the second operand. + +

    +     function getbinhandler (op1, op2, event)
    +       return metatable(op1)[event] or metatable(op2)[event]
    +     end
    +

    +By using this function, +the behavior of the op1 + op2 is + +

    +     function add_event (op1, op2)
    +       local o1, o2 = tonumber(op1), tonumber(op2)
    +       if o1 and o2 then  -- both operands are numeric?
    +         return o1 + o2   -- '+' here is the primitive 'add'
    +       else  -- at least one of the operands is not numeric
    +         local h = getbinhandler(op1, op2, "__add")
    +         if h then
    +           -- call the handler with both operands
    +           return (h(op1, op2))
    +         else  -- no handler available: default behavior
    +           error(···)
    +         end
    +       end
    +     end
    +

    +

  • + +
  • "sub": +the - operation. + +Behavior similar to the "add" operation. +
  • + +
  • "mul": +the * operation. + +Behavior similar to the "add" operation. +
  • + +
  • "div": +the / operation. + +Behavior similar to the "add" operation. +
  • + +
  • "mod": +the % operation. + +Behavior similar to the "add" operation, +with the operation +o1 - floor(o1/o2)*o2 as the primitive operation. +
  • + +
  • "pow": +the ^ (exponentiation) operation. + +Behavior similar to the "add" operation, +with the function pow (from the C math library) +as the primitive operation. +
  • + +
  • "unm": +the unary - operation. + + +
    +     function unm_event (op)
    +       local o = tonumber(op)
    +       if o then  -- operand is numeric?
    +         return -o  -- '-' here is the primitive 'unm'
    +       else  -- the operand is not numeric.
    +         -- Try to get a handler from the operand
    +         local h = metatable(op).__unm
    +         if h then
    +           -- call the handler with the operand
    +           return (h(op))
    +         else  -- no handler available: default behavior
    +           error(···)
    +         end
    +       end
    +     end
    +

    +

  • + +
  • "concat": +the .. (concatenation) operation. + + +
    +     function concat_event (op1, op2)
    +       if (type(op1) == "string" or type(op1) == "number") and
    +          (type(op2) == "string" or type(op2) == "number") then
    +         return op1 .. op2  -- primitive string concatenation
    +       else
    +         local h = getbinhandler(op1, op2, "__concat")
    +         if h then
    +           return (h(op1, op2))
    +         else
    +           error(···)
    +         end
    +       end
    +     end
    +

    +

  • + +
  • "len": +the # operation. + + +
    +     function len_event (op)
    +       if type(op) == "string" then
    +         return strlen(op)      -- primitive string length
    +       else
    +         local h = metatable(op).__len
    +         if h then
    +           return (h(op))       -- call handler with the operand
    +         elseif type(op) == "table" then
    +           return #op              -- primitive table length
    +         else  -- no handler available: error
    +           error(···)
    +         end
    +       end
    +     end
    +

    +See §3.4.6 for a description of the length of a table. +

  • + +
  • "eq": +the == operation. + +The function getequalhandler defines how Lua chooses a metamethod +for equality. +A metamethod is selected only when both values +being compared have the same type +and the same metamethod for the selected operation, +and the values are either tables or full userdata. + +
    +     function getequalhandler (op1, op2)
    +       if type(op1) ~= type(op2) or
    +          (type(op1) ~= "table" and type(op1) ~= "userdata") then
    +         return nil     -- different values
    +       end
    +       local mm1 = metatable(op1).__eq
    +       local mm2 = metatable(op2).__eq
    +       if mm1 == mm2 then return mm1 else return nil end
    +     end
    +

    +The "eq" event is defined as follows: + +

    +     function eq_event (op1, op2)
    +       if op1 == op2 then   -- primitive equal?
    +         return true   -- values are equal
    +       end
    +       -- try metamethod
    +       local h = getequalhandler(op1, op2)
    +       if h then
    +         return not not h(op1, op2)
    +       else
    +         return false
    +       end
    +     end
    +

    +Note that the result is always a boolean. +

  • + +
  • "lt": +the < operation. + + +
    +     function lt_event (op1, op2)
    +       if type(op1) == "number" and type(op2) == "number" then
    +         return op1 < op2   -- numeric comparison
    +       elseif type(op1) == "string" and type(op2) == "string" then
    +         return op1 < op2   -- lexicographic comparison
    +       else
    +         local h = getbinhandler(op1, op2, "__lt")
    +         if h then
    +           return not not h(op1, op2)
    +         else
    +           error(···)
    +         end
    +       end
    +     end
    +

    +Note that the result is always a boolean. +

  • + +
  • "le": +the <= operation. + + +
    +     function le_event (op1, op2)
    +       if type(op1) == "number" and type(op2) == "number" then
    +         return op1 <= op2   -- numeric comparison
    +       elseif type(op1) == "string" and type(op2) == "string" then
    +         return op1 <= op2   -- lexicographic comparison
    +       else
    +         local h = getbinhandler(op1, op2, "__le")
    +         if h then
    +           return not not h(op1, op2)
    +         else
    +           h = getbinhandler(op1, op2, "__lt")
    +           if h then
    +             return not h(op2, op1)
    +           else
    +             error(···)
    +           end
    +         end
    +       end
    +     end
    +

    +Note that, in the absence of a "le" metamethod, +Lua tries the "lt", assuming that a <= b is +equivalent to not (b < a). + + +

    +As with the other comparison operators, +the result is always a boolean. +

  • + +
  • "index": +The indexing access table[key]. +Note that the metamethod is tried only +when key is not present in table. +(When table is not a table, +no key is ever present, +so the metamethod is always tried.) + + +
    +     function gettable_event (table, key)
    +       local h
    +       if type(table) == "table" then
    +         local v = rawget(table, key)
    +         -- if key is present, return raw value
    +         if v ~= nil then return v end
    +         h = metatable(table).__index
    +         if h == nil then return nil end
    +       else
    +         h = metatable(table).__index
    +         if h == nil then
    +           error(···)
    +         end
    +       end
    +       if type(h) == "function" then
    +         return (h(table, key))     -- call the handler
    +       else return h[key]           -- or repeat operation on it
    +       end
    +     end
    +

    +

  • + +
  • "newindex": +The indexing assignment table[key] = value. +Note that the metamethod is tried only +when key is not present in table. + + +
    +     function settable_event (table, key, value)
    +       local h
    +       if type(table) == "table" then
    +         local v = rawget(table, key)
    +         -- if key is present, do raw assignment
    +         if v ~= nil then rawset(table, key, value); return end
    +         h = metatable(table).__newindex
    +         if h == nil then rawset(table, key, value); return end
    +       else
    +         h = metatable(table).__newindex
    +         if h == nil then
    +           error(···)
    +         end
    +       end
    +       if type(h) == "function" then
    +         h(table, key,value)           -- call the handler
    +       else h[key] = value             -- or repeat operation on it
    +       end
    +     end
    +

    +

  • + +
  • "call": +called when Lua calls a value. + + +
    +     function function_event (func, ...)
    +       if type(func) == "function" then
    +         return func(...)   -- primitive call
    +       else
    +         local h = metatable(func).__call
    +         if h then
    +           return h(func, ...)
    +         else
    +           error(···)
    +         end
    +       end
    +     end
    +

    +

  • + +
+ + + + +

2.5 – Garbage Collection

+ +

+Lua performs automatic memory management. +This means that +you have to worry neither about allocating memory for new objects +nor about freeing it when the objects are no longer needed. +Lua manages memory automatically by running +a garbage collector to collect all dead objects +(that is, objects that are no longer accessible from Lua). +All memory used by Lua is subject to automatic management: +strings, tables, userdata, functions, threads, internal structures, etc. + + +

+Lua implements an incremental mark-and-sweep collector. +It uses two numbers to control its garbage-collection cycles: +the garbage-collector pause and +the garbage-collector step multiplier. +Both use percentage points as units +(e.g., a value of 100 means an internal value of 1). + + +

+The garbage-collector pause +controls how long the collector waits before starting a new cycle. +Larger values make the collector less aggressive. +Values smaller than 100 mean the collector will not wait to +start a new cycle. +A value of 200 means that the collector waits for the total memory in use +to double before starting a new cycle. + + +

+The garbage-collector step multiplier +controls the relative speed of the collector relative to +memory allocation. +Larger values make the collector more aggressive but also increase +the size of each incremental step. +Values smaller than 100 make the collector too slow and +can result in the collector never finishing a cycle. +The default is 200, +which means that the collector runs at "twice" +the speed of memory allocation. + + +

+If you set the step multiplier to a very large number +(larger than 10% of the maximum number of +bytes that the program may use), +the collector behaves like a stop-the-world collector. +If you then set the pause to 200, +the collector behaves as in old Lua versions, +doing a complete collection every time Lua doubles its +memory usage. + + +

+You can change these numbers by calling lua_gc in C +or collectgarbage in Lua. +You can also use these functions to control +the collector directly (e.g., stop and restart it). + + +

+As an experimental feature in Lua 5.2, +you can change the collector's operation mode +from incremental to generational. +A generational collector assumes that most objects die young, +and therefore it traverses only young (recently created) objects. +This behavior can reduce the time used by the collector, +but also increases memory usage (as old dead objects may accumulate). +To mitigate this second problem, +from time to time the generational collector performs a full collection. +Remember that this is an experimental feature; +you are welcome to try it, +but check your gains. + + + +

2.5.1 – Garbage-Collection Metamethods

+ +

+You can set garbage-collector metamethods for tables +and, using the C API, +for full userdata (see §2.4). +These metamethods are also called finalizers. +Finalizers allow you to coordinate Lua's garbage collection +with external resource management +(such as closing files, network or database connections, +or freeing your own memory). + + +

+For an object (table or userdata) to be finalized when collected, +you must mark it for finalization. + +You mark an object for finalization when you set its metatable +and the metatable has a field indexed by the string "__gc". +Note that if you set a metatable without a __gc field +and later create that field in the metatable, +the object will not be marked for finalization. +However, after an object is marked, +you can freely change the __gc field of its metatable. + + +

+When a marked object becomes garbage, +it is not collected immediately by the garbage collector. +Instead, Lua puts it in a list. +After the collection, +Lua does the equivalent of the following function +for each object in that list: + +

+     function gc_event (obj)
+       local h = metatable(obj).__gc
+       if type(h) == "function" then
+         h(obj)
+       end
+     end
+
+ +

+At the end of each garbage-collection cycle, +the finalizers for objects are called in +the reverse order that they were marked for collection, +among those collected in that cycle; +that is, the first finalizer to be called is the one associated +with the object marked last in the program. +The execution of each finalizer may occur at any point during +the execution of the regular code. + + +

+Because the object being collected must still be used by the finalizer, +it (and other objects accessible only through it) +must be resurrected by Lua. +Usually, this resurrection is transient, +and the object memory is freed in the next garbage-collection cycle. +However, if the finalizer stores the object in some global place +(e.g., a global variable), +then there is a permanent resurrection. +In any case, +the object memory is freed only when it becomes completely inaccessible; +its finalizer will never be called twice. + + +

+When you close a state (see lua_close), +Lua calls the finalizers of all objects marked for finalization, +following the reverse order that they were marked. +If any finalizer marks new objects for collection during that phase, +these new objects will not be finalized. + + + + + +

2.5.2 – Weak Tables

+ +

+A weak table is a table whose elements are +weak references. +A weak reference is ignored by the garbage collector. +In other words, +if the only references to an object are weak references, +then the garbage collector will collect that object. + + +

+A weak table can have weak keys, weak values, or both. +A table with weak keys allows the collection of its keys, +but prevents the collection of its values. +A table with both weak keys and weak values allows the collection of +both keys and values. +In any case, if either the key or the value is collected, +the whole pair is removed from the table. +The weakness of a table is controlled by the +__mode field of its metatable. +If the __mode field is a string containing the character 'k', +the keys in the table are weak. +If __mode contains 'v', +the values in the table are weak. + + +

+A table with weak keys and strong values +is also called an ephemeron table. +In an ephemeron table, +a value is considered reachable only if its key is reachable. +In particular, +if the only reference to a key comes through its value, +the pair is removed. + + +

+Any change in the weakness of a table may take effect only +at the next collect cycle. +In particular, if you change the weakness to a stronger mode, +Lua may still collect some items from that table +before the change takes effect. + + +

+Only objects that have an explicit construction +are removed from weak tables. +Values, such as numbers and light C functions, +are not subject to garbage collection, +and therefore are not removed from weak tables +(unless its associated value is collected). +Although strings are subject to garbage collection, +they do not have an explicit construction, +and therefore are not removed from weak tables. + + +

+Resurrected objects +(that is, objects being finalized +and objects accessible only through objects being finalized) +have a special behavior in weak tables. +They are removed from weak values before running their finalizers, +but are removed from weak keys only in the next collection +after running their finalizers, when such objects are actually freed. +This behavior allows the finalizer to access properties +associated with the object through weak tables. + + +

+If a weak table is among the resurrected objects in a collection cycle, +it may not be properly cleared until the next cycle. + + + + + + + +

2.6 – Coroutines

+ +

+Lua supports coroutines, +also called collaborative multithreading. +A coroutine in Lua represents an independent thread of execution. +Unlike threads in multithread systems, however, +a coroutine only suspends its execution by explicitly calling +a yield function. + + +

+You create a coroutine by calling coroutine.create. +Its sole argument is a function +that is the main function of the coroutine. +The create function only creates a new coroutine and +returns a handle to it (an object of type thread); +it does not start the coroutine. + + +

+You execute a coroutine by calling coroutine.resume. +When you first call coroutine.resume, +passing as its first argument +a thread returned by coroutine.create, +the coroutine starts its execution, +at the first line of its main function. +Extra arguments passed to coroutine.resume are passed on +to the coroutine main function. +After the coroutine starts running, +it runs until it terminates or yields. + + +

+A coroutine can terminate its execution in two ways: +normally, when its main function returns +(explicitly or implicitly, after the last instruction); +and abnormally, if there is an unprotected error. +In the first case, coroutine.resume returns true, +plus any values returned by the coroutine main function. +In case of errors, coroutine.resume returns false +plus an error message. + + +

+A coroutine yields by calling coroutine.yield. +When a coroutine yields, +the corresponding coroutine.resume returns immediately, +even if the yield happens inside nested function calls +(that is, not in the main function, +but in a function directly or indirectly called by the main function). +In the case of a yield, coroutine.resume also returns true, +plus any values passed to coroutine.yield. +The next time you resume the same coroutine, +it continues its execution from the point where it yielded, +with the call to coroutine.yield returning any extra +arguments passed to coroutine.resume. + + +

+Like coroutine.create, +the coroutine.wrap function also creates a coroutine, +but instead of returning the coroutine itself, +it returns a function that, when called, resumes the coroutine. +Any arguments passed to this function +go as extra arguments to coroutine.resume. +coroutine.wrap returns all the values returned by coroutine.resume, +except the first one (the boolean error code). +Unlike coroutine.resume, +coroutine.wrap does not catch errors; +any error is propagated to the caller. + + +

+As an example of how coroutines work, +consider the following code: + +

+     function foo (a)
+       print("foo", a)
+       return coroutine.yield(2*a)
+     end
+     
+     co = coroutine.create(function (a,b)
+           print("co-body", a, b)
+           local r = foo(a+1)
+           print("co-body", r)
+           local r, s = coroutine.yield(a+b, a-b)
+           print("co-body", r, s)
+           return b, "end"
+     end)
+     
+     print("main", coroutine.resume(co, 1, 10))
+     print("main", coroutine.resume(co, "r"))
+     print("main", coroutine.resume(co, "x", "y"))
+     print("main", coroutine.resume(co, "x", "y"))
+

+When you run it, it produces the following output: + +

+     co-body 1       10
+     foo     2
+     main    true    4
+     co-body r
+     main    true    11      -9
+     co-body x       y
+     main    true    10      end
+     main    false   cannot resume dead coroutine
+
+ +

+You can also create and manipulate coroutines through the C API: +see functions lua_newthread, lua_resume, +and lua_yield. + + + + + +

3 – The Language

+ +

+This section describes the lexis, the syntax, and the semantics of Lua. +In other words, +this section describes +which tokens are valid, +how they can be combined, +and what their combinations mean. + + +

+Language constructs will be explained using the usual extended BNF notation, +in which +{a} means 0 or more a's, and +[a] means an optional a. +Non-terminals are shown like non-terminal, +keywords are shown like kword, +and other terminal symbols are shown like ‘=’. +The complete syntax of Lua can be found in §9 +at the end of this manual. + + + +

3.1 – Lexical Conventions

+ +

+Lua is a free-form language. +It ignores spaces (including new lines) and comments +between lexical elements (tokens), +except as delimiters between names and keywords. + + +

+Names +(also called identifiers) +in Lua can be any string of letters, +digits, and underscores, +not beginning with a digit. +Identifiers are used to name variables, table fields, and labels. + + +

+The following keywords are reserved +and cannot be used as names: + + +

+     and       break     do        else      elseif    end
+     false     for       function  goto      if        in
+     local     nil       not       or        repeat    return
+     then      true      until     while
+
+ +

+Lua is a case-sensitive language: +and is a reserved word, but And and AND +are two different, valid names. +As a convention, names starting with an underscore followed by +uppercase letters (such as _VERSION) +are reserved for variables used by Lua. + + +

+The following strings denote other tokens: + +

+     +     -     *     /     %     ^     #
+     ==    ~=    <=    >=    <     >     =
+     (     )     {     }     [     ]     ::
+     ;     :     ,     .     ..    ...
+
+ +

+Literal strings +can be delimited by matching single or double quotes, +and can contain the following C-like escape sequences: +'\a' (bell), +'\b' (backspace), +'\f' (form feed), +'\n' (newline), +'\r' (carriage return), +'\t' (horizontal tab), +'\v' (vertical tab), +'\\' (backslash), +'\"' (quotation mark [double quote]), +and '\'' (apostrophe [single quote]). +A backslash followed by a real newline +results in a newline in the string. +The escape sequence '\z' skips the following span +of white-space characters, +including line breaks; +it is particularly useful to break and indent a long literal string +into multiple lines without adding the newlines and spaces +into the string contents. + + +

+A byte in a literal string can also be specified by its numerical value. +This can be done with the escape sequence \xXX, +where XX is a sequence of exactly two hexadecimal digits, +or with the escape sequence \ddd, +where ddd is a sequence of up to three decimal digits. +(Note that if a decimal escape is to be followed by a digit, +it must be expressed using exactly three digits.) +Strings in Lua can contain any 8-bit value, including embedded zeros, +which can be specified as '\0'. + + +

+Literal strings can also be defined using a long format +enclosed by long brackets. +We define an opening long bracket of level n as an opening +square bracket followed by n equal signs followed by another +opening square bracket. +So, an opening long bracket of level 0 is written as [[, +an opening long bracket of level 1 is written as [=[, +and so on. +A closing long bracket is defined similarly; +for instance, a closing long bracket of level 4 is written as ]====]. +A long literal starts with an opening long bracket of any level and +ends at the first closing long bracket of the same level. +It can contain any text except a closing bracket of the proper level. +Literals in this bracketed form can run for several lines, +do not interpret any escape sequences, +and ignore long brackets of any other level. +Any kind of end-of-line sequence +(carriage return, newline, carriage return followed by newline, +or newline followed by carriage return) +is converted to a simple newline. + + +

+Any byte in a literal string not +explicitly affected by the previous rules represents itself. +However, Lua opens files for parsing in text mode, +and the system file functions may have problems with +some control characters. +So, it is safer to represent +non-text data as a quoted literal with +explicit escape sequences for non-text characters. + + +

+For convenience, +when the opening long bracket is immediately followed by a newline, +the newline is not included in the string. +As an example, in a system using ASCII +(in which 'a' is coded as 97, +newline is coded as 10, and '1' is coded as 49), +the five literal strings below denote the same string: + +

+     a = 'alo\n123"'
+     a = "alo\n123\""
+     a = '\97lo\10\04923"'
+     a = [[alo
+     123"]]
+     a = [==[
+     alo
+     123"]==]
+
+ +

+A numerical constant can be written with an optional fractional part +and an optional decimal exponent, +marked by a letter 'e' or 'E'. +Lua also accepts hexadecimal constants, +which start with 0x or 0X. +Hexadecimal constants also accept an optional fractional part +plus an optional binary exponent, +marked by a letter 'p' or 'P'. +Examples of valid numerical constants are + +

+     3     3.0     3.1416     314.16e-2     0.31416E1
+     0xff  0x0.1E  0xA23p-4   0X1.921FB54442D18P+1
+
+ +

+A comment starts with a double hyphen (--) +anywhere outside a string. +If the text immediately after -- is not an opening long bracket, +the comment is a short comment, +which runs until the end of the line. +Otherwise, it is a long comment, +which runs until the corresponding closing long bracket. +Long comments are frequently used to disable code temporarily. + + + + + +

3.2 – Variables

+ +

+Variables are places that store values. +There are three kinds of variables in Lua: +global variables, local variables, and table fields. + + +

+A single name can denote a global variable or a local variable +(or a function's formal parameter, +which is a particular kind of local variable): + +

+	var ::= Name
+

+Name denotes identifiers, as defined in §3.1. + + +

+Any variable name is assumed to be global unless explicitly declared +as a local (see §3.3.7). +Local variables are lexically scoped: +local variables can be freely accessed by functions +defined inside their scope (see §3.5). + + +

+Before the first assignment to a variable, its value is nil. + + +

+Square brackets are used to index a table: + +

+	var ::= prefixexp ‘[’ exp ‘]’
+

+The meaning of accesses to table fields can be changed via metatables. +An access to an indexed variable t[i] is equivalent to +a call gettable_event(t,i). +(See §2.4 for a complete description of the +gettable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +

+The syntax var.Name is just syntactic sugar for +var["Name"]: + +

+	var ::= prefixexp ‘.’ Name
+
+ +

+An access to a global variable x +is equivalent to _ENV.x. +Due to the way that chunks are compiled, +_ENV is never a global name (see §2.2). + + + + + +

3.3 – Statements

+ +

+Lua supports an almost conventional set of statements, +similar to those in Pascal or C. +This set includes +assignments, control structures, function calls, +and variable declarations. + + + +

3.3.1 – Blocks

+ +

+A block is a list of statements, +which are executed sequentially: + +

+	block ::= {stat}
+

+Lua has empty statements +that allow you to separate statements with semicolons, +start a block with a semicolon +or write two semicolons in sequence: + +

+	stat ::= ‘;’
+
+ +

+Function calls and assignments +can start with an open parenthesis. +This possibility leads to an ambiguity in Lua's grammar. +Consider the following fragment: + +

+     a = b + c
+     (print or io.write)('done')
+

+The grammar could see it in two ways: + +

+     a = b + c(print or io.write)('done')
+     
+     a = b + c; (print or io.write)('done')
+

+The current parser always sees such constructions +in the first way, +interpreting the open parenthesis +as the start of the arguments to a call. +To avoid this ambiguity, +it is a good practice to always precede with a semicolon +statements that start with a parenthesis: + +

+     ;(print or io.write)('done')
+
+ +

+A block can be explicitly delimited to produce a single statement: + +

+	stat ::= do block end
+

+Explicit blocks are useful +to control the scope of variable declarations. +Explicit blocks are also sometimes used to +add a return statement in the middle +of another block (see §3.3.4). + + + + + +

3.3.2 – Chunks

+ +

+The unit of compilation of Lua is called a chunk. +Syntactically, +a chunk is simply a block: + +

+	chunk ::= block
+
+ +

+Lua handles a chunk as the body of an anonymous function +with a variable number of arguments +(see §3.4.10). +As such, chunks can define local variables, +receive arguments, and return values. +Moreover, such anonymous function is compiled as in the +scope of an external local variable called _ENV (see §2.2). +The resulting function always has _ENV as its only upvalue, +even if it does not use that variable. + + +

+A chunk can be stored in a file or in a string inside the host program. +To execute a chunk, +Lua first precompiles the chunk into instructions for a virtual machine, +and then it executes the compiled code +with an interpreter for the virtual machine. + + +

+Chunks can also be precompiled into binary form; +see program luac for details. +Programs in source and compiled forms are interchangeable; +Lua automatically detects the file type and acts accordingly. + + + + + + +

3.3.3 – Assignment

+ +

+Lua allows multiple assignments. +Therefore, the syntax for assignment +defines a list of variables on the left side +and a list of expressions on the right side. +The elements in both lists are separated by commas: + +

+	stat ::= varlist ‘=’ explist
+	varlist ::= var {‘,’ var}
+	explist ::= exp {‘,’ exp}
+

+Expressions are discussed in §3.4. + + +

+Before the assignment, +the list of values is adjusted to the length of +the list of variables. +If there are more values than needed, +the excess values are thrown away. +If there are fewer values than needed, +the list is extended with as many nil's as needed. +If the list of expressions ends with a function call, +then all values returned by that call enter the list of values, +before the adjustment +(except when the call is enclosed in parentheses; see §3.4). + + +

+The assignment statement first evaluates all its expressions +and only then are the assignments performed. +Thus the code + +

+     i = 3
+     i, a[i] = i+1, 20
+

+sets a[3] to 20, without affecting a[4] +because the i in a[i] is evaluated (to 3) +before it is assigned 4. +Similarly, the line + +

+     x, y = y, x
+

+exchanges the values of x and y, +and + +

+     x, y, z = y, z, x
+

+cyclically permutes the values of x, y, and z. + + +

+The meaning of assignments to global variables +and table fields can be changed via metatables. +An assignment to an indexed variable t[i] = val is equivalent to +settable_event(t,i,val). +(See §2.4 for a complete description of the +settable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +

+An assignment to a global variable x = val +is equivalent to the assignment +_ENV.x = val (see §2.2). + + + + + +

3.3.4 – Control Structures

+The control structures +if, while, and repeat have the usual meaning and +familiar syntax: + + + + +

+	stat ::= while exp do block end
+	stat ::= repeat block until exp
+	stat ::= if exp then block {elseif exp then block} [else block] end
+

+Lua also has a for statement, in two flavors (see §3.3.5). + + +

+The condition expression of a +control structure can return any value. +Both false and nil are considered false. +All values different from nil and false are considered true +(in particular, the number 0 and the empty string are also true). + + +

+In the repeat–until loop, +the inner block does not end at the until keyword, +but only after the condition. +So, the condition can refer to local variables +declared inside the loop block. + + +

+The goto statement transfers the program control to a label. +For syntactical reasons, +labels in Lua are considered statements too: + + + +

+	stat ::= goto Name
+	stat ::= label
+	label ::= ‘::’ Name ‘::’
+
+ +

+A label is visible in the entire block where it is defined, +except +inside nested blocks where a label with the same name is defined and +inside nested functions. +A goto may jump to any visible label as long as it does not +enter into the scope of a local variable. + + +

+Labels and empty statements are called void statements, +as they perform no actions. + + +

+The break statement terminates the execution of a +while, repeat, or for loop, +skipping to the next statement after the loop: + + +

+	stat ::= break
+

+A break ends the innermost enclosing loop. + + +

+The return statement is used to return values +from a function or a chunk (which is a function in disguise). + +Functions can return more than one value, +so the syntax for the return statement is + +

+	stat ::= return [explist] [‘;’]
+
+ +

+The return statement can only be written +as the last statement of a block. +If it is really necessary to return in the middle of a block, +then an explicit inner block can be used, +as in the idiom do return end, +because now return is the last statement in its (inner) block. + + + + + +

3.3.5 – For Statement

+ +

+ +The for statement has two forms: +one numeric and one generic. + + +

+The numeric for loop repeats a block of code while a +control variable runs through an arithmetic progression. +It has the following syntax: + +

+	stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
+

+The block is repeated for name starting at the value of +the first exp, until it passes the second exp by steps of the +third exp. +More precisely, a for statement like + +

+     for v = e1, e2, e3 do block end
+

+is equivalent to the code: + +

+     do
+       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
+       if not (var and limit and step) then error() end
+       while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
+         local v = var
+         block
+         var = var + step
+       end
+     end
+

+Note the following: + +

    + +
  • +All three control expressions are evaluated only once, +before the loop starts. +They must all result in numbers. +
  • + +
  • +var, limit, and step are invisible variables. +The names shown here are for explanatory purposes only. +
  • + +
  • +If the third expression (the step) is absent, +then a step of 1 is used. +
  • + +
  • +You can use break to exit a for loop. +
  • + +
  • +The loop variable v is local to the loop; +you cannot use its value after the for ends or is broken. +If you need this value, +assign it to another variable before breaking or exiting the loop. +
  • + +
+ +

+The generic for statement works over functions, +called iterators. +On each iteration, the iterator function is called to produce a new value, +stopping when this new value is nil. +The generic for loop has the following syntax: + +

+	stat ::= for namelist in explist do block end
+	namelist ::= Name {‘,’ Name}
+

+A for statement like + +

+     for var_1, ···, var_n in explist do block end
+

+is equivalent to the code: + +

+     do
+       local f, s, var = explist
+       while true do
+         local var_1, ···, var_n = f(s, var)
+         if var_1 == nil then break end
+         var = var_1
+         block
+       end
+     end
+

+Note the following: + +

    + +
  • +explist is evaluated only once. +Its results are an iterator function, +a state, +and an initial value for the first iterator variable. +
  • + +
  • +f, s, and var are invisible variables. +The names are here for explanatory purposes only. +
  • + +
  • +You can use break to exit a for loop. +
  • + +
  • +The loop variables var_i are local to the loop; +you cannot use their values after the for ends. +If you need these values, +then assign them to other variables before breaking or exiting the loop. +
  • + +
+ + + + +

3.3.6 – Function Calls as Statements

+To allow possible side-effects, +function calls can be executed as statements: + +

+	stat ::= functioncall
+

+In this case, all returned values are thrown away. +Function calls are explained in §3.4.9. + + + + + +

3.3.7 – Local Declarations

+Local variables can be declared anywhere inside a block. +The declaration can include an initial assignment: + +

+	stat ::= local namelist [‘=’ explist]
+

+If present, an initial assignment has the same semantics +of a multiple assignment (see §3.3.3). +Otherwise, all variables are initialized with nil. + + +

+A chunk is also a block (see §3.3.2), +and so local variables can be declared in a chunk outside any explicit block. + + +

+The visibility rules for local variables are explained in §3.5. + + + + + + + +

3.4 – Expressions

+ +

+The basic expressions in Lua are the following: + +

+	exp ::= prefixexp
+	exp ::= nil | false | true
+	exp ::= Number
+	exp ::= String
+	exp ::= functiondef
+	exp ::= tableconstructor
+	exp ::= ‘...’
+	exp ::= exp binop exp
+	exp ::= unop exp
+	prefixexp ::= var | functioncall | ‘(’ exp ‘)’
+
+ +

+Numbers and literal strings are explained in §3.1; +variables are explained in §3.2; +function definitions are explained in §3.4.10; +function calls are explained in §3.4.9; +table constructors are explained in §3.4.8. +Vararg expressions, +denoted by three dots ('...'), can only be used when +directly inside a vararg function; +they are explained in §3.4.10. + + +

+Binary operators comprise arithmetic operators (see §3.4.1), +relational operators (see §3.4.3), logical operators (see §3.4.4), +and the concatenation operator (see §3.4.5). +Unary operators comprise the unary minus (see §3.4.1), +the unary not (see §3.4.4), +and the unary length operator (see §3.4.6). + + +

+Both function calls and vararg expressions can result in multiple values. +If a function call is used as a statement (see §3.3.6), +then its return list is adjusted to zero elements, +thus discarding all returned values. +If an expression is used as the last (or the only) element +of a list of expressions, +then no adjustment is made +(unless the expression is enclosed in parentheses). +In all other contexts, +Lua adjusts the result list to one element, +either discarding all values except the first one +or adding a single nil if there are no values. + + +

+Here are some examples: + +

+     f()                -- adjusted to 0 results
+     g(f(), x)          -- f() is adjusted to 1 result
+     g(x, f())          -- g gets x plus all results from f()
+     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)
+     a,b = ...          -- a gets the first vararg parameter, b gets
+                        -- the second (both a and b can get nil if there
+                        -- is no corresponding vararg parameter)
+     
+     a,b,c = x, f()     -- f() is adjusted to 2 results
+     a,b,c = f()        -- f() is adjusted to 3 results
+     return f()         -- returns all results from f()
+     return ...         -- returns all received vararg parameters
+     return x,y,f()     -- returns x, y, and all results from f()
+     {f()}              -- creates a list with all results from f()
+     {...}              -- creates a list with all vararg parameters
+     {f(), nil}         -- f() is adjusted to 1 result
+
+ +

+Any expression enclosed in parentheses always results in only one value. +Thus, +(f(x,y,z)) is always a single value, +even if f returns several values. +(The value of (f(x,y,z)) is the first value returned by f +or nil if f does not return any values.) + + + +

3.4.1 – Arithmetic Operators

+Lua supports the usual arithmetic operators: +the binary + (addition), +- (subtraction), * (multiplication), +/ (division), % (modulo), and ^ (exponentiation); +and unary - (mathematical negation). +If the operands are numbers, or strings that can be converted to +numbers (see §3.4.2), +then all operations have the usual meaning. +Exponentiation works for any exponent. +For instance, x^(-0.5) computes the inverse of the square root of x. +Modulo is defined as + +

+     a % b == a - math.floor(a/b)*b
+

+That is, it is the remainder of a division that rounds +the quotient towards minus infinity. + + + + + +

3.4.2 – Coercion

+ +

+Lua provides automatic conversion between +string and number values at run time. +Any arithmetic operation applied to a string tries to convert +this string to a number, following the rules of the Lua lexer. +(The string may have leading and trailing spaces and a sign.) +Conversely, whenever a number is used where a string is expected, +the number is converted to a string, in a reasonable format. +For complete control over how numbers are converted to strings, +use the format function from the string library +(see string.format). + + + + + +

3.4.3 – Relational Operators

+The relational operators in Lua are + +

+     ==    ~=    <     >     <=    >=
+

+These operators always result in false or true. + + +

+Equality (==) first compares the type of its operands. +If the types are different, then the result is false. +Otherwise, the values of the operands are compared. +Numbers and strings are compared in the usual way. +Tables, userdata, and threads +are compared by reference: +two objects are considered equal only if they are the same object. +Every time you create a new object +(a table, userdata, or thread), +this new object is different from any previously existing object. +Closures with the same reference are always equal. +Closures with any detectable difference +(different behavior, different definition) are always different. + + +

+You can change the way that Lua compares tables and userdata +by using the "eq" metamethod (see §2.4). + + +

+The conversion rules of §3.4.2 +do not apply to equality comparisons. +Thus, "0"==0 evaluates to false, +and t[0] and t["0"] denote different +entries in a table. + + +

+The operator ~= is exactly the negation of equality (==). + + +

+The order operators work as follows. +If both arguments are numbers, then they are compared as such. +Otherwise, if both arguments are strings, +then their values are compared according to the current locale. +Otherwise, Lua tries to call the "lt" or the "le" +metamethod (see §2.4). +A comparison a > b is translated to b < a +and a >= b is translated to b <= a. + + + + + +

3.4.4 – Logical Operators

+The logical operators in Lua are +and, or, and not. +Like the control structures (see §3.3.4), +all logical operators consider both false and nil as false +and anything else as true. + + +

+The negation operator not always returns false or true. +The conjunction operator and returns its first argument +if this value is false or nil; +otherwise, and returns its second argument. +The disjunction operator or returns its first argument +if this value is different from nil and false; +otherwise, or returns its second argument. +Both and and or use short-cut evaluation; +that is, +the second operand is evaluated only if necessary. +Here are some examples: + +

+     10 or 20            --> 10
+     10 or error()       --> 10
+     nil or "a"          --> "a"
+     nil and 10          --> nil
+     false and error()   --> false
+     false and nil       --> false
+     false or nil        --> nil
+     10 and 20           --> 20
+

+(In this manual, +--> indicates the result of the preceding expression.) + + + + + +

3.4.5 – Concatenation

+The string concatenation operator in Lua is +denoted by two dots ('..'). +If both operands are strings or numbers, then they are converted to +strings according to the rules mentioned in §3.4.2. +Otherwise, the __concat metamethod is called (see §2.4). + + + + + +

3.4.6 – The Length Operator

+ +

+The length operator is denoted by the unary prefix operator #. +The length of a string is its number of bytes +(that is, the usual meaning of string length when each +character is one byte). + + +

+A program can modify the behavior of the length operator for +any value but strings through the __len metamethod (see §2.4). + + +

+Unless a __len metamethod is given, +the length of a table t is only defined if the +table is a sequence, +that is, +the set of its positive numeric keys is equal to {1..n} +for some integer n. +In that case, n is its length. +Note that a table like + +

+     {10, 20, nil, 40}
+

+is not a sequence, because it has the key 4 +but does not have the key 3. +(So, there is no n such that the set {1..n} is equal +to the set of positive numeric keys of that table.) +Note, however, that non-numeric keys do not interfere +with whether a table is a sequence. + + + + + +

3.4.7 – Precedence

+Operator precedence in Lua follows the table below, +from lower to higher priority: + +

+     or
+     and
+     <     >     <=    >=    ~=    ==
+     ..
+     +     -
+     *     /     %
+     not   #     - (unary)
+     ^
+

+As usual, +you can use parentheses to change the precedences of an expression. +The concatenation ('..') and exponentiation ('^') +operators are right associative. +All other binary operators are left associative. + + + + + +

3.4.8 – Table Constructors

+Table constructors are expressions that create tables. +Every time a constructor is evaluated, a new table is created. +A constructor can be used to create an empty table +or to create a table and initialize some of its fields. +The general syntax for constructors is + +

+	tableconstructor ::= ‘{’ [fieldlist] ‘}’
+	fieldlist ::= field {fieldsep field} [fieldsep]
+	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
+	fieldsep ::= ‘,’ | ‘;’
+
+ +

+Each field of the form [exp1] = exp2 adds to the new table an entry +with key exp1 and value exp2. +A field of the form name = exp is equivalent to +["name"] = exp. +Finally, fields of the form exp are equivalent to +[i] = exp, where i are consecutive numerical integers, +starting with 1. +Fields in the other formats do not affect this counting. +For example, + +

+     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
+

+is equivalent to + +

+     do
+       local t = {}
+       t[f(1)] = g
+       t[1] = "x"         -- 1st exp
+       t[2] = "y"         -- 2nd exp
+       t.x = 1            -- t["x"] = 1
+       t[3] = f(x)        -- 3rd exp
+       t[30] = 23
+       t[4] = 45          -- 4th exp
+       a = t
+     end
+
+ +

+If the last field in the list has the form exp +and the expression is a function call or a vararg expression, +then all values returned by this expression enter the list consecutively +(see §3.4.9). + + +

+The field list can have an optional trailing separator, +as a convenience for machine-generated code. + + + + + +

3.4.9 – Function Calls

+A function call in Lua has the following syntax: + +

+	functioncall ::= prefixexp args
+

+In a function call, +first prefixexp and args are evaluated. +If the value of prefixexp has type function, +then this function is called +with the given arguments. +Otherwise, the prefixexp "call" metamethod is called, +having as first parameter the value of prefixexp, +followed by the original call arguments +(see §2.4). + + +

+The form + +

+	functioncall ::= prefixexp ‘:’ Name args
+

+can be used to call "methods". +A call v:name(args) +is syntactic sugar for v.name(v,args), +except that v is evaluated only once. + + +

+Arguments have the following syntax: + +

+	args ::= ‘(’ [explist] ‘)’
+	args ::= tableconstructor
+	args ::= String
+

+All argument expressions are evaluated before the call. +A call of the form f{fields} is +syntactic sugar for f({fields}); +that is, the argument list is a single new table. +A call of the form f'string' +(or f"string" or f[[string]]) +is syntactic sugar for f('string'); +that is, the argument list is a single literal string. + + +

+A call of the form return functioncall is called +a tail call. +Lua implements proper tail calls +(or proper tail recursion): +in a tail call, +the called function reuses the stack entry of the calling function. +Therefore, there is no limit on the number of nested tail calls that +a program can execute. +However, a tail call erases any debug information about the +calling function. +Note that a tail call only happens with a particular syntax, +where the return has one single function call as argument; +this syntax makes the calling function return exactly +the returns of the called function. +So, none of the following examples are tail calls: + +

+     return (f(x))        -- results adjusted to 1
+     return 2 * f(x)
+     return x, f(x)       -- additional results
+     f(x); return         -- results discarded
+     return x or f(x)     -- results adjusted to 1
+
+ + + + +

3.4.10 – Function Definitions

+ +

+The syntax for function definition is + +

+	functiondef ::= function funcbody
+	funcbody ::= ‘(’ [parlist] ‘)’ block end
+
+ +

+The following syntactic sugar simplifies function definitions: + +

+	stat ::= function funcname funcbody
+	stat ::= local function Name funcbody
+	funcname ::= Name {‘.’ Name} [‘:’ Name]
+

+The statement + +

+     function f () body end
+

+translates to + +

+     f = function () body end
+

+The statement + +

+     function t.a.b.c.f () body end
+

+translates to + +

+     t.a.b.c.f = function () body end
+

+The statement + +

+     local function f () body end
+

+translates to + +

+     local f; f = function () body end
+

+not to + +

+     local f = function () body end
+

+(This only makes a difference when the body of the function +contains references to f.) + + +

+A function definition is an executable expression, +whose value has type function. +When Lua precompiles a chunk, +all its function bodies are precompiled too. +Then, whenever Lua executes the function definition, +the function is instantiated (or closed). +This function instance (or closure) +is the final value of the expression. + + +

+Parameters act as local variables that are +initialized with the argument values: + +

+	parlist ::= namelist [‘,’ ‘...’] | ‘...’
+

+When a function is called, +the list of arguments is adjusted to +the length of the list of parameters, +unless the function is a vararg function, +which is indicated by three dots ('...') +at the end of its parameter list. +A vararg function does not adjust its argument list; +instead, it collects all extra arguments and supplies them +to the function through a vararg expression, +which is also written as three dots. +The value of this expression is a list of all actual extra arguments, +similar to a function with multiple results. +If a vararg expression is used inside another expression +or in the middle of a list of expressions, +then its return list is adjusted to one element. +If the expression is used as the last element of a list of expressions, +then no adjustment is made +(unless that last expression is enclosed in parentheses). + + +

+As an example, consider the following definitions: + +

+     function f(a, b) end
+     function g(a, b, ...) end
+     function r() return 1,2,3 end
+

+Then, we have the following mapping from arguments to parameters and +to the vararg expression: + +

+     CALL            PARAMETERS
+     
+     f(3)             a=3, b=nil
+     f(3, 4)          a=3, b=4
+     f(3, 4, 5)       a=3, b=4
+     f(r(), 10)       a=1, b=10
+     f(r())           a=1, b=2
+     
+     g(3)             a=3, b=nil, ... -->  (nothing)
+     g(3, 4)          a=3, b=4,   ... -->  (nothing)
+     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
+     g(5, r())        a=5, b=1,   ... -->  2  3
+
+ +

+Results are returned using the return statement (see §3.3.4). +If control reaches the end of a function +without encountering a return statement, +then the function returns with no results. + + +

+ +There is a system-dependent limit on the number of values +that a function may return. +This limit is guaranteed to be larger than 1000. + + +

+The colon syntax +is used for defining methods, +that is, functions that have an implicit extra parameter self. +Thus, the statement + +

+     function t.a.b.c:f (params) body end
+

+is syntactic sugar for + +

+     t.a.b.c.f = function (self, params) body end
+
+ + + + + + +

3.5 – Visibility Rules

+ +

+ +Lua is a lexically scoped language. +The scope of a local variable begins at the first statement after +its declaration and lasts until the last non-void statement +of the innermost block that includes the declaration. +Consider the following example: + +

+     x = 10                -- global variable
+     do                    -- new block
+       local x = x         -- new 'x', with value 10
+       print(x)            --> 10
+       x = x+1
+       do                  -- another block
+         local x = x+1     -- another 'x'
+         print(x)          --> 12
+       end
+       print(x)            --> 11
+     end
+     print(x)              --> 10  (the global one)
+
+ +

+Notice that, in a declaration like local x = x, +the new x being declared is not in scope yet, +and so the second x refers to the outside variable. + + +

+Because of the lexical scoping rules, +local variables can be freely accessed by functions +defined inside their scope. +A local variable used by an inner function is called +an upvalue, or external local variable, +inside the inner function. + + +

+Notice that each execution of a local statement +defines new local variables. +Consider the following example: + +

+     a = {}
+     local x = 20
+     for i=1,10 do
+       local y = 0
+       a[i] = function () y=y+1; return x+y end
+     end
+

+The loop creates ten closures +(that is, ten instances of the anonymous function). +Each of these closures uses a different y variable, +while all of them share the same x. + + + + + +

4 – The Application Program Interface

+ +

+ +This section describes the C API for Lua, that is, +the set of C functions available to the host program to communicate +with Lua. +All API functions and related types and constants +are declared in the header file lua.h. + + +

+Even when we use the term "function", +any facility in the API may be provided as a macro instead. +Except where stated otherwise, +all such macros use each of their arguments exactly once +(except for the first argument, which is always a Lua state), +and so do not generate any hidden side-effects. + + +

+As in most C libraries, +the Lua API functions do not check their arguments for validity or consistency. +However, you can change this behavior by compiling Lua +with the macro LUA_USE_APICHECK defined. + + + +

4.1 – The Stack

+ +

+Lua uses a virtual stack to pass values to and from C. +Each element in this stack represents a Lua value +(nil, number, string, etc.). + + +

+Whenever Lua calls C, the called function gets a new stack, +which is independent of previous stacks and of stacks of +C functions that are still active. +This stack initially contains any arguments to the C function +and it is where the C function pushes its results +to be returned to the caller (see lua_CFunction). + + +

+For convenience, +most query operations in the API do not follow a strict stack discipline. +Instead, they can refer to any element in the stack +by using an index: +A positive index represents an absolute stack position +(starting at 1); +a negative index represents an offset relative to the top of the stack. +More specifically, if the stack has n elements, +then index 1 represents the first element +(that is, the element that was pushed onto the stack first) +and +index n represents the last element; +index -1 also represents the last element +(that is, the element at the top) +and index -n represents the first element. + + + + + +

4.2 – Stack Size

+ +

+When you interact with the Lua API, +you are responsible for ensuring consistency. +In particular, +you are responsible for controlling stack overflow. +You can use the function lua_checkstack +to ensure that the stack has extra slots when pushing new elements. + + +

+Whenever Lua calls C, +it ensures that the stack has at least LUA_MINSTACK extra slots. +LUA_MINSTACK is defined as 20, +so that usually you do not have to worry about stack space +unless your code has loops pushing elements onto the stack. + + +

+When you call a Lua function +without a fixed number of results (see lua_call), +Lua ensures that the stack has enough size for all results, +but it does not ensure any extra space. +So, before pushing anything in the stack after such a call +you should use lua_checkstack. + + + + + +

4.3 – Valid and Acceptable Indices

+ +

+Any function in the API that receives stack indices +works only with valid indices or acceptable indices. + + +

+A valid index is an index that refers to a +real position within the stack, that is, +its position lies between 1 and the stack top +(1 ≤ abs(index) ≤ top). + +Usually, functions that can modify the value at an index +require valid indices. + + +

+Unless otherwise noted, +any function that accepts valid indices also accepts pseudo-indices, +which represent some Lua values that are accessible to C code +but which are not in the stack. +Pseudo-indices are used to access the registry +and the upvalues of a C function (see §4.4). + + +

+Functions that do not need a specific stack position, +but only a value in the stack (e.g., query functions), +can be called with acceptable indices. +An acceptable index can be any valid index, +including the pseudo-indices, +but it also can be any positive index after the stack top +within the space allocated for the stack, +that is, indices up to the stack size. +(Note that 0 is never an acceptable index.) +Except when noted otherwise, +functions in the API work with acceptable indices. + + +

+Acceptable indices serve to avoid extra tests +against the stack top when querying the stack. +For instance, a C function can query its third argument +without the need to first check whether there is a third argument, +that is, without the need to check whether 3 is a valid index. + + +

+For functions that can be called with acceptable indices, +any non-valid index is treated as if it +contains a value of a virtual type LUA_TNONE, +which behaves like a nil value. + + + + + +

4.4 – C Closures

+ +

+When a C function is created, +it is possible to associate some values with it, +thus creating a C closure +(see lua_pushcclosure); +these values are called upvalues and are +accessible to the function whenever it is called. + + +

+Whenever a C function is called, +its upvalues are located at specific pseudo-indices. +These pseudo-indices are produced by the macro +lua_upvalueindex. +The first value associated with a function is at position +lua_upvalueindex(1), and so on. +Any access to lua_upvalueindex(n), +where n is greater than the number of upvalues of the +current function (but not greater than 256), +produces an acceptable but invalid index. + + + + + +

4.5 – Registry

+ +

+Lua provides a registry, +a predefined table that can be used by any C code to +store whatever Lua values it needs to store. +The registry table is always located at pseudo-index +LUA_REGISTRYINDEX, +which is a valid index. +Any C library can store data into this table, +but it should take care to choose keys +that are different from those used +by other libraries, to avoid collisions. +Typically, you should use as key a string containing your library name, +or a light userdata with the address of a C object in your code, +or any Lua object created by your code. +As with global names, +string keys starting with an underscore followed by +uppercase letters are reserved for Lua. + + +

+The integer keys in the registry are used by the reference mechanism, +implemented by the auxiliary library, +and by some predefined values. +Therefore, integer keys should not be used for other purposes. + + +

+When you create a new Lua state, +its registry comes with some predefined values. +These predefined values are indexed with integer keys +defined as constants in lua.h. +The following constants are defined: + +

    +
  • LUA_RIDX_MAINTHREAD: At this index the registry has +the main thread of the state. +(The main thread is the one created together with the state.) +
  • + +
  • LUA_RIDX_GLOBALS: At this index the registry has +the global environment. +
  • +
+ + + + +

4.6 – Error Handling in C

+ +

+Internally, Lua uses the C longjmp facility to handle errors. +(You can also choose to use exceptions if you compile Lua as C++; +search for LUAI_THROW in the source code.) +When Lua faces any error +(such as a memory allocation error, type errors, syntax errors, +and runtime errors) +it raises an error; +that is, it does a long jump. +A protected environment uses setjmp +to set a recovery point; +any error jumps to the most recent active recovery point. + + +

+If an error happens outside any protected environment, +Lua calls a panic function (see lua_atpanic) +and then calls abort, +thus exiting the host application. +Your panic function can avoid this exit by +never returning +(e.g., doing a long jump to your own recovery point outside Lua). + + +

+The panic function runs as if it were a message handler (see §2.3); +in particular, the error message is at the top of the stack. +However, there is no guarantees about stack space. +To push anything on the stack, +the panic function should first check the available space (see §4.2). + + +

+Most functions in the API can throw an error, +for instance due to a memory allocation error. +The documentation for each function indicates whether +it can throw errors. + + +

+Inside a C function you can throw an error by calling lua_error. + + + + + +

4.7 – Handling Yields in C

+ +

+Internally, Lua uses the C longjmp facility to yield a coroutine. +Therefore, if a function foo calls an API function +and this API function yields +(directly or indirectly by calling another function that yields), +Lua cannot return to foo any more, +because the longjmp removes its frame from the C stack. + + +

+To avoid this kind of problem, +Lua raises an error whenever it tries to yield across an API call, +except for three functions: +lua_yieldk, lua_callk, and lua_pcallk. +All those functions receive a continuation function +(as a parameter called k) to continue execution after a yield. + + +

+We need to set some terminology to explain continuations. +We have a C function called from Lua which we will call +the original function. +This original function then calls one of those three functions in the C API, +which we will call the callee function, +that then yields the current thread. +(This can happen when the callee function is lua_yieldk, +or when the callee function is either lua_callk or lua_pcallk +and the function called by them yields.) + + +

+Suppose the running thread yields while executing the callee function. +After the thread resumes, +it eventually will finish running the callee function. +However, +the callee function cannot return to the original function, +because its frame in the C stack was destroyed by the yield. +Instead, Lua calls a continuation function, +which was given as an argument to the callee function. +As the name implies, +the continuation function should continue the task +of the original function. + + +

+Lua treats the continuation function as if it were the original function. +The continuation function receives the same Lua stack +from the original function, +in the same state it would be if the callee function had returned. +(For instance, +after a lua_callk the function and its arguments are +removed from the stack and replaced by the results from the call.) +It also has the same upvalues. +Whatever it returns is handled by Lua as if it were the return +of the original function. + + +

+The only difference in the Lua state between the original function +and its continuation is the result of a call to lua_getctx. + + + + + +

4.8 – Functions and Types

+ +

+Here we list all functions and types from the C API in +alphabetical order. +Each function has an indicator like this: +[-o, +p, x] + + +

+The first field, o, +is how many elements the function pops from the stack. +The second field, p, +is how many elements the function pushes onto the stack. +(Any function always pushes its results after popping its arguments.) +A field in the form x|y means the function can push (or pop) +x or y elements, +depending on the situation; +an interrogation mark '?' means that +we cannot know how many elements the function pops/pushes +by looking only at its arguments +(e.g., they may depend on what is on the stack). +The third field, x, +tells whether the function may throw errors: +'-' means the function never throws any error; +'e' means the function may throw errors; +'v' means the function may throw an error on purpose. + + + +


lua_absindex

+[-0, +0, –] +

int lua_absindex (lua_State *L, int idx);
+ +

+Converts the acceptable index idx into an absolute index +(that is, one that does not depend on the stack top). + + + + + +


lua_Alloc

+
typedef void * (*lua_Alloc) (void *ud,
+                             void *ptr,
+                             size_t osize,
+                             size_t nsize);
+ +

+The type of the memory-allocation function used by Lua states. +The allocator function must provide a +functionality similar to realloc, +but not exactly the same. +Its arguments are +ud, an opaque pointer passed to lua_newstate; +ptr, a pointer to the block being allocated/reallocated/freed; +osize, the original size of the block or some code about what +is being allocated; +nsize, the new size of the block. + + +

+When ptr is not NULL, +osize is the size of the block pointed by ptr, +that is, the size given when it was allocated or reallocated. + + +

+When ptr is NULL, +osize encodes the kind of object that Lua is allocating. +osize is any of +LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, +LUA_TUSERDATA, or LUA_TTHREAD when (and only when) +Lua is creating a new object of that type. +When osize is some other value, +Lua is allocating memory for something else. + + +

+Lua assumes the following behavior from the allocator function: + + +

+When nsize is zero, +the allocator should behave like free +and return NULL. + + +

+When nsize is not zero, +the allocator should behave like realloc. +The allocator returns NULL +if and only if it cannot fulfill the request. +Lua assumes that the allocator never fails when +osize >= nsize. + + +

+Here is a simple implementation for the allocator function. +It is used in the auxiliary library by luaL_newstate. + +

+     static void *l_alloc (void *ud, void *ptr, size_t osize,
+                                                size_t nsize) {
+       (void)ud;  (void)osize;  /* not used */
+       if (nsize == 0) {
+         free(ptr);
+         return NULL;
+       }
+       else
+         return realloc(ptr, nsize);
+     }
+

+Note that Standard C ensures +that free(NULL) has no effect and that +realloc(NULL, size) is equivalent to malloc(size). +This code assumes that realloc does not fail when shrinking a block. +(Although Standard C does not ensure this behavior, +it seems to be a safe assumption.) + + + + + +


lua_arith

+[-(2|1), +1, e] +

void lua_arith (lua_State *L, int op);
+ +

+Performs an arithmetic operation over the two values +(or one, in the case of negation) +at the top of the stack, +with the value at the top being the second operand, +pops these values, and pushes the result of the operation. +The function follows the semantics of the corresponding Lua operator +(that is, it may call metamethods). + + +

+The value of op must be one of the following constants: + +

+ + + + +

lua_atpanic

+[-0, +0, –] +

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
+ +

+Sets a new panic function and returns the old one (see §4.6). + + + + + +


lua_call

+[-(nargs+1), +nresults, e] +

void lua_call (lua_State *L, int nargs, int nresults);
+ +

+Calls a function. + + +

+To call a function you must use the following protocol: +first, the function to be called is pushed onto the stack; +then, the arguments to the function are pushed +in direct order; +that is, the first argument is pushed first. +Finally you call lua_call; +nargs is the number of arguments that you pushed onto the stack. +All arguments and the function value are popped from the stack +when the function is called. +The function results are pushed onto the stack when the function returns. +The number of results is adjusted to nresults, +unless nresults is LUA_MULTRET. +In this case, all results from the function are pushed. +Lua takes care that the returned values fit into the stack space. +The function results are pushed onto the stack in direct order +(the first result is pushed first), +so that after the call the last result is on the top of the stack. + + +

+Any error inside the called function is propagated upwards +(with a longjmp). + + +

+The following example shows how the host program can do the +equivalent to this Lua code: + +

+     a = f("how", t.x, 14)
+

+Here it is in C: + +

+     lua_getglobal(L, "f");                  /* function to be called */
+     lua_pushstring(L, "how");                        /* 1st argument */
+     lua_getglobal(L, "t");                    /* table to be indexed */
+     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
+     lua_remove(L, -2);                  /* remove 't' from the stack */
+     lua_pushinteger(L, 14);                          /* 3rd argument */
+     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
+     lua_setglobal(L, "a");                         /* set global 'a' */
+

+Note that the code above is "balanced": +at its end, the stack is back to its original configuration. +This is considered good programming practice. + + + + + +


lua_callk

+[-(nargs + 1), +nresults, e] +

void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
+                lua_CFunction k);
+ +

+This function behaves exactly like lua_call, +but allows the called function to yield (see §4.7). + + + + + +


lua_CFunction

+
typedef int (*lua_CFunction) (lua_State *L);
+ +

+Type for C functions. + + +

+In order to communicate properly with Lua, +a C function must use the following protocol, +which defines the way parameters and results are passed: +a C function receives its arguments from Lua in its stack +in direct order (the first argument is pushed first). +So, when the function starts, +lua_gettop(L) returns the number of arguments received by the function. +The first argument (if any) is at index 1 +and its last argument is at index lua_gettop(L). +To return values to Lua, a C function just pushes them onto the stack, +in direct order (the first result is pushed first), +and returns the number of results. +Any other value in the stack below the results will be properly +discarded by Lua. +Like a Lua function, a C function called by Lua can also return +many results. + + +

+As an example, the following function receives a variable number +of numerical arguments and returns their average and sum: + +

+     static int foo (lua_State *L) {
+       int n = lua_gettop(L);    /* number of arguments */
+       lua_Number sum = 0;
+       int i;
+       for (i = 1; i <= n; i++) {
+         if (!lua_isnumber(L, i)) {
+           lua_pushstring(L, "incorrect argument");
+           lua_error(L);
+         }
+         sum += lua_tonumber(L, i);
+       }
+       lua_pushnumber(L, sum/n);        /* first result */
+       lua_pushnumber(L, sum);         /* second result */
+       return 2;                   /* number of results */
+     }
+
+ + + + +

lua_checkstack

+[-0, +0, –] +

int lua_checkstack (lua_State *L, int extra);
+ +

+Ensures that there are at least extra free stack slots in the stack. +It returns false if it cannot fulfill the request, +because it would cause the stack to be larger than a fixed maximum size +(typically at least a few thousand elements) or +because it cannot allocate memory for the new stack size. +This function never shrinks the stack; +if the stack is already larger than the new size, +it is left unchanged. + + + + + +


lua_close

+[-0, +0, –] +

void lua_close (lua_State *L);
+ +

+Destroys all objects in the given Lua state +(calling the corresponding garbage-collection metamethods, if any) +and frees all dynamic memory used by this state. +On several platforms, you may not need to call this function, +because all resources are naturally released when the host program ends. +On the other hand, long-running programs that create multiple states, +such as daemons or web servers, +might need to close states as soon as they are not needed. + + + + + +


lua_compare

+[-0, +0, e] +

int lua_compare (lua_State *L, int index1, int index2, int op);
+ +

+Compares two Lua values. +Returns 1 if the value at index index1 satisfies op +when compared with the value at index index2, +following the semantics of the corresponding Lua operator +(that is, it may call metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices is non valid. + + +

+The value of op must be one of the following constants: + +

    + +
  • LUA_OPEQ: compares for equality (==)
  • +
  • LUA_OPLT: compares for less than (<)
  • +
  • LUA_OPLE: compares for less or equal (<=)
  • + +
+ + + + +

lua_concat

+[-n, +1, e] +

void lua_concat (lua_State *L, int n);
+ +

+Concatenates the n values at the top of the stack, +pops them, and leaves the result at the top. +If n is 1, the result is the single value on the stack +(that is, the function does nothing); +if n is 0, the result is the empty string. +Concatenation is performed following the usual semantics of Lua +(see §3.4.5). + + + + + +


lua_copy

+[-0, +0, –] +

void lua_copy (lua_State *L, int fromidx, int toidx);
+ +

+Moves the element at index fromidx +into the valid index toidx +without shifting any element +(therefore replacing the value at that position). + + + + + +


lua_createtable

+[-0, +1, e] +

void lua_createtable (lua_State *L, int narr, int nrec);
+ +

+Creates a new empty table and pushes it onto the stack. +Parameter narr is a hint for how many elements the table +will have as a sequence; +parameter nrec is a hint for how many other elements +the table will have. +Lua may use these hints to preallocate memory for the new table. +This pre-allocation is useful for performance when you know in advance +how many elements the table will have. +Otherwise you can use the function lua_newtable. + + + + + +


lua_dump

+[-0, +0, e] +

int lua_dump (lua_State *L, lua_Writer writer, void *data);
+ +

+Dumps a function as a binary chunk. +Receives a Lua function on the top of the stack +and produces a binary chunk that, +if loaded again, +results in a function equivalent to the one dumped. +As it produces parts of the chunk, +lua_dump calls function writer (see lua_Writer) +with the given data +to write them. + + +

+The value returned is the error code returned by the last +call to the writer; +0 means no errors. + + +

+This function does not pop the Lua function from the stack. + + + + + +


lua_error

+[-1, +0, v] +

int lua_error (lua_State *L);
+ +

+Generates a Lua error. +The error message (which can actually be a Lua value of any type) +must be on the stack top. +This function does a long jump, +and therefore never returns +(see luaL_error). + + + + + +


lua_gc

+[-0, +0, e] +

int lua_gc (lua_State *L, int what, int data);
+ +

+Controls the garbage collector. + + +

+This function performs several tasks, +according to the value of the parameter what: + +

    + +
  • LUA_GCSTOP: +stops the garbage collector. +
  • + +
  • LUA_GCRESTART: +restarts the garbage collector. +
  • + +
  • LUA_GCCOLLECT: +performs a full garbage-collection cycle. +
  • + +
  • LUA_GCCOUNT: +returns the current amount of memory (in Kbytes) in use by Lua. +
  • + +
  • LUA_GCCOUNTB: +returns the remainder of dividing the current amount of bytes of +memory in use by Lua by 1024. +
  • + +
  • LUA_GCSTEP: +performs an incremental step of garbage collection. +The step "size" is controlled by data +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of data. +The function returns 1 if the step finished a +garbage-collection cycle. +
  • + +
  • LUA_GCSETPAUSE: +sets data as the new value +for the pause of the collector (see §2.5). +The function returns the previous value of the pause. +
  • + +
  • LUA_GCSETSTEPMUL: +sets data as the new value for the step multiplier of +the collector (see §2.5). +The function returns the previous value of the step multiplier. +
  • + +
  • LUA_GCISRUNNING: +returns a boolean that tells whether the collector is running +(i.e., not stopped). +
  • + +
  • LUA_GCGEN: +changes the collector to generational mode +(see §2.5). +
  • + +
  • LUA_GCINC: +changes the collector to incremental mode. +This is the default mode. +
  • + +
+ +

+For more details about these options, +see collectgarbage. + + + + + +


lua_getallocf

+[-0, +0, –] +

lua_Alloc lua_getallocf (lua_State *L, void **ud);
+ +

+Returns the memory-allocation function of a given state. +If ud is not NULL, Lua stores in *ud the +opaque pointer passed to lua_newstate. + + + + + +


lua_getctx

+[-0, +0, –] +

int lua_getctx (lua_State *L, int *ctx);
+ +

+This function is called by a continuation function (see §4.7) +to retrieve the status of the thread and a context information. + + +

+When called in the original function, +lua_getctx always returns LUA_OK +and does not change the value of its argument ctx. +When called inside a continuation function, +lua_getctx returns LUA_YIELD and sets +the value of ctx to be the context information +(the value passed as the ctx argument +to the callee together with the continuation function). + + +

+When the callee is lua_pcallk, +Lua may also call its continuation function +to handle errors during the call. +That is, upon an error in the function called by lua_pcallk, +Lua may not return to the original function +but instead may call the continuation function. +In that case, a call to lua_getctx will return the error code +(the value that would be returned by lua_pcallk); +the value of ctx will be set to the context information, +as in the case of a yield. + + + + + +


lua_getfield

+[-0, +1, e] +

void lua_getfield (lua_State *L, int index, const char *k);
+ +

+Pushes onto the stack the value t[k], +where t is the value at the given index. +As in Lua, this function may trigger a metamethod +for the "index" event (see §2.4). + + + + + +


lua_getglobal

+[-0, +1, e] +

void lua_getglobal (lua_State *L, const char *name);
+ +

+Pushes onto the stack the value of the global name. + + + + + +


lua_getmetatable

+[-0, +(0|1), –] +

int lua_getmetatable (lua_State *L, int index);
+ +

+Pushes onto the stack the metatable of the value at the given index. +If the value does not have a metatable, +the function returns 0 and pushes nothing on the stack. + + + + + +


lua_gettable

+[-1, +1, e] +

void lua_gettable (lua_State *L, int index);
+ +

+Pushes onto the stack the value t[k], +where t is the value at the given index +and k is the value at the top of the stack. + + +

+This function pops the key from the stack +(putting the resulting value in its place). +As in Lua, this function may trigger a metamethod +for the "index" event (see §2.4). + + + + + +


lua_gettop

+[-0, +0, –] +

int lua_gettop (lua_State *L);
+ +

+Returns the index of the top element in the stack. +Because indices start at 1, +this result is equal to the number of elements in the stack +(and so 0 means an empty stack). + + + + + +


lua_getuservalue

+[-0, +1, –] +

void lua_getuservalue (lua_State *L, int index);
+ +

+Pushes onto the stack the Lua value associated with the userdata +at the given index. +This Lua value must be a table or nil. + + + + + +


lua_insert

+[-1, +1, –] +

void lua_insert (lua_State *L, int index);
+ +

+Moves the top element into the given valid index, +shifting up the elements above this index to open space. +This function cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +


lua_Integer

+
typedef ptrdiff_t lua_Integer;
+ +

+The type used by the Lua API to represent signed integral values. + + +

+By default it is a ptrdiff_t, +which is usually the largest signed integral type the machine handles +"comfortably". + + + + + +


lua_isboolean

+[-0, +0, –] +

int lua_isboolean (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a boolean, +and 0 otherwise. + + + + + +


lua_iscfunction

+[-0, +0, –] +

int lua_iscfunction (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a C function, +and 0 otherwise. + + + + + +


lua_isfunction

+[-0, +0, –] +

int lua_isfunction (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a function +(either C or Lua), and 0 otherwise. + + + + + +


lua_islightuserdata

+[-0, +0, –] +

int lua_islightuserdata (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a light userdata, +and 0 otherwise. + + + + + +


lua_isnil

+[-0, +0, –] +

int lua_isnil (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is nil, +and 0 otherwise. + + + + + +


lua_isnone

+[-0, +0, –] +

int lua_isnone (lua_State *L, int index);
+ +

+Returns 1 if the given index is not valid, +and 0 otherwise. + + + + + +


lua_isnoneornil

+[-0, +0, –] +

int lua_isnoneornil (lua_State *L, int index);
+ +

+Returns 1 if the given index is not valid +or if the value at this index is nil, +and 0 otherwise. + + + + + +


lua_isnumber

+[-0, +0, –] +

int lua_isnumber (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a number +or a string convertible to a number, +and 0 otherwise. + + + + + +


lua_isstring

+[-0, +0, –] +

int lua_isstring (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a string +or a number (which is always convertible to a string), +and 0 otherwise. + + + + + +


lua_istable

+[-0, +0, –] +

int lua_istable (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a table, +and 0 otherwise. + + + + + +


lua_isthread

+[-0, +0, –] +

int lua_isthread (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a thread, +and 0 otherwise. + + + + + +


lua_isuserdata

+[-0, +0, –] +

int lua_isuserdata (lua_State *L, int index);
+ +

+Returns 1 if the value at the given index is a userdata +(either full or light), and 0 otherwise. + + + + + +


lua_len

+[-0, +1, e] +

void lua_len (lua_State *L, int index);
+ +

+Returns the "length" of the value at the given index; +it is equivalent to the '#' operator in Lua (see §3.4.6). +The result is pushed on the stack. + + + + + +


lua_load

+[-0, +1, –] +

int lua_load (lua_State *L,
+              lua_Reader reader,
+              void *data,
+              const char *source,
+              const char *mode);
+ +

+Loads a Lua chunk (without running it). +If there are no errors, +lua_load pushes the compiled chunk as a Lua +function on top of the stack. +Otherwise, it pushes an error message. + + +

+The return values of lua_load are: + +

    + +
  • LUA_OK: no errors;
  • + +
  • LUA_ERRSYNTAX: +syntax error during precompilation;
  • + +
  • LUA_ERRMEM: +memory allocation error;
  • + +
  • LUA_ERRGCMM: +error while running a __gc metamethod. +(This error has no relation with the chunk being loaded. +It is generated by the garbage collector.) +
  • + +
+ +

+The lua_load function uses a user-supplied reader function +to read the chunk (see lua_Reader). +The data argument is an opaque value passed to the reader function. + + +

+The source argument gives a name to the chunk, +which is used for error messages and in debug information (see §4.9). + + +

+lua_load automatically detects whether the chunk is text or binary +and loads it accordingly (see program luac). +The string mode works as in function load, +with the addition that +a NULL value is equivalent to the string "bt". + + +

+lua_load uses the stack internally, +so the reader function should always leave the stack +unmodified when returning. + + +

+If the resulting function has one upvalue, +this upvalue is set to the value of the global environment +stored at index LUA_RIDX_GLOBALS in the registry (see §4.5). +When loading main chunks, +this upvalue will be the _ENV variable (see §2.2). + + + + + +


lua_newstate

+[-0, +0, –] +

lua_State *lua_newstate (lua_Alloc f, void *ud);
+ +

+Creates a new thread running in a new, independent state. +Returns NULL if cannot create the thread or the state +(due to lack of memory). +The argument f is the allocator function; +Lua does all memory allocation for this state through this function. +The second argument, ud, is an opaque pointer that Lua +passes to the allocator in every call. + + + + + +


lua_newtable

+[-0, +1, e] +

void lua_newtable (lua_State *L);
+ +

+Creates a new empty table and pushes it onto the stack. +It is equivalent to lua_createtable(L, 0, 0). + + + + + +


lua_newthread

+[-0, +1, e] +

lua_State *lua_newthread (lua_State *L);
+ +

+Creates a new thread, pushes it on the stack, +and returns a pointer to a lua_State that represents this new thread. +The new thread returned by this function shares with the original thread +its global environment, +but has an independent execution stack. + + +

+There is no explicit function to close or to destroy a thread. +Threads are subject to garbage collection, +like any Lua object. + + + + + +


lua_newuserdata

+[-0, +1, e] +

void *lua_newuserdata (lua_State *L, size_t size);
+ +

+This function allocates a new block of memory with the given size, +pushes onto the stack a new full userdata with the block address, +and returns this address. +The host program can freely use this memory. + + + + + +


lua_next

+[-1, +(2|0), e] +

int lua_next (lua_State *L, int index);
+ +

+Pops a key from the stack, +and pushes a key–value pair from the table at the given index +(the "next" pair after the given key). +If there are no more elements in the table, +then lua_next returns 0 (and pushes nothing). + + +

+A typical traversal looks like this: + +

+     /* table is in the stack at index 't' */
+     lua_pushnil(L);  /* first key */
+     while (lua_next(L, t) != 0) {
+       /* uses 'key' (at index -2) and 'value' (at index -1) */
+       printf("%s - %s\n",
+              lua_typename(L, lua_type(L, -2)),
+              lua_typename(L, lua_type(L, -1)));
+       /* removes 'value'; keeps 'key' for next iteration */
+       lua_pop(L, 1);
+     }
+
+ +

+While traversing a table, +do not call lua_tolstring directly on a key, +unless you know that the key is actually a string. +Recall that lua_tolstring may change +the value at the given index; +this confuses the next call to lua_next. + + +

+See function next for the caveats of modifying +the table during its traversal. + + + + + +


lua_Number

+
typedef double lua_Number;
+ +

+The type of numbers in Lua. +By default, it is double, but that can be changed in luaconf.h. +Through this configuration file you can change +Lua to operate with another type for numbers (e.g., float or long). + + + + + +


lua_pcall

+[-(nargs + 1), +(nresults|1), –] +

int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
+ +

+Calls a function in protected mode. + + +

+Both nargs and nresults have the same meaning as +in lua_call. +If there are no errors during the call, +lua_pcall behaves exactly like lua_call. +However, if there is any error, +lua_pcall catches it, +pushes a single value on the stack (the error message), +and returns an error code. +Like lua_call, +lua_pcall always removes the function +and its arguments from the stack. + + +

+If msgh is 0, +then the error message returned on the stack +is exactly the original error message. +Otherwise, msgh is the stack index of a +message handler. +(In the current implementation, this index cannot be a pseudo-index.) +In case of runtime errors, +this function will be called with the error message +and its return value will be the message +returned on the stack by lua_pcall. + + +

+Typically, the message handler is used to add more debug +information to the error message, such as a stack traceback. +Such information cannot be gathered after the return of lua_pcall, +since by then the stack has unwound. + + +

+The lua_pcall function returns one of the following codes +(defined in lua.h): + +

    + +
  • LUA_OK (0): +success.
  • + +
  • LUA_ERRRUN: +a runtime error. +
  • + +
  • LUA_ERRMEM: +memory allocation error. +For such errors, Lua does not call the message handler. +
  • + +
  • LUA_ERRERR: +error while running the message handler. +
  • + +
  • LUA_ERRGCMM: +error while running a __gc metamethod. +(This error typically has no relation with the function being called. +It is generated by the garbage collector.) +
  • + +
+ + + + +

lua_pcallk

+[-(nargs + 1), +(nresults|1), –] +

int lua_pcallk (lua_State *L,
+                int nargs,
+                int nresults,
+                int errfunc,
+                int ctx,
+                lua_CFunction k);
+ +

+This function behaves exactly like lua_pcall, +but allows the called function to yield (see §4.7). + + + + + +


lua_pop

+[-n, +0, –] +

void lua_pop (lua_State *L, int n);
+ +

+Pops n elements from the stack. + + + + + +


lua_pushboolean

+[-0, +1, –] +

void lua_pushboolean (lua_State *L, int b);
+ +

+Pushes a boolean value with value b onto the stack. + + + + + +


lua_pushcclosure

+[-n, +1, e] +

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
+ +

+Pushes a new C closure onto the stack. + + +

+When a C function is created, +it is possible to associate some values with it, +thus creating a C closure (see §4.4); +these values are then accessible to the function whenever it is called. +To associate values with a C function, +first these values should be pushed onto the stack +(when there are multiple values, the first value is pushed first). +Then lua_pushcclosure +is called to create and push the C function onto the stack, +with the argument n telling how many values should be +associated with the function. +lua_pushcclosure also pops these values from the stack. + + +

+The maximum value for n is 255. + + +

+When n is zero, +this function creates a light C function, +which is just a pointer to the C function. +In that case, it never throws a memory error. + + + + + +


lua_pushcfunction

+[-0, +1, –] +

void lua_pushcfunction (lua_State *L, lua_CFunction f);
+ +

+Pushes a C function onto the stack. +This function receives a pointer to a C function +and pushes onto the stack a Lua value of type function that, +when called, invokes the corresponding C function. + + +

+Any function to be registered in Lua must +follow the correct protocol to receive its parameters +and return its results (see lua_CFunction). + + +

+lua_pushcfunction is defined as a macro: + +

+     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)
+

+Note that f is used twice. + + + + + +


lua_pushfstring

+[-0, +1, e] +

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
+ +

+Pushes onto the stack a formatted string +and returns a pointer to this string. +It is similar to the ANSI C function sprintf, +but has some important differences: + +

    + +
  • +You do not have to allocate space for the result: +the result is a Lua string and Lua takes care of memory allocation +(and deallocation, through garbage collection). +
  • + +
  • +The conversion specifiers are quite restricted. +There are no flags, widths, or precisions. +The conversion specifiers can only be +'%%' (inserts a '%' in the string), +'%s' (inserts a zero-terminated string, with no size restrictions), +'%f' (inserts a lua_Number), +'%p' (inserts a pointer as a hexadecimal numeral), +'%d' (inserts an int), and +'%c' (inserts an int as a byte). +
  • + +
+ + + + +

lua_pushglobaltable

+[-0, +1, –] +

void lua_pushglobaltable (lua_State *L);
+ +

+Pushes the global environment onto the stack. + + + + + +


lua_pushinteger

+[-0, +1, –] +

void lua_pushinteger (lua_State *L, lua_Integer n);
+ +

+Pushes a number with value n onto the stack. + + + + + +


lua_pushlightuserdata

+[-0, +1, –] +

void lua_pushlightuserdata (lua_State *L, void *p);
+ +

+Pushes a light userdata onto the stack. + + +

+Userdata represent C values in Lua. +A light userdata represents a pointer, a void*. +It is a value (like a number): +you do not create it, it has no individual metatable, +and it is not collected (as it was never created). +A light userdata is equal to "any" +light userdata with the same C address. + + + + + +


lua_pushliteral

+[-0, +1, e] +

const char *lua_pushliteral (lua_State *L, const char *s);
+ +

+This macro is equivalent to lua_pushlstring, +but can be used only when s is a literal string. +It automatically provides the string length. + + + + + +


lua_pushlstring

+[-0, +1, e] +

const char *lua_pushlstring (lua_State *L, const char *s, size_t len);
+ +

+Pushes the string pointed to by s with size len +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at s can be freed or reused immediately after +the function returns. +The string can contain any binary data, +including embedded zeros. + + +

+Returns a pointer to the internal copy of the string. + + + + + +


lua_pushnil

+[-0, +1, –] +

void lua_pushnil (lua_State *L);
+ +

+Pushes a nil value onto the stack. + + + + + +


lua_pushnumber

+[-0, +1, –] +

void lua_pushnumber (lua_State *L, lua_Number n);
+ +

+Pushes a number with value n onto the stack. + + + + + +


lua_pushstring

+[-0, +1, e] +

const char *lua_pushstring (lua_State *L, const char *s);
+ +

+Pushes the zero-terminated string pointed to by s +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at s can be freed or reused immediately after +the function returns. + + +

+Returns a pointer to the internal copy of the string. + + +

+If s is NULL, pushes nil and returns NULL. + + + + + +


lua_pushthread

+[-0, +1, –] +

int lua_pushthread (lua_State *L);
+ +

+Pushes the thread represented by L onto the stack. +Returns 1 if this thread is the main thread of its state. + + + + + +


lua_pushunsigned

+[-0, +1, –] +

void lua_pushunsigned (lua_State *L, lua_Unsigned n);
+ +

+Pushes a number with value n onto the stack. + + + + + +


lua_pushvalue

+[-0, +1, –] +

void lua_pushvalue (lua_State *L, int index);
+ +

+Pushes a copy of the element at the given index +onto the stack. + + + + + +


lua_pushvfstring

+[-0, +1, e] +

const char *lua_pushvfstring (lua_State *L,
+                              const char *fmt,
+                              va_list argp);
+ +

+Equivalent to lua_pushfstring, except that it receives a va_list +instead of a variable number of arguments. + + + + + +


lua_rawequal

+[-0, +0, –] +

int lua_rawequal (lua_State *L, int index1, int index2);
+ +

+Returns 1 if the two values in indices index1 and +index2 are primitively equal +(that is, without calling metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices are non valid. + + + + + +


lua_rawget

+[-1, +1, –] +

void lua_rawget (lua_State *L, int index);
+ +

+Similar to lua_gettable, but does a raw access +(i.e., without metamethods). + + + + + +


lua_rawgeti

+[-0, +1, –] +

void lua_rawgeti (lua_State *L, int index, int n);
+ +

+Pushes onto the stack the value t[n], +where t is the table at the given index. +The access is raw; +that is, it does not invoke metamethods. + + + + + +


lua_rawgetp

+[-0, +1, –] +

void lua_rawgetp (lua_State *L, int index, const void *p);
+ +

+Pushes onto the stack the value t[k], +where t is the table at the given index and +k is the pointer p represented as a light userdata. +The access is raw; +that is, it does not invoke metamethods. + + + + + +


lua_rawlen

+[-0, +0, –] +

size_t lua_rawlen (lua_State *L, int index);
+ +

+Returns the raw "length" of the value at the given index: +for strings, this is the string length; +for tables, this is the result of the length operator ('#') +with no metamethods; +for userdata, this is the size of the block of memory allocated +for the userdata; +for other values, it is 0. + + + + + +


lua_rawset

+[-2, +0, e] +

void lua_rawset (lua_State *L, int index);
+ +

+Similar to lua_settable, but does a raw assignment +(i.e., without metamethods). + + + + + +


lua_rawseti

+[-1, +0, e] +

void lua_rawseti (lua_State *L, int index, int n);
+ +

+Does the equivalent of t[n] = v, +where t is the table at the given index +and v is the value at the top of the stack. + + +

+This function pops the value from the stack. +The assignment is raw; +that is, it does not invoke metamethods. + + + + + +


lua_rawsetp

+[-1, +0, e] +

void lua_rawsetp (lua_State *L, int index, const void *p);
+ +

+Does the equivalent of t[k] = v, +where t is the table at the given index, +k is the pointer p represented as a light userdata, +and v is the value at the top of the stack. + + +

+This function pops the value from the stack. +The assignment is raw; +that is, it does not invoke metamethods. + + + + + +


lua_Reader

+
typedef const char * (*lua_Reader) (lua_State *L,
+                                    void *data,
+                                    size_t *size);
+ +

+The reader function used by lua_load. +Every time it needs another piece of the chunk, +lua_load calls the reader, +passing along its data parameter. +The reader must return a pointer to a block of memory +with a new piece of the chunk +and set size to the block size. +The block must exist until the reader function is called again. +To signal the end of the chunk, +the reader must return NULL or set size to zero. +The reader function may return pieces of any size greater than zero. + + + + + +


lua_register

+[-0, +0, e] +

void lua_register (lua_State *L, const char *name, lua_CFunction f);
+ +

+Sets the C function f as the new value of global name. +It is defined as a macro: + +

+     #define lua_register(L,n,f) \
+            (lua_pushcfunction(L, f), lua_setglobal(L, n))
+
+ + + + +

lua_remove

+[-1, +0, –] +

void lua_remove (lua_State *L, int index);
+ +

+Removes the element at the given valid index, +shifting down the elements above this index to fill the gap. +This function cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +


lua_replace

+[-1, +0, –] +

void lua_replace (lua_State *L, int index);
+ +

+Moves the top element into the given valid index +without shifting any element +(therefore replacing the value at the given index), +and then pops the top element. + + + + + +


lua_resume

+[-?, +?, –] +

int lua_resume (lua_State *L, lua_State *from, int nargs);
+ +

+Starts and resumes a coroutine in a given thread. + + +

+To start a coroutine, +you push onto the thread stack the main function plus any arguments; +then you call lua_resume, +with nargs being the number of arguments. +This call returns when the coroutine suspends or finishes its execution. +When it returns, the stack contains all values passed to lua_yield, +or all values returned by the body function. +lua_resume returns +LUA_YIELD if the coroutine yields, +LUA_OK if the coroutine finishes its execution +without errors, +or an error code in case of errors (see lua_pcall). + + +

+In case of errors, +the stack is not unwound, +so you can use the debug API over it. +The error message is on the top of the stack. + + +

+To resume a coroutine, +you remove any results from the last lua_yield, +put on its stack only the values to +be passed as results from yield, +and then call lua_resume. + + +

+The parameter from represents the coroutine that is resuming L. +If there is no such coroutine, +this parameter can be NULL. + + + + + +


lua_setallocf

+[-0, +0, –] +

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+ +

+Changes the allocator function of a given state to f +with user data ud. + + + + + +


lua_setfield

+[-1, +0, e] +

void lua_setfield (lua_State *L, int index, const char *k);
+ +

+Does the equivalent to t[k] = v, +where t is the value at the given index +and v is the value at the top of the stack. + + +

+This function pops the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see §2.4). + + + + + +


lua_setglobal

+[-1, +0, e] +

void lua_setglobal (lua_State *L, const char *name);
+ +

+Pops a value from the stack and +sets it as the new value of global name. + + + + + +


lua_setmetatable

+[-1, +0, –] +

void lua_setmetatable (lua_State *L, int index);
+ +

+Pops a table from the stack and +sets it as the new metatable for the value at the given index. + + + + + +


lua_settable

+[-2, +0, e] +

void lua_settable (lua_State *L, int index);
+ +

+Does the equivalent to t[k] = v, +where t is the value at the given index, +v is the value at the top of the stack, +and k is the value just below the top. + + +

+This function pops both the key and the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see §2.4). + + + + + +


lua_settop

+[-?, +?, –] +

void lua_settop (lua_State *L, int index);
+ +

+Accepts any index, or 0, +and sets the stack top to this index. +If the new top is larger than the old one, +then the new elements are filled with nil. +If index is 0, then all stack elements are removed. + + + + + +


lua_setuservalue

+[-1, +0, –] +

void lua_setuservalue (lua_State *L, int index);
+ +

+Pops a table or nil from the stack and sets it as +the new value associated to the userdata at the given index. + + + + + +


lua_State

+
typedef struct lua_State lua_State;
+ +

+An opaque structure that points to a thread and indirectly +(through the thread) to the whole state of a Lua interpreter. +The Lua library is fully reentrant: +it has no global variables. +All information about a state is accessible through this structure. + + +

+A pointer to this structure must be passed as the first argument to +every function in the library, except to lua_newstate, +which creates a Lua state from scratch. + + + + + +


lua_status

+[-0, +0, –] +

int lua_status (lua_State *L);
+ +

+Returns the status of the thread L. + + +

+The status can be 0 (LUA_OK) for a normal thread, +an error code if the thread finished the execution +of a lua_resume with an error, +or LUA_YIELD if the thread is suspended. + + +

+You can only call functions in threads with status LUA_OK. +You can resume threads with status LUA_OK +(to start a new coroutine) or LUA_YIELD +(to resume a coroutine). + + + + + +


lua_toboolean

+[-0, +0, –] +

int lua_toboolean (lua_State *L, int index);
+ +

+Converts the Lua value at the given index to a C boolean +value (0 or 1). +Like all tests in Lua, +lua_toboolean returns true for any Lua value +different from false and nil; +otherwise it returns false. +(If you want to accept only actual boolean values, +use lua_isboolean to test the value's type.) + + + + + +


lua_tocfunction

+[-0, +0, –] +

lua_CFunction lua_tocfunction (lua_State *L, int index);
+ +

+Converts a value at the given index to a C function. +That value must be a C function; +otherwise, returns NULL. + + + + + +


lua_tointeger

+[-0, +0, –] +

lua_Integer lua_tointeger (lua_State *L, int index);
+ +

+Equivalent to lua_tointegerx with isnum equal to NULL. + + + + + +


lua_tointegerx

+[-0, +0, –] +

lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);
+ +

+Converts the Lua value at the given index +to the signed integral type lua_Integer. +The Lua value must be a number or a string convertible to a number +(see §3.4.2); +otherwise, lua_tointegerx returns 0. + + +

+If the number is not an integer, +it is truncated in some non-specified way. + + +

+If isnum is not NULL, +its referent is assigned a boolean value that +indicates whether the operation succeeded. + + + + + +


lua_tolstring

+[-0, +0, e] +

const char *lua_tolstring (lua_State *L, int index, size_t *len);
+ +

+Converts the Lua value at the given index to a C string. +If len is not NULL, +it also sets *len with the string length. +The Lua value must be a string or a number; +otherwise, the function returns NULL. +If the value is a number, +then lua_tolstring also +changes the actual value in the stack to a string. +(This change confuses lua_next +when lua_tolstring is applied to keys during a table traversal.) + + +

+lua_tolstring returns a fully aligned pointer +to a string inside the Lua state. +This string always has a zero ('\0') +after its last character (as in C), +but can contain other zeros in its body. +Because Lua has garbage collection, +there is no guarantee that the pointer returned by lua_tolstring +will be valid after the corresponding value is removed from the stack. + + + + + +


lua_tonumber

+[-0, +0, –] +

lua_Number lua_tonumber (lua_State *L, int index);
+ +

+Equivalent to lua_tonumberx with isnum equal to NULL. + + + + + +


lua_tonumberx

+[-0, +0, –] +

lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);
+ +

+Converts the Lua value at the given index +to the C type lua_Number (see lua_Number). +The Lua value must be a number or a string convertible to a number +(see §3.4.2); +otherwise, lua_tonumberx returns 0. + + +

+If isnum is not NULL, +its referent is assigned a boolean value that +indicates whether the operation succeeded. + + + + + +


lua_topointer

+[-0, +0, –] +

const void *lua_topointer (lua_State *L, int index);
+ +

+Converts the value at the given index to a generic +C pointer (void*). +The value can be a userdata, a table, a thread, or a function; +otherwise, lua_topointer returns NULL. +Different objects will give different pointers. +There is no way to convert the pointer back to its original value. + + +

+Typically this function is used only for debug information. + + + + + +


lua_tostring

+[-0, +0, e] +

const char *lua_tostring (lua_State *L, int index);
+ +

+Equivalent to lua_tolstring with len equal to NULL. + + + + + +


lua_tothread

+[-0, +0, –] +

lua_State *lua_tothread (lua_State *L, int index);
+ +

+Converts the value at the given index to a Lua thread +(represented as lua_State*). +This value must be a thread; +otherwise, the function returns NULL. + + + + + +


lua_tounsigned

+[-0, +0, –] +

lua_Unsigned lua_tounsigned (lua_State *L, int index);
+ +

+Equivalent to lua_tounsignedx with isnum equal to NULL. + + + + + +


lua_tounsignedx

+[-0, +0, –] +

lua_Unsigned lua_tounsignedx (lua_State *L, int index, int *isnum);
+ +

+Converts the Lua value at the given index +to the unsigned integral type lua_Unsigned. +The Lua value must be a number or a string convertible to a number +(see §3.4.2); +otherwise, lua_tounsignedx returns 0. + + +

+If the number is not an integer, +it is truncated in some non-specified way. +If the number is outside the range of representable values, +it is normalized to the remainder of its division by +one more than the maximum representable value. + + +

+If isnum is not NULL, +its referent is assigned a boolean value that +indicates whether the operation succeeded. + + + + + +


lua_touserdata

+[-0, +0, –] +

void *lua_touserdata (lua_State *L, int index);
+ +

+If the value at the given index is a full userdata, +returns its block address. +If the value is a light userdata, +returns its pointer. +Otherwise, returns NULL. + + + + + +


lua_type

+[-0, +0, –] +

int lua_type (lua_State *L, int index);
+ +

+Returns the type of the value in the given valid index, +or LUA_TNONE for a non-valid (but acceptable) index. +The types returned by lua_type are coded by the following constants +defined in lua.h: +LUA_TNIL, +LUA_TNUMBER, +LUA_TBOOLEAN, +LUA_TSTRING, +LUA_TTABLE, +LUA_TFUNCTION, +LUA_TUSERDATA, +LUA_TTHREAD, +and +LUA_TLIGHTUSERDATA. + + + + + +


lua_typename

+[-0, +0, –] +

const char *lua_typename (lua_State *L, int tp);
+ +

+Returns the name of the type encoded by the value tp, +which must be one the values returned by lua_type. + + + + + +


lua_Unsigned

+
typedef unsigned long lua_Unsigned;
+ +

+The type used by the Lua API to represent unsigned integral values. +It must have at least 32 bits. + + +

+By default it is an unsigned int or an unsigned long, +whichever can hold 32-bit values. + + + + + +


lua_upvalueindex

+[-0, +0, –] +

int lua_upvalueindex (int i);
+ +

+Returns the pseudo-index that represents the i-th upvalue of +the running function (see §4.4). + + + + + +


lua_version

+[-0, +0, v] +

const lua_Number *lua_version (lua_State *L);
+ +

+Returns the address of the version number stored in the Lua core. +When called with a valid lua_State, +returns the address of the version used to create that state. +When called with NULL, +returns the address of the version running the call. + + + + + +


lua_Writer

+
typedef int (*lua_Writer) (lua_State *L,
+                           const void* p,
+                           size_t sz,
+                           void* ud);
+ +

+The type of the writer function used by lua_dump. +Every time it produces another piece of chunk, +lua_dump calls the writer, +passing along the buffer to be written (p), +its size (sz), +and the data parameter supplied to lua_dump. + + +

+The writer returns an error code: +0 means no errors; +any other value means an error and stops lua_dump from +calling the writer again. + + + + + +


lua_xmove

+[-?, +?, –] +

void lua_xmove (lua_State *from, lua_State *to, int n);
+ +

+Exchange values between different threads of the same state. + + +

+This function pops n values from the stack from, +and pushes them onto the stack to. + + + + + +


lua_yield

+[-?, +?, –] +

int lua_yield (lua_State *L, int nresults);
+ +

+This function is equivalent to lua_yieldk, +but it has no continuation (see §4.7). +Therefore, when the thread resumes, +it returns to the function that called +the function calling lua_yield. + + + + + +


lua_yieldk

+[-?, +?, –] +

int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k);
+ +

+Yields a coroutine. + + +

+This function should only be called as the +return expression of a C function, as follows: + +

+     return lua_yieldk (L, n, i, k);
+

+When a C function calls lua_yieldk in that way, +the running coroutine suspends its execution, +and the call to lua_resume that started this coroutine returns. +The parameter nresults is the number of values from the stack +that are passed as results to lua_resume. + + +

+When the coroutine is resumed again, +Lua calls the given continuation function k to continue +the execution of the C function that yielded (see §4.7). +This continuation function receives the same stack +from the previous function, +with the results removed and +replaced by the arguments passed to lua_resume. +Moreover, +the continuation function may access the value ctx +by calling lua_getctx. + + + + + + + +

4.9 – The Debug Interface

+ +

+Lua has no built-in debugging facilities. +Instead, it offers a special interface +by means of functions and hooks. +This interface allows the construction of different +kinds of debuggers, profilers, and other tools +that need "inside information" from the interpreter. + + + +


lua_Debug

+
typedef struct lua_Debug {
+  int event;
+  const char *name;           /* (n) */
+  const char *namewhat;       /* (n) */
+  const char *what;           /* (S) */
+  const char *source;         /* (S) */
+  int currentline;            /* (l) */
+  int linedefined;            /* (S) */
+  int lastlinedefined;        /* (S) */
+  unsigned char nups;         /* (u) number of upvalues */
+  unsigned char nparams;      /* (u) number of parameters */
+  char isvararg;              /* (u) */
+  char istailcall;            /* (t) */
+  char short_src[LUA_IDSIZE]; /* (S) */
+  /* private part */
+  other fields
+} lua_Debug;
+ +

+A structure used to carry different pieces of +information about a function or an activation record. +lua_getstack fills only the private part +of this structure, for later use. +To fill the other fields of lua_Debug with useful information, +call lua_getinfo. + + +

+The fields of lua_Debug have the following meaning: + +

    + +
  • source: +the source of the chunk that created the function. +If source starts with a '@', +it means that the function was defined in a file where +the file name follows the '@'. +If source starts with a '=', +the remainder of its contents describe the source in a user-dependent manner. +Otherwise, +the function was defined in a string where +source is that string. +
  • + +
  • short_src: +a "printable" version of source, to be used in error messages. +
  • + +
  • linedefined: +the line number where the definition of the function starts. +
  • + +
  • lastlinedefined: +the line number where the definition of the function ends. +
  • + +
  • what: +the string "Lua" if the function is a Lua function, +"C" if it is a C function, +"main" if it is the main part of a chunk. +
  • + +
  • currentline: +the current line where the given function is executing. +When no line information is available, +currentline is set to -1. +
  • + +
  • name: +a reasonable name for the given function. +Because functions in Lua are first-class values, +they do not have a fixed name: +some functions can be the value of multiple global variables, +while others can be stored only in a table field. +The lua_getinfo function checks how the function was +called to find a suitable name. +If it cannot find a name, +then name is set to NULL. +
  • + +
  • namewhat: +explains the name field. +The value of namewhat can be +"global", "local", "method", +"field", "upvalue", or "" (the empty string), +according to how the function was called. +(Lua uses the empty string when no other option seems to apply.) +
  • + +
  • istailcall: +true if this function invocation was called by a tail call. +In this case, the caller of this level is not in the stack. +
  • + +
  • nups: +the number of upvalues of the function. +
  • + +
  • nparams: +the number of fixed parameters of the function +(always 0 for C functions). +
  • + +
  • isvararg: +true if the function is a vararg function +(always true for C functions). +
  • + +
+ + + + +

lua_gethook

+[-0, +0, –] +

lua_Hook lua_gethook (lua_State *L);
+ +

+Returns the current hook function. + + + + + +


lua_gethookcount

+[-0, +0, –] +

int lua_gethookcount (lua_State *L);
+ +

+Returns the current hook count. + + + + + +


lua_gethookmask

+[-0, +0, –] +

int lua_gethookmask (lua_State *L);
+ +

+Returns the current hook mask. + + + + + +


lua_getinfo

+[-(0|1), +(0|1|2), e] +

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+ +

+Gets information about a specific function or function invocation. + + +

+To get information about a function invocation, +the parameter ar must be a valid activation record that was +filled by a previous call to lua_getstack or +given as argument to a hook (see lua_Hook). + + +

+To get information about a function you push it onto the stack +and start the what string with the character '>'. +(In that case, +lua_getinfo pops the function from the top of the stack.) +For instance, to know in which line a function f was defined, +you can write the following code: + +

+     lua_Debug ar;
+     lua_getglobal(L, "f");  /* get global 'f' */
+     lua_getinfo(L, ">S", &ar);
+     printf("%d\n", ar.linedefined);
+
+ +

+Each character in the string what +selects some fields of the structure ar to be filled or +a value to be pushed on the stack: + +

    + +
  • 'n': fills in the field name and namewhat; +
  • + +
  • 'S': +fills in the fields source, short_src, +linedefined, lastlinedefined, and what; +
  • + +
  • 'l': fills in the field currentline; +
  • + +
  • 't': fills in the field istailcall; +
  • + +
  • 'u': fills in the fields +nups, nparams, and isvararg; +
  • + +
  • 'f': +pushes onto the stack the function that is +running at the given level; +
  • + +
  • 'L': +pushes onto the stack a table whose indices are the +numbers of the lines that are valid on the function. +(A valid line is a line with some associated code, +that is, a line where you can put a break point. +Non-valid lines include empty lines and comments.) +
  • + +
+ +

+This function returns 0 on error +(for instance, an invalid option in what). + + + + + +


lua_getlocal

+[-0, +(0|1), –] +

const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
+ +

+Gets information about a local variable of +a given activation record or a given function. + + +

+In the first case, +the parameter ar must be a valid activation record that was +filled by a previous call to lua_getstack or +given as argument to a hook (see lua_Hook). +The index n selects which local variable to inspect; +see debug.getlocal for details about variable indices +and names. + + +

+lua_getlocal pushes the variable's value onto the stack +and returns its name. + + +

+In the second case, ar should be NULL and the function +to be inspected must be at the top of the stack. +In this case, only parameters of Lua functions are visible +(as there is no information about what variables are active) +and no values are pushed onto the stack. + + +

+Returns NULL (and pushes nothing) +when the index is greater than +the number of active local variables. + + + + + +


lua_getstack

+[-0, +0, –] +

int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+ +

+Gets information about the interpreter runtime stack. + + +

+This function fills parts of a lua_Debug structure with +an identification of the activation record +of the function executing at a given level. +Level 0 is the current running function, +whereas level n+1 is the function that has called level n +(except for tail calls, which do not count on the stack). +When there are no errors, lua_getstack returns 1; +when called with a level greater than the stack depth, +it returns 0. + + + + + +


lua_getupvalue

+[-0, +(0|1), –] +

const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+ +

+Gets information about a closure's upvalue. +(For Lua functions, +upvalues are the external local variables that the function uses, +and that are consequently included in its closure.) +lua_getupvalue gets the index n of an upvalue, +pushes the upvalue's value onto the stack, +and returns its name. +funcindex points to the closure in the stack. +(Upvalues have no particular order, +as they are active through the whole function. +So, they are numbered in an arbitrary order.) + + +

+Returns NULL (and pushes nothing) +when the index is greater than the number of upvalues. +For C functions, this function uses the empty string "" +as a name for all upvalues. + + + + + +


lua_Hook

+
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+ +

+Type for debugging hook functions. + + +

+Whenever a hook is called, its ar argument has its field +event set to the specific event that triggered the hook. +Lua identifies these events with the following constants: +LUA_HOOKCALL, LUA_HOOKRET, +LUA_HOOKTAILCALL, LUA_HOOKLINE, +and LUA_HOOKCOUNT. +Moreover, for line events, the field currentline is also set. +To get the value of any other field in ar, +the hook must call lua_getinfo. + + +

+For call events, event can be LUA_HOOKCALL, +the normal value, or LUA_HOOKTAILCALL, for a tail call; +in this case, there will be no corresponding return event. + + +

+While Lua is running a hook, it disables other calls to hooks. +Therefore, if a hook calls back Lua to execute a function or a chunk, +this execution occurs without any calls to hooks. + + +

+Hook functions cannot have continuations, +that is, they cannot call lua_yieldk, +lua_pcallk, or lua_callk with a non-null k. + + +

+Hook functions can yield under the following conditions: +Only count and line events can yield +and they cannot yield any value; +to yield a hook function must finish its execution +calling lua_yield with nresults equal to zero. + + + + + +


lua_sethook

+[-0, +0, –] +

int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
+ +

+Sets the debugging hook function. + + +

+Argument f is the hook function. +mask specifies on which events the hook will be called: +it is formed by a bitwise or of the constants +LUA_MASKCALL, +LUA_MASKRET, +LUA_MASKLINE, +and LUA_MASKCOUNT. +The count argument is only meaningful when the mask +includes LUA_MASKCOUNT. +For each event, the hook is called as explained below: + +

    + +
  • The call hook: is called when the interpreter calls a function. +The hook is called just after Lua enters the new function, +before the function gets its arguments. +
  • + +
  • The return hook: is called when the interpreter returns from a function. +The hook is called just before Lua leaves the function. +There is no standard way to access the values +to be returned by the function. +
  • + +
  • The line hook: is called when the interpreter is about to +start the execution of a new line of code, +or when it jumps back in the code (even to the same line). +(This event only happens while Lua is executing a Lua function.) +
  • + +
  • The count hook: is called after the interpreter executes every +count instructions. +(This event only happens while Lua is executing a Lua function.) +
  • + +
+ +

+A hook is disabled by setting mask to zero. + + + + + +


lua_setlocal

+[-(0|1), +0, –] +

const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
+ +

+Sets the value of a local variable of a given activation record. +Parameters ar and n are as in lua_getlocal +(see lua_getlocal). +lua_setlocal assigns the value at the top of the stack +to the variable and returns its name. +It also pops the value from the stack. + + +

+Returns NULL (and pops nothing) +when the index is greater than +the number of active local variables. + + + + + +


lua_setupvalue

+[-(0|1), +0, –] +

const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+ +

+Sets the value of a closure's upvalue. +It assigns the value at the top of the stack +to the upvalue and returns its name. +It also pops the value from the stack. +Parameters funcindex and n are as in the lua_getupvalue +(see lua_getupvalue). + + +

+Returns NULL (and pops nothing) +when the index is greater than the number of upvalues. + + + + + +


lua_upvalueid

+[-0, +0, –] +

void *lua_upvalueid (lua_State *L, int funcindex, int n);
+ +

+Returns an unique identifier for the upvalue numbered n +from the closure at index funcindex. +Parameters funcindex and n are as in the lua_getupvalue +(see lua_getupvalue) +(but n cannot be greater than the number of upvalues). + + +

+These unique identifiers allow a program to check whether different +closures share upvalues. +Lua closures that share an upvalue +(that is, that access a same external local variable) +will return identical ids for those upvalue indices. + + + + + +


lua_upvaluejoin

+[-0, +0, –] +

void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
+                                    int funcindex2, int n2);
+ +

+Make the n1-th upvalue of the Lua closure at index funcindex1 +refer to the n2-th upvalue of the Lua closure at index funcindex2. + + + + + + + +

5 – The Auxiliary Library

+ +

+ +The auxiliary library provides several convenient functions +to interface C with Lua. +While the basic API provides the primitive functions for all +interactions between C and Lua, +the auxiliary library provides higher-level functions for some +common tasks. + + +

+All functions and types from the auxiliary library +are defined in header file lauxlib.h and +have a prefix luaL_. + + +

+All functions in the auxiliary library are built on +top of the basic API, +and so they provide nothing that cannot be done with that API. +Nevertheless, the use of the auxiliary library ensures +more consistency to your code. + + +

+Several functions in the auxiliary library use internally some +extra stack slots. +When a function in the auxiliary library uses less than five slots, +it does not check the stack size; +it simply assumes that there are enough slots. + + +

+Several functions in the auxiliary library are used to +check C function arguments. +Because the error message is formatted for arguments +(e.g., "bad argument #1"), +you should not use these functions for other stack values. + + +

+Functions called luaL_check* +always throw an error if the check is not satisfied. + + + +

5.1 – Functions and Types

+ +

+Here we list all functions and types from the auxiliary library +in alphabetical order. + + + +


luaL_addchar

+[-?, +?, e] +

void luaL_addchar (luaL_Buffer *B, char c);
+ +

+Adds the byte c to the buffer B +(see luaL_Buffer). + + + + + +


luaL_addlstring

+[-?, +?, e] +

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
+ +

+Adds the string pointed to by s with length l to +the buffer B +(see luaL_Buffer). +The string can contain embedded zeros. + + + + + +


luaL_addsize

+[-?, +?, e] +

void luaL_addsize (luaL_Buffer *B, size_t n);
+ +

+Adds to the buffer B (see luaL_Buffer) +a string of length n previously copied to the +buffer area (see luaL_prepbuffer). + + + + + +


luaL_addstring

+[-?, +?, e] +

void luaL_addstring (luaL_Buffer *B, const char *s);
+ +

+Adds the zero-terminated string pointed to by s +to the buffer B +(see luaL_Buffer). +The string cannot contain embedded zeros. + + + + + +


luaL_addvalue

+[-1, +?, e] +

void luaL_addvalue (luaL_Buffer *B);
+ +

+Adds the value at the top of the stack +to the buffer B +(see luaL_Buffer). +Pops the value. + + +

+This is the only function on string buffers that can (and must) +be called with an extra element on the stack, +which is the value to be added to the buffer. + + + + + +


luaL_argcheck

+[-0, +0, v] +

void luaL_argcheck (lua_State *L,
+                    int cond,
+                    int arg,
+                    const char *extramsg);
+ +

+Checks whether cond is true. +If not, raises an error with a standard message. + + + + + +


luaL_argerror

+[-0, +0, v] +

int luaL_argerror (lua_State *L, int arg, const char *extramsg);
+ +

+Raises an error with a standard message +that includes extramsg as a comment. + + +

+This function never returns, +but it is an idiom to use it in C functions +as return luaL_argerror(args). + + + + + +


luaL_Buffer

+
typedef struct luaL_Buffer luaL_Buffer;
+ +

+Type for a string buffer. + + +

+A string buffer allows C code to build Lua strings piecemeal. +Its pattern of use is as follows: + +

    + +
  • First declare a variable b of type luaL_Buffer.
  • + +
  • Then initialize it with a call luaL_buffinit(L, &b).
  • + +
  • +Then add string pieces to the buffer calling any of +the luaL_add* functions. +
  • + +
  • +Finish by calling luaL_pushresult(&b). +This call leaves the final string on the top of the stack. +
  • + +
+ +

+If you know beforehand the total size of the resulting string, +you can use the buffer like this: + +

    + +
  • First declare a variable b of type luaL_Buffer.
  • + +
  • Then initialize it and preallocate a space of +size sz with a call luaL_buffinitsize(L, &b, sz).
  • + +
  • Then copy the string into that space.
  • + +
  • +Finish by calling luaL_pushresultsize(&b, sz), +where sz is the total size of the resulting string +copied into that space. +
  • + +
+ +

+During its normal operation, +a string buffer uses a variable number of stack slots. +So, while using a buffer, you cannot assume that you know where +the top of the stack is. +You can use the stack between successive calls to buffer operations +as long as that use is balanced; +that is, +when you call a buffer operation, +the stack is at the same level +it was immediately after the previous buffer operation. +(The only exception to this rule is luaL_addvalue.) +After calling luaL_pushresult the stack is back to its +level when the buffer was initialized, +plus the final string on its top. + + + + + +


luaL_buffinit

+[-0, +0, –] +

void luaL_buffinit (lua_State *L, luaL_Buffer *B);
+ +

+Initializes a buffer B. +This function does not allocate any space; +the buffer must be declared as a variable +(see luaL_Buffer). + + + + + +


luaL_buffinitsize

+[-?, +?, e] +

char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);
+ +

+Equivalent to the sequence +luaL_buffinit, luaL_prepbuffsize. + + + + + +


luaL_callmeta

+[-0, +(0|1), e] +

int luaL_callmeta (lua_State *L, int obj, const char *e);
+ +

+Calls a metamethod. + + +

+If the object at index obj has a metatable and this +metatable has a field e, +this function calls this field passing the object as its only argument. +In this case this function returns true and pushes onto the +stack the value returned by the call. +If there is no metatable or no metamethod, +this function returns false (without pushing any value on the stack). + + + + + +


luaL_checkany

+[-0, +0, v] +

void luaL_checkany (lua_State *L, int arg);
+ +

+Checks whether the function has an argument +of any type (including nil) at position arg. + + + + + +


luaL_checkint

+[-0, +0, v] +

int luaL_checkint (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a number +and returns this number cast to an int. + + + + + +


luaL_checkinteger

+[-0, +0, v] +

lua_Integer luaL_checkinteger (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a number +and returns this number cast to a lua_Integer. + + + + + +


luaL_checklong

+[-0, +0, v] +

long luaL_checklong (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a number +and returns this number cast to a long. + + + + + +


luaL_checklstring

+[-0, +0, v] +

const char *luaL_checklstring (lua_State *L, int arg, size_t *l);
+ +

+Checks whether the function argument arg is a string +and returns this string; +if l is not NULL fills *l +with the string's length. + + +

+This function uses lua_tolstring to get its result, +so all conversions and caveats of that function apply here. + + + + + +


luaL_checknumber

+[-0, +0, v] +

lua_Number luaL_checknumber (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a number +and returns this number. + + + + + +


luaL_checkoption

+[-0, +0, v] +

int luaL_checkoption (lua_State *L,
+                      int arg,
+                      const char *def,
+                      const char *const lst[]);
+ +

+Checks whether the function argument arg is a string and +searches for this string in the array lst +(which must be NULL-terminated). +Returns the index in the array where the string was found. +Raises an error if the argument is not a string or +if the string cannot be found. + + +

+If def is not NULL, +the function uses def as a default value when +there is no argument arg or when this argument is nil. + + +

+This is a useful function for mapping strings to C enums. +(The usual convention in Lua libraries is +to use strings instead of numbers to select options.) + + + + + +


luaL_checkstack

+[-0, +0, v] +

void luaL_checkstack (lua_State *L, int sz, const char *msg);
+ +

+Grows the stack size to top + sz elements, +raising an error if the stack cannot grow to that size. +msg is an additional text to go into the error message +(or NULL for no additional text). + + + + + +


luaL_checkstring

+[-0, +0, v] +

const char *luaL_checkstring (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a string +and returns this string. + + +

+This function uses lua_tolstring to get its result, +so all conversions and caveats of that function apply here. + + + + + +


luaL_checktype

+[-0, +0, v] +

void luaL_checktype (lua_State *L, int arg, int t);
+ +

+Checks whether the function argument arg has type t. +See lua_type for the encoding of types for t. + + + + + +


luaL_checkudata

+[-0, +0, v] +

void *luaL_checkudata (lua_State *L, int arg, const char *tname);
+ +

+Checks whether the function argument arg is a userdata +of the type tname (see luaL_newmetatable) and +returns the userdata address (see lua_touserdata). + + + + + +


luaL_checkunsigned

+[-0, +0, v] +

lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);
+ +

+Checks whether the function argument arg is a number +and returns this number cast to a lua_Unsigned. + + + + + +


luaL_checkversion

+[-0, +0, –] +

void luaL_checkversion (lua_State *L);
+ +

+Checks whether the core running the call, +the core that created the Lua state, +and the code making the call are all using the same version of Lua. +Also checks whether the core running the call +and the core that created the Lua state +are using the same address space. + + + + + +


luaL_dofile

+[-0, +?, e] +

int luaL_dofile (lua_State *L, const char *filename);
+ +

+Loads and runs the given file. +It is defined as the following macro: + +

+     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
+

+It returns false if there are no errors +or true in case of errors. + + + + + +


luaL_dostring

+[-0, +?, –] +

int luaL_dostring (lua_State *L, const char *str);
+ +

+Loads and runs the given string. +It is defined as the following macro: + +

+     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))
+

+It returns false if there are no errors +or true in case of errors. + + + + + +


luaL_error

+[-0, +0, v] +

int luaL_error (lua_State *L, const char *fmt, ...);
+ +

+Raises an error. +The error message format is given by fmt +plus any extra arguments, +following the same rules of lua_pushfstring. +It also adds at the beginning of the message the file name and +the line number where the error occurred, +if this information is available. + + +

+This function never returns, +but it is an idiom to use it in C functions +as return luaL_error(args). + + + + + +


luaL_execresult

+[-0, +3, e] +

int luaL_execresult (lua_State *L, int stat);
+ +

+This function produces the return values for +process-related functions in the standard library +(os.execute and io.close). + + + + + +


luaL_fileresult

+[-0, +(1|3), e] +

int luaL_fileresult (lua_State *L, int stat, const char *fname);
+ +

+This function produces the return values for +file-related functions in the standard library +(io.open, os.rename, file:seek, etc.). + + + + + +


luaL_getmetafield

+[-0, +(0|1), e] +

int luaL_getmetafield (lua_State *L, int obj, const char *e);
+ +

+Pushes onto the stack the field e from the metatable +of the object at index obj. +If the object does not have a metatable, +or if the metatable does not have this field, +returns false and pushes nothing. + + + + + +


luaL_getmetatable

+[-0, +1, –] +

void luaL_getmetatable (lua_State *L, const char *tname);
+ +

+Pushes onto the stack the metatable associated with name tname +in the registry (see luaL_newmetatable). + + + + + +


luaL_getsubtable

+[-0, +1, e] +

int luaL_getsubtable (lua_State *L, int idx, const char *fname);
+ +

+Ensures that the value t[fname], +where t is the value at index idx, +is a table, +and pushes that table onto the stack. +Returns true if it finds a previous table there +and false if it creates a new table. + + + + + +


luaL_gsub

+[-0, +1, e] +

const char *luaL_gsub (lua_State *L,
+                       const char *s,
+                       const char *p,
+                       const char *r);
+ +

+Creates a copy of string s by replacing +any occurrence of the string p +with the string r. +Pushes the resulting string on the stack and returns it. + + + + + +


luaL_len

+[-0, +0, e] +

int luaL_len (lua_State *L, int index);
+ +

+Returns the "length" of the value at the given index +as a number; +it is equivalent to the '#' operator in Lua (see §3.4.6). +Raises an error if the result of the operation is not a number. +(This case only can happen through metamethods.) + + + + + +


luaL_loadbuffer

+[-0, +1, –] +

int luaL_loadbuffer (lua_State *L,
+                     const char *buff,
+                     size_t sz,
+                     const char *name);
+ +

+Equivalent to luaL_loadbufferx with mode equal to NULL. + + + + + +


luaL_loadbufferx

+[-0, +1, –] +

int luaL_loadbufferx (lua_State *L,
+                      const char *buff,
+                      size_t sz,
+                      const char *name,
+                      const char *mode);
+ +

+Loads a buffer as a Lua chunk. +This function uses lua_load to load the chunk in the +buffer pointed to by buff with size sz. + + +

+This function returns the same results as lua_load. +name is the chunk name, +used for debug information and error messages. +The string mode works as in function lua_load. + + + + + +


luaL_loadfile

+[-0, +1, e] +

int luaL_loadfile (lua_State *L, const char *filename);
+ +

+Equivalent to luaL_loadfilex with mode equal to NULL. + + + + + +


luaL_loadfilex

+[-0, +1, e] +

int luaL_loadfilex (lua_State *L, const char *filename,
+                                            const char *mode);
+ +

+Loads a file as a Lua chunk. +This function uses lua_load to load the chunk in the file +named filename. +If filename is NULL, +then it loads from the standard input. +The first line in the file is ignored if it starts with a #. + + +

+The string mode works as in function lua_load. + + +

+This function returns the same results as lua_load, +but it has an extra error code LUA_ERRFILE +if it cannot open/read the file or the file has a wrong mode. + + +

+As lua_load, this function only loads the chunk; +it does not run it. + + + + + +


luaL_loadstring

+[-0, +1, –] +

int luaL_loadstring (lua_State *L, const char *s);
+ +

+Loads a string as a Lua chunk. +This function uses lua_load to load the chunk in +the zero-terminated string s. + + +

+This function returns the same results as lua_load. + + +

+Also as lua_load, this function only loads the chunk; +it does not run it. + + + + + +


luaL_newlib

+[-0, +1, e] +

void luaL_newlib (lua_State *L, const luaL_Reg *l);
+ +

+Creates a new table and registers there +the functions in list l. +It is implemented as the following macro: + +

+     (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
+
+ + + + +

luaL_newlibtable

+[-0, +1, e] +

void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);
+ +

+Creates a new table with a size optimized +to store all entries in the array l +(but does not actually store them). +It is intended to be used in conjunction with luaL_setfuncs +(see luaL_newlib). + + +

+It is implemented as a macro. +The array l must be the actual array, +not a pointer to it. + + + + + +


luaL_newmetatable

+[-0, +1, e] +

int luaL_newmetatable (lua_State *L, const char *tname);
+ +

+If the registry already has the key tname, +returns 0. +Otherwise, +creates a new table to be used as a metatable for userdata, +adds it to the registry with key tname, +and returns 1. + + +

+In both cases pushes onto the stack the final value associated +with tname in the registry. + + + + + +


luaL_newstate

+[-0, +0, –] +

lua_State *luaL_newstate (void);
+ +

+Creates a new Lua state. +It calls lua_newstate with an +allocator based on the standard C realloc function +and then sets a panic function (see §4.6) that prints +an error message to the standard error output in case of fatal +errors. + + +

+Returns the new state, +or NULL if there is a memory allocation error. + + + + + +


luaL_openlibs

+[-0, +0, e] +

void luaL_openlibs (lua_State *L);
+ +

+Opens all standard Lua libraries into the given state. + + + + + +


luaL_optint

+[-0, +0, v] +

int luaL_optint (lua_State *L, int arg, int d);
+ +

+If the function argument arg is a number, +returns this number cast to an int. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


luaL_optinteger

+[-0, +0, v] +

lua_Integer luaL_optinteger (lua_State *L,
+                             int arg,
+                             lua_Integer d);
+ +

+If the function argument arg is a number, +returns this number cast to a lua_Integer. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


luaL_optlong

+[-0, +0, v] +

long luaL_optlong (lua_State *L, int arg, long d);
+ +

+If the function argument arg is a number, +returns this number cast to a long. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


luaL_optlstring

+[-0, +0, v] +

const char *luaL_optlstring (lua_State *L,
+                             int arg,
+                             const char *d,
+                             size_t *l);
+ +

+If the function argument arg is a string, +returns this string. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + +

+If l is not NULL, +fills the position *l with the result's length. + + + + + +


luaL_optnumber

+[-0, +0, v] +

lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);
+ +

+If the function argument arg is a number, +returns this number. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


luaL_optstring

+[-0, +0, v] +

const char *luaL_optstring (lua_State *L,
+                            int arg,
+                            const char *d);
+ +

+If the function argument arg is a string, +returns this string. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


luaL_optunsigned

+[-0, +0, v] +

lua_Unsigned luaL_optunsigned (lua_State *L,
+                               int arg,
+                               lua_Unsigned u);
+ +

+If the function argument arg is a number, +returns this number cast to a lua_Unsigned. +If this argument is absent or is nil, +returns u. +Otherwise, raises an error. + + + + + +


luaL_prepbuffer

+[-?, +?, e] +

char *luaL_prepbuffer (luaL_Buffer *B);
+ +

+Equivalent to luaL_prepbuffsize +with the predefined size LUAL_BUFFERSIZE. + + + + + +


luaL_prepbuffsize

+[-?, +?, e] +

char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);
+ +

+Returns an address to a space of size sz +where you can copy a string to be added to buffer B +(see luaL_Buffer). +After copying the string into this space you must call +luaL_addsize with the size of the string to actually add +it to the buffer. + + + + + +


luaL_pushresult

+[-?, +1, e] +

void luaL_pushresult (luaL_Buffer *B);
+ +

+Finishes the use of buffer B leaving the final string on +the top of the stack. + + + + + +


luaL_pushresultsize

+[-?, +1, e] +

void luaL_pushresultsize (luaL_Buffer *B, size_t sz);
+ +

+Equivalent to the sequence luaL_addsize, luaL_pushresult. + + + + + +


luaL_ref

+[-1, +0, e] +

int luaL_ref (lua_State *L, int t);
+ +

+Creates and returns a reference, +in the table at index t, +for the object at the top of the stack (and pops the object). + + +

+A reference is a unique integer key. +As long as you do not manually add integer keys into table t, +luaL_ref ensures the uniqueness of the key it returns. +You can retrieve an object referred by reference r +by calling lua_rawgeti(L, t, r). +Function luaL_unref frees a reference and its associated object. + + +

+If the object at the top of the stack is nil, +luaL_ref returns the constant LUA_REFNIL. +The constant LUA_NOREF is guaranteed to be different +from any reference returned by luaL_ref. + + + + + +


luaL_Reg

+
typedef struct luaL_Reg {
+  const char *name;
+  lua_CFunction func;
+} luaL_Reg;
+ +

+Type for arrays of functions to be registered by +luaL_setfuncs. +name is the function name and func is a pointer to +the function. +Any array of luaL_Reg must end with an sentinel entry +in which both name and func are NULL. + + + + + +


luaL_requiref

+[-0, +1, e] +

void luaL_requiref (lua_State *L, const char *modname,
+                    lua_CFunction openf, int glb);
+ +

+Calls function openf with string modname as an argument +and sets the call result in package.loaded[modname], +as if that function has been called through require. + + +

+If glb is true, +also stores the result into global modname. + + +

+Leaves a copy of that result on the stack. + + + + + +


luaL_setfuncs

+[-nup, +0, e] +

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
+ +

+Registers all functions in the array l +(see luaL_Reg) into the table on the top of the stack +(below optional upvalues, see next). + + +

+When nup is not zero, +all functions are created sharing nup upvalues, +which must be previously pushed on the stack +on top of the library table. +These values are popped from the stack after the registration. + + + + + +


luaL_setmetatable

+[-0, +0, –] +

void luaL_setmetatable (lua_State *L, const char *tname);
+ +

+Sets the metatable of the object at the top of the stack +as the metatable associated with name tname +in the registry (see luaL_newmetatable). + + + + + +


luaL_testudata

+[-0, +0, e] +

void *luaL_testudata (lua_State *L, int arg, const char *tname);
+ +

+This function works like luaL_checkudata, +except that, when the test fails, +it returns NULL instead of throwing an error. + + + + + +


luaL_tolstring

+[-0, +1, e] +

const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
+ +

+Converts any Lua value at the given index to a C string +in a reasonable format. +The resulting string is pushed onto the stack and also +returned by the function. +If len is not NULL, +the function also sets *len with the string length. + + +

+If the value has a metatable with a "__tostring" field, +then luaL_tolstring calls the corresponding metamethod +with the value as argument, +and uses the result of the call as its result. + + + + + +


luaL_traceback

+[-0, +1, e] +

void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
+                     int level);
+ +

+Creates and pushes a traceback of the stack L1. +If msg is not NULL it is appended +at the beginning of the traceback. +The level parameter tells at which level +to start the traceback. + + + + + +


luaL_typename

+[-0, +0, –] +

const char *luaL_typename (lua_State *L, int index);
+ +

+Returns the name of the type of the value at the given index. + + + + + +


luaL_unref

+[-0, +0, –] +

void luaL_unref (lua_State *L, int t, int ref);
+ +

+Releases reference ref from the table at index t +(see luaL_ref). +The entry is removed from the table, +so that the referred object can be collected. +The reference ref is also freed to be used again. + + +

+If ref is LUA_NOREF or LUA_REFNIL, +luaL_unref does nothing. + + + + + +


luaL_where

+[-0, +1, e] +

void luaL_where (lua_State *L, int lvl);
+ +

+Pushes onto the stack a string identifying the current position +of the control at level lvl in the call stack. +Typically this string has the following format: + +

+     chunkname:currentline:
+

+Level 0 is the running function, +level 1 is the function that called the running function, +etc. + + +

+This function is used to build a prefix for error messages. + + + + + + + +

6 – Standard Libraries

+ +

+The standard Lua libraries provide useful functions +that are implemented directly through the C API. +Some of these functions provide essential services to the language +(e.g., type and getmetatable); +others provide access to "outside" services (e.g., I/O); +and others could be implemented in Lua itself, +but are quite useful or have critical performance requirements that +deserve an implementation in C (e.g., table.sort). + + +

+All libraries are implemented through the official C API +and are provided as separate C modules. +Currently, Lua has the following standard libraries: + +

    + +
  • basic library (§6.1);
  • + +
  • coroutine library (§6.2);
  • + +
  • package library (§6.3);
  • + +
  • string manipulation (§6.4);
  • + +
  • table manipulation (§6.5);
  • + +
  • mathematical functions (§6.6) (sin, log, etc.);
  • + +
  • bitwise operations (§6.7);
  • + +
  • input and output (§6.8);
  • + +
  • operating system facilities (§6.9);
  • + +
  • debug facilities (§6.10).
  • + +

+Except for the basic and the package libraries, +each library provides all its functions as fields of a global table +or as methods of its objects. + + +

+To have access to these libraries, +the C host program should call the luaL_openlibs function, +which opens all standard libraries. +Alternatively, +the host program can open them individually by using +luaL_requiref to call +luaopen_base (for the basic library), +luaopen_package (for the package library), +luaopen_coroutine (for the coroutine library), +luaopen_string (for the string library), +luaopen_table (for the table library), +luaopen_math (for the mathematical library), +luaopen_bit32 (for the bit library), +luaopen_io (for the I/O library), +luaopen_os (for the Operating System library), +and luaopen_debug (for the debug library). +These functions are declared in lualib.h. + + + +

6.1 – Basic Functions

+ +

+The basic library provides core functions to Lua. +If you do not include this library in your application, +you should check carefully whether you need to provide +implementations for some of its facilities. + + +

+


assert (v [, message])

+Issues an error when +the value of its argument v is false (i.e., nil or false); +otherwise, returns all its arguments. +message is an error message; +when absent, it defaults to "assertion failed!" + + + + +

+


collectgarbage ([opt [, arg]])

+ + +

+This function is a generic interface to the garbage collector. +It performs different functions according to its first argument, opt: + +

    + +
  • "collect": +performs a full garbage-collection cycle. +This is the default option. +
  • + +
  • "stop": +stops automatic execution of the garbage collector. +The collector will run only when explicitly invoked, +until a call to restart it. +
  • + +
  • "restart": +restarts automatic execution of the garbage collector. +
  • + +
  • "count": +returns the total memory in use by Lua (in Kbytes) and +a second value with the total memory in bytes modulo 1024. +The first value has a fractional part, +so the following equality is always true: + +
    +     k, b = collectgarbage("count")
    +     assert(k*1024 == math.floor(k)*1024 + b)
    +

    +(The second result is useful when Lua is compiled +with a non floating-point type for numbers.) +

  • + +
  • "step": +performs a garbage-collection step. +The step "size" is controlled by arg +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of arg. +Returns true if the step finished a collection cycle. +
  • + +
  • "setpause": +sets arg as the new value for the pause of +the collector (see §2.5). +Returns the previous value for pause. +
  • + +
  • "setstepmul": +sets arg as the new value for the step multiplier of +the collector (see §2.5). +Returns the previous value for step. +
  • + +
  • "isrunning": +returns a boolean that tells whether the collector is running +(i.e., not stopped). +
  • + +
  • "generational": +changes the collector to generational mode. +This is an experimental feature (see §2.5). +
  • + +
  • "incremental": +changes the collector to incremental mode. +This is the default mode. +
  • + +
+ + + +

+


dofile ([filename])

+Opens the named file and executes its contents as a Lua chunk. +When called without arguments, +dofile executes the contents of the standard input (stdin). +Returns all values returned by the chunk. +In case of errors, dofile propagates the error +to its caller (that is, dofile does not run in protected mode). + + + + +

+


error (message [, level])

+Terminates the last protected function called +and returns message as the error message. +Function error never returns. + + +

+Usually, error adds some information about the error position +at the beginning of the message, if the message is a string. +The level argument specifies how to get the error position. +With level 1 (the default), the error position is where the +error function was called. +Level 2 points the error to where the function +that called error was called; and so on. +Passing a level 0 avoids the addition of error position information +to the message. + + + + +

+


_G

+A global variable (not a function) that +holds the global environment (see §2.2). +Lua itself does not use this variable; +changing its value does not affect any environment, +nor vice-versa. + + + + +

+


getmetatable (object)

+ + +

+If object does not have a metatable, returns nil. +Otherwise, +if the object's metatable has a "__metatable" field, +returns the associated value. +Otherwise, returns the metatable of the given object. + + + + +

+


ipairs (t)

+ + +

+If t has a metamethod __ipairs, +calls it with t as argument and returns the first three +results from the call. + + +

+Otherwise, +returns three values: an iterator function, the table t, and 0, +so that the construction + +

+     for i,v in ipairs(t) do body end
+

+will iterate over the pairs (1,t[1]), (2,t[2]), ..., +up to the first integer key absent from the table. + + + + +

+


load (ld [, source [, mode [, env]]])

+ + +

+Loads a chunk. + + +

+If ld is a string, the chunk is this string. +If ld is a function, +load calls it repeatedly to get the chunk pieces. +Each call to ld must return a string that concatenates +with previous results. +A return of an empty string, nil, or no value signals the end of the chunk. + + +

+If there are no syntactic errors, +returns the compiled chunk as a function; +otherwise, returns nil plus the error message. + + +

+If the resulting function has upvalues, +the first upvalue is set to the value of env, +if that parameter is given, +or to the value of the global environment. +(When you load a main chunk, +the resulting function will always have exactly one upvalue, +the _ENV variable (see §2.2). +When you load a binary chunk created from a function (see string.dump), +the resulting function can have arbitrary upvalues.) + + +

+source is used as the source of the chunk for error messages +and debug information (see §4.9). +When absent, +it defaults to ld, if ld is a string, +or to "=(load)" otherwise. + + +

+The string mode controls whether the chunk can be text or binary +(that is, a precompiled chunk). +It may be the string "b" (only binary chunks), +"t" (only text chunks), +or "bt" (both binary and text). +The default is "bt". + + + + +

+


loadfile ([filename [, mode [, env]]])

+ + +

+Similar to load, +but gets the chunk from file filename +or from the standard input, +if no file name is given. + + + + +

+


next (table [, index])

+ + +

+Allows a program to traverse all fields of a table. +Its first argument is a table and its second argument +is an index in this table. +next returns the next index of the table +and its associated value. +When called with nil as its second argument, +next returns an initial index +and its associated value. +When called with the last index, +or with nil in an empty table, +next returns nil. +If the second argument is absent, then it is interpreted as nil. +In particular, +you can use next(t) to check whether a table is empty. + + +

+The order in which the indices are enumerated is not specified, +even for numeric indices. +(To traverse a table in numeric order, +use a numerical for.) + + +

+The behavior of next is undefined if, +during the traversal, +you assign any value to a non-existent field in the table. +You may however modify existing fields. +In particular, you may clear existing fields. + + + + +

+


pairs (t)

+ + +

+If t has a metamethod __pairs, +calls it with t as argument and returns the first three +results from the call. + + +

+Otherwise, +returns three values: the next function, the table t, and nil, +so that the construction + +

+     for k,v in pairs(t) do body end
+

+will iterate over all key–value pairs of table t. + + +

+See function next for the caveats of modifying +the table during its traversal. + + + + +

+


pcall (f [, arg1, ···])

+ + +

+Calls function f with +the given arguments in protected mode. +This means that any error inside f is not propagated; +instead, pcall catches the error +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In such case, pcall also returns all results from the call, +after this first result. +In case of any error, pcall returns false plus the error message. + + + + +

+


print (···)

+Receives any number of arguments +and prints their values to stdout, +using the tostring function to convert each argument to a string. +print is not intended for formatted output, +but only as a quick way to show a value, +for instance for debugging. +For complete control over the output, +use string.format and io.write. + + + + +

+


rawequal (v1, v2)

+Checks whether v1 is equal to v2, +without invoking any metamethod. +Returns a boolean. + + + + +

+


rawget (table, index)

+Gets the real value of table[index], +without invoking any metamethod. +table must be a table; +index may be any value. + + + + +

+


rawlen (v)

+Returns the length of the object v, +which must be a table or a string, +without invoking any metamethod. +Returns an integer number. + + + + +

+


rawset (table, index, value)

+Sets the real value of table[index] to value, +without invoking any metamethod. +table must be a table, +index any value different from nil and NaN, +and value any Lua value. + + +

+This function returns table. + + + + +

+


select (index, ···)

+ + +

+If index is a number, +returns all arguments after argument number index; +a negative number indexes from the end (-1 is the last argument). +Otherwise, index must be the string "#", +and select returns the total number of extra arguments it received. + + + + +

+


setmetatable (table, metatable)

+ + +

+Sets the metatable for the given table. +(You cannot change the metatable of other types from Lua, only from C.) +If metatable is nil, +removes the metatable of the given table. +If the original metatable has a "__metatable" field, +raises an error. + + +

+This function returns table. + + + + +

+


tonumber (e [, base])

+ + +

+When called with no base, +tonumber tries to convert its argument to a number. +If the argument is already a number or +a string convertible to a number (see §3.4.2), +then tonumber returns this number; +otherwise, it returns nil. + + +

+When called with base, +then e should be a string to be interpreted as +an integer numeral in that base. +The base may be any integer between 2 and 36, inclusive. +In bases above 10, the letter 'A' (in either upper or lower case) +represents 10, 'B' represents 11, and so forth, +with 'Z' representing 35. +If the string e is not a valid numeral in the given base, +the function returns nil. + + + + +

+


tostring (v)

+Receives a value of any type and +converts it to a string in a reasonable format. +(For complete control of how numbers are converted, +use string.format.) + + +

+If the metatable of v has a "__tostring" field, +then tostring calls the corresponding value +with v as argument, +and uses the result of the call as its result. + + + + +

+


type (v)

+Returns the type of its only argument, coded as a string. +The possible results of this function are +"nil" (a string, not the value nil), +"number", +"string", +"boolean", +"table", +"function", +"thread", +and "userdata". + + + + +

+


_VERSION

+A global variable (not a function) that +holds a string containing the current interpreter version. +The current contents of this variable is "Lua 5.2". + + + + +

+


xpcall (f, msgh [, arg1, ···])

+ + +

+This function is similar to pcall, +except that it sets a new message handler msgh. + + + + + + + +

6.2 – Coroutine Manipulation

+ +

+The operations related to coroutines comprise a sub-library of +the basic library and come inside the table coroutine. +See §2.6 for a general description of coroutines. + + +

+


coroutine.create (f)

+ + +

+Creates a new coroutine, with body f. +f must be a Lua function. +Returns this new coroutine, +an object with type "thread". + + + + +

+


coroutine.resume (co [, val1, ···])

+ + +

+Starts or continues the execution of coroutine co. +The first time you resume a coroutine, +it starts running its body. +The values val1, ... are passed +as the arguments to the body function. +If the coroutine has yielded, +resume restarts it; +the values val1, ... are passed +as the results from the yield. + + +

+If the coroutine runs without any errors, +resume returns true plus any values passed to yield +(if the coroutine yields) or any values returned by the body function +(if the coroutine terminates). +If there is any error, +resume returns false plus the error message. + + + + +

+


coroutine.running ()

+ + +

+Returns the running coroutine plus a boolean, +true when the running coroutine is the main one. + + + + +

+


coroutine.status (co)

+ + +

+Returns the status of coroutine co, as a string: +"running", +if the coroutine is running (that is, it called status); +"suspended", if the coroutine is suspended in a call to yield, +or if it has not started running yet; +"normal" if the coroutine is active but not running +(that is, it has resumed another coroutine); +and "dead" if the coroutine has finished its body function, +or if it has stopped with an error. + + + + +

+


coroutine.wrap (f)

+ + +

+Creates a new coroutine, with body f. +f must be a Lua function. +Returns a function that resumes the coroutine each time it is called. +Any arguments passed to the function behave as the +extra arguments to resume. +Returns the same values returned by resume, +except the first boolean. +In case of error, propagates the error. + + + + +

+


coroutine.yield (···)

+ + +

+Suspends the execution of the calling coroutine. +Any arguments to yield are passed as extra results to resume. + + + + + + + +

6.3 – Modules

+ +

+The package library provides basic +facilities for loading modules in Lua. +It exports one function directly in the global environment: +require. +Everything else is exported in a table package. + + +

+


require (modname)

+ + +

+Loads the given module. +The function starts by looking into the package.loaded table +to determine whether modname is already loaded. +If it is, then require returns the value stored +at package.loaded[modname]. +Otherwise, it tries to find a loader for the module. + + +

+To find a loader, +require is guided by the package.searchers sequence. +By changing this sequence, +we can change how require looks for a module. +The following explanation is based on the default configuration +for package.searchers. + + +

+First require queries package.preload[modname]. +If it has a value, +this value (which should be a function) is the loader. +Otherwise require searches for a Lua loader using the +path stored in package.path. +If that also fails, it searches for a C loader using the +path stored in package.cpath. +If that also fails, +it tries an all-in-one loader (see package.searchers). + + +

+Once a loader is found, +require calls the loader with two arguments: +modname and an extra value dependent on how it got the loader. +(If the loader came from a file, +this extra value is the file name.) +If the loader returns any non-nil value, +require assigns the returned value to package.loaded[modname]. +If the loader does not return a non-nil value and +has not assigned any value to package.loaded[modname], +then require assigns true to this entry. +In any case, require returns the +final value of package.loaded[modname]. + + +

+If there is any error loading or running the module, +or if it cannot find any loader for the module, +then require raises an error. + + + + +

+


package.config

+ + +

+A string describing some compile-time configurations for packages. +This string is a sequence of lines: + +

    + +
  • The first line is the directory separator string. +Default is '\' for Windows and '/' for all other systems.
  • + +
  • The second line is the character that separates templates in a path. +Default is ';'.
  • + +
  • The third line is the string that marks the +substitution points in a template. +Default is '?'.
  • + +
  • The fourth line is a string that, in a path in Windows, +is replaced by the executable's directory. +Default is '!'.
  • + +
  • The fifth line is a mark to ignore all text before it +when building the luaopen_ function name. +Default is '-'.
  • + +
+ + + +

+


package.cpath

+ + +

+The path used by require to search for a C loader. + + +

+Lua initializes the C path package.cpath in the same way +it initializes the Lua path package.path, +using the environment variable LUA_CPATH_5_2 +or the environment variable LUA_CPATH +or a default path defined in luaconf.h. + + + + +

+


package.loaded

+ + +

+A table used by require to control which +modules are already loaded. +When you require a module modname and +package.loaded[modname] is not false, +require simply returns the value stored there. + + +

+This variable is only a reference to the real table; +assignments to this variable do not change the +table used by require. + + + + +

+


package.loadlib (libname, funcname)

+ + +

+Dynamically links the host program with the C library libname. + + +

+If funcname is "*", +then it only links with the library, +making the symbols exported by the library +available to other dynamically linked libraries. +Otherwise, +it looks for a function funcname inside the library +and returns this function as a C function. +So, funcname must follow the lua_CFunction prototype +(see lua_CFunction). + + +

+This is a low-level function. +It completely bypasses the package and module system. +Unlike require, +it does not perform any path searching and +does not automatically adds extensions. +libname must be the complete file name of the C library, +including if necessary a path and an extension. +funcname must be the exact name exported by the C library +(which may depend on the C compiler and linker used). + + +

+This function is not supported by Standard C. +As such, it is only available on some platforms +(Windows, Linux, Mac OS X, Solaris, BSD, +plus other Unix systems that support the dlfcn standard). + + + + +

+


package.path

+ + +

+The path used by require to search for a Lua loader. + + +

+At start-up, Lua initializes this variable with +the value of the environment variable LUA_PATH_5_2 or +the environment variable LUA_PATH or +with a default path defined in luaconf.h, +if those environment variables are not defined. +Any ";;" in the value of the environment variable +is replaced by the default path. + + + + +

+


package.preload

+ + +

+A table to store loaders for specific modules +(see require). + + +

+This variable is only a reference to the real table; +assignments to this variable do not change the +table used by require. + + + + +

+


package.searchers

+ + +

+A table used by require to control how to load modules. + + +

+Each entry in this table is a searcher function. +When looking for a module, +require calls each of these searchers in ascending order, +with the module name (the argument given to require) as its +sole parameter. +The function can return another function (the module loader) +plus an extra value that will be passed to that loader, +or a string explaining why it did not find that module +(or nil if it has nothing to say). + + +

+Lua initializes this table with four searcher functions. + + +

+The first searcher simply looks for a loader in the +package.preload table. + + +

+The second searcher looks for a loader as a Lua library, +using the path stored at package.path. +The search is done as described in function package.searchpath. + + +

+The third searcher looks for a loader as a C library, +using the path given by the variable package.cpath. +Again, +the search is done as described in function package.searchpath. +For instance, +if the C path is the string + +

+     "./?.so;./?.dll;/usr/local/?/init.so"
+

+the searcher for module foo +will try to open the files ./foo.so, ./foo.dll, +and /usr/local/foo/init.so, in that order. +Once it finds a C library, +this searcher first uses a dynamic link facility to link the +application with the library. +Then it tries to find a C function inside the library to +be used as the loader. +The name of this C function is the string "luaopen_" +concatenated with a copy of the module name where each dot +is replaced by an underscore. +Moreover, if the module name has a hyphen, +its prefix up to (and including) the first hyphen is removed. +For instance, if the module name is a.v1-b.c, +the function name will be luaopen_b_c. + + +

+The fourth searcher tries an all-in-one loader. +It searches the C path for a library for +the root name of the given module. +For instance, when requiring a.b.c, +it will search for a C library for a. +If found, it looks into it for an open function for +the submodule; +in our example, that would be luaopen_a_b_c. +With this facility, a package can pack several C submodules +into one single library, +with each submodule keeping its original open function. + + +

+All searchers except the first one (preload) return as the extra value +the file name where the module was found, +as returned by package.searchpath. +The first searcher returns no extra value. + + + + +

+


package.searchpath (name, path [, sep [, rep]])

+ + +

+Searches for the given name in the given path. + + +

+A path is a string containing a sequence of +templates separated by semicolons. +For each template, +the function replaces each interrogation mark (if any) +in the template with a copy of name +wherein all occurrences of sep +(a dot, by default) +were replaced by rep +(the system's directory separator, by default), +and then tries to open the resulting file name. + + +

+For instance, if the path is the string + +

+     "./?.lua;./?.lc;/usr/local/?/init.lua"
+

+the search for the name foo.a +will try to open the files +./foo/a.lua, ./foo/a.lc, and +/usr/local/foo/a/init.lua, in that order. + + +

+Returns the resulting name of the first file that it can +open in read mode (after closing the file), +or nil plus an error message if none succeeds. +(This error message lists all file names it tried to open.) + + + + + + + +

6.4 – String Manipulation

+ +

+This library provides generic functions for string manipulation, +such as finding and extracting substrings, and pattern matching. +When indexing a string in Lua, the first character is at position 1 +(not at 0, as in C). +Indices are allowed to be negative and are interpreted as indexing backwards, +from the end of the string. +Thus, the last character is at position -1, and so on. + + +

+The string library provides all its functions inside the table +string. +It also sets a metatable for strings +where the __index field points to the string table. +Therefore, you can use the string functions in object-oriented style. +For instance, string.byte(s,i) +can be written as s:byte(i). + + +

+The string library assumes one-byte character encodings. + + +

+


string.byte (s [, i [, j]])

+Returns the internal numerical codes of the characters s[i], +s[i+1], ..., s[j]. +The default value for i is 1; +the default value for j is i. +These indices are corrected +following the same rules of function string.sub. + + +

+Numerical codes are not necessarily portable across platforms. + + + + +

+


string.char (···)

+Receives zero or more integers. +Returns a string with length equal to the number of arguments, +in which each character has the internal numerical code equal +to its corresponding argument. + + +

+Numerical codes are not necessarily portable across platforms. + + + + +

+


string.dump (function)

+ + +

+Returns a string containing a binary representation of the given function, +so that a later load on this string returns +a copy of the function (but with new upvalues). + + + + +

+


string.find (s, pattern [, init [, plain]])

+ + +

+Looks for the first match of +pattern in the string s. +If it finds a match, then find returns the indices of s +where this occurrence starts and ends; +otherwise, it returns nil. +A third, optional numerical argument init specifies +where to start the search; +its default value is 1 and can be negative. +A value of true as a fourth, optional argument plain +turns off the pattern matching facilities, +so the function does a plain "find substring" operation, +with no characters in pattern being considered magic. +Note that if plain is given, then init must be given as well. + + +

+If the pattern has captures, +then in a successful match +the captured values are also returned, +after the two indices. + + + + +

+


string.format (formatstring, ···)

+ + +

+Returns a formatted version of its variable number of arguments +following the description given in its first argument (which must be a string). +The format string follows the same rules as the ANSI C function sprintf. +The only differences are that the options/modifiers +*, h, L, l, n, +and p are not supported +and that there is an extra option, q. +The q option formats a string between double quotes, +using escape sequences when necessary to ensure that +it can safely be read back by the Lua interpreter. +For instance, the call + +

+     string.format('%q', 'a string with "quotes" and \n new line')
+

+may produce the string: + +

+     "a string with \"quotes\" and \
+      new line"
+
+ +

+Options +A and a (when available), +E, e, f, +G, and g all expect a number as argument. +Options c, d, +i, o, u, X, and x +also expect a number, +but the range of that number may be limited by +the underlying C implementation. +For options o, u, X, and x, +the number cannot be negative. +Option q expects a string; +option s expects a string without embedded zeros. +If the argument to option s is not a string, +it is converted to one following the same rules of tostring. + + + + +

+


string.gmatch (s, pattern)

+Returns an iterator function that, +each time it is called, +returns the next captures from pattern over the string s. +If pattern specifies no captures, +then the whole match is produced in each call. + + +

+As an example, the following loop +will iterate over all the words from string s, +printing one per line: + +

+     s = "hello world from Lua"
+     for w in string.gmatch(s, "%a+") do
+       print(w)
+     end
+

+The next example collects all pairs key=value from the +given string into a table: + +

+     t = {}
+     s = "from=world, to=Lua"
+     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
+       t[k] = v
+     end
+
+ +

+For this function, a caret '^' at the start of a pattern does not +work as an anchor, as this would prevent the iteration. + + + + +

+


string.gsub (s, pattern, repl [, n])

+Returns a copy of s +in which all (or the first n, if given) +occurrences of the pattern have been +replaced by a replacement string specified by repl, +which can be a string, a table, or a function. +gsub also returns, as its second value, +the total number of matches that occurred. +The name gsub comes from Global SUBstitution. + + +

+If repl is a string, then its value is used for replacement. +The character % works as an escape character: +any sequence in repl of the form %d, +with d between 1 and 9, +stands for the value of the d-th captured substring. +The sequence %0 stands for the whole match. +The sequence %% stands for a single %. + + +

+If repl is a table, then the table is queried for every match, +using the first capture as the key. + + +

+If repl is a function, then this function is called every time a +match occurs, with all captured substrings passed as arguments, +in order. + + +

+In any case, +if the pattern specifies no captures, +then it behaves as if the whole pattern was inside a capture. + + +

+If the value returned by the table query or by the function call +is a string or a number, +then it is used as the replacement string; +otherwise, if it is false or nil, +then there is no replacement +(that is, the original match is kept in the string). + + +

+Here are some examples: + +

+     x = string.gsub("hello world", "(%w+)", "%1 %1")
+     --> x="hello hello world world"
+     
+     x = string.gsub("hello world", "%w+", "%0 %0", 1)
+     --> x="hello hello world"
+     
+     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
+     --> x="world hello Lua from"
+     
+     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
+     --> x="home = /home/roberto, user = roberto"
+     
+     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
+           return load(s)()
+         end)
+     --> x="4+5 = 9"
+     
+     local t = {name="lua", version="5.2"}
+     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
+     --> x="lua-5.2.tar.gz"
+
+ + + +

+


string.len (s)

+Receives a string and returns its length. +The empty string "" has length 0. +Embedded zeros are counted, +so "a\000bc\000" has length 5. + + + + +

+


string.lower (s)

+Receives a string and returns a copy of this string with all +uppercase letters changed to lowercase. +All other characters are left unchanged. +The definition of what an uppercase letter is depends on the current locale. + + + + +

+


string.match (s, pattern [, init])

+Looks for the first match of +pattern in the string s. +If it finds one, then match returns +the captures from the pattern; +otherwise it returns nil. +If pattern specifies no captures, +then the whole match is returned. +A third, optional numerical argument init specifies +where to start the search; +its default value is 1 and can be negative. + + + + +

+


string.rep (s, n [, sep])

+Returns a string that is the concatenation of n copies of +the string s separated by the string sep. +The default value for sep is the empty string +(that is, no separator). + + + + +

+


string.reverse (s)

+Returns a string that is the string s reversed. + + + + +

+


string.sub (s, i [, j])

+Returns the substring of s that +starts at i and continues until j; +i and j can be negative. +If j is absent, then it is assumed to be equal to -1 +(which is the same as the string length). +In particular, +the call string.sub(s,1,j) returns a prefix of s +with length j, +and string.sub(s, -i) returns a suffix of s +with length i. + + +

+If, after the translation of negative indices, +i is less than 1, +it is corrected to 1. +If j is greater than the string length, +it is corrected to that length. +If, after these corrections, +i is greater than j, +the function returns the empty string. + + + + +

+


string.upper (s)

+Receives a string and returns a copy of this string with all +lowercase letters changed to uppercase. +All other characters are left unchanged. +The definition of what a lowercase letter is depends on the current locale. + + + +

6.4.1 – Patterns

+ + +

Character Class:

+A character class is used to represent a set of characters. +The following combinations are allowed in describing a character class: + +

    + +
  • x: +(where x is not one of the magic characters +^$()%.[]*+-?) +represents the character x itself. +
  • + +
  • .: (a dot) represents all characters.
  • + +
  • %a: represents all letters.
  • + +
  • %c: represents all control characters.
  • + +
  • %d: represents all digits.
  • + +
  • %g: represents all printable characters except space.
  • + +
  • %l: represents all lowercase letters.
  • + +
  • %p: represents all punctuation characters.
  • + +
  • %s: represents all space characters.
  • + +
  • %u: represents all uppercase letters.
  • + +
  • %w: represents all alphanumeric characters.
  • + +
  • %x: represents all hexadecimal digits.
  • + +
  • %x: (where x is any non-alphanumeric character) +represents the character x. +This is the standard way to escape the magic characters. +Any punctuation character (even the non magic) +can be preceded by a '%' +when used to represent itself in a pattern. +
  • + +
  • [set]: +represents the class which is the union of all +characters in set. +A range of characters can be specified by +separating the end characters of the range, +in ascending order, with a '-', +All classes %x described above can also be used as +components in set. +All other characters in set represent themselves. +For example, [%w_] (or [_%w]) +represents all alphanumeric characters plus the underscore, +[0-7] represents the octal digits, +and [0-7%l%-] represents the octal digits plus +the lowercase letters plus the '-' character. + + +

    +The interaction between ranges and classes is not defined. +Therefore, patterns like [%a-z] or [a-%%] +have no meaning. +

  • + +
  • [^set]: +represents the complement of set, +where set is interpreted as above. +
  • + +

+For all classes represented by single letters (%a, %c, etc.), +the corresponding uppercase letter represents the complement of the class. +For instance, %S represents all non-space characters. + + +

+The definitions of letter, space, and other character groups +depend on the current locale. +In particular, the class [a-z] may not be equivalent to %l. + + + + + +

Pattern Item:

+A pattern item can be + +

    + +
  • +a single character class, +which matches any single character in the class; +
  • + +
  • +a single character class followed by '*', +which matches 0 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +
  • + +
  • +a single character class followed by '+', +which matches 1 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +
  • + +
  • +a single character class followed by '-', +which also matches 0 or more repetitions of characters in the class. +Unlike '*', +these repetition items will always match the shortest possible sequence; +
  • + +
  • +a single character class followed by '?', +which matches 0 or 1 occurrence of a character in the class; +
  • + +
  • +%n, for n between 1 and 9; +such item matches a substring equal to the n-th captured string +(see below); +
  • + +
  • +%bxy, where x and y are two distinct characters; +such item matches strings that start with x, end with y, +and where the x and y are balanced. +This means that, if one reads the string from left to right, +counting +1 for an x and -1 for a y, +the ending y is the first y where the count reaches 0. +For instance, the item %b() matches expressions with +balanced parentheses. +
  • + +
  • +%f[set], a frontier pattern; +such item matches an empty string at any position such that +the next character belongs to set +and the previous character does not belong to set. +The set set is interpreted as previously described. +The beginning and the end of the subject are handled as if +they were the character '\0'. +
  • + +
+ + + + +

Pattern:

+A pattern is a sequence of pattern items. +A caret '^' at the beginning of a pattern anchors the match at the +beginning of the subject string. +A '$' at the end of a pattern anchors the match at the +end of the subject string. +At other positions, +'^' and '$' have no special meaning and represent themselves. + + + + + +

Captures:

+A pattern can contain sub-patterns enclosed in parentheses; +they describe captures. +When a match succeeds, the substrings of the subject string +that match captures are stored (captured) for future use. +Captures are numbered according to their left parentheses. +For instance, in the pattern "(a*(.)%w(%s*))", +the part of the string matching "a*(.)%w(%s*)" is +stored as the first capture (and therefore has number 1); +the character matching "." is captured with number 2, +and the part matching "%s*" has number 3. + + +

+As a special case, the empty capture () captures +the current string position (a number). +For instance, if we apply the pattern "()aa()" on the +string "flaaap", there will be two captures: 3 and 5. + + + + + + + + + + + +

6.5 – Table Manipulation

+ +

+This library provides generic functions for table manipulation. +It provides all its functions inside the table table. + + +

+Remember that, whenever an operation needs the length of a table, +the table should be a proper sequence +or have a __len metamethod (see §3.4.6). +All functions ignore non-numeric keys +in tables given as arguments. + + +

+For performance reasons, +all table accesses (get/set) performed by these functions are raw. + + +

+


table.concat (list [, sep [, i [, j]]])

+ + +

+Given a list where all elements are strings or numbers, +returns the string list[i]..sep..list[i+1] ··· sep..list[j]. +The default value for sep is the empty string, +the default for i is 1, +and the default for j is #list. +If i is greater than j, returns the empty string. + + + + +

+


table.insert (list, [pos,] value)

+ + +

+Inserts element value at position pos in list, +shifting up the elements +list[pos], list[pos+1], ···, list[#list]. +The default value for pos is #list+1, +so that a call table.insert(t,x) inserts x at the end +of list t. + + + + +

+


table.pack (···)

+ + +

+Returns a new table with all parameters stored into keys 1, 2, etc. +and with a field "n" with the total number of parameters. +Note that the resulting table may not be a sequence. + + + + +

+


table.remove (list [, pos])

+ + +

+Removes from list the element at position pos, +returning the value of the removed element. +When pos is an integer between 1 and #list, +it shifts down the elements +list[pos+1], list[pos+2], ···, list[#list] +and erases element list[#list]; +The index pos can also be 0 when #list is 0, +or #list + 1; +in those cases, the function erases the element list[pos]. + + +

+The default value for pos is #list, +so that a call table.remove(t) removes the last element +of list t. + + + + +

+


table.sort (list [, comp])

+ + +

+Sorts list elements in a given order, in-place, +from list[1] to list[#list]. +If comp is given, +then it must be a function that receives two list elements +and returns true when the first element must come +before the second in the final order +(so that not comp(list[i+1],list[i]) will be true after the sort). +If comp is not given, +then the standard Lua operator < is used instead. + + +

+The sort algorithm is not stable; +that is, elements considered equal by the given order +may have their relative positions changed by the sort. + + + + +

+


table.unpack (list [, i [, j]])

+ + +

+Returns the elements from the given table. +This function is equivalent to + +

+     return list[i], list[i+1], ···, list[j]
+

+By default, i is 1 and j is #list. + + + + + + + +

6.6 – Mathematical Functions

+ +

+This library is an interface to the standard C math library. +It provides all its functions inside the table math. + + +

+


math.abs (x)

+ + +

+Returns the absolute value of x. + + + + +

+


math.acos (x)

+ + +

+Returns the arc cosine of x (in radians). + + + + +

+


math.asin (x)

+ + +

+Returns the arc sine of x (in radians). + + + + +

+


math.atan (x)

+ + +

+Returns the arc tangent of x (in radians). + + + + +

+


math.atan2 (y, x)

+ + +

+Returns the arc tangent of y/x (in radians), +but uses the signs of both parameters to find the +quadrant of the result. +(It also handles correctly the case of x being zero.) + + + + +

+


math.ceil (x)

+ + +

+Returns the smallest integer larger than or equal to x. + + + + +

+


math.cos (x)

+ + +

+Returns the cosine of x (assumed to be in radians). + + + + +

+


math.cosh (x)

+ + +

+Returns the hyperbolic cosine of x. + + + + +

+


math.deg (x)

+ + +

+Returns the angle x (given in radians) in degrees. + + + + +

+


math.exp (x)

+ + +

+Returns the value ex. + + + + +

+


math.floor (x)

+ + +

+Returns the largest integer smaller than or equal to x. + + + + +

+


math.fmod (x, y)

+ + +

+Returns the remainder of the division of x by y +that rounds the quotient towards zero. + + + + +

+


math.frexp (x)

+ + +

+Returns m and e such that x = m2e, +e is an integer and the absolute value of m is +in the range [0.5, 1) +(or zero when x is zero). + + + + +

+


math.huge

+ + +

+The value HUGE_VAL, +a value larger than or equal to any other numerical value. + + + + +

+


math.ldexp (m, e)

+ + +

+Returns m2e (e should be an integer). + + + + +

+


math.log (x [, base])

+ + +

+Returns the logarithm of x in the given base. +The default for base is e +(so that the function returns the natural logarithm of x). + + + + +

+


math.max (x, ···)

+ + +

+Returns the maximum value among its arguments. + + + + +

+


math.min (x, ···)

+ + +

+Returns the minimum value among its arguments. + + + + +

+


math.modf (x)

+ + +

+Returns two numbers, +the integral part of x and the fractional part of x. + + + + +

+


math.pi

+ + +

+The value of π. + + + + +

+


math.pow (x, y)

+ + +

+Returns xy. +(You can also use the expression x^y to compute this value.) + + + + +

+


math.rad (x)

+ + +

+Returns the angle x (given in degrees) in radians. + + + + +

+


math.random ([m [, n]])

+ + +

+This function is an interface to the simple +pseudo-random generator function rand provided by Standard C. +(No guarantees can be given for its statistical properties.) + + +

+When called without arguments, +returns a uniform pseudo-random real number +in the range [0,1). +When called with an integer number m, +math.random returns +a uniform pseudo-random integer in the range [1, m]. +When called with two integer numbers m and n, +math.random returns a uniform pseudo-random +integer in the range [m, n]. + + + + +

+


math.randomseed (x)

+ + +

+Sets x as the "seed" +for the pseudo-random generator: +equal seeds produce equal sequences of numbers. + + + + +

+


math.sin (x)

+ + +

+Returns the sine of x (assumed to be in radians). + + + + +

+


math.sinh (x)

+ + +

+Returns the hyperbolic sine of x. + + + + +

+


math.sqrt (x)

+ + +

+Returns the square root of x. +(You can also use the expression x^0.5 to compute this value.) + + + + +

+


math.tan (x)

+ + +

+Returns the tangent of x (assumed to be in radians). + + + + +

+


math.tanh (x)

+ + +

+Returns the hyperbolic tangent of x. + + + + + + + +

6.7 – Bitwise Operations

+ +

+This library provides bitwise operations. +It provides all its functions inside the table bit32. + + +

+Unless otherwise stated, +all functions accept numeric arguments in the range +(-251,+251); +each argument is normalized to +the remainder of its division by 232 +and truncated to an integer (in some unspecified way), +so that its final value falls in the range [0,232 - 1]. +Similarly, all results are in the range [0,232 - 1]. +Note that bit32.bnot(0) is 0xFFFFFFFF, +which is different from -1. + + +

+


bit32.arshift (x, disp)

+ + +

+Returns the number x shifted disp bits to the right. +The number disp may be any representable integer. +Negative displacements shift to the left. + + +

+This shift operation is what is called arithmetic shift. +Vacant bits on the left are filled +with copies of the higher bit of x; +vacant bits on the right are filled with zeros. +In particular, +displacements with absolute values higher than 31 +result in zero or 0xFFFFFFFF (all original bits are shifted out). + + + + +

+


bit32.band (···)

+ + +

+Returns the bitwise and of its operands. + + + + +

+


bit32.bnot (x)

+ + +

+Returns the bitwise negation of x. +For any integer x, +the following identity holds: + +

+     assert(bit32.bnot(x) == (-1 - x) % 2^32)
+
+ + + +

+


bit32.bor (···)

+ + +

+Returns the bitwise or of its operands. + + + + +

+


bit32.btest (···)

+ + +

+Returns a boolean signaling +whether the bitwise and of its operands is different from zero. + + + + +

+


bit32.bxor (···)

+ + +

+Returns the bitwise exclusive or of its operands. + + + + +

+


bit32.extract (n, field [, width])

+ + +

+Returns the unsigned number formed by the bits +field to field + width - 1 from n. +Bits are numbered from 0 (least significant) to 31 (most significant). +All accessed bits must be in the range [0, 31]. + + +

+The default for width is 1. + + + + +

+


bit32.replace (n, v, field [, width])

+ + +

+Returns a copy of n with +the bits field to field + width - 1 +replaced by the value v. +See bit32.extract for details about field and width. + + + + +

+


bit32.lrotate (x, disp)

+ + +

+Returns the number x rotated disp bits to the left. +The number disp may be any representable integer. + + +

+For any valid displacement, +the following identity holds: + +

+     assert(bit32.lrotate(x, disp) == bit32.lrotate(x, disp % 32))
+

+In particular, +negative displacements rotate to the right. + + + + +

+


bit32.lshift (x, disp)

+ + +

+Returns the number x shifted disp bits to the left. +The number disp may be any representable integer. +Negative displacements shift to the right. +In any direction, vacant bits are filled with zeros. +In particular, +displacements with absolute values higher than 31 +result in zero (all bits are shifted out). + + +

+For positive displacements, +the following equality holds: + +

+     assert(bit32.lshift(b, disp) == (b * 2^disp) % 2^32)
+
+ + + +

+


bit32.rrotate (x, disp)

+ + +

+Returns the number x rotated disp bits to the right. +The number disp may be any representable integer. + + +

+For any valid displacement, +the following identity holds: + +

+     assert(bit32.rrotate(x, disp) == bit32.rrotate(x, disp % 32))
+

+In particular, +negative displacements rotate to the left. + + + + +

+


bit32.rshift (x, disp)

+ + +

+Returns the number x shifted disp bits to the right. +The number disp may be any representable integer. +Negative displacements shift to the left. +In any direction, vacant bits are filled with zeros. +In particular, +displacements with absolute values higher than 31 +result in zero (all bits are shifted out). + + +

+For positive displacements, +the following equality holds: + +

+     assert(bit32.rshift(b, disp) == math.floor(b % 2^32 / 2^disp))
+
+ +

+This shift operation is what is called logical shift. + + + + + + + +

6.8 – Input and Output Facilities

+ +

+The I/O library provides two different styles for file manipulation. +The first one uses implicit file descriptors; +that is, there are operations to set a default input file and a +default output file, +and all input/output operations are over these default files. +The second style uses explicit file descriptors. + + +

+When using implicit file descriptors, +all operations are supplied by table io. +When using explicit file descriptors, +the operation io.open returns a file descriptor +and then all operations are supplied as methods of the file descriptor. + + +

+The table io also provides +three predefined file descriptors with their usual meanings from C: +io.stdin, io.stdout, and io.stderr. +The I/O library never closes these files. + + +

+Unless otherwise stated, +all I/O functions return nil on failure +(plus an error message as a second result and +a system-dependent error code as a third result) +and some value different from nil on success. +On non-Posix systems, +the computation of the error message and error code +in case of errors +may be not thread safe, +because they rely on the global C variable errno. + + +

+


io.close ([file])

+ + +

+Equivalent to file:close(). +Without a file, closes the default output file. + + + + +

+


io.flush ()

+ + +

+Equivalent to io.output():flush(). + + + + +

+


io.input ([file])

+ + +

+When called with a file name, it opens the named file (in text mode), +and sets its handle as the default input file. +When called with a file handle, +it simply sets this file handle as the default input file. +When called without parameters, +it returns the current default input file. + + +

+In case of errors this function raises the error, +instead of returning an error code. + + + + +

+


io.lines ([filename ···])

+ + +

+Opens the given file name in read mode +and returns an iterator function that +works like file:lines(···) over the opened file. +When the iterator function detects the end of file, +it returns nil (to finish the loop) and automatically closes the file. + + +

+The call io.lines() (with no file name) is equivalent +to io.input():lines(); +that is, it iterates over the lines of the default input file. +In this case it does not close the file when the loop ends. + + +

+In case of errors this function raises the error, +instead of returning an error code. + + + + +

+


io.open (filename [, mode])

+ + +

+This function opens a file, +in the mode specified in the string mode. +It returns a new file handle, +or, in case of errors, nil plus an error message. + + +

+The mode string can be any of the following: + +

    +
  • "r": read mode (the default);
  • +
  • "w": write mode;
  • +
  • "a": append mode;
  • +
  • "r+": update mode, all previous data is preserved;
  • +
  • "w+": update mode, all previous data is erased;
  • +
  • "a+": append update mode, previous data is preserved, + writing is only allowed at the end of file.
  • +

+The mode string can also have a 'b' at the end, +which is needed in some systems to open the file in binary mode. + + + + +

+


io.output ([file])

+ + +

+Similar to io.input, but operates over the default output file. + + + + +

+


io.popen (prog [, mode])

+ + +

+This function is system dependent and is not available +on all platforms. + + +

+Starts program prog in a separated process and returns +a file handle that you can use to read data from this program +(if mode is "r", the default) +or to write data to this program +(if mode is "w"). + + + + +

+


io.read (···)

+ + +

+Equivalent to io.input():read(···). + + + + +

+


io.tmpfile ()

+ + +

+Returns a handle for a temporary file. +This file is opened in update mode +and it is automatically removed when the program ends. + + + + +

+


io.type (obj)

+ + +

+Checks whether obj is a valid file handle. +Returns the string "file" if obj is an open file handle, +"closed file" if obj is a closed file handle, +or nil if obj is not a file handle. + + + + +

+


io.write (···)

+ + +

+Equivalent to io.output():write(···). + + + + +

+


file:close ()

+ + +

+Closes file. +Note that files are automatically closed when +their handles are garbage collected, +but that takes an unpredictable amount of time to happen. + + +

+When closing a file handle created with io.popen, +file:close returns the same values +returned by os.execute. + + + + +

+


file:flush ()

+ + +

+Saves any written data to file. + + + + +

+


file:lines (···)

+ + +

+Returns an iterator function that, +each time it is called, +reads the file according to the given formats. +When no format is given, +uses "*l" as a default. +As an example, the construction + +

+     for c in file:lines(1) do body end
+

+will iterate over all characters of the file, +starting at the current position. +Unlike io.lines, this function does not close the file +when the loop ends. + + +

+In case of errors this function raises the error, +instead of returning an error code. + + + + +

+


file:read (···)

+ + +

+Reads the file file, +according to the given formats, which specify what to read. +For each format, +the function returns a string (or a number) with the characters read, +or nil if it cannot read data with the specified format. +When called without formats, +it uses a default format that reads the next line +(see below). + + +

+The available formats are + +

    + +
  • "*n": +reads a number; +this is the only format that returns a number instead of a string. +
  • + +
  • "*a": +reads the whole file, starting at the current position. +On end of file, it returns the empty string. +
  • + +
  • "*l": +reads the next line skipping the end of line, +returning nil on end of file. +This is the default format. +
  • + +
  • "*L": +reads the next line keeping the end of line (if present), +returning nil on end of file. +
  • + +
  • number: +reads a string with up to this number of bytes, +returning nil on end of file. +If number is zero, +it reads nothing and returns an empty string, +or nil on end of file. +
  • + +
+ + + +

+


file:seek ([whence [, offset]])

+ + +

+Sets and gets the file position, +measured from the beginning of the file, +to the position given by offset plus a base +specified by the string whence, as follows: + +

    +
  • "set": base is position 0 (beginning of the file);
  • +
  • "cur": base is current position;
  • +
  • "end": base is end of file;
  • +

+In case of success, seek returns the final file position, +measured in bytes from the beginning of the file. +If seek fails, it returns nil, +plus a string describing the error. + + +

+The default value for whence is "cur", +and for offset is 0. +Therefore, the call file:seek() returns the current +file position, without changing it; +the call file:seek("set") sets the position to the +beginning of the file (and returns 0); +and the call file:seek("end") sets the position to the +end of the file, and returns its size. + + + + +

+


file:setvbuf (mode [, size])

+ + +

+Sets the buffering mode for an output file. +There are three available modes: + +

    + +
  • "no": +no buffering; the result of any output operation appears immediately. +
  • + +
  • "full": +full buffering; output operation is performed only +when the buffer is full or when +you explicitly flush the file (see io.flush). +
  • + +
  • "line": +line buffering; output is buffered until a newline is output +or there is any input from some special files +(such as a terminal device). +
  • + +

+For the last two cases, size +specifies the size of the buffer, in bytes. +The default is an appropriate size. + + + + +

+


file:write (···)

+ + +

+Writes the value of each of its arguments to file. +The arguments must be strings or numbers. + + +

+In case of success, this function returns file. +Otherwise it returns nil plus a string describing the error. + + + + + + + +

6.9 – Operating System Facilities

+ +

+This library is implemented through table os. + + +

+


os.clock ()

+ + +

+Returns an approximation of the amount in seconds of CPU time +used by the program. + + + + +

+


os.date ([format [, time]])

+ + +

+Returns a string or a table containing date and time, +formatted according to the given string format. + + +

+If the time argument is present, +this is the time to be formatted +(see the os.time function for a description of this value). +Otherwise, date formats the current time. + + +

+If format starts with '!', +then the date is formatted in Coordinated Universal Time. +After this optional character, +if format is the string "*t", +then date returns a table with the following fields: +year (four digits), month (1–12), day (1–31), +hour (0–23), min (0–59), sec (0–61), +wday (weekday, Sunday is 1), +yday (day of the year), +and isdst (daylight saving flag, a boolean). +This last field may be absent +if the information is not available. + + +

+If format is not "*t", +then date returns the date as a string, +formatted according to the same rules as the ANSI C function strftime. + + +

+When called without arguments, +date returns a reasonable date and time representation that depends on +the host system and on the current locale +(that is, os.date() is equivalent to os.date("%c")). + + +

+On non-Posix systems, +this function may be not thread safe +because of its reliance on C function gmtime and C function localtime. + + + + +

+


os.difftime (t2, t1)

+ + +

+Returns the number of seconds from time t1 to time t2. +In POSIX, Windows, and some other systems, +this value is exactly t2-t1. + + + + +

+


os.execute ([command])

+ + +

+This function is equivalent to the ANSI C function system. +It passes command to be executed by an operating system shell. +Its first result is true +if the command terminated successfully, +or nil otherwise. +After this first result +the function returns a string and a number, +as follows: + +

    + +
  • "exit": +the command terminated normally; +the following number is the exit status of the command. +
  • + +
  • "signal": +the command was terminated by a signal; +the following number is the signal that terminated the command. +
  • + +
+ +

+When called without a command, +os.execute returns a boolean that is true if a shell is available. + + + + +

+


os.exit ([code [, close])

+ + +

+Calls the ANSI C function exit to terminate the host program. +If code is true, +the returned status is EXIT_SUCCESS; +if code is false, +the returned status is EXIT_FAILURE; +if code is a number, +the returned status is this number. +The default value for code is true. + + +

+If the optional second argument close is true, +closes the Lua state before exiting. + + + + +

+


os.getenv (varname)

+ + +

+Returns the value of the process environment variable varname, +or nil if the variable is not defined. + + + + +

+


os.remove (filename)

+ + +

+Deletes the file (or empty directory, on POSIX systems) +with the given name. +If this function fails, it returns nil, +plus a string describing the error and the error code. + + + + +

+


os.rename (oldname, newname)

+ + +

+Renames file or directory named oldname to newname. +If this function fails, it returns nil, +plus a string describing the error and the error code. + + + + +

+


os.setlocale (locale [, category])

+ + +

+Sets the current locale of the program. +locale is a system-dependent string specifying a locale; +category is an optional string describing which category to change: +"all", "collate", "ctype", +"monetary", "numeric", or "time"; +the default category is "all". +The function returns the name of the new locale, +or nil if the request cannot be honored. + + +

+If locale is the empty string, +the current locale is set to an implementation-defined native locale. +If locale is the string "C", +the current locale is set to the standard C locale. + + +

+When called with nil as the first argument, +this function only returns the name of the current locale +for the given category. + + +

+This function may be not thread safe +because of its reliance on C function setlocale. + + + + +

+


os.time ([table])

+ + +

+Returns the current time when called without arguments, +or a time representing the date and time specified by the given table. +This table must have fields year, month, and day, +and may have fields +hour (default is 12), +min (default is 0), +sec (default is 0), +and isdst (default is nil). +For a description of these fields, see the os.date function. + + +

+The returned value is a number, whose meaning depends on your system. +In POSIX, Windows, and some other systems, +this number counts the number +of seconds since some given start time (the "epoch"). +In other systems, the meaning is not specified, +and the number returned by time can be used only as an argument to +os.date and os.difftime. + + + + +

+


os.tmpname ()

+ + +

+Returns a string with a file name that can +be used for a temporary file. +The file must be explicitly opened before its use +and explicitly removed when no longer needed. + + +

+On POSIX systems, +this function also creates a file with that name, +to avoid security risks. +(Someone else might create the file with wrong permissions +in the time between getting the name and creating the file.) +You still have to open the file to use it +and to remove it (even if you do not use it). + + +

+When possible, +you may prefer to use io.tmpfile, +which automatically removes the file when the program ends. + + + + + + + +

6.10 – The Debug Library

+ +

+This library provides +the functionality of the debug interface (§4.9) to Lua programs. +You should exert care when using this library. +Several of its functions +violate basic assumptions about Lua code +(e.g., that variables local to a function +cannot be accessed from outside; +that userdata metatables cannot be changed by Lua code; +that Lua programs do not crash) +and therefore can compromise otherwise secure code. +Moreover, some functions in this library may be slow. + + +

+All functions in this library are provided +inside the debug table. +All functions that operate over a thread +have an optional first argument which is the +thread to operate over. +The default is always the current thread. + + +

+


debug.debug ()

+ + +

+Enters an interactive mode with the user, +running each string that the user enters. +Using simple commands and other debug facilities, +the user can inspect global and local variables, +change their values, evaluate expressions, and so on. +A line containing only the word cont finishes this function, +so that the caller continues its execution. + + +

+Note that commands for debug.debug are not lexically nested +within any function and so have no direct access to local variables. + + + + +

+


debug.gethook ([thread])

+ + +

+Returns the current hook settings of the thread, as three values: +the current hook function, the current hook mask, +and the current hook count +(as set by the debug.sethook function). + + + + +

+


debug.getinfo ([thread,] f [, what])

+ + +

+Returns a table with information about a function. +You can give the function directly +or you can give a number as the value of f, +which means the function running at level f of the call stack +of the given thread: +level 0 is the current function (getinfo itself); +level 1 is the function that called getinfo +(except for tail calls, which do not count on the stack); +and so on. +If f is a number larger than the number of active functions, +then getinfo returns nil. + + +

+The returned table can contain all the fields returned by lua_getinfo, +with the string what describing which fields to fill in. +The default for what is to get all information available, +except the table of valid lines. +If present, +the option 'f' +adds a field named func with the function itself. +If present, +the option 'L' +adds a field named activelines with the table of +valid lines. + + +

+For instance, the expression debug.getinfo(1,"n").name returns +a table with a name for the current function, +if a reasonable name can be found, +and the expression debug.getinfo(print) +returns a table with all available information +about the print function. + + + + +

+


debug.getlocal ([thread,] f, local)

+ + +

+This function returns the name and the value of the local variable +with index local of the function at level f of the stack. +This function accesses not only explicit local variables, +but also parameters, temporaries, etc. + + +

+The first parameter or local variable has index 1, and so on, +until the last active variable. +Negative indices refer to vararg parameters; +-1 is the first vararg parameter. +The function returns nil if there is no variable with the given index, +and raises an error when called with a level out of range. +(You can call debug.getinfo to check whether the level is valid.) + + +

+Variable names starting with '(' (open parenthesis) +represent internal variables +(loop control variables, temporaries, varargs, and C function locals). + + +

+The parameter f may also be a function. +In that case, getlocal returns only the name of function parameters. + + + + +

+


debug.getmetatable (value)

+ + +

+Returns the metatable of the given value +or nil if it does not have a metatable. + + + + +

+


debug.getregistry ()

+ + +

+Returns the registry table (see §4.5). + + + + +

+


debug.getupvalue (f, up)

+ + +

+This function returns the name and the value of the upvalue +with index up of the function f. +The function returns nil if there is no upvalue with the given index. + + + + +

+


debug.getuservalue (u)

+ + +

+Returns the Lua value associated to u. +If u is not a userdata, +returns nil. + + + + +

+


debug.sethook ([thread,] hook, mask [, count])

+ + +

+Sets the given function as a hook. +The string mask and the number count describe +when the hook will be called. +The string mask may have the following characters, +with the given meaning: + +

    +
  • 'c': the hook is called every time Lua calls a function;
  • +
  • 'r': the hook is called every time Lua returns from a function;
  • +
  • 'l': the hook is called every time Lua enters a new line of code.
  • +

+With a count different from zero, +the hook is called after every count instructions. + + +

+When called without arguments, +debug.sethook turns off the hook. + + +

+When the hook is called, its first parameter is a string +describing the event that has triggered its call: +"call" (or "tail call"), +"return", +"line", and "count". +For line events, +the hook also gets the new line number as its second parameter. +Inside a hook, +you can call getinfo with level 2 to get more information about +the running function +(level 0 is the getinfo function, +and level 1 is the hook function). + + + + +

+


debug.setlocal ([thread,] level, local, value)

+ + +

+This function assigns the value value to the local variable +with index local of the function at level level of the stack. +The function returns nil if there is no local +variable with the given index, +and raises an error when called with a level out of range. +(You can call getinfo to check whether the level is valid.) +Otherwise, it returns the name of the local variable. + + +

+See debug.getlocal for more information about +variable indices and names. + + + + +

+


debug.setmetatable (value, table)

+ + +

+Sets the metatable for the given value to the given table +(which can be nil). +Returns value. + + + + +

+


debug.setupvalue (f, up, value)

+ + +

+This function assigns the value value to the upvalue +with index up of the function f. +The function returns nil if there is no upvalue +with the given index. +Otherwise, it returns the name of the upvalue. + + + + +

+


debug.setuservalue (udata, value)

+ + +

+Sets the given value as +the Lua value associated to the given udata. +value must be a table or nil; +udata must be a full userdata. + + +

+Returns udata. + + + + +

+


debug.traceback ([thread,] [message [, level]])

+ + +

+If message is present but is neither a string nor nil, +this function returns message without further processing. +Otherwise, +it returns a string with a traceback of the call stack. +An optional message string is appended +at the beginning of the traceback. +An optional level number tells at which level +to start the traceback +(default is 1, the function calling traceback). + + + + +

+


debug.upvalueid (f, n)

+ + +

+Returns an unique identifier (as a light userdata) +for the upvalue numbered n +from the given function. + + +

+These unique identifiers allow a program to check whether different +closures share upvalues. +Lua closures that share an upvalue +(that is, that access a same external local variable) +will return identical ids for those upvalue indices. + + + + +

+


debug.upvaluejoin (f1, n1, f2, n2)

+ + +

+Make the n1-th upvalue of the Lua closure f1 +refer to the n2-th upvalue of the Lua closure f2. + + + + + + + +

7 – Lua Standalone

+ +

+Although Lua has been designed as an extension language, +to be embedded in a host C program, +it is also frequently used as a standalone language. +An interpreter for Lua as a standalone language, +called simply lua, +is provided with the standard distribution. +The standalone interpreter includes +all standard libraries, including the debug library. +Its usage is: + +

+     lua [options] [script [args]]
+

+The options are: + +

    +
  • -e stat: executes string stat;
  • +
  • -l mod: "requires" mod;
  • +
  • -i: enters interactive mode after running script;
  • +
  • -v: prints version information;
  • +
  • -E: ignores environment variables;
  • +
  • --: stops handling options;
  • +
  • -: executes stdin as a file and stops handling options.
  • +

+After handling its options, lua runs the given script, +passing to it the given args as string arguments. +When called without arguments, +lua behaves as lua -v -i +when the standard input (stdin) is a terminal, +and as lua - otherwise. + + +

+When called without option -E, +the interpreter checks for an environment variable LUA_INIT_5_2 +(or LUA_INIT if it is not defined) +before running any argument. +If the variable content has the format @filename, +then lua executes the file. +Otherwise, lua executes the string itself. + + +

+When called with option -E, +besides ignoring LUA_INIT, +Lua also ignores +the values of LUA_PATH and LUA_CPATH, +setting the values of +package.path and package.cpath +with the default paths defined in luaconf.h. + + +

+All options are handled in order, except -i and -E. +For instance, an invocation like + +

+     $ lua -e'a=1' -e 'print(a)' script.lua
+

+will first set a to 1, then print the value of a, +and finally run the file script.lua with no arguments. +(Here $ is the shell prompt. Your prompt may be different.) + + +

+Before starting to run the script, +lua collects all arguments in the command line +in a global table called arg. +The script name is stored at index 0, +the first argument after the script name goes to index 1, +and so on. +Any arguments before the script name +(that is, the interpreter name plus the options) +go to negative indices. +For instance, in the call + +

+     $ lua -la b.lua t1 t2
+

+the interpreter first runs the file a.lua, +then creates a table + +

+     arg = { [-2] = "lua", [-1] = "-la",
+             [0] = "b.lua",
+             [1] = "t1", [2] = "t2" }
+

+and finally runs the file b.lua. +The script is called with arg[1], arg[2], ... +as arguments; +it can also access these arguments with the vararg expression '...'. + + +

+In interactive mode, +if you write an incomplete statement, +the interpreter waits for its completion +by issuing a different prompt. + + +

+In case of unprotected errors in the script, +the interpreter reports the error to the standard error stream. +If the error object is a string, +the interpreter adds a stack traceback to it. +Otherwise, if the error object has a metamethod __tostring, +the interpreter calls this metamethod to produce the final message. +Finally, if the error object is nil, +the interpreter does not report the error. + + +

+When finishing normally, +the interpreter closes its main Lua state +(see lua_close). +The script can avoid this step by +calling os.exit to terminate. + + +

+To allow the use of Lua as a +script interpreter in Unix systems, +the standalone interpreter skips +the first line of a chunk if it starts with #. +Therefore, Lua scripts can be made into executable programs +by using chmod +x and the #! form, +as in + +

+     #!/usr/local/bin/lua
+

+(Of course, +the location of the Lua interpreter may be different in your machine. +If lua is in your PATH, +then + +

+     #!/usr/bin/env lua
+

+is a more portable solution.) + + + +

8 – Incompatibilities with the Previous Version

+ +

+Here we list the incompatibilities that you may find when moving a program +from Lua 5.1 to Lua 5.2. +You can avoid some incompatibilities by compiling Lua with +appropriate options (see file luaconf.h). +However, +all these compatibility options will be removed in the next version of Lua. +Similarly, +all features marked as deprecated in Lua 5.1 +have been removed in Lua 5.2. + + + +

8.1 – Changes in the Language

+
    + +
  • +The concept of environment changed. +Only Lua functions have environments. +To set the environment of a Lua function, +use the variable _ENV or the function load. + + +

    +C functions no longer have environments. +Use an upvalue with a shared table if you need to keep +shared state among several C functions. +(You may use luaL_setfuncs to open a C library +with all functions sharing a common upvalue.) + + +

    +To manipulate the "environment" of a userdata +(which is now called user value), +use the new functions +lua_getuservalue and lua_setuservalue. +

  • + +
  • +Lua identifiers cannot use locale-dependent letters. +
  • + +
  • +Doing a step or a full collection in the garbage collector +does not restart the collector if it has been stopped. +
  • + +
  • +Weak tables with weak keys now perform like ephemeron tables. +
  • + +
  • +The event tail return in debug hooks was removed. +Instead, tail calls generate a special new event, +tail call, so that the debugger can know that +there will not be a corresponding return event. +
  • + +
  • +Equality between function values has changed. +Now, a function definition may not create a new value; +it may reuse some previous value if there is no +observable difference to the new function. +
  • + +
+ + + + +

8.2 – Changes in the Libraries

+
    + +
  • +Function module is deprecated. +It is easy to set up a module with regular Lua code. +Modules are not expected to set global variables. +
  • + +
  • +Functions setfenv and getfenv were removed, +because of the changes in environments. +
  • + +
  • +Function math.log10 is deprecated. +Use math.log with 10 as its second argument, instead. +
  • + +
  • +Function loadstring is deprecated. +Use load instead; it now accepts string arguments +and are exactly equivalent to loadstring. +
  • + +
  • +Function table.maxn is deprecated. +Write it in Lua if you really need it. +
  • + +
  • +Function os.execute now returns true when command +terminates successfully and nil plus error information +otherwise. +
  • + +
  • +Function unpack was moved into the table library +and therefore must be called as table.unpack. +
  • + +
  • +Character class %z in patterns is deprecated, +as now patterns may contain '\0' as a regular character. +
  • + +
  • +The table package.loaders was renamed package.searchers. +
  • + +
  • +Lua does not have bytecode verification anymore. +So, all functions that load code +(load and loadfile) +are potentially insecure when loading untrusted binary data. +(Actually, those functions were already insecure because +of flaws in the verification algorithm.) +When in doubt, +use the mode argument of those functions +to restrict them to loading textual chunks. +
  • + +
  • +The standard paths in the official distribution may +change between versions. +
  • + +
+ + + + +

8.3 – Changes in the API

+
    + +
  • +Pseudoindex LUA_GLOBALSINDEX was removed. +You must get the global environment from the registry +(see §4.5). +
  • + +
  • +Pseudoindex LUA_ENVIRONINDEX +and functions lua_getfenv/lua_setfenv +were removed, +as C functions no longer have environments. +
  • + +
  • +Function luaL_register is deprecated. +Use luaL_setfuncs so that your module does not create globals. +(Modules are not expected to set global variables anymore.) +
  • + +
  • +The osize argument to the allocation function +may not be zero when creating a new block, +that is, when ptr is NULL +(see lua_Alloc). +Use only the test ptr == NULL to check whether +the block is new. +
  • + +
  • +Finalizers (__gc metamethods) for userdata are called in the +reverse order that they were marked for finalization, +not that they were created (see §2.5.1). +(Most userdata are marked immediately after they are created.) +Moreover, +if the metatable does not have a __gc field when set, +the finalizer will not be called, +even if it is set later. +
  • + +
  • +luaL_typerror was removed. +Write your own version if you need it. +
  • + +
  • +Function lua_cpcall is deprecated. +You can simply push the function with lua_pushcfunction +and call it with lua_pcall. +
  • + +
  • +Functions lua_equal and lua_lessthan are deprecated. +Use the new lua_compare with appropriate options instead. +
  • + +
  • +Function lua_objlen was renamed lua_rawlen. +
  • + +
  • +Function lua_load has an extra parameter, mode. +Pass NULL to simulate the old behavior. +
  • + +
  • +Function lua_resume has an extra parameter, from. +Pass NULL or the thread doing the call. +
  • + +
+ + + + +

9 – The Complete Syntax of Lua

+ +

+Here is the complete syntax of Lua in extended BNF. +(It does not describe operator precedences.) + + + + +

+
+	chunk ::= block
+
+	block ::= {stat} [retstat]
+
+	stat ::=  ‘;’ | 
+		 varlist ‘=’ explist | 
+		 functioncall | 
+		 label | 
+		 break | 
+		 goto Name | 
+		 do block end | 
+		 while exp do block end | 
+		 repeat block until exp | 
+		 if exp then block {elseif exp then block} [else block] end | 
+		 for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
+		 for namelist in explist do block end | 
+		 function funcname funcbody | 
+		 local function Name funcbody | 
+		 local namelist [‘=’ explist] 
+
+	retstat ::= return [explist] [‘;’]
+
+	label ::= ‘::’ Name ‘::’
+
+	funcname ::= Name {‘.’ Name} [‘:’ Name]
+
+	varlist ::= var {‘,’ var}
+
+	var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 
+
+	namelist ::= Name {‘,’ Name}
+
+	explist ::= exp {‘,’ exp}
+
+	exp ::=  nil | false | true | Number | String | ‘...’ | functiondef | 
+		 prefixexp | tableconstructor | exp binop exp | unop exp 
+
+	prefixexp ::= var | functioncall | ‘(’ exp ‘)’
+
+	functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 
+
+	args ::=  ‘(’ [explist] ‘)’ | tableconstructor | String 
+
+	functiondef ::= function funcbody
+
+	funcbody ::= ‘(’ [parlist] ‘)’ block end
+
+	parlist ::= namelist [‘,’ ‘...’] | ‘...’
+
+	tableconstructor ::= ‘{’ [fieldlist] ‘}’
+
+	fieldlist ::= field {fieldsep field} [fieldsep]
+
+	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
+
+	fieldsep ::= ‘,’ | ‘;’
+
+	binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘^’ | ‘%’ | ‘..’ | 
+		 ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
+		 and | or
+
+	unop ::= ‘-’ | not | ‘#’
+
+
+ +

+ + + + + + + +


+ +Last update: +Thu Mar 21 12:58:59 BRT 2013 + + + + + diff --git a/radio/src/lua/doc/osi-certified-72x60.png b/radio/src/lua/doc/osi-certified-72x60.png new file mode 100644 index 0000000000000000000000000000000000000000..07df5f6ee7a7a8b2108025dcd815f73f145a83af GIT binary patch literal 3774 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 + + +Lua 5.2 readme + + + + + + + +
+

+Lua +Welcome to Lua 5.2 +

+ +

+about +· +installation +· +changes +· +license +· +reference manual + +

About Lua

+ +

+Lua is a powerful, fast, lightweight, embeddable scripting language +developed by a +team +at +PUC-Rio, +the Pontifical Catholic University of Rio de Janeiro in Brazil. +Lua is +free software +used in many products and projects around the world. + +

+Lua's +official web site +provides complete information +about Lua, +including +an +executive summary +and +updated +documentation, +especially the +reference manual, +which may differ slightly from the +local copy +distributed in this package. + +

Installing Lua

+ +

+Lua is distributed in +source +form. +You need to build it before using it. +Building Lua should be straightforward +because +Lua is implemented in pure ANSI C and compiles unmodified in all known +platforms that have an ANSI C compiler. +Lua also compiles unmodified as C++. +The instructions given below for building Lua are for Unix-like platforms. +See also +instructions for other systems +and +customization options. + +

+If you don't have the time or the inclination to compile Lua yourself, +get a binary from +LuaBinaries. +Try also +Lua for Windows, +an easy-to-use distribution of Lua that includes many useful libraries. + +

Building Lua

+ +

+In most Unix-like platforms, simply do "make" with a suitable target. +Here are the details. + +

    +
  1. +Open a terminal window and move to +the top-level directory, which is named lua-5.2.2. +The Makefile there controls both the build process and the installation process. +

    +

  2. + Do "make" and see if your platform is listed. + The platforms currently supported are: +

    +

    + aix ansi bsd freebsd generic linux macosx mingw posix solaris +

    +

    + If your platform is listed, just do "make xxx", where xxx + is your platform name. +

    + If your platform is not listed, try the closest one or posix, generic, + ansi, in this order. +

    +

  3. +The compilation takes only a few moments +and produces three files in the src directory: +lua (the interpreter), +luac (the compiler), +and liblua.a (the library). +

    +

  4. + To check that Lua has been built correctly, do "make test" + after building Lua. This will run the interpreter and print its version string. +
+

+If you're running Linux and get compilation errors, +make sure you have installed the readline development package. +If you get link errors after that, +then try "make linux MYLIBS=-ltermcap". + +

Installing Lua

+

+ Once you have built Lua, you may want to install it in an official + place in your system. In this case, do "make install". The official + place and the way to install files are defined in the Makefile. You'll + probably need the right permissions to install files. + +

+ To build and install Lua in one step, do "make xxx install", + where xxx is your platform name. + +

+ To install Lua locally, do "make local". + This will create a directory install with subdirectories + bin, include, lib, man, + and install Lua as listed below. + + To install Lua locally, but in some other directory, do + "make install INSTALL_TOP=xxx", where xxx is your chosen directory. + +

+
+ bin: +
+ lua luac +
+ include: +
+ lua.h luaconf.h lualib.h lauxlib.h lua.hpp +
+ lib: +
+ liblua.a +
+ man/man1: +
+ lua.1 luac.1 +
+ +

+ These are the only directories you need for development. + If you only want to run Lua programs, + you only need the files in bin and man. + The files in include and lib are needed for + embedding Lua in C or C++ programs. + +

Customization

+

+ Three kinds of things can be customized by editing a file: +

    +
  • Where and how to install Lua — edit Makefile. +
  • How to build Lua — edit src/Makefile. +
  • Lua features — edit src/luaconf.h. +
+ +

+ You don't actually need to edit the Makefiles because you may set the + relevant variables in the command line when invoking make. + Nevertheless, it's probably best to edit and save the Makefiles to + record the changes you need. + +

+ On the other hand, if you need to customize some Lua features, you'll need + to edit src/luaconf.h before building and installing Lua. + The edited file will be the one installed, and + it will be used by any Lua clients that you build, to ensure consistency. + Further customization is available to experts by editing the Lua sources. + +

+ We strongly recommend that you enable dynamic loading in src/luaconf.h. + This is done automatically for all platforms listed above that have + this feature and also for Windows. + +

Building Lua on other systems

+ +

+ If you're not using the usual Unix tools, then the instructions for + building Lua depend on the compiler you use. You'll need to create + projects (or whatever your compiler uses) for building the library, + the interpreter, and the compiler, as follows: + +

+
+library: +
+lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c +lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c +ltm.c lundump.c lvm.c lzio.c +lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c +lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c +
+interpreter: +
+ library, lua.c +
+compiler: +
+ library, luac.c +
+ +

+ To use Lua as a library in your own programs you'll need to know how to + create and use libraries with your compiler. Moreover, to dynamically load + C libraries for Lua you'll need to know how to create dynamic libraries + and you'll need to make sure that the Lua API functions are accessible to + those dynamic libraries — but don't link the Lua library + into each dynamic library. For Unix, we recommend that the Lua library + be linked statically into the host program and its symbols exported for + dynamic linking; src/Makefile does this for the Lua interpreter. + For Windows, we recommend that the Lua library be a DLL. + +

+ As mentioned above, you may edit src/luaconf.h to customize + some features before building Lua. + +

Changes since Lua 5.1

+ +

+Here are the main changes introduced in Lua 5.2. +The +reference manual +lists the +incompatibilities that had to be introduced. + +

Main changes

+
    +
  • yieldable pcall and metamethods +
  • new lexical scheme for globals +
  • ephemeron tables +
  • new library for bitwise operations +
  • light C functions +
  • emergency garbage collector +
  • goto statement +
  • finalizers for tables +
+ +Here are the other changes introduced in Lua 5.2: +

Language

+
    +
  • no more fenv for threads or functions +
  • tables honor the __len metamethod +
  • hex and \z escapes in strings +
  • support for hexadecimal floats +
  • order metamethods work for different types +
  • no more verification of opcode consistency +
  • hook event "tail return" replaced by "tail call" +
  • empty statement +
  • break statement may appear in the middle of a block +
+ +

Libraries

+
    +
  • arguments for function called through xpcall +
  • optional 'mode' argument to load and loadfile (to control binary x text) +
  • optional 'env' argument to load and loadfile (environment for loaded chunk) +
  • loadlib may load libraries with global names (RTLD_GLOBAL) +
  • new function package.searchpath +
  • modules receive their paths when loaded +
  • optional base in math.log +
  • optional separator in string.rep +
  • file:write returns file +
  • closing a pipe returns exit status +
  • os.exit may close state +
  • new metamethods __pairs and __ipairs +
  • new option 'isrunning' for collectgarbage and lua_gc +
  • frontier patterns +
  • \0 in patterns +
  • new option *L for io.read +
  • options for io.lines +
  • debug.getlocal can access function varargs +
+ +

C API

+
    +
  • main thread predefined in the registry +
  • new functions +lua_absindex, +lua_arith, +lua_compare, +lua_copy, +lua_len, +lua_rawgetp, +lua_rawsetp, +lua_upvalueid, +lua_upvaluejoin, +lua_version. +
  • new functions +luaL_checkversion, +luaL_setmetatable, +luaL_testudata, +luaL_tolstring. +
  • lua_pushstring and pushlstring return string +
  • nparams and isvararg available in debug API +
  • new lua_Unsigned +
+ +

Implementation

+
    +
  • max constants per function raised to 226 +
  • generational mode for garbage collection (experimental) +
  • NaN trick (experimental) +
  • internal (immutable) version of ctypes +
  • simpler implementation for string buffers +
  • parser uses much less C-stack space (no more auto arrays) +
+ +

Lua standalone interpreter

+
    +
  • new -E option to avoid environment variables +
  • handling of non-string error messages +
+ +

License

+ +[osi certified] + + +

+Lua is free software distributed under the terms of the +MIT license +reproduced below; +it may be used for any purpose, including commercial purposes, +at absolutely no cost without having to ask us. + +The only requirement is that if you do use Lua, +then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation. + +For details, see +this. + +

+Copyright © 1994–2013 Lua.org, PUC-Rio. + +

+Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +

+The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +

+

+ +


+ +Last update: +Fri Feb 22 09:24:20 BRT 2013 + + + + + diff --git a/radio/src/lua/src/Makefile b/radio/src/lua/src/Makefile new file mode 100644 index 000000000..fea895bc0 --- /dev/null +++ b/radio/src/lua/src/Makefile @@ -0,0 +1,187 @@ +# Makefile for building Lua +# See ../doc/readme.html for installation and customization instructions. + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc +CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) +LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) + +AR= ar rcu +RANLIB= ranlib +RM= rm -f + +SYSCFLAGS= +SYSLDFLAGS= +SYSLIBS= + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= +MYOBJS= + +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ + lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ + ltm.o lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ + lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o +BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o + +ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +# Targets start here. +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(BASE_O) + $(AR) $@ $(BASE_O) + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c + +echo: + @echo "PLAT= $(PLAT)" + @echo "CC= $(CC)" + @echo "CFLAGS= $(CFLAGS)" + @echo "LDFLAGS= $(SYSLDFLAGS)" + @echo "LIBS= $(LIBS)" + @echo "AR= $(AR)" + @echo "RANLIB= $(RANLIB)" + @echo "RM= $(RM)" + +# Convenience targets for popular platforms +ALL= all + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + +aix: + $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" + +ansi: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" + +bsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" + +freebsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" + +generic: $(ALL) + +linux: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" + +macosx: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" + +mingw: + $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" + +solaris: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h ltable.h lundump.h \ + lvm.h +lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h +lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + lstring.h ltable.h lvm.h +lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h +lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h +ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \ + lstring.h ltable.h lundump.h lvm.h +ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \ + lstate.h ltm.h lzio.h lmem.h +lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \ + lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h +lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h +loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lvm.h +lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \ + lstring.h lgc.h ltable.h +lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \ + ltable.h +lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ + ltm.h lzio.h lstring.h lgc.h +lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h +ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ + lmem.h lstring.h lgc.h ltable.h +lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h +lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h +lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h +lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ + lzio.h + diff --git a/radio/src/lua/src/lapi.c b/radio/src/lua/src/lapi.c new file mode 100644 index 000000000..791d85454 --- /dev/null +++ b/radio/src/lua/src/lapi.c @@ -0,0 +1,1284 @@ +/* +** $Id: lapi.c,v 2.171 2013/03/16 21:10:18 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lapi_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + + +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) + +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) + +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) + +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) + +#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") + +#define api_checkstackindex(L, i, o) \ + api_check(L, isstackindex(i, o), "index not in the stack") + + +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; + else return o; + } + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return L->top + idx; + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; + } + } +} + + +/* +** to be called by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res; + CallInfo *ci = L->ci; + lua_lock(L); + if (L->stack_last - L->top > size) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); + } + if (res && ci->top < L->top + size) + ci->top = L->top + size; /* adjust frame top */ + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; +} + + + +/* +** basic stack manipulation +*/ + + +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func + idx); +} + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - (L->ci->func + 1)); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) + setnilvalue(L->top++); + L->top = (func + 1) + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = index2addr(L, idx); + api_checkstackindex(L, idx, p); + while (++p < L->top) setobjs2s(L, p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = index2addr(L, idx); + api_checkstackindex(L, idx, p); + for (q = L->top; q > p; q--) /* use L->top as a temporary */ + setobjs2s(L, q, q - 1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +static void moveto (lua_State *L, TValue *fr, int idx) { + TValue *to = index2addr(L, idx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + lua_lock(L); + api_checknelems(L, 1); + moveto(L, L->top - 1, idx); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr; + lua_lock(L); + fr = index2addr(L, fromidx); + moveto(L, fr, toidx); + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2addr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (isvalid(o) ? ttypenv(o) : LUA_TNONE); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return ttypename(t); +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2addr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; +} + + +LUA_API void lua_arith (lua_State *L, int op) { + StkId o1; /* 1st operand */ + StkId o2; /* 2nd operand */ + lua_lock(L); + if (op != LUA_OPUNM) /* all other operations expect two operands */ + api_checknelems(L, 2); + else { /* for unary minus, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + L->top++; + } + o1 = L->top - 2; + o2 = L->top - 1; + if (ttisnumber(o1) && ttisnumber(o2)) { + setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); + } + else + luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { + StkId o1, o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; +} + + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + if (isnum) *isnum = 1; + return nvalue(o); + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + if (isnum) *isnum = 1; + return res; + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + lua_Unsigned res; + lua_Number num = nvalue(o); + lua_number2unsigned(res, num); + if (isnum) *isnum = 1; + return res; + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2addr(L, idx); + if (!ttisstring(o)) { + lua_lock(L); /* `luaV_tostring' may create a new string */ + if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaC_checkGC(L); + o = index2addr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) *len = tsvalue(o)->len; + return svalue(o); +} + + +LUA_API size_t lua_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttypenv(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttypenv(o)) { + case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttype(o)) { + 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_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + luai_checknum(L, L->top, + luaG_runerror(L, "C API - attempt to push a signaling NaN")); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setnvalue(L->top, cast_num(n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { + lua_Number n; + lua_lock(L); + n = lua_unsigned2number(u); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; + lua_lock(L); + luaC_checkGC(L); + ts = luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + lua_unlock(L); + return getstr(ts); +} + + +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) { + lua_pushnil(L); + return NULL; + } + else { + TString *ts; + lua_lock(L); + luaC_checkGC(L); + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + lua_unlock(L); + return getstr(ts); + } +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + 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); + } + else { + Closure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + luaC_checkGC(L); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top + n); + setclCvalue(L, L->top, cl); + } + api_incr_top(L); + 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 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_getglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_gettable(L, gt, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + setsvalue2s(L, L->top, luaS_new(L, k)); + api_incr_top(L); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; + lua_lock(L); + luaC_checkGC(L); + t = luaH_new(L); + sethvalue(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = index2addr(L, objindex); + switch (ttypenv(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttypenv(obj)]; + break; + } + if (mt == NULL) + res = 0; + else { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2addr(L, idx); + api_check(L, ttisuserdata(o), "userdata expected"); + if (uvalue(o)->env) { + sethvalue(L, L->top, uvalue(o)->env); + } else + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_setglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + api_checknelems(L, 1); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_settable(L, gt, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + StkId t; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + setsvalue2s(L, L->top++, luaS_new(L, k)); + luaV_settable(L, t, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + invalidateTMcache(hvalue(t)); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId t; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + luaH_setint(L, hvalue(t), n, L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top - 1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2addr(L, objindex); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + mt = hvalue(L->top - 1); + } + switch (ttypenv(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrierback(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, rawuvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: { + G(L)->mt[ttypenv(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API void lua_setuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttisuserdata(o), "userdata expected"); + if (ttisnil(L->top - 1)) + uvalue(o)->env = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + uvalue(o)->env = hvalue(L->top - 1); + luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + } + L->top--; + lua_unlock(L); +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + + +LUA_API int lua_getctx (lua_State *L, int *ctx) { + if (L->ci->callstatus & CIST_YIELDED) { + if (ctx) *ctx = L->ci->u.c.ctx; + return L->ci->u.c.status; + } + else return LUA_OK; +} + + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k) { + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults, 1); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_call(L, func, nresults, 0); /* just do the call */ + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults, 0); +} + + + +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2addr(L, errfunc); + api_checkstackindex(L, errfunc, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->extra = savestack(L, c.func); + ci->u.c.old_allowhook = L->allowhook; + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + /* mark that function may do error recovery */ + ci->callstatus |= CIST_YPCALL; + luaD_call(L, c.func, nresults, 1); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname, const char *mode) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues == 1) { /* does it have one upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_barrier(L, f->upvals[0], gt); + } + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, getproto(o), writer, data, 0); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->gcrunning = 0; + break; + } + case LUA_GCRESTART: { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: { + if (g->gckind == KGC_GEN) { /* generational mode? */ + res = (g->GCestimate == 0); /* true if it will do major collection */ + luaC_forcestep(L); /* do a single step */ + } + else { + lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; + if (g->gcrunning) + debt += g->GCdebt; /* include current debt */ + luaE_setdebt(g, debt); + luaC_forcestep(L); + if (g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + } + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETMAJORINC: { + res = g->gcmajorinc; + g->gcmajorinc = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + case LUA_GCGEN: { /* change collector to generational mode */ + luaC_changemode(L, KGC_GEN); + break; + } + case LUA_GCINC: { /* change collector to incremental mode */ + luaC_changemode(L, KGC_NORMAL); + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaC_checkGC(L); + luaV_concat(L, n); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size, NULL); + setuvalue(L, L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val, + GCObject **owner) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = obj2gco(f); + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (owner) *owner = obj2gco(f->upvals[n - 1]); + name = p->upvalues[n-1].name; + return (name == NULL) ? "" : getstr(name); + } + default: return NULL; /* not a closure */ + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ + StkId fi; + lua_lock(L); + fi = index2addr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, owner, L->top); + } + lua_unlock(L); + return name; +} + + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + LClosure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + *up1 = *up2; + luaC_objbarrier(L, f1, *up2); +} + diff --git a/radio/src/lua/src/lapi.h b/radio/src/lua/src/lapi.h new file mode 100644 index 000000000..0909a3911 --- /dev/null +++ b/radio/src/lua/src/lapi.h @@ -0,0 +1,24 @@ +/* +** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "llimits.h" +#include "lstate.h" + +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") + + +#endif diff --git a/radio/src/lua/src/lauxlib.c b/radio/src/lua/src/lauxlib.c new file mode 100644 index 000000000..1c52b82a6 --- /dev/null +++ b/radio/src/lua/src/lauxlib.c @@ -0,0 +1,997 @@ +/* +** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c + +#include "lua.h" + +#include "lauxlib.h" + + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + + +#if defined(USE_FATFS) +int lua__getc(FIL *f) +{ + char c; + UINT result; + if (f_read(f, &c, 1, &result) == FR_OK && result == 1) + return c; + else + return -1; +} +#endif + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushglobaltable(L); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + + +static int countlevels (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +static int typeerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + typeerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + + +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +#if !defined(inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); /* try to get metatable */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { + /* keep some extra space to run error routines, if needed */ + const int extra = LUA_MINSTACK; + if (!lua_checkstack(L, space + extra)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tolstring(L, narg, len); + if (!s) tag_error(L, narg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + int isnum; + lua_Number d = lua_tonumberx(L, narg, &isnum); + if (!isnum) + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, narg, def); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + int isnum; + lua_Integer d = lua_tointegerx(L, narg, &isnum); + if (!isnum) + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { + int isnum; + lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); + if (!isnum) + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); +} + + +LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, + lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, narg, def); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->initb) + + +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); + /* move content to new buffer */ + memcpy(newbuff, B->b, B->n * sizeof(char)); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int n; /* number of pre-read characters */ +#if defined(USE_FATFS) + FIL f; +#else + FILE *f; /* file being read */ +#endif + char buff[LUAL_BUFFERSIZE]; /* area for reading file */ +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ +#if defined(USE_FATFS) + UINT f_read_size; + FRESULT result = f_read(&lf->f, lf->buff, sizeof(lf->buff), &f_read_size); + if (result != FR_OK || f_read_size == 0) return NULL; + *size = f_read_size; +#else + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ +#endif + } + return lf->buff; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ + int c; + lf->n = 0; + do { + c = lua_getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return lua_getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = lua_getc(lf->f); + } while (c != EOF && c != '\n') ; + *cp = lua_getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { +#if defined(USE_FATFS) + return errfile(L, "open", fnameindex); +#else + lua_pushliteral(L, "=stdin"); + lf.f = stdin; +#endif + } + else { + lua_pushfstring(L, "@%s", filename); +#if defined(USE_FATFS) + FRESULT result = f_open(&lf.f, filename, FA_OPEN_EXISTING | FA_READ); + if (result != FR_OK) return errfile(L, "open", fnameindex); +#else + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); +#endif + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ +#if !defined(USE_FATFS) + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } +#endif + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); +#if defined(USE_FATFS) + readstatus = 0; + if (filename) f_close(&lf.f); +#else + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ +#endif + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); +} + + +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + +/* }====================================================== */ + + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = lua_absindex(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API int luaL_len (lua_State *L, int idx) { + int l; + int isnum; + lua_len(L, idx); + l = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not a number"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ + switch (lua_type(L, idx)) { + case LUA_TNUMBER: + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the _LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ + lua_getfield(L, -1, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} + +#endif +/* }====================================================== */ + +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkversion(L); + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + lua_getfield(L, idx, fname); + if (lua_istable(L, -1)) return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** stripped-down 'require'. Calls 'openf' to open a module, +** registers the result in 'package.loaded' table and, if 'glb' +** is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* open module */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_pushvalue(L, -2); /* make copy of module (call result) */ + lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ + lua_pop(L, 1); /* remove _LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of 'mod' */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after `p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { + const lua_Number *v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + diff --git a/radio/src/lua/src/lauxlib.h b/radio/src/lua/src/lauxlib.h new file mode 100644 index 000000000..d66471b0b --- /dev/null +++ b/radio/src/lua/src/lauxlib.h @@ -0,0 +1,215 @@ +/* +** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include + +#include "lua.h" + + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); +LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, + lua_Unsigned def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API int (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { +#if defined(USE_FATFS) + FIL *f; /* stream (NULL for incompletely created streams) */ +#else + FILE *f; /* stream (NULL for incompletely created streams) */ +#endif + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +#endif + + diff --git a/radio/src/lua/src/lbaselib.c b/radio/src/lua/src/lbaselib.c new file mode 100644 index 000000000..a9521e536 --- /dev/null +++ b/radio/src/lua/src/lbaselib.c @@ -0,0 +1,456 @@ +/* +** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include + +#define lbaselib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + size_t l; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tolstring(L, -1, &l); /* get result */ + if (s == NULL) + return luaL_error(L, + LUA_QL("tostring") " must return a string to " LUA_QL("print")); + if (i>1) luai_writestring("\t", 1); + luai_writestring(s, l); + lua_pop(L, 1); /* pop result */ + } + luai_writeline(); + return 0; +} + + +#define SPACECHARS " \f\n\r\t\v" + +static int luaB_tonumber (lua_State *L) { + if (lua_isnoneornil(L, 2)) { /* standard conversion */ + int isnum; + lua_Number n = lua_tonumberx(L, 1, &isnum); + if (isnum) { + lua_pushnumber(L, n); + return 1; + } /* else not a number; must be something */ + luaL_checkany(L, 1); + } + else { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *e = s + l; /* end point for 's' */ + int base = luaL_checkint(L, 2); + int neg = 0; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (isalnum((unsigned char)*s)) { + lua_Number n = 0; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : toupper((unsigned char)*s) - 'A' + 10; + if (digit >= base) break; /* invalid numeral; force a fail */ + n = n * (lua_Number)base + (lua_Number)digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + if (s == e) { /* no invalid trailing characters? */ + lua_pushnumber(L, (neg) ? -n : n); + return 1; + } /* else not a number */ + } /* else not a number */ + } + lua_pushnil(L); /* not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "setmajorinc", "isrunning", "generational", "incremental", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, o, ex); + switch (o) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + lua_pushinteger(L, b); + return 2; + } + case LUA_GCSTEP: case LUA_GCISRUNNING: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushinteger(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, luaL_typename(L, 1)); + return 1; +} + + +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ + luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + return pairsmeta(L, "__pairs", 0, luaB_next); +} + + +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + i++; /* next value */ + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); + return (lua_isnil(L, -1)) ? 1 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + return pairsmeta(L, "__ipairs", 1, ipairsaux); +} + + +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else { /* error (message is on top of the stack) */ + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); +} + + +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** Reader for generic `load' function: `lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)(ud); /* not used */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); +} + + +static int luaB_load (lua_State *L) { + int status; + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); +} + +/* }====================================================== */ + + +static int dofilecont (lua_State *L) { + return lua_gettop(L) - 1; +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L); +} + + +static int luaB_assert (lua_State *L) { + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + int i = luaL_checkint(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - i; + } +} + + +static int finishpcall (lua_State *L, int status) { + if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ + lua_settop(L, 0); /* create space for return values */ + lua_pushboolean(L, 0); + lua_pushstring(L, "stack overflow"); + return 2; /* return false, msg */ + } + lua_pushboolean(L, status); /* first result (status) */ + lua_replace(L, 1); /* put first result in first slot */ + return lua_gettop(L); +} + + +static int pcallcont (lua_State *L) { + int status = lua_getctx(L, NULL); + return finishpcall(L, (status == LUA_YIELD)); +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + lua_pushnil(L); + lua_insert(L, 1); /* create space for status result */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); +} + + +static int luaB_xpcall (lua_State *L) { + int status; + int n = lua_gettop(L); + luaL_argcheck(L, n >= 2, 2, "value expected"); + lua_pushvalue(L, 1); /* exchange function... */ + lua_copy(L, 2, 1); /* ...and error handler */ + lua_replace(L, 2); + status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + {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; +} + diff --git a/radio/src/lua/src/lbitlib.c b/radio/src/lua/src/lbitlib.c new file mode 100644 index 000000000..5910f135d --- /dev/null +++ b/radio/src/lua/src/lbitlib.c @@ -0,0 +1,210 @@ +/* +** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + +typedef lua_Unsigned b_uint; + + + +static b_uint andaux (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = ~(b_uint)0; + for (i = 1; i <= n; i++) + r &= luaL_checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + b_uint r = andaux(L); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + b_uint r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r |= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r ^= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + b_uint r = ~luaL_checkunsigned(L, 1); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, b_uint r, int i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + lua_pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); +} + + +static int b_arshift (lua_State *L) { + b_uint r = luaL_checkunsigned(L, 1); + int i = luaL_checkint(L, 2); + if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ + lua_pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, int i) { + b_uint r = luaL_checkunsigned(L, 1); + i &= (LUA_NBITS - 1); /* i = i % NBITS */ + r = trim(r); + r = (r << i) | (r >> (LUA_NBITS - i)); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkint(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkint(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + int f = luaL_checkint(L, farg); + int w = luaL_optint(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = w; + return f; +} + + +static int b_extract (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + b_uint v = luaL_checkunsigned(L, 2); + int f = fieldargs(L, 3, &w); + int m = mask(w); + v &= m; /* erase bits outside given width */ + r = (r & ~(m << f)) | (v << f); + lua_pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + diff --git a/radio/src/lua/src/lcode.c b/radio/src/lua/src/lcode.c new file mode 100644 index 000000000..56c26ac8a --- /dev/null +++ b/radio/src/lua/src/lcode.c @@ -0,0 +1,881 @@ +/* +** $Id: lcode.c,v 2.62 2012/08/16 17:34:28 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int isnumeral(expdesc *e) { + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + int l = from + n - 1; /* last register to set nil */ + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + + +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { + level++; /* argument is +1 to reserve 0 as non-op */ + while (list != NO_JUMP) { + int next = getjump(fs, list); + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + list = next; + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + + +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.info); +} + + +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + TValue *idx = luaH_set(L, fs->h, key); + Proto *f = fs->f; + int k, oldsize; + if (ttisnumber(idx)) { + lua_Number n = nvalue(idx); + lua_number2int(k, n); + if (luaV_rawequalobj(&f->k[k], v)) + return k; + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); + go through and create a new entry for this value */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setnvalue(idx, cast_num(k)); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + int n; + lua_State *L = fs->ls->L; + TValue o; + setnvalue(&o, r); + if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ + /* use raw representation as key to avoid numeric problems */ + setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); + n = addk(fs, L->top - 1, &o); + L->top--; + } + else + n = addk(fs, &o, &o); /* regular case */ + return n; +} + + +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + + +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->ls->L, &k, fs->h); + return addk(fs, &k, &v); +} + + +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.info = GETARG_A(getcode(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codek(fs, reg, e->u.info); + break; + } + case VKNUM: { + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put value on it */ + return e->u.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.info; +} + + +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ + e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.info); + } + else break; + } + case VKNUM: { + e->u.info = luaK_numberK(fs, e->u.nval); + e->k = VK; + /* go through */ + } + case VK: { + if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ + return RKASK(e->u.info); + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, ex); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); + freeexp(fs, key); +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + invertjump(fs, e); + pc = e->u.info; + break; + } + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + + +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + pc = e->u.info; + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + lua_assert(!hasjumps(t)); + t->u.ind.t = t->u.info; + t->u.ind.idx = luaK_exp2RK(fs, k); + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL + : check_exp(vkisinreg(t->k), VLOCAL); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) + return 0; /* do not attempt to divide by 0 */ + r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; + int o1 = luaK_exp2RK(fs, e1); + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } + else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + luaK_fixline(fs, line); + } +} + + +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, + expdesc *e2) { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (isnumeral(e)) /* minus constant? */ + e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ + else { + luaK_exp2anyreg(fs, e); + codearith(fs, OP_UNM, e, &e2, line); + } + break; + } + case OPR_NOT: codenot(fs, e); break; + case OPR_LEN: { + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2, line); + break; + } + default: lua_assert(0); + } +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, + expdesc *e1, expdesc *e2, int line) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: { + codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); + break; + } + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else if (c <= MAXARG_Ax) { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } + else + luaX_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/radio/src/lua/src/lcode.h b/radio/src/lua/src/lcode.h new file mode 100644 index 000000000..5a1fa9fea --- /dev/null +++ b/radio/src/lua/src/lcode.h @@ -0,0 +1,83 @@ +/* +** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums (ORDER OP) +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/radio/src/lua/src/lcorolib.c b/radio/src/lua/src/lcorolib.c new file mode 100644 index 000000000..e2f601eb6 --- /dev/null +++ b/radio/src/lua/src/lcorolib.c @@ -0,0 +1,154 @@ +/* +** $Id: lcorolib.c,v 1.5 2013/02/21 13:44:53 roberto Exp $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + + +#include + + +#define lcorolib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/radio/src/lua/src/lctype.c b/radio/src/lua/src/lctype.c new file mode 100644 index 000000000..55e433a5d --- /dev/null +++ b/radio/src/lua/src/lctype.c @@ -0,0 +1,52 @@ +/* +** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/radio/src/lua/src/lctype.h b/radio/src/lua/src/lctype.h new file mode 100644 index 000000000..99c7d1223 --- /dev/null +++ b/radio/src/lua/src/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/radio/src/lua/src/ldblib.c b/radio/src/lua/src/ldblib.c new file mode 100644 index 000000000..596d10d30 --- /dev/null +++ b/radio/src/lua/src/ldblib.c @@ -0,0 +1,396 @@ +/* +** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define ldblib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define HOOKKEY "_HKEY" + + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ +} + + +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); + return 1; +} + + +static int db_setuservalue (lua_State *L) { + if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) + luaL_argerror(L, 1, "full userdata expected, got light userdata"); + luaL_checktype(L, 1, LUA_TUSERDATA); + if (!lua_isnoneornil(L, 2)) + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + lua_setuservalue(L, 1); + return 1; +} + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsb (lua_State *L, const char *i, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, i); +} + + +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; + } +} + + +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) { + lua_pushvalue(L, -2); + lua_remove(L, -3); + } + else + lua_xmove(L1, L, 1); + lua_setfield(L, -2, fname); +} + + +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnStu"); + if (lua_isnumber(L, arg+1)) { + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, arg+1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, arg+1); + lua_xmove(L, L1, 1); + } + else + return luaL_argerror(L, arg+1, "function or level expected"); + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_createtable(L, 0, 2); + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) { + settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + int nvar = luaL_checkint(L, arg+2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; + } + else { /* stack-level argument */ + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + name = lua_getlocal(L1, &ar, nvar); + if (name) { + lua_xmove(L1, L, 1); /* push local value */ + lua_pushstring(L, name); /* push name */ + lua_pushvalue(L, -2); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + lua_xmove(L, L1, 1); + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + +static int checkupval (lua_State *L, int argf, int argnup) { + lua_Debug ar; + int nup = luaL_checkint(L, argnup); + luaL_checktype(L, argf, LUA_TFUNCTION); + lua_pushvalue(L, argf); + lua_getinfo(L, ">u", &ar); + luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); + return nup; +} + + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + gethooktable(L); + lua_pushthread(L); + lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } + if (gethooktable(L) == 0) { /* creating hook table? */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + luai_writestringerror("%s", "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) + luai_writestringerror("%s\n", lua_tostring(L, -1)); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +static int db_traceback (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); + return 1; +} + diff --git a/radio/src/lua/src/ldebug.c b/radio/src/lua/src/ldebug.c new file mode 100644 index 000000000..7e04f9d09 --- /dev/null +++ b/radio/src/lua/src/ldebug.c @@ -0,0 +1,580 @@ +/* +** $Id: ldebug.c,v 2.90 2012/08/16 17:34:28 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + + +#define ldebug_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +} + + +static int currentline (CallInfo *ci) { + return getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + int nparams = clLvalue(ci->func)->p->numparams; + if (n >= ci->u.l.base - ci->func - nparams) + return NULL; /* no such vararg */ + else { + *pos = ci->func + nparams + n; + return "(*vararg)"; /* generic name for any vararg */ + } +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + const char *name = NULL; + StkId base; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ + else + return NULL; /* no name */ + } + *pos = base + (n - 1); + return name; +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + lua_lock(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = 0; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = 0; /* to avoid warnings */ + const char *name = findlocal(L, ar->i_ci, n, &pos); + lua_lock(L); + if (name) + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (noLuaClosure(cl)) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (noLuaClosure(f)) { + setnilvalue(L->top); + api_incr_top(L); + } + else { + int i; + TValue v; + int *lineinfo = f->l.p->lineinfo; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ + } +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': { + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = NULL; + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *cl; + CallInfo *ci; + StkId func; + lua_lock(L); + if (*what == '>') { + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else { + ci = ar->i_ci; + func = ci->func; + lua_assert(ttisfunction(ci->func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) { + setobjs2s(L, L->top, func); + api_incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); + + +/* +** find a "name" for the RK value 'c' +*/ +static void kname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) { /* is 'c' a constant? */ + TValue *kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) { /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; + } + /* else no reasonable name found */ + } + else { /* 'c' is a register */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') { /* found a constant name? */ + return; /* 'name' already filled */ + } + /* else no reasonable name found */ + } + *name = "?"; /* no reasonable name found */ +} + + +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + switch (op) { + case OP_LOADNIL: { + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = pc; + break; + } + case OP_TFORCALL: { + if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (reg >= a) setreg = pc; /* affect all registers above base */ + break; + } + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip `lastpc'? */ + if (pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_TEST: { + if (reg == a) setreg = pc; /* jumped code can change 'a' */ + break; + } + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = pc; + break; + } + } + return setreg; +} + + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + TMS tm; + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* all other instructions can call only through metamethods */ + case OP_SELF: + case OP_GETTABUP: + case OP_GETTABLE: tm = TM_INDEX; break; + case OP_SETTABUP: + case OP_SETTABLE: tm = TM_NEWINDEX; break; + case OP_EQ: tm = TM_EQ; break; + case OP_ADD: tm = TM_ADD; break; + case OP_SUB: tm = TM_SUB; break; + case OP_MUL: tm = TM_MUL; break; + case OP_DIV: tm = TM_DIV; break; + case OP_MOD: tm = TM_MOD; break; + case OP_POW: tm = TM_POW; break; + case OP_UNM: tm = TM_UNM; break; + case OP_LEN: tm = TM_LEN; break; + case OP_LT: tm = TM_LT; break; + case OP_LE: tm = TM_LE; break; + case OP_CONCAT: tm = TM_CONCAT; break; + default: + return NULL; /* else no useful name can be found */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; +} + +/* }====================================================== */ + + + +/* +** only ANSI way to check whether a pointer points to an array +** (used only for error messages, so efficiency is not a big concern) +*/ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->u.l.base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + CallInfo *ci = L->ci; + const char *name = NULL; + const char *t = objtypename(o); + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } + if (kind) + luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; + lua_assert(!ttisstring(p1) && !ttisnumber(p2)); + luaG_typeerror(L, p1, "concatenate"); +} + + +l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = objtypename(p1); + const char *t2 = objtypename(p2); + if (t1 == t2) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(ci); + TString *src = ci_func(ci)->p->source; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +l_noret luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + L->top++; + luaD_call(L, L->top - 2, 1, 0); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/radio/src/lua/src/ldebug.h b/radio/src/lua/src/ldebug.h new file mode 100644 index 000000000..fe39556b0 --- /dev/null +++ b/radio/src/lua/src/ldebug.h @@ -0,0 +1,34 @@ +/* +** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) + + +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); + +#endif diff --git a/radio/src/lua/src/ldo.c b/radio/src/lua/src/ldo.c new file mode 100644 index 000000000..aafa3dca2 --- /dev/null +++ b/radio/src/lua/src/ldo.c @@ -0,0 +1,673 @@ +/* +** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By +** default, Lua handles errors with exceptions when compiling as +** C++ code, with _longjmp/_setjmp when asked to use them, and with +** longjmp/setjmp otherwise. +*/ +#if !defined(LUAI_THROW) + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) \ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + +#endif + + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + default: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else { /* thread has no error handler */ + L->status = cast_byte(errcode); /* mark it as dead */ + if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (G(L)->panic) { /* panic function? */ + lua_unlock(L); + G(L)->panic(L); /* call it (last chance to jump out) */ + } + abort(); + } + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls; + struct lua_longjmp lj; + lj.status = LUA_OK; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls; + return lj.status; +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top = (ci->top - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; + } +} + + +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; + correctstack(L, oldstack); +} + + +void luaD_growstack (lua_State *L, int n) { + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } +} + + +static int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L->stack_last); + if (lim < ci->top) lim = ci->top; + } + return cast_int(lim - L->stack) + 1; /* part of stack in use */ +} + + +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; + if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ + goodsize >= L->stacksize) /* would grow instead of shrink? */ + condmovestack(L); /* don't change stack (change only for debugging) */ + else + luaD_reallocstack(L, goodsize); /* shrink it */ +} + + +void luaD_hook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + CallInfo *ci = L->ci; + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } +} + + +static void callhook (lua_State *L, CallInfo *ci) { + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + StkId base, fixed; + lua_assert(actual >= nfixargs); + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; itop++, fixed + i); + setnilvalue(fixed + i); + } + return base; +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ + return func; +} + + + +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) + + +/* +** returns true if function has been executed (C function) +*/ +int luaD_precall (lua_State *L, StkId func, int nresults) { + lua_CFunction f; + CallInfo *ci; + int n; /* number of arguments (Lua) or returns (C) */ + ptrdiff_t funcr = savestack(L, func); + switch (ttype(func)) { + case LUA_TLCF: /* light C function */ + f = fvalue(func); + goto Cfunc; + case LUA_TCCL: { /* C closure */ + f = clCvalue(func)->f; + Cfunc: + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = restorestack(L, funcr); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, L->top - n); + return 1; + } + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + n = cast_int(L->top - func) - 1; /* number of real arguments */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n); + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + ci->top = base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + L->top = ci->top; + luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; + } + default: { /* not a function */ + func = tryfuncTM(L, func); /* retry with 'function' tag method */ + return luaD_precall(L, func, nresults); /* now it must be a function */ + } + } +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci = L->ci; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { + if (L->hookmask & LUA_MASKRET) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->ci = ci = ci->previous; /* back to caller */ + /* move results to correct place */ + for (i = wanted; i != 0 && firstResult < L->top; i--) + setobjs2s(L, res++, firstResult++); + while (i-- > 0) + setnilvalue(res++); + L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + if (!allowyield) L->nny++; + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ + if (!allowyield) L->nny--; + L->nCcalls--; +} + + +static void finishCcall (lua_State *L) { + CallInfo *ci = L->ci; + int n; + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ + L->errfunc = ci->u.c.old_errfunc; + } + /* finish 'lua_callk'/'lua_pcall' */ + adjustresults(L, ci->nresults); + /* call continuation function */ + if (!(ci->callstatus & CIST_STAT)) /* no call status? */ + ci->u.c.status = LUA_YIELD; /* 'default' status */ + lua_assert(ci->u.c.status != LUA_OK); + ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); + lua_lock(L); + api_checknelems(L, n); + /* finish 'luaD_precall' */ + luaD_poscall(L, L->top - n); +} + + +static void unroll (lua_State *L, void *ud) { + UNUSED(ud); + for (;;) { + if (L->ci == &L->base_ci) /* stack is empty? */ + return; /* coroutine finished normally */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L); + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ + } + } +} + + +/* +** check whether thread has a suspended protected call +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = ci->u.c.old_allowhook; + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + ci->callstatus |= CIST_STAT; /* call has error status */ + ci->u.c.status = status; /* (here it is) */ + return 1; /* continue running the coroutine */ +} + + +/* +** signal an error in the call to 'resume', not in the execution of the +** coroutine itself. (Such errors should not be handled by any coroutine +** error handler and should not kill the coroutine.) +*/ +static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { + L->top = firstArg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + luaD_throw(L, -1); /* jump back to 'lua_resume' */ +} + + +/* +** do the work for 'lua_resume' in protected mode +*/ +static void resume (lua_State *L, void *ud) { + int nCcalls = L->nCcalls; + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (nCcalls >= LUAI_MAXCCALLS) + resume_error(L, "C stack overflow", firstArg); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (ci != &L->base_ci) /* not in base level? */ + resume_error(L, "cannot resume non-suspended coroutine", firstArg); + /* coroutine is in base level; start running it */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else if (L->status != LUA_YIELD) + resume_error(L, "cannot resume dead coroutine", firstArg); + else { /* resuming from previous yield */ + L->status = LUA_OK; + ci->func = restorestack(L, ci->extra); + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation? */ + int n; + ci->u.c.status = LUA_YIELD; /* 'default' status */ + ci->callstatus |= CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ + } + unroll(L, NULL); + } + lua_assert(nCcalls == L->nCcalls); +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { + int status; + lua_lock(L); + luai_userstateresume(L, nargs); + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* yield or regular error */ + while (status != LUA_OK && status != LUA_YIELD) { /* error? */ + if (recover(L, status)) /* recover point? */ + status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ + else { /* unrecoverable error */ + L->status = cast_byte(status); /* mark thread as `dead' */ + seterrorobj(L, status, L->top); + L->ci->top = L->top; + break; + } + } + lua_assert(status == L->status); + } + L->nny = 1; /* do not allow yields */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); + lua_unlock(L); + return status; +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { + CallInfo *ci = L->ci; + luai_userstateyield(L, nresults); + lua_lock(L); + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + ci->extra = savestack(L, ci->func); /* save current 'func' */ + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != LUA_OK) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; + L->allowhook = old_allowhooks; + L->nny = old_nny; + luaD_shrinkstack(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; + const char *name; +}; + + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + +static void f_parser (lua_State *L, void *ud) { + int i; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, &p->buff, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); + for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ + UpVal *up = luaF_newupval(L); + cl->l.upvals[i] = up; + luaC_objbarrier(L, cl, up); + } +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { + struct SParser p; + int status; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; + return status; +} + + diff --git a/radio/src/lua/src/ldo.h b/radio/src/lua/src/ldo.h new file mode 100644 index 000000000..27b837d99 --- /dev/null +++ b/radio/src/lua/src/ldo.h @@ -0,0 +1,46 @@ +/* +** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ + luaD_growstack(L, n); else condmovestack(L); + + +#define incr_top(L) {L->top++; luaD_checkstack(L,0);} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, + int allowyield); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); + +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +#endif + diff --git a/radio/src/lua/src/ldump.c b/radio/src/lua/src/ldump.c new file mode 100644 index 000000000..d5e6a47cb --- /dev/null +++ b/radio/src/lua/src/ldump.c @@ -0,0 +1,173 @@ +/* +** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +typedef struct { + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; +} DumpState; + +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status==0) + { + lua_unlock(D->L); + D->status=(*D->writer)(D->L,b,size,D->data); + lua_lock(D->L); + } +} + +static void DumpChar(int y, DumpState* D) +{ + char x=(char)y; + DumpVar(x,D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void* b, int n, size_t size, DumpState* D) +{ + DumpInt(n,D); + DumpMem(b,n,size,D); +} + +static void DumpString(const TString* s, DumpState* D) +{ + if (s==NULL) + { + size_t size=0; + DumpVar(size,D); + } + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size*sizeof(char),D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; ik[i]; + DumpChar(ttypenv(o),D); + switch (ttypenv(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; + default: lua_assert(0); + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; ip[i],D); +} + +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i,n=f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i].instack,D); + DumpChar(f->upvalues[i].idx,D); + } +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + DumpString((D->strip) ? NULL : f->source,D); + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo,n,sizeof(int),D); + n= (D->strip) ? 0 : f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } + n= (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i].name,D); +} + +static void DumpFunction(const Proto* f, DumpState* D) +{ + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpUpvalues(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + lu_byte h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); +} + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) +{ + DumpState D; + D.L=L; + D.writer=w; + D.data=data; + D.strip=strip; + D.status=0; + DumpHeader(&D); + DumpFunction(f,&D); + return D.status; +} diff --git a/radio/src/lua/src/lfunc.c b/radio/src/lua/src/lfunc.c new file mode 100644 index 000000000..c2128405b --- /dev/null +++ b/radio/src/lua/src/lfunc.c @@ -0,0 +1,161 @@ +/* +** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c +#define LUA_CORE + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +Closure *luaF_newCclosure (lua_State *L, int n) { + Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; + c->c.nupvalues = cast_byte(n); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int n) { + Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; + c->l.p = NULL; + c->l.nupvalues = cast_byte(n); + while (n--) c->l.upvals[n] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *uv; + while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { + GCObject *o = obj2gco(p); + lua_assert(p->v != &p->u.value); + lua_assert(!isold(o) || isold(obj2gco(L))); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, o)) /* is it dead? */ + changewhite(o); /* resurrect it */ + return p; + } + pp = &p->next; + } + /* not found: create a new one */ + uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; + uv->v = level; /* current value lives in the stack */ + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + return uv; +} + + +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + global_State *g = G(L); + while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o) && uv->v != &uv->u.value); + L->openupval = uv->next; /* remove from `open' list */ + if (isdead(g, o)) + luaF_freeupval(L, uv); /* free upvalue */ + else { + unlinkupval(uv); /* remove upvalue from 'uvhead' list */ + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ + uv->v = &uv->u.value; /* now current value lives here */ + gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ + g->allgc = o; + luaC_checkupvalcolor(g, uv); + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/radio/src/lua/src/lfunc.h b/radio/src/lua/src/lfunc.h new file mode 100644 index 000000000..e236a717c --- /dev/null +++ b/radio/src/lua/src/lfunc.h @@ -0,0 +1,33 @@ +/* +** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); +LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/radio/src/lua/src/lgc.c b/radio/src/lua/src/lgc.c new file mode 100644 index 000000000..535e988ae --- /dev/null +++ b/radio/src/lua/src/lgc.c @@ -0,0 +1,1213 @@ +/* +** $Id: lgc.c,v 2.140 2013/03/16 21:10:18 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +/* +** cost of sweeping one element (the size of a small object divided +** by some adjust for the sweep speed) +*/ +#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) + +/* maximum number of elements to sweep in each single step */ +#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) + +/* maximum number of finalizers to call in each GC step */ +#define GCFINALIZENUM 4 + + +/* +** macro to adjust 'stepmul': 'stepmul' is actually used like +** 'stepmul / STEPMULADJ' (value chosen by tests) +*/ +#define STEPMULADJ 200 + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + + +/* +** 'makewhite' erases all color bits plus the old bit and then +** sets only the current white bit +*/ +#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) +#define makewhite(g,x) \ + (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) + +#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) +#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) + + +#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) + +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) + + +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) + + +#define markvalue(g,o) { checkconsistency(o); \ + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + +static void reallymarkobject (global_State *g, GCObject *o); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + + +/* +** link table 'h' into list pointed by 'p' +*/ +#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) + + +/* +** if key is not marked, mark its entry as dead (therefore removing it +** from the table) +*/ +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (valiswhite(gkey(n))) + setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ +} + + +/* +** tells whether a key or value can be cleared from a weak +** table. Non-collectable objects are never removed from weak +** tables. Strings behave as `values', so are never removed too. for +** other objects: if really collected, cannot keep them; for objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const TValue *o) { + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) { + markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); +} + + +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. +*/ +void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + lua_assert(g->gcstate != GCSpause); + lua_assert(gch(o)->tt != LUA_TTABLE); + if (keepinvariantout(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. (Current implementation +** only works for tables; access to 'gclist' is not uniform across +** different types.) +*/ +void luaC_barrierback_ (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); + black2gray(o); /* make object gray (again) */ + gco2t(o)->gclist = g->grayagain; + g->grayagain = o; +} + + +/* +** barrier for prototypes. When creating first closure (cache is +** NULL), use a forward barrier; this may be the only closure of the +** prototype (if it is a "regular" function, with a single instance) +** and the prototype may be big, so it is better to avoid traversing +** it again. Otherwise, use a backward barrier, to avoid marking all +** possible instances. +*/ +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { + global_State *g = G(L); + lua_assert(isblack(obj2gco(p))); + if (p->cache == NULL) { /* first time? */ + luaC_objbarrier(L, p, c); + } + else { /* use a backward barrier */ + black2gray(obj2gco(p)); /* make prototype gray (again) */ + p->gclist = g->grayagain; + g->grayagain = obj2gco(p); + } +} + + +/* +** check color (and invariants) for an upvalue that was closed, +** i.e., moved into the 'allgc' list +*/ +void luaC_checkupvalcolor (global_State *g, UpVal *uv) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o)); /* open upvalues are never black */ + if (isgray(o)) { + if (keepinvariant(g)) { + resetoldbit(o); /* see MOVE OLD rule */ + gray2black(o); /* it is being visited now */ + markvalue(g, uv->v); + } + else { + lua_assert(issweepphase(g)); + makewhite(g, o); + } + } +} + + +/* +** create a new collectable object (with given type and size) and link +** it to '*list'. 'offset' tells how many bytes to allocate before the +** object itself (used only by states). +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, + int offset) { + global_State *g = G(L); + char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); + GCObject *o = obj2gco(raw + offset); + if (list == NULL) + list = &g->allgc; /* standard list for collectable objects */ + gch(o)->marked = luaC_white(g); + gch(o)->tt = tt; + gch(o)->next = *list; + *list = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** mark an object. Userdata, strings, and closed upvalues are visited +** and turned black here. Other objects are marked gray and added +** to appropriate list to be visited (and turned black) later. (Open +** upvalues are already linked in 'headuv' list.) +*/ +static void reallymarkobject (global_State *g, GCObject *o) { + lu_mem size; + white2gray(o); + switch (gch(o)->tt) { + case LUA_TSHRSTR: + case LUA_TLNGSTR: { + size = sizestring(gco2ts(o)); + break; /* nothing else to mark; make it black */ + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + markobject(g, mt); + markobject(g, gco2u(o)->env); + size = sizeudata(gco2u(o)); + break; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v != &uv->u.value) /* open? */ + return; /* open upvalues remain gray */ + size = sizeof(UpVal); + break; + } + case LUA_TLCL: { + gco2lcl(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TCCL: { + gco2ccl(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TTABLE: { + linktable(gco2t(o), &g->gray); + return; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + return; + } + default: lua_assert(0); return; + } + gray2black(o); + g->GCmemtrav += size; +} + + +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobject(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static void markbeingfnz (global_State *g) { + GCObject *o; + for (o = g->tobefnz; o != NULL; o = gch(o)->next) { + makewhite(g, o); + reallymarkobject(g, o); + } +} + + +/* +** mark all values stored in marked open upvalues. (See comment in +** 'lstate.h'.) +*/ +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +/* +** mark root set and reset all gray lists, to start a new +** incremental (or full) collection +*/ +static void restartcollection (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (do not + traverse it just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (hasclears) + linktable(h, &g->weak); /* has to be cleared later */ + else /* no white values */ + linktable(h, &g->grayagain); /* no need to clean */ +} + + +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int prop = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + int i; + /* traverse array part (numeric keys are 'strong') */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + prop = 1; /* must propagate again */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + if (prop) + linktable(h, &g->ephemeron); /* have to propagate again */ + else if (hasclears) /* does table have white keys? */ + linktable(h, &g->allweak); /* may have to clean white keys */ + else /* no white keys */ + linktable(h, &g->grayagain); /* no need to clean */ + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } + } +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobject(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + black2gray(obj2gco(h)); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linktable(h, &g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * cast(size_t, sizenode(h)); +} + + +static int traverseproto (global_State *g, Proto *f) { + int i; + if (f->cache && iswhite(obj2gco(f->cache))) + f->cache = NULL; /* allow cache to be collected */ + markobject(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobject(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobject(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobject(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto *) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; +} + + +static lu_mem traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return sizeCclosure(cl->nupvalues); +} + +static lu_mem traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobject(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->upvals[i]); + return sizeLclosure(cl->nupvalues); +} + + +static lu_mem traversestack (global_State *g, lua_State *th) { + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + for (; o < th->top; o++) + markvalue(g, o); + if (g->gcstate == GCSatomic) { /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + } + return sizeof(lua_State) + sizeof(TValue) * th->stacksize; +} + + +/* +** traverse one gray object, turning it to black (except for threads, +** which are always gray). +*/ +static void propagatemark (global_State *g) { + lu_mem size; + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (gch(o)->tt) { + case LUA_TTABLE: { + Table *h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + size = traversetable(g, h); + break; + } + case LUA_TLCL: { + LClosure *cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseLclosure(g, cl); + break; + } + case LUA_TCCL: { + CClosure *cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseCclosure(g, cl); + break; + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; /* remove from 'gray' list */ + th->gclist = g->grayagain; + g->grayagain = o; /* insert into 'grayagain' list */ + black2gray(o); + size = traversestack(g, th); + break; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; /* remove from 'gray' list */ + size = traverseproto(g, p); + break; + } + default: lua_assert(0); return; + } + g->GCmemtrav += size; +} + + +static void propagateall (global_State *g) { + while (g->gray) propagatemark(g); +} + + +static void propagatelist (global_State *g, GCObject *l) { + lua_assert(g->gray == NULL); /* no grays left */ + g->gray = l; + propagateall(g); /* traverse all elements from 'l' */ +} + +/* +** retraverse all gray lists. Because tables may be reinserted in other +** lists when traversed, traverse the original lists to avoid traversing +** twice the same table (which is not wrong, but inefficient) +*/ +static void retraversegrays (global_State *g) { + GCObject *weak = g->weak; /* save original lists */ + GCObject *grayagain = g->grayagain; + GCObject *ephemeron = g->ephemeron; + g->weak = g->grayagain = g->ephemeron = NULL; + propagateall(g); /* traverse main gray list */ + propagatelist(g, grayagain); + propagatelist(g, weak); + propagatelist(g, ephemeron); +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables will return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearkeys (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (gch(o)->tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TLCL: { + luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); + break; + } + case LUA_TCCL: { + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + break; + } + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2t(o)); break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; + case LUA_TSHRSTR: + G(L)->strt.nuse--; + /* go through */ + case LUA_TLNGSTR: { + luaM_freemem(L, o, sizestring(gco2ts(o))); + break; + } + default: lua_assert(0); + } +} + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); + + +/* +** sweep the (open) upvalues of a thread and resize its stack and +** list of call-info structures. +*/ +static void sweepthread (lua_State *L, lua_State *L1) { + if (L1->stack == NULL) return; /* stack not completely built yet */ + sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ + luaE_freeCI(L1); /* free extra CallInfo slots */ + /* should not change the stack during an emergency gc cycle */ + if (G(L)->gckind != KGC_EMERGENCY) + luaD_shrinkstack(L1); +} + + +/* +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead (not alive) object is one marked with the "old" +** (non current) white and not fixed. +** In non-generational mode, change all non-dead objects back to white, +** preparing for next collection cycle. +** In generational mode, keep black objects black, and also mark them as +** old; stop when hitting an old object, as all objects after that +** one will be old too. +** When object is a thread, sweep its list of open upvalues too. +*/ +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + global_State *g = G(L); + int ow = otherwhite(g); + int toclear, toset; /* bits to clear and to set in all live objects */ + int tostop; /* stop sweep when this is true */ + if (isgenerational(g)) { /* generational mode? */ + toclear = ~0; /* clear nothing */ + toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ + tostop = bitmask(OLDBIT); /* do not sweep old generation */ + } + else { /* normal mode */ + toclear = maskcolors; /* clear all color bits + old bit */ + toset = luaC_white(g); /* make object white */ + tostop = 0; /* do not stop */ + } + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; + int marked = gch(curr)->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = gch(curr)->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { + if (testbits(marked, tostop)) + return NULL; /* stop sweeping this list */ + if (gch(curr)->tt == LUA_TTHREAD) + sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ + /* update marks */ + gch(curr)->marked = cast_byte((marked & toclear) | toset); + p = &gch(curr)->next; /* go to next element */ + } + } + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { + GCObject ** old = p; + int i = 0; + do { + i++; + p = sweeplist(L, p, 1); + } while (p == old); + if (n) *n += i; + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ + int hs = g->strt.size / 2; /* half the size of the string table */ + if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ + luaS_resize(L, hs); /* halve its size */ + luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ + } +} + + +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(isfinalized(o)); + g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ + gch(o)->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ + lua_assert(!isold(o)); /* see MOVE OLD rule */ + if (!keepinvariantout(g)) /* not keeping invariant? */ + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_call(L, L->top - 2, 0, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { + global_State *g = G(L); + const TValue *tm; + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error object? */ + const char *msg = (ttisstring(L->top - 1)) + ? svalue(L->top - 1) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } + } +} + + +/* +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) +*/ +static void separatetobefnz (lua_State *L, int all) { + global_State *g = G(L); + GCObject **p = &g->finobj; + GCObject *curr; + GCObject **lastnext = &g->tobefnz; + /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ + while (*lastnext != NULL) + lastnext = &gch(*lastnext)->next; + while ((curr = *p) != NULL) { /* traverse all finalizable objects */ + lua_assert(!isfinalized(curr)); + lua_assert(testbit(gch(curr)->marked, SEPARATED)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &gch(curr)->next; /* don't bother with it */ + else { + l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ + *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ + gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &gch(curr)->next; + } + } +} + + +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ + isfinalized(o) || /* ... or is finalized... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + GCheader *ho = gch(o); + if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ + lua_assert(issweepphase(g)); + g->sweepgc = sweeptolive(L, g->sweepgc, NULL); + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } + *p = ho->next; /* remove 'o' from root list */ + ho->next = g->finobj; /* link it in list 'finobj' */ + g->finobj = o; + l_setbit(ho->marked, SEPARATED); /* mark it as such */ + if (!keepinvariantout(g)) /* not keeping invariant? */ + makewhite(g, o); /* "sweep" object */ + else + resetoldbit(o); /* see MOVE OLD rule */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** set a reasonable "time" to wait before starting a new GC cycle; +** cycle will start when memory use hits threshold +*/ +static void setpause (global_State *g, l_mem estimate) { + l_mem debt, threshold; + estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ + threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * g->gcpause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = -cast(l_mem, threshold - gettotalbytes(g)); + luaE_setdebt(g, debt); +} + + +#define sweepphases \ + (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) + + +/* +** enter first sweep phase (strings) and prepare pointers for other +** sweep phases. The calls to 'sweeptolive' make pointers point to an +** object inside the list (instead of to the header), so that the real +** sweep do not need to skip objects created between "now" and the start +** of the real sweep. +** Returns how many objects it swept. +*/ +static int entersweep (lua_State *L) { + global_State *g = G(L); + int n = 0; + g->gcstate = GCSsweepstring; + lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); + /* prepare to sweep strings, finalizable objects, and regular objects */ + g->sweepstrgc = 0; + g->sweepfin = sweeptolive(L, &g->finobj, &n); + g->sweepgc = sweeptolive(L, &g->allgc, &n); + return n; +} + + +/* +** change GC mode +*/ +void luaC_changemode (lua_State *L, int mode) { + global_State *g = G(L); + if (mode == g->gckind) return; /* nothing to change */ + if (mode == KGC_GEN) { /* change to generational mode */ + /* make sure gray lists are consistent */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + g->GCestimate = gettotalbytes(g); + g->gckind = KGC_GEN; + } + else { /* change to incremental mode */ + /* sweep all objects to turn them back to white + (as white has not changed, nothing extra will be collected) */ + g->gckind = KGC_NORMAL; + entersweep(L); + luaC_runtilstate(L, ~sweepphases); + } +} + + +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L, int propagateerrors) { + global_State *g = G(L); + while (g->tobefnz) { + resetoldbit(g->tobefnz); + GCTM(L, propagateerrors); + } +} + + +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + int i; + separatetobefnz(L, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L, 0); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ + sweepwholelist(L, &g->allgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); + lua_assert(g->strt.nuse == 0); +} + + +static l_mem atomic (lua_State *L) { + global_State *g = G(L); + l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ + GCObject *origweak, *origall; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark basic metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + propagateall(g); /* propagate changes */ + work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ + /* traverse objects caught by write barrier and by 'remarkupvals' */ + retraversegrays(g); + work -= g->GCmemtrav; /* restart counting */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + work += g->GCmemtrav; /* stop counting (objects being finalized) */ + separatetobefnz(L, 0); /* separate objects to be finalized */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate `preserveness' */ + work -= g->GCmemtrav; /* restart counting */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + work += g->GCmemtrav; /* complete counting */ + return work; /* estimate of memory marked by 'atomic' */ +} + + +static lu_mem singlestep (lua_State *L) { + global_State *g = G(L); + switch (g->gcstate) { + case GCSpause: { + /* start to count memory traversed */ + g->GCmemtrav = g->strt.size * sizeof(GCObject*); + lua_assert(!isgenerational(g)); + restartcollection(g); + g->gcstate = GCSpropagate; + return g->GCmemtrav; + } + case GCSpropagate: { + if (g->gray) { + lu_mem oldtrav = g->GCmemtrav; + propagatemark(g); + return g->GCmemtrav - oldtrav; /* memory traversed in this step */ + } + else { /* no more `gray' objects */ + lu_mem work; + int sw; + g->gcstate = GCSatomic; /* finish mark phase */ + g->GCestimate = g->GCmemtrav; /* save what was counted */; + work = atomic(L); /* add what was traversed by 'atomic' */ + g->GCestimate += work; /* estimate of total memory traversed */ + sw = entersweep(L); + return work + sw * GCSWEEPCOST; + } + } + case GCSsweepstring: { + int i; + for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) + sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); + g->sweepstrgc += i; + if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ + g->gcstate = GCSsweepudata; + return i * GCSWEEPCOST; + } + case GCSsweepudata: { + if (g->sweepfin) { + g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; + } + else { + g->gcstate = GCSsweep; + return 0; + } + } + case GCSsweep: { + if (g->sweepgc) { + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; + } + else { + /* sweep main thread */ + GCObject *mt = obj2gco(g->mainthread); + sweeplist(L, &mt, 1); + checkSizes(L); + g->gcstate = GCSpause; /* finish collection */ + return GCSWEEPCOST; + } + } + default: lua_assert(0); return 0; + } +} + + +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { + global_State *g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); +} + + +static void generationalcollection (lua_State *L) { + global_State *g = G(L); + lua_assert(g->gcstate == GCSpropagate); + if (g->GCestimate == 0) { /* signal for another major collection? */ + luaC_fullgc(L, 0); /* perform a full regular collection */ + g->GCestimate = gettotalbytes(g); /* update control */ + } + else { + lu_mem estimate = g->GCestimate; + luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ + g->gcstate = GCSpropagate; /* skip restart */ + if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) + g->GCestimate = 0; /* signal for a major collection */ + else + g->GCestimate = estimate; /* keep estimate from last major coll. */ + + } + setpause(g, gettotalbytes(g)); + lua_assert(g->gcstate == GCSpropagate); +} + + +static void incstep (lua_State *L) { + global_State *g = G(L); + l_mem debt = g->GCdebt; + int stepmul = g->gcstepmul; + if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ + /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + do { /* always perform at least one single step */ + lu_mem work = singlestep(L); /* do some work */ + debt -= work; + } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g, g->GCestimate); /* pause until next cycle */ + else { + debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ + luaE_setdebt(g, debt); + } +} + + +/* +** performs a basic GC step +*/ +void luaC_forcestep (lua_State *L) { + global_State *g = G(L); + int i; + if (isgenerational(g)) generationalcollection(L); + else incstep(L); + /* run a few finalizers (or all of them at the end of a collect cycle) */ + for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) + GCTM(L, 1); /* call one finalizer */ +} + + +/* +** performs a basic GC step only if collector is running +*/ +void luaC_step (lua_State *L) { + global_State *g = G(L); + if (g->gcrunning) luaC_forcestep(L); + else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ +} + + + +/* +** performs a full GC cycle; if "isemergency", does not call +** finalizers (which could change stack positions) +*/ +void luaC_fullgc (lua_State *L, int isemergency) { + global_State *g = G(L); + int origkind = g->gckind; + lua_assert(origkind != KGC_EMERGENCY); + if (isemergency) /* do not run finalizers during emergency GC */ + g->gckind = KGC_EMERGENCY; + else { + g->gckind = KGC_NORMAL; + callallpendingfinalizers(L, 1); + } + if (keepinvariant(g)) { /* may there be some black objects? */ + /* must sweep all objects to turn them back to white + (as white has not changed, nothing will be collected) */ + entersweep(L); + } + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ + luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ + if (origkind == KGC_GEN) { /* generational mode? */ + /* generational mode must be kept in propagate phase */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + } + g->gckind = origkind; + setpause(g, gettotalbytes(g)); + if (!isemergency) /* do not run finalizers during emergency GC */ + callallpendingfinalizers(L, 1); +} + +/* }====================================================== */ + + diff --git a/radio/src/lua/src/lgc.h b/radio/src/lua/src/lgc.h new file mode 100644 index 000000000..dee270b4d --- /dev/null +++ b/radio/src/lua/src/lgc.h @@ -0,0 +1,157 @@ +/* +** $Id: lgc.h,v 2.58 2012/09/11 12:53:08 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ + + + +/* how much to allocate before next GC step */ +#if !defined(GCSTEPSIZE) +/* ~100 small strings */ +#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) +#endif + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpropagate 0 +#define GCSatomic 1 +#define GCSsweepstring 2 +#define GCSsweepudata 3 +#define GCSsweep 4 +#define GCSpause 5 + + +#define issweepphase(g) \ + (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) + +#define isgenerational(g) ((g)->gckind == KGC_GEN) + +/* +** macros to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a non-generational collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. During a generational collection, the +** invariant must be kept all times. +*/ + +#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) + + +/* +** Outside the collector, the state in generational mode is kept in +** 'propagate', so 'keepinvariant' is always true. +*/ +#define keepinvariantout(g) \ + check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ + g->gcstate <= GCSatomic) + + +/* +** some useful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) + + +/* Layout for bit use in `marked' field: */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been separated for finalization */ +#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ +#define FIXEDBIT 5 /* object is fixed (should not be collected) */ +#define OLDBIT 6 /* object is old (only in generational mode) */ +/* bit 7 is currently used by tests (luaL_checkmemory) */ + +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) testbits((x)->gch.marked, WHITEBITS) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) + +#define isold(x) testbit((x)->gch.marked, OLDBIT) + +/* MOVE OLD rule: whenever an object is moved to the beginning of + a GC list, its old bit must be cleared */ +#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) + +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +#define luaC_condGC(L,c) \ + {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} +#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierback_(L,p); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarrierback(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } + +#define luaC_barrierproto(L,p,c) \ + { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } + +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_forcestep (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, + GCObject **list, int offset); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); +LUAI_FUNC void luaC_changemode (lua_State *L, int mode); + +#endif diff --git a/radio/src/lua/src/linit.c b/radio/src/lua/src/linit.c new file mode 100644 index 000000000..58e8c1dd9 --- /dev/null +++ b/radio/src/lua/src/linit.c @@ -0,0 +1,66 @@ +/* +** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $ +** Initialization of libraries for lua.c and other clients +** See Copyright Notice in lua.h +*/ + + +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +*/ + + +#define linit_c + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {"_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_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +/* +** these libs are preloaded and must be required before used +*/ +static const luaL_Reg preloadedlibs[] = { + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib; + /* call open functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } + /* add open functions from 'preloadedlibs' into 'package.preload' table */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); + for (lib = preloadedlibs; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); + } + lua_pop(L, 1); /* remove _PRELOAD table */ +} + diff --git a/radio/src/lua/src/liolib.c b/radio/src/lua/src/liolib.c new file mode 100644 index 000000000..8d61394da --- /dev/null +++ b/radio/src/lua/src/liolib.c @@ -0,0 +1,663 @@ +/* +** $Id: liolib.c,v 2.111 2013/03/21 13:57:27 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +/* +** POSIX idiosyncrasy! +** This definition must come before the inclusion of 'stdio.h'; it +** should not affect non-POSIX systems +*/ +#if !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif + + +#include +#include +#include + +#define liolib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if !defined(lua_checkmode) + +/* +** Check whether 'mode' matches '[rwa]%+?b?'. +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#define lua_checkmode(mode) \ + (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ + (*mode != '+' || ++mode) && /* skip if char is '+' */ \ + (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ + (*mode == '\0')) + +#endif + +/* +** {====================================================== +** lua_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(lua_popen) /* { */ + +#if defined(LUA_USE_POPEN) /* { */ + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, pclose(file)) + +#elif defined(LUA_WIN) /* }{ */ + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, _pclose(file)) + + +#else /* }{ */ + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), -1) + + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +/* +** {====================================================== +** lua_fseek/lua_ftell: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(lua_fseek) /* { */ + +#if defined(LUA_USE_POSIX) + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) +/* Windows (but not DDK) and Visual C++ 2005 or higher */ + +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else + +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif + +#endif /* } */ + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) + + +static int io_type (lua_State *L) { + LStream *p; + luaL_checkany(L, 1); + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + lua_pushnil(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + +static FILE *tofile (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; +} + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; +} + + +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); +} + + +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; +} + + +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, lua_pclose(L, p->f)); +} + + +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newprefile(L); + p->f = lua_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); + return p->f; +} + + +static int g_iofile (lua_State *L, const char *f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int toclose) { + int i; + int n = lua_gettop(L) - 1; /* number of arguments to read */ + /* ensure that arguments will fit here and into 'io_readline' stack */ + luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); + lua_pushvalue(L, 1); /* file handle */ + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ + lua_pushcclosure(L, io_readline, 3 + n); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else { /* open a new file */ + const char *filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); + return 1; +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = lua_getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f, int chop) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_rawlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +#define MAX_SIZE_T (~(size_t)0) + +static void read_all (lua_State *L, FILE *f) { + size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + char *p = luaL_prepbuffsize(&b, rlen); + size_t nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + if (nr < rlen) break; /* eof? */ + else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ + rlen *= 2; /* double buffer size at each iteration */ + } + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f, 1); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return luaL_fileresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (!lua_isnil(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - arg; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + lua_Number p3 = luaL_optnumber(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Number)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (op) + return luaL_fileresult(L, 0, NULL); /* error */ + else { + lua_pushnumber(L, (lua_Number)l_ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return luaL_fileresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +} + + +/* +** functions for 'io' library +*/ +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +/* +** methods for file handles +*/ +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ +} + + +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; +} + diff --git a/radio/src/lua/src/llex.c b/radio/src/lua/src/llex.c new file mode 100644 index 000000000..1a32e348b --- /dev/null +++ b/radio/src/lua/src/llex.c @@ -0,0 +1,527 @@ +/* +** $Id: llex.c,v 2.63 2013/03/16 21:10:18 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "lctype.h" +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", "::", "", + "", "", "" +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static l_noret lexerror (LexState *ls, const char *msg, int token); + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZET/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.extra = cast_byte(i+1); /* reserved word */ + } +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + lua_assert(token == cast(unsigned char, token)); + return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : + luaO_pushfstring(ls->L, "char(%d)", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, LUA_QS, s); + else /* names, strings, and numerals */ + return s; + } +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + + +static l_noret lexerror (LexState *ls, const char *msg, int token) { + char buff[LUA_IDSIZE]; + luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); +} + + +/* +** creates a new string and anchors it in function's table so that +** it will not be collected until the end of the function's compilation +** (by that time it should be anchored in function's prototype) +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TValue *o; /* entry for `str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->fs->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? (see 'addK') */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + L->top--; /* remove string from stack */ + return ts; +} + + +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + luaX_syntaxerror(ls, "chunk has too many lines"); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->decpoint = '.'; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_new(L, LUA_ENV); /* create env name */ + luaS_fix(ls->envn); /* never collect this name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (ls->current == '\0' || !strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +/* +** change all characters 'from' in buffer to 'to' +*/ +static void buffreplace (LexState *ls, char from, char to) { + size_t n = luaZ_bufflen(ls->buff); + char *p = luaZ_buffer(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + + +#if !defined(getlocaledecpoint) +#define getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + + +#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) + +/* +** in case of format error, try to change decimal point separator to +** the one defined in the current locale and check again +*/ +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + char old = ls->decpoint; + ls->decpoint = getlocaledecpoint(); + buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ + if (!buff2d(ls->buff, &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +/* +** this function is quite liberal in what it accepts, as 'luaO_str2d' +** will reject ill-formed numerals. +*/ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next(ls, expo)) /* exponent part? */ + check_next(ls, "+-"); /* optional exponent sign */ + if (lisxdigit(ls->current) || ls->current == '.') + save_and_next(ls); + else break; + } + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +/* +** skip a sequence '[=*[' or ']=*]' and return its number of '='s or +** -1 if sequence is malformed +*/ +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ + goto endloop; + } + break; + } + case '\n': case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void escerror (LexState *ls, int *c, int n, const char *msg) { + int i; + luaZ_resetbuffer(ls->buff); /* prepare error message */ + save(ls, '\\'); + for (i = 0; i < n && c[i] != EOZ; i++) + save(ls, c[i]); + lexerror(ls, msg, TK_STRING); +} + + +static int readhexaesc (LexState *ls) { + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ + c[i] = next(ls); + if (!lisxdigit(c[i])) + escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + luaO_hexavalue(c[i]); + } + return r; +} + + +static int readdecesc (LexState *ls) { + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10*r + c[i] - '0'; + next(ls); + } + if (r > UCHAR_MAX) + escerror(ls, c, i, "decimal escape too large"); + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); + } + goto no_save; + } + default: { + if (!lisdigit(ls->current)) + escerror(ls, &ls->current, 1, "invalid escape sequence"); + /* digital escape \ddd */ + c = readdecesc(ls); + goto only_save; + } + } + read_save: next(ls); /* read next character */ + only_save: save(ls, c); /* save 'c' */ + no_save: break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') return '='; + else { next(ls); return TK_EQ; } + } + case '<': { + next(ls); + if (ls->current != '=') return '<'; + else { next(ls); return TK_LE; } + } + case '>': { + next(ls); + if (ls->current != '=') return '>'; + else { next(ls); return TK_GE; } + } + case '~': { + next(ls); + if (ls->current != '=') return '~'; + else { next(ls); return TK_NE; } + } + case ':': { + next(ls); + if (ls->current != ':') return ':'; + else { next(ls); return TK_DBCOLON; } + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + /* else go through */ + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + case EOZ: { + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->tsv.extra - 1 + FIRST_RESERVED; + else { + return TK_NAME; + } + } + else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +int luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/radio/src/lua/src/llex.h b/radio/src/lua/src/llex.h new file mode 100644 index 000000000..9ca8a2994 --- /dev/null +++ b/radio/src/lua/src/llex.h @@ -0,0 +1,78 @@ +/* +** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, + TK_NUMBER, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +/* state of the lexer plus state of the parser when shared by all + functions */ +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* current function (parser) */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ + TString *source; /* current source name */ + TString *envn; /* environment variable name */ + char decpoint; /* locale decimal point */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source, int firstchar); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/radio/src/lua/src/llimits.h b/radio/src/lua/src/llimits.h new file mode 100644 index 000000000..1b8c79bda --- /dev/null +++ b/radio/src/lua/src/llimits.h @@ -0,0 +1,309 @@ +/* +** $Id: llimits.h,v 1.103 2013/02/20 14:08:56 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +typedef unsigned LUA_INT32 lu_int32; + +typedef LUAI_UMEM lu_mem; + +typedef LUAI_MEM l_mem; + + + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) + +#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((unsigned int)(lu_mem)(p)) + + + +/* type to ensure maximum alignment */ +#if !defined(LUAI_USER_ALIGNMENT_T) +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#endif + +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; + + +/* result of a `usual argument conversion' over lua_Number */ +typedef LUAI_UACNUMBER l_uacNumber; + + +/* internal assertions for in-house debugging */ +#if defined(lua_assert) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) { if (!(c)) lua_assert(0); } +#else +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) +#endif + +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) + +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,e) assert(e) +#else +#define luai_apicheck(L,e) lua_assert(e) +#endif + +#endif + +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#define cast(t, exp) ((t)(exp)) + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + + + +/* +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in an unsigned char.) +*/ +#define MAXUPVAL UCHAR_MAX + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef lu_int32 Instruction; + + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + + +/* minimum size for the string table (must be power of 2) */ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + + +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions on threads when you defined +** LUAI_EXTRASPACE and need to do something extra when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + +/* +** lua_number2int is a macro to convert lua_Number to int. +** lua_number2integer is a macro to convert lua_Number to lua_Integer. +** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. +** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. +** luai_hashnum is a macro to hash a lua_Number value into an integer. +** The hash must be deterministic and give reasonable values for +** both small and large values (outside the range of integers). +*/ + +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} +#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with + a 32-bit int type */ + +union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#else +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } + +#define luai_hashnum(i,n) \ + { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ + (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ + +#define lua_number2int(i,n) lua_number2int32(i, n, int) +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +/* the trick can be expanded to lua_Integer when it is a 32-bit value */ +#if defined(LUA_IEEELL) +#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) +#endif + +#endif /* } */ + + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2int) +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + +#if !defined(lua_number2integer) +#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) +#endif + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, + so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + + + +#if defined(ltable_c) && !defined(luai_hashnum) + +#include +#include + +#define luai_hashnum(i,n) { int e; \ + n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ + lua_number2int(i, n); i += e; } + +#endif + + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L) condmovestack(L) +#else +#define condchangemem(L) \ + ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) +#endif + +#endif diff --git a/radio/src/lua/src/lmathlib.c b/radio/src/lua/src/lmathlib.c new file mode 100644 index 000000000..20292d720 --- /dev/null +++ b/radio/src/lua/src/lmathlib.c @@ -0,0 +1,278 @@ +/* +** $Id: lmathlib.c,v 1.83 2013/03/07 18:21:32 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI ((lua_Number)(3.1415926535897932384626433832795)) +#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + lua_Number ip; + lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); + if (base == (lua_Number)10.0) res = l_mathop(log10)(x); + else res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; +} + +#if defined(LUA_COMPAT_LOG10) +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} +#endif + +static int math_exp (lua_State *L) { + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = luaL_checkint(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + lua_Number u = luaL_checknumber(L, 1); + luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); + lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ + break; + } + case 2: { /* lower and upper limits */ + lua_Number l = luaL_checknumber(L, 1); + lua_Number u = luaL_checknumber(L, 2); + luaL_argcheck(L, l <= u, 2, "interval is empty"); + lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkunsigned(L, 1)); + (void)rand(); /* discard first value to avoid undesirable correlations */ + return 0; +} + + +static 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}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, +#if defined(LUA_COMPAT_LOG10) + {"log10", math_log10}, +#endif + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, + {NULL, NULL} +}; + + +/* +** 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; +} + diff --git a/radio/src/lua/src/lmem.c b/radio/src/lua/src/lmem.c new file mode 100644 index 000000000..83d2349ee --- /dev/null +++ b/radio/src/lua/src/lmem.c @@ -0,0 +1,98 @@ +/* +** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#define lmem_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no +** matter 'x'). +** +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL); +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *what) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +l_noret luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; + global_State *g = G(L); + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); +#if defined(HARDMEMTESTS) + if (nsize > realosize && g->gcrunning) + luaC_fullgc(L, 1); /* force a GC whenever possible */ +#endif + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + api_check(L, nsize > realosize, + "realloc cannot fail when shrinking a block"); + if (g->gcrunning) { + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; + return newblock; +} + diff --git a/radio/src/lua/src/lmem.h b/radio/src/lua/src/lmem.h new file mode 100644 index 000000000..5f850999a --- /dev/null +++ b/radio/src/lua/src/lmem.h @@ -0,0 +1,57 @@ +/* +** $Id: lmem.h,v 1.40 2013/02/20 14:08:21 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + + +/* +** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is +** always constant. +** The macro is somewhat complex to avoid warnings: +** +1 avoids warnings of "comparison has constant result"; +** cast to 'void' avoids warnings of "value unused". +*/ +#define luaM_reallocv(L,b,on,n,e) \ + (cast(void, \ + (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) + +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + +LUAI_FUNC l_noret luaM_toobig (lua_State *L); + +/* not to be called directly */ +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *what); + +#endif + diff --git a/radio/src/lua/src/loadlib.c b/radio/src/lua/src/loadlib.c new file mode 100644 index 000000000..3849a7859 --- /dev/null +++ b/radio/src/lua/src/loadlib.c @@ -0,0 +1,731 @@ +/* +** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. +*/ + + +/* +** if needed, includes windows header before everything else +*/ +#if defined(_WIN32) +#include +#endif + + +#include +#include + + +#define loadlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** LUA_PATH and LUA_CPATH are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH) +#define LUA_PATH "LUA_PATH" +#endif + +#if !defined(LUA_CPATH) +#define LUA_CPATH "LUA_CPATH" +#endif + +#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + +#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX +#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_PATH_SEP) +#define LUA_PATH_SEP ";" +#endif +#if !defined (LUA_PATH_MARK) +#define LUA_PATH_MARK "?" +#endif +#if !defined (LUA_EXEC_DIR) +#define LUA_EXEC_DIR "!" +#endif +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +/* table (in the registry) that keeps handles for all loaded C libraries */ +#define CLIBS "_CLIBS" + +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +/* +** system-dependent functions +*/ +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path, int seeglb); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_USE_DLOPEN) +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +static void ll_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *ll_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#undef setprogdir + +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); +} + + +static void *ll_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + +#else +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void ll_unloadlib (void *lib) { + (void)(lib); /* not used */ +} + + +static void *ll_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + +static void *ll_checkclib (lua_State *L, const char *path) { + void *plib; + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; +} + + +static void ll_addtoclib (lua_State *L, const char *path, void *plib) { + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib +** handles in list CLIBS +*/ +static int gctm (lua_State *L) { + int n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + ll_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void *reg = ll_checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = ll_load(L, path, *sym == '*'); + if (reg == NULL) return ERRLIB; /* unable to load library */ + ll_addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else { + lua_CFunction f = ll_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { +#if defined(USE_FATFS) + FIL f; + FRESULT result = f_open(&f, filename, FA_OPEN_EXISTING | FA_READ); + if (result != FR_OK) return 0; + f_close(&f); +#else + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); +#endif + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename = luaL_gsub(L, lua_tostring(L, -1), + LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_remove(L, -2); /* remove file name */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ + } + luaL_pushresult(&msg); /* create error message */ + return NULL; /* not found */ +} + + +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module " LUA_QS + " from file " LUA_QS ":\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int searcher_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +} + + +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *funcname; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + funcname = lua_pushlstring(L, modname, mark - modname); + funcname = lua_pushfstring(L, LUA_POF"%s", funcname); + stat = ll_loadfunc(L, filename, funcname); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + funcname = lua_pushfstring(L, LUA_POF"%s", modname); + return ll_loadfunc(L, filename, funcname); +} + + +static int searcher_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); +} + + +static int searcher_Croot (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; +} + + +static int searcher_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ + if (!lua_istable(L, 3)) + luaL_error(L, LUA_QL("package.searchers") " must be a table"); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + lua_rawgeti(L, 3, i); /* get a searcher */ + if (lua_isnil(L, -1)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_isnil(L, -1)) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +/* +** changes the environment variable of calling function +*/ +static void set_env (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, LUA_QL("module") " not called from a Lua function"); + lua_pushvalue(L, -2); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module table */ + /* check whether table already has a _NAME field */ + lua_getfield(L, -1, "_NAME"); + if (!lua_isnil(L, -1)) /* is table an initialized module? */ + lua_pop(L, 1); + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + set_env(L); + dooptions(L, lastarg); + return 1; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushglobaltable(L); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + +#endif +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +static void setpath (lua_State *L, const char *fieldname, const char *envname1, + const char *envname2, const char *def) { + const char *path = getenv(envname1); + if (path == NULL) /* no environment variable? */ + path = getenv(envname2); /* try alternative name */ + if (path == NULL || noenv(L)) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) + {"seeall", ll_seeall}, +#endif + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) + {"module", ll_module}, +#endif + {"require", ll_require}, + {NULL, NULL} +}; + + +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with pre-defined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i+1); + } +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + /* create table CLIBS to keep track of loaded C libraries */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); + lua_createtable(L, 0, 1); /* metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + /* create `package' table */ + luaL_newlib(L, pk_funcs); + createsearcherstable(L); +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ + /* set field 'path' */ + setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); + /* set field 'cpath' */ + setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ +} + diff --git a/radio/src/lua/src/lobject.c b/radio/src/lua/src/lobject.c new file mode 100644 index 000000000..51eb7f0b9 --- /dev/null +++ b/radio/src/lua/src/lobject.c @@ -0,0 +1,287 @@ +/* +** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= 0x10) { + x = (x+1) >> 1; + e++; + } + return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 0x1f; + if (e == 0) return x; + else return ((x & 7) + 8) << (e - 1); +} + + +int luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = 0; + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(NULL, v1, v2); + case LUA_OPSUB: return luai_numsub(NULL, v1, v2); + case LUA_OPMUL: return luai_nummul(NULL, v1, v2); + case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); + case LUA_OPMOD: return luai_nummod(NULL, v1, v2); + case LUA_OPPOW: return luai_numpow(NULL, v1, v2); + case LUA_OPUNM: return luai_numunm(NULL, v1); + default: lua_assert(0); return 0; + } +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return ltolower(c) - 'a' + 10; +} + + +#if !defined(lua_strx2number) + +#include + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + +static lua_Number readhexa (const char **s, lua_Number r, int *count) { + for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ + r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); + (*count)++; + } + return r; +} + + +/* +** convert an hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + lua_Number r = 0.0; + int e = 0, i = 0; + int neg = 0; /* 1 if number is negative */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + s += 2; /* skip '0x' */ + r = readhexa(&s, r, &i); /* read integer part */ + if (*s == '.') { + s++; /* skip dot */ + r = readhexa(&s, r, &e); /* read fractional part */ + } + if (i == 0 && e == 0) + return 0.0; /* invalid format (no digit) */ + e *= -4; /* each fractional digit divides value by 2^-4 */ + *endptr = cast(char *, s); /* valid up to here */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; + int neg1; + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + goto ret; /* must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + } + *endptr = cast(char *, s); /* valid up to here */ + ret: + if (neg) r = -r; + return l_mathop(ldexp)(r, e); +} + +#endif + + +int luaO_str2d (const char *s, size_t len, lua_Number *result) { + char *endptr; + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ + *result = lua_strx2number(s, &endptr); + else + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* nothing recognized */ + while (lisspace(cast_uchar(*endptr))) endptr++; + return (endptr == s + len); /* OK if no trailing characters */ +} + + + +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); +} + + +/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 0; + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + luaD_checkstack(L, 2); /* fmt + item */ + pushstr(L, fmt, e - fmt); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s, strlen(s)); + break; + } + case 'c': { + char buff; + buff = cast(char, va_arg(argp, int)); + pushstr(L, &buff, 1); + break; + } + case 'd': { + setnvalue(L->top++, cast_num(va_arg(argp, int))); + break; + } + case 'f': { + setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + int l = sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff, l); + break; + } + case '%': { + pushstr(L, "%", 1); + break; + } + default: { + luaG_runerror(L, + "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), + *(e + 1)); + } + } + n += 2; + fmt = e+2; + } + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + diff --git a/radio/src/lua/src/lobject.h b/radio/src/lua/src/lobject.h new file mode 100644 index 000000000..dd23b9143 --- /dev/null +++ b/radio/src/lua/src/lobject.h @@ -0,0 +1,607 @@ +/* +** $Id: lobject.h,v 2.71 2012/09/11 18:21:44 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO LUA_NUMTAGS +#define LUA_TUPVAL (LUA_NUMTAGS+1) +#define LUA_TDEADKEY (LUA_NUMTAGS+2) + +/* +** number of all possible tags (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTAGS (LUA_TUPVAL+2) + + +/* +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* value) +** bits 4-5: variant bits +** bit 6: whether value is collectable +*/ + +#define VARBITS (3 << 4) + + +/* +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Variant tags for strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + +/* +** Union of all Lua values +*/ +typedef union Value Value; + + +#define numfield lua_Number n; /* numbers */ + + + +/* +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. +*/ + +#define TValuefields Value value_; int tt_ + +typedef struct lua_TValue TValue; + + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) +#define num_(o) (val_(o).n) + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttype(o) (rttype(o) & 0x3F) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttypenv(o) (novariant(rttype(o))) + + +/* Macros to test type */ +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttypenv(o) == (t)) +#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) + +#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) + +/* Macros to access values */ +#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 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) +#define uvalue(o) (&rawuvalue(o)->uv) +#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 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) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + + +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* Macros for internal tests */ +#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) + +#define checkliveness(g,obj) \ + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && !isdead(g,gcvalue(obj)))) + + +/* Macros to set values */ +#define settt_(o,t) ((o)->tt_=(t)) + +#define setnvalue(obj,x) \ + { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(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 setbvalue(obj,x) \ + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io=(obj); GCObject *i_g=(x); \ + val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } + +#define setsvalue(L,obj,x) \ + { TValue *io=(obj); \ + TString *x_ = (x); \ + val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ + checkliveness(G(L),io); } + +#define setuvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(G(L),io); } + +#define setthvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ + checkliveness(G(L),io); } + +#define setclLvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(G(L),io); } + +#define setclCvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(G(L),io); } + +#define sethvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ + checkliveness(G(L),io); } + +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) + + + +#define setobj(L,obj1,obj2) \ + { const TValue *io2=(obj2); TValue *io1=(obj1); \ + io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + checkliveness(G(L),io1); } + + +/* +** different types of assignments, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + + +/* check whether a number is valid (useful only for NaN trick) */ +#define luai_checknum(L,o,c) { /* empty */ } + + +/* +** {====================================================== +** NaN Trick +** ======================================================= +*/ +#if defined(LUA_NANTRICK) + +/* +** numbers are represented in the 'd_' field. All other values have the +** value (NNMARK | tag) in 'tt__'. A number with such pattern would be +** a "signaled NaN", which is never generated by regular operations by +** the CPU (nor by 'strtod') +*/ + +/* allows for external implementation for part of the trick */ +#if !defined(NNMARK) /* { */ + + +#if !defined(LUA_IEEEENDIAN) +#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' +#endif + + +#define NNMARK 0x7FF7A500 +#define NNMASK 0x7FFFFF00 + +#undef TValuefields +#undef NILCONSTANT + +#if (LUA_IEEEENDIAN == 0) /* { */ + +/* little endian */ +#define TValuefields \ + union { struct { Value v__; int tt__; } i; double d__; } u +#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#else /* }{ */ + +/* big endian */ +#define TValuefields \ + union { struct { int tt__; Value v__; } i; double d__; } u +#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#endif /* } */ + +#endif /* } */ + + +/* correspondence with standard representation */ +#undef val_ +#define val_(o) v_(o) +#undef num_ +#define num_(o) d_(o) + + +#undef numfield +#define numfield /* no such field; numbers are the entire struct */ + +/* basic check to distinguish numbers from non-numbers */ +#undef ttisnumber +#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) + +#define tag2tt(t) (NNMARK | (t)) + +#undef rttype +#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) + +#undef settt_ +#define settt_(o,t) (tt_(o) = tag2tt(t)) + +#undef setnvalue +#define setnvalue(obj,x) \ + { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } + +#undef setobj +#define setobj(L,obj1,obj2) \ + { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ + o1_->u = o2_->u; \ + checkliveness(G(L),o1_); } + + +/* +** these redefinitions are not mandatory, but these forms are more efficient +*/ + +#undef checktag +#undef checktype +#define checktag(o,t) (tt_(o) == tag2tt(t)) +#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) + +#undef ttisequal +#define ttisequal(o1,o2) \ + (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) + + +#undef luai_checknum +#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } + +#endif +/* }====================================================== */ + + + +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + + +union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + numfield /* numbers */ +}; + + +struct lua_TValue { + TValuefields; +}; + + +typedef TValue *StkId; /* index to stack elements */ + + + + +/* +** Header for string value; string bytes follow the end of this structure +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + unsigned int hash; + size_t len; /* number of characters in string */ + } tsv; +} TString; + + +/* get the actual string (array of bytes) from a TString */ +#define getstr(ts) cast(const char *, (ts) + 1) + +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(rawtsvalue(o)) + + +/* +** Header for userdata; memory area follows the end of this structure +*/ +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; /* number of bytes */ + } uv; +} Udata; + + + +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +} Upvaldesc; + + +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TValue *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ + Upvaldesc *upvalues; /* upvalue information */ + union Closure *cache; /* last created closure with this prototype */ + TString *source; /* used for debug information */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte numparams; /* number of fixed parameters */ + lu_byte is_vararg; + lu_byte maxstacksize; /* maximum stack used by this function */ +} Proto; + + + +/* +** Lua Upvalues +*/ +typedef struct UpVal { + CommonHeader; + TValue *v; /* points to stack or to its own value */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; /* list of upvalues */ +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; /* list of upvalues */ +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + struct Node *next; /* for chaining */ + } nk; + TValue tvk; +} TKey; + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + +/* +** (address of) a fixed nil value +*/ +#define luaO_nilobject (&luaO_nilobject_) + + +LUAI_DDEC const TValue luaO_nilobject_; + + +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_ceillog2 (unsigned int x); +LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); +LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); +LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/radio/src/lua/src/lopcodes.c b/radio/src/lua/src/lopcodes.c new file mode 100644 index 000000000..ef7369275 --- /dev/null +++ b/radio/src/lua/src/lopcodes.c @@ -0,0 +1,107 @@ +/* +** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADKX", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETTABUP", + "GETTABLE", + "SETTABUP", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "EXTRAARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ +}; + diff --git a/radio/src/lua/src/lopcodes.h b/radio/src/lua/src/lopcodes.h new file mode 100644 index 000000000..07d2b3f39 --- /dev/null +++ b/radio/src/lua/src/lopcodes.h @@ -0,0 +1,288 @@ +/* +** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + 'Ax' : 26 bits ('A', 'B', and 'C' together) + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C +#define POS_Ax POS_A + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<= R(A) + 1 */ +OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) > 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/radio/src/lua/src/loslib.c b/radio/src/lua/src/loslib.c new file mode 100644 index 000000000..d991b9deb --- /dev/null +++ b/radio/src/lua/src/loslib.c @@ -0,0 +1,322 @@ +/* +** $Id: loslib.c,v 1.40 2012/10/19 15:54:02 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define loslib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** list of valid conversion specifiers for the 'strftime' function +*/ +#if !defined(LUA_STRFTIMEOPTIONS) + +#if !defined(LUA_USE_POSIX) +#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } +#else +#define LUA_STRFTIMEOPTIONS \ + { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ + "", "E", "cCxXyY", \ + "O", "deHImMSuUVwWy" } +#endif + +#endif + + + +/* +** By default, Lua uses tmpnam except when POSIX is available, where it +** uses mkstemp. +*/ +#if defined(LUA_USE_MKSTEMP) +#include +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#elif !defined(lua_tmpnam) + +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif + + +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ +#if defined(LUA_USE_GMTIME_R) + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#elif !defined(l_gmtime) + +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) + +#endif + + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return luaL_fileresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res, isnum; + lua_getfield(L, -1, key); + res = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static const char *checkoption (lua_State *L, const char *conv, char *buff) { + static const char *const options[] = LUA_STRFTIMEOPTIONS; + unsigned int i; + for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { + if (*conv != '\0' && strchr(options[i], *conv) != NULL) { + buff[1] = *conv; + if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ + buff[2] = '\0'; /* end buffer */ + return conv + 1; + } + else if (*(conv + 1) != '\0' && + strchr(options[i + 1], *(conv + 1)) != NULL) { + buff[2] = *(conv + 1); /* valid two-char conversion specifier */ + buff[3] = '\0'; /* end buffer */ + return conv + 2; + } + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip `!' */ + } + else + stm = l_localtime(&t, &tmr); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[4]; + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (*s) { + if (*s != '%') /* no conversion specifier? */ + luaL_addchar(&b, *s++); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + s = checkoption(L, s + 1, cc); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = luaL_optint(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; +} + + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); + return 1; +} + diff --git a/radio/src/lua/src/lparser.c b/radio/src/lua/src/lparser.c new file mode 100644 index 000000000..d8f5b4ffc --- /dev/null +++ b/radio/src/lua/src/lparser.c @@ -0,0 +1,1638 @@ +/* +** $Id: lparser.c,v 2.130 2013/02/06 13:37:39 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + short firstlabel; /* index of first label in this block */ + short firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isloop; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void statement (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + /* last token from outer function must be EOS */ + lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove 'near to' from final message */ + luaX_syntaxerror(ls, msg); +} + + +static l_noret error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); +} + + +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "%s expected (to close %s at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname (LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} + + +static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; + } +} + + +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +} + + +static int searchupvalue (FuncState *fs, TString *name) { + int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (luaS_eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + if (luaS_eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + return -1; /* not found */ +} + + +/* + Mark block where variable at given level was defined + (to emit close instructions later). +*/ +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl->nactvar > level) bl = bl->previous; + bl->upval = 1; +} + + +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + return VVOID; /* default is global */ + else { + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ + return VVOID; /* not found; is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void enterlevel (LexState *ls) { + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(luaS_eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local " LUA_QS, + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int findlabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n++; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void findgotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (luaS_eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + + +/* +** "export" pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +/* +** create a label named "break" to resolve break statements +*/ +static void breaklabel (LexState *ls) { + TString *n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* +** generates an error for an undefined 'goto'; choose appropriate +** message when label name is a reserved word (which can only be 'break') +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label " LUA_QS " for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ +} + + +/* +** adds a new prototype into list of prototypes +*/ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; +} + + +/* +** codes instruction to create new closure in parent function. +** The OP_CLOSURE instruction must use the last available register, +** so that, if it invokes the GC, the GC knows which registers +** are in use at that time. +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ +} + + +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + lua_State *L = ls->L; + Proto *f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nups = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f = fs->f; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L); + /* anchor table of constants (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + enterblock(fs, bl, 0); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaK_ret(fs, 0, 0); /* final return */ + leaveblock(fs); + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + /* last token read was anchored in defunct function; must re-anchor it */ + anchor_token(ls); + L->top--; /* pop table of constants */ + luaC_checkGC(L); +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [`;'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyregup(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void field (LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + field(ls, &cc); + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); + f->is_vararg = 1; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> `(' parlist `)' block END */ + FuncState new_fs; + BlockCnt bl; + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + + +static int explist (LexState *ls, expdesc *v) { + /* explist -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f, int line) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist ] `)' */ + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + } + } +} + + +static void suffixedexp (LexState *ls, expdesc *v) { + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + primaryexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyregup(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v, line); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + suffixedexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ + {10, 9}, {5, 4}, /* ^, .. (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v, line); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + int line = ls->linenumber; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2, line); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static void block (LexState *ls) { + /* block -> statlist */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + statlist(ls); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/local value in a safe place and +** use this safe copy in the previous assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist */ + int nexps; + checknext(ls, '='); + nexps = explist(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (luaS_eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label " LUA_QS " already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +/* skip no-op statements */ +static void skipnoopstat (LexState *ls) { + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ + FuncState *fs = ls->fs; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, fs->pc); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + findgotos(ls, &ll->arr[l]); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_jumpto(fs, whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int reg; + expr(ls, &e); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + + +static void test_then_block (LexState *ls, int *escapelist) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + luaX_next(ls); /* skip IF or ELSEIF */ + expr(ls, &v); /* read condition */ + checknext(ls, TK_THEN); + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* `then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* `else' part */ + check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +} + + +static void localfunc (LexState *ls) { + expdesc b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls)); + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {fieldsel} [`:' NAME] */ + int ismethod = 0; + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int ismethod; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ + v.prev = NULL; + assignment(ls, &v, 1); + } + else { /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + if (block_follow(ls, 1) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ +} + + +static void statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); + switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; + } + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); +} + +/* }====================================================================== */ + + +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ + /* anchor closure (to avoid being collected) */ + setclLvalue(L, L->top, cl); + incr_top(L); + funcstate.f = cl->l.p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + return cl; /* it's on the stack too */ +} + diff --git a/radio/src/lua/src/lparser.h b/radio/src/lua/src/lparser.h new file mode 100644 index 000000000..301167d4f --- /dev/null +++ b/radio/src/lua/src/lparser.h @@ -0,0 +1,119 @@ +/* +** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VNONRELOC, /* info = result register */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in 'upvalues' */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + +typedef struct expdesc { + expkind k; + union { + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + int info; /* for generic use */ + lua_Number nval; /* for VKNUM */ + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} Vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; + + +/* control of blocks */ +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to `pc' */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ + lu_byte nactvar; /* number of active local variables */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ +} FuncState; + + +LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); + + +#endif diff --git a/radio/src/lua/src/lstate.c b/radio/src/lua/src/lstate.c new file mode 100644 index 000000000..207a106d5 --- /dev/null +++ b/radio/src/lua/src/lstate.c @@ -0,0 +1,322 @@ +/* +** $Id: lstate.c,v 2.99 2012/10/02 17:40:53 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#if !defined(LUAI_GCPAUSE) +#define LUAI_GCPAUSE 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMAJOR) +#define LUAI_GCMAJOR 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMUL) +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#endif + + +#define MEMERRMSG "not enough memory" + + +/* +** a macro to help the creation of a unique random seed when a state is +** created; the seed is used to randomize hashes. +*/ +#if !defined(luai_makeseed) +#include +#define luai_makeseed() cast(unsigned int, time(NULL)) +#endif + + + +/* +** thread state + extra space +*/ +typedef struct LX { +#if defined(LUAI_EXTRASPACE) + char buff[LUAI_EXTRASPACE]; +#endif + lua_State l; +} LX; + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + LX l; + global_State g; +} LG; + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** Compute an initial seed as random as possible. In ANSI, rely on +** Address Space Layout Randomization (if present) to increase +** randomness.. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast(size_t, e); \ + memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int makeseed (lua_State *L) { + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + g->totalbytes -= (debt - g->GCdebt); + g->GCdebt = debt; +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + return ci; +} + + +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + } +} + + +static void stack_init (lua_State *L1, lua_State *L) { + int i; CallInfo *ci; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ +} + + +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue mt; + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &mt, L); + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &mt, luaH_new(L)); + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); +} + + +/* +** open parts of the state that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + init_registry(L, g); + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaS_fix(g->memerrmsg); /* it should never be collected */ + g->gcrunning = 1; /* allow gc */ +} + + +/* +** preinitialize a state with consistent values without allocating +** any memory (to avoid errors) +*/ +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->ci = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->nCcalls = 0; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->nny = 1; + L->status = LUA_OK; + L->errfunc = 0; +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeallobjects(L); /* collect all objects */ + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + luaZ_freebuffer(L, &g->buff); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; + setthvalue(L, L->top, L1); + api_incr_top(L); + preinit_state(L1, G(L)); + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(L1); + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); + if (l == NULL) return NULL; + L = &l->l.l; + g = &l->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + g->gckind = KGC_NORMAL; + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->seed = makeseed(L); + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->gcrunning = 0; /* no GC while building state */ + g->GCestimate = 0; + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->version = lua_version(NULL); + g->gcstate = GCSpause; + g->allgc = NULL; + g->finobj = NULL; + g->tobefnz = NULL; + g->sweepgc = g->sweepfin = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->gcpause = LUAI_GCPAUSE; + g->gcmajorinc = LUAI_GCMAJOR; + g->gcstepmul = LUAI_GCMUL; + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + else + luai_userstateopen(L); + return L; +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + luai_userstateclose(L); + close_state(L); +} + + diff --git a/radio/src/lua/src/lstate.h b/radio/src/lua/src/lstate.h new file mode 100644 index 000000000..c8a31f5c0 --- /dev/null +++ b/radio/src/lua/src/lstate.h @@ -0,0 +1,228 @@ +/* +** $Id: lstate.h,v 2.82 2012/07/02 13:37:04 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + +/* + +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed. +** +** Lua keeps most objects linked in list g->allgc. The link uses field +** 'next' of the CommonHeader. +** +** Strings are kept in several lists headed by the array g->strt.hash. +** +** Open upvalues are not subject to independent garbage collection. They +** are collected together with their respective threads. Lua keeps a +** double-linked list with all open upvalues (g->uvhead) so that it can +** mark objects referred by them. (They are always gray, so they must +** be remarked in the atomic step. Usually their contents would be marked +** when traversing the respective threads, but the thread may already be +** dead, while the upvalue is still accessible through closures.) +** +** Objects with finalizers are kept in the list g->finobj. +** +** The list g->tobefnz links all objects being finalized. + +*/ + + +struct lua_longjmp; /* defined in ldo.c */ + + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + +/* kinds of Garbage Collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ +#define KGC_GEN 2 /* generational collection */ + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** information about a call +*/ +typedef struct CallInfo { + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ + short nresults; /* expected number of results from this function */ + lu_byte callstatus; + ptrdiff_t extra; + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + int ctx; /* context info. in case of yields */ + lua_CFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lu_byte old_allowhook; + lu_byte status; + } c; + } u; +} CallInfo; + + +/* +** Bits in CallInfo status +*/ +#define CIST_LUA (1<<0) /* call is running a Lua function */ +#define CIST_HOOKED (1<<1) /* call is running a debug hook */ +#define CIST_REENTRY (1<<2) /* call is running on same invocation of + luaV_execute of previous call */ +#define CIST_YIELDED (1<<3) /* call reentered after suspension */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_STAT (1<<5) /* call has an error status (pcall) */ +#define CIST_TAIL (1<<6) /* call was tail called */ +#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ + + +#define isLua(ci) ((ci)->callstatus & CIST_LUA) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCmemtrav; /* memory traversed by the GC */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + unsigned int seed; /* randomized seed for hashes */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *allgc; /* list of all collectable objects */ + GCObject *finobj; /* list of collectable objects with finalizers */ + GCObject **sweepgc; /* current position of sweep in list 'allgc' */ + GCObject **sweepfin; /* current position of sweep in list 'finobj' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + UpVal uvhead; /* head of double-linked list of all open upvalues */ + Mbuffer buff; /* temporary buffer for string concatenation */ + int gcpause; /* size of pause between successive GCs */ + int gcmajorinc; /* pause between major collections (only in gen. mode) */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + struct lua_State *mainthread; + const lua_Number *version; /* pointer to version number */ + TString *memerrmsg; /* memory-error message */ + TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *oldpc; /* last pc traced */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + int stacksize; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; /* common header */ + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +#define gch(o) (&(o)->gch) + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) \ + check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) +#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) +#define gco2cl(o) \ + check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) +#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any Lua object into a GCObject */ +#define obj2gco(v) (cast(GCObject *, (v))) + + +/* actual number of total bytes allocated */ +#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); + + +#endif + diff --git a/radio/src/lua/src/lstring.c b/radio/src/lua/src/lstring.c new file mode 100644 index 000000000..8b5af0b2e --- /dev/null +++ b/radio/src/lua/src/lstring.c @@ -0,0 +1,185 @@ +/* +** $Id: lstring.c,v 2.26 2013/01/08 13:50:10 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c +#define LUA_CORE + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT 5 +#endif + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { + size_t len = a->tsv.len; + lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->tsv.len) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +} + + +/* +** equality for strings +*/ +int luaS_eqstr (TString *a, TString *b) { + return (a->tsv.tt == b->tsv.tt) && + (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { + unsigned int h = seed ^ cast(unsigned int, l); + size_t l1; + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (l1 = l; l1 >= step; l1 -= step) + h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); + return h; +} + + +/* +** resizes the string table +*/ +void luaS_resize (lua_State *L, int newsize) { + int i; + stringtable *tb = &G(L)->strt; + /* cannot resize while GC is traversing strings */ + luaC_runtilstate(L, ~bitmask(GCSsweepstring)); + if (newsize > tb->size) { + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; + } + /* rehash */ + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + tb->hash[i] = NULL; + while (p) { /* for each node in the list */ + GCObject *next = gch(p)->next; /* save next */ + unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ + gch(p)->next = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + resetoldbit(p); /* see MOVE OLD rule */ + p = next; + } + } + if (newsize < tb->size) { + /* shrinking slice must be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + } + tb->size = newsize; +} + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, const char *str, size_t l, + int tag, unsigned int h, GCObject **list) { + TString *ts; + size_t totalsize; /* total size of TString object */ + totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); + ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.extra = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + return ts; +} + + +/* +** creates a new short string, inserting it into string table +*/ +static TString *newshrstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + GCObject **list; /* (pointer to) list where it will be inserted */ + stringtable *tb = &G(L)->strt; + TString *s; + if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + list = &tb->hash[lmod(h, tb->size)]; + s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); + tb->nuse++; + return s; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + global_State *g = G(L); + unsigned int h = luaS_hash(str, l, g->seed); + for (o = g->strt.hash[lmod(h, g->strt.size)]; + o != NULL; + o = gch(o)->next) { + TString *ts = rawgco2ts(o); + if (h == ts->tsv.hash && + l == ts->tsv.len && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ + changewhite(o); /* resurrect it */ + return ts; + } + } + return newshrstr(L, str, l, h); /* not found; create a new string */ +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else { + if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); + } +} + + +/* +** new zero-terminated string +*/ +TString *luaS_new (lua_State *L, const char *str) { + return luaS_newlstr(L, str, strlen(str)); +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + return u; +} + diff --git a/radio/src/lua/src/lstring.h b/radio/src/lua/src/lstring.h new file mode 100644 index 000000000..d312ff3d2 --- /dev/null +++ b/radio/src/lua/src/lstring.h @@ -0,0 +1,46 @@ +/* +** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) + +#define sizeudata(u) (sizeof(union Udata)+(u)->len) + +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + + +/* +** test whether a string is a reserved word +*/ +#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) + + +LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); +LUAI_FUNC int luaS_eqstr (TString *a, TString *b); +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); + + +#endif diff --git a/radio/src/lua/src/lstrlib.c b/radio/src/lua/src/lstrlib.c new file mode 100644 index 000000000..e60d2ba29 --- /dev/null +++ b/radio/src/lua/src/lstrlib.c @@ -0,0 +1,1017 @@ +/* +** $Id: lstrlib.c,v 1.178 2012/08/14 18:12:34 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lstrlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, (lua_Integer)l); + return 1; +} + + +/* translate a relative string position: negative means back from end */ +static size_t posrelat (ptrdiff_t pos, size_t len) { + if (pos >= 0) return (size_t)pos; + else if (0u - (size_t)pos > len) return 0; + else return len - ((size_t)-pos) + 1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + size_t start = posrelat(luaL_checkinteger(L, 2), l); + size_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > l) end = l; + if (start <= end) + lua_pushlstring(L, s + start - 1, end - start + 1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l, i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i=0; i> 1) + +static int str_rep (lua_State *L) { + size_t l, lsep; + const char *s = luaL_checklstring(L, 1, &l); + int n = luaL_checkint(L, 2); + const char *sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = n * l + (n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ + memcpy(p, sep, lsep * sizeof(char)); p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi < 1) posi = 1; + if (pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* (size_t -> int) overflow? */ + return luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; /* deprecated option */ + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (MatchState *ms, const char *s, const char *p, + const char *ep) { + if (s >= ms->src_end) + return 0; + else { + int c = uchar(*s); + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } + } +} + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern " + "(missing arguments to " LUA_QL("%%b") ")"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while (singlematch(ms, s + i, p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (singlematch(ms, s, p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + if (ms->matchdepth-- == 0) + luaL_error(ms->L, "pattern too complex"); + init: /* using goto's to optimize tail recursion */ + if (p != ms->p_end) { /* end of pattern? */ + switch (*p) { + case '(': { /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': { /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': { + if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) { + p += 4; goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s - 1); + if (!matchbracketclass(uchar(previous), p, ep - 1) && + matchbracketclass(uchar(*s), p, ep - 1)) { + p = ep; goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) { + p += 2; goto init; /* return match(ms, s, p + 2) */ + } + break; + } + default: goto dflt; + } + break; + } + default: dflt: { /* pattern class plus optional suffix */ + const char *ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) { + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ + } + else { /* matched once */ + switch (*ep) { /* handle optional suffix */ + case '?': { /* optional */ + const char *res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else { + p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* go through */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ + } + } + break; + } + } + } + ms->matchdepth++; + return s; +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index"); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > ls + 1) { /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { + /* do a plain search */ + const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); + if (s2) { + lua_pushinteger(L, s2 - s + 1); + lua_pushinteger(L, s2 - s + lp); + return 2; + } + } + else { + MatchState ms; + const char *s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = s; + ms.src_end = s + ls; + ms.p_end = p + lp; + do { + const char *res; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, s1 - s + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { + MatchState ms; + size_t ls, lp; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); + const char *src; + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = s; + ms.src_end = s+ls; + ms.p_end = p + lp; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + if ((e = match(&ms, src, p)) != NULL) { + lua_Integer newstart = e-s; + if (e == src) newstart++; /* empty match? go at least one position */ + lua_pushinteger(L, newstart); + lua_replace(L, lua_upvalueindex(3)); + return push_captures(&ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + luaL_checkstring(L, 1); + luaL_checkstring(L, 2); + lua_settop(L, 2); + lua_pushinteger(L, 0); + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + const char *news = lua_tolstring(ms->L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC) + luaL_error(ms->L, "invalid use of " LUA_QL("%c") + " in replacement string", L_ESC); + luaL_addchar(b, news[i]); + } + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e, int tr) { + lua_State *L = ms->L; + switch (tr) { + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl, lp; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checklstring(L, 2, &lp); + int tr = lua_type(L, 3); + size_t max_s = luaL_optinteger(L, 4, srcl+1); + int anchor = (*p == '^'); + size_t n = 0; + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = src; + ms.src_end = src+srcl; + ms.p_end = p + lp; + while (n < max_s) { + const char *e; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e, tr); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_addchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +/* +** LUA_INTFRMLEN is the length modifier for integer conversions in +** 'string.format'; LUA_INTFRM_T is the integer type corresponding to +** the previous length +*/ +#if !defined(LUA_INTFRMLEN) /* { */ +#if defined(LUA_USE_LONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif +#endif /* } */ + + +/* +** LUA_FLTFRMLEN is the length modifier for float conversions in +** 'string.format'; LUA_FLTFRM_T is the float type corresponding to +** the previous length +*/ +#if !defined(LUA_FLTFRMLEN) + +#define LUA_FLTFRMLEN "" +#define LUA_FLTFRM_T double + +#endif + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + + +static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_addchar(b, '"'); + while (l--) { + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (*s == '\0' || iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + sprintf(buff, "\\%d", (int)uchar(*s)); + else + sprintf(buff, "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); + s++; + } + luaL_addchar(b, '"'); +} + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + nb = sprintf(buff, form, luaL_checkint(L, arg)); + break; + } + case 'd': case 'i': { + lua_Number n = luaL_checknumber(L, arg); + LUA_INTFRM_T ni = (LUA_INTFRM_T)n; + lua_Number diff = n - (lua_Number)ni; + luaL_argcheck(L, -1 < diff && diff < 1, arg, + "not a number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, ni); + break; + } + case 'o': case 'u': case 'x': case 'X': { + lua_Number n = luaL_checknumber(L, arg); + unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; + lua_Number diff = n - (lua_Number)ni; + luaL_argcheck(L, -1 < diff && diff < 1, arg, + "not a non-negative number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, ni); + break; + } + case 'e': case 'E': case 'f': +#if defined(LUA_USE_AFORMAT) + case 'a': case 'A': +#endif + case 'g': case 'G': { + addlenmod(form, LUA_FLTFRMLEN); + nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, &b, arg); + break; + } + case 's': { + size_t l; + const char *s = luaL_tolstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + luaL_addvalue(&b); + break; + } + else { + nb = sprintf(buff, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addsize(&b, nb); + } + } + luaL_pushresult(&b); + return 1; +} + +/* }====================================================== */ + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* table to be metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); + createmetatable(L); + return 1; +} + diff --git a/radio/src/lua/src/ltable.c b/radio/src/lua/src/ltable.c new file mode 100644 index 000000000..305149d6b --- /dev/null +++ b/radio/src/lua/src/ltable.c @@ -0,0 +1,589 @@ +/* +** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include + +#define ltable_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT >= 32 +#define MAXBITS 30 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +#define dummynode (&dummynode_) + +#define isdummy(n) ((n) == dummynode) + +static const Node dummynode_ = { + {NILCONSTANT}, /* value */ + {{NILCONSTANT, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + int i; + luai_hashnum(i, n); + if (i < 0) { + if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ + i = 0; /* handle INT_MIN */ + i = -i; /* must be a positive value */ + } + return hashmod(t, i); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TLNGSTR: { + TString *s = rawtsvalue(key); + if (s->tsv.extra == 0) { /* no hash? */ + s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); + s->tsv.extra = 1; /* now it has its hash */ + } + return hashstr(t, rawtsvalue(key)); + } + case LUA_TSHRSTR: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TValue *key) { + if (ttisnumber(key)) { + lua_Number n = nvalue(key); + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signaled by -1. +*/ +static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); + for (;;) { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } + else n = gnext(n); + if (n == NULL) + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + } + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast_num(i+1)); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, gkey(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static int computesizes (int nums[], int *narray) { + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ + } + } + if (a == *narray) break; /* all elements already counted */ + } + if (n - *narray > 1024) + *narray += 1024; + else + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[luaO_ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(gkey(n), nums); + totaluse++; + } + } + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common `dummynode' */ + lsize = 0; + } + else { + int i; + lsize = luaO_ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i=0; ilsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ +} + +void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + luaH_setint(L, t, i + 1, &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } + } + if (!isdummy(nold)) + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = isdummy(t->node) ? 0 : sizenode(t); + luaH_resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + luaH_resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L) { + Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; + t->metatable = NULL; + t->flags = cast_byte(~0); + t->array = NULL; + t->sizearray = 0; + setnodevector(L, t, 0); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (!isdummy(t->node)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree > t->node) { + t->lastfree--; + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) + luaG_runerror(L, "table index is NaN"); + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' take care of TM cache and GC barrier */ + return luaH_set(L, t, key); /* insert key into grown table */ + } + lua_assert(!isdummy(n)); + othern = mainposition(t, gkey(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + setobj2t(L, gkey(mp), key); + luaC_barrierback(L, obj2gco(t), key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getint (Table *t, int key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { + lua_Number nk = cast_num(key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } +} + + +/* +** search function for short strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + lua_assert(key->tsv.tt == LUA_TSHRSTR); + do { /* check whether `key' is somewhere in the chain */ + if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNIL: return luaO_nilobject; + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) /* index is int? */ + return luaH_getint(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else return luaH_newkey(L, t, key); +} + + +void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; + if (p != luaO_nilobject) + cell = cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + cell = luaH_newkey(L, t, &k); + } + setobj2t(L, cell, value); +} + + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getint(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getint(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (isdummy(t->node)) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (Node *n) { return isdummy(n); } + +#endif diff --git a/radio/src/lua/src/ltable.h b/radio/src/lua/src/ltable.h new file mode 100644 index 000000000..2f6f5c2dc --- /dev/null +++ b/radio/src/lua/src/ltable.h @@ -0,0 +1,41 @@ +/* +** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.tvk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define invalidateTMcache(t) ((t)->flags = 0) + + +LUAI_FUNC const TValue *luaH_getint (Table *t, int key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC int luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (Node *n); +#endif + + +#endif diff --git a/radio/src/lua/src/ltablib.c b/radio/src/lua/src/ltablib.c new file mode 100644 index 000000000..c61903b08 --- /dev/null +++ b/radio/src/lua/src/ltablib.c @@ -0,0 +1,282 @@ +/* +** $Id: ltablib.c,v 1.65 2013/03/07 18:17:24 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) + + + +#if defined(LUA_COMPAT_MAXN) +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} +#endif + + +static int tinsert (lua_State *L) { + int e = aux_getn(L, 1) + 1; /* first empty element */ + int pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + int i; + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + } + } + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int size = aux_getn(L, 1); + int pos = luaL_optint(L, 2, size); + if (pos != size) /* validate 'pos' if given */ + luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ; pos < size; pos++) { + lua_rawgeti(L, 1, pos+1); + lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ + } + lua_pushnil(L); + lua_rawseti(L, 1, pos); /* t[pos] = nil */ + return 1; +} + + +static void addfield (lua_State *L, luaL_Buffer *b, int i) { + lua_rawgeti(L, 1, i); + if (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for " + LUA_QL("concat"), luaL_typename(L, -1), i); + luaL_addvalue(b); +} + + +static int tconcat (lua_State *L) { + luaL_Buffer b; + size_t lsep; + int i, last; + const char *sep = luaL_optlstring(L, 2, "", &lsep); + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 3, 1); + last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); + luaL_buffinit(L, &b); + for (; i < last; i++) { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); + } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); + luaL_pushresult(&b); + return 1; +} + + +/* +** {====================================================== +** Pack/unpack +** ======================================================= +*/ + +static int pack (lua_State *L) { + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_pushinteger(L, n); + lua_setfield(L, -2, "n"); /* t.n = number of elements */ + if (n > 0) { /* at least one element? */ + int i; + lua_pushvalue(L, 1); + lua_rawseti(L, -2, 1); /* insert first element */ + lua_replace(L, 1); /* move table into index 1 */ + for (i = n; i >= 2; i--) /* assign other elements */ + lua_rawseti(L, 1, i); + } + return 1; /* return table */ +} + + +static int unpack (lua_State *L) { + int i, e, n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ + n = e - i + 1; /* number of elements */ + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ + lua_rawgeti(L, 1, i); + return n; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Quicksort +** (based on `Algorithms in MODULA-3', Robert Sedgewick; +** Addison-Wesley, 1993.) +** ======================================================= +*/ + + +static void set2 (lua_State *L, int i, int j) { + lua_rawseti(L, 1, i); + lua_rawseti(L, 1, j); +} + +static int sort_comp (lua_State *L, int a, int b) { + if (!lua_isnil(L, 2)) { /* function? */ + int res; + lua_pushvalue(L, 2); + lua_pushvalue(L, a-1); /* -1 to compensate function */ + lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ + lua_call(L, 2, 1); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; + } + else /* a < b? */ + return lua_compare(L, a, b, LUA_OPLT); +} + +static void auxsort (lua_State *L, int l, int u) { + while (l < u) { /* for tail recursion */ + int i, j; + /* sort elements a[l], a[(l+u)/2] and a[u] */ + lua_rawgeti(L, 1, l); + lua_rawgeti(L, 1, u); + if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ + set2(L, l, u); /* swap a[l] - a[u] */ + else + lua_pop(L, 2); + if (u-l == 1) break; /* only 2 elements */ + i = (l+u)/2; + lua_rawgeti(L, 1, i); + lua_rawgeti(L, 1, l); + if (sort_comp(L, -2, -1)) /* a[i]= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>=u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j<=l) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + if (j + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +static const char udatatypename[] = "userdata"; + +LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { + "no value", + "nil", "boolean", 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", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttypenv(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/radio/src/lua/src/ltm.h b/radio/src/lua/src/ltm.h new file mode 100644 index 000000000..89bdc19a1 --- /dev/null +++ b/radio/src/lua/src/ltm.h @@ -0,0 +1,57 @@ +/* +** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_LEN, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +#define ttypename(x) luaT_typenames_[(x) + 1] +#define objtypename(x) ttypename(ttypenv(x)) + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; + + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +#endif diff --git a/radio/src/lua/src/lua.c b/radio/src/lua/src/lua.c new file mode 100644 index 000000000..c2c1e547d --- /dev/null +++ b/radio/src/lua/src/lua.c @@ -0,0 +1,496 @@ +/* +** $Id: lua.c,v 1.206 2012/09/29 20:07:06 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT) +#define LUA_INIT "LUA_INIT" +#endif + +#define LUA_INITVERSION \ + LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#if defined(LUA_USE_ISATTY) +#include +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +** lua_readline defines how to show a prompt and then read a line from +** the standard input. +** lua_saveline defines how to "save" a read line in a "history". +** lua_freeline defines how to free a line read by lua_readline. +*/ +#if defined(LUA_USE_READLINE) + +#include +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) + +#elif !defined(lua_readline) + +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } + +#endif + + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + + +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); +} + + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (const char *badoption) { + luai_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + luai_writestringerror("'%s' needs argument\n", badoption); + else + luai_writestringerror("unrecognized option '%s'\n", badoption); + luai_writestringerror( + "usage: %s [options] [script [args]]\n" + "Available options are:\n" + " -e stat execute string " LUA_QL("stat") "\n" + " -i enter interactive mode after executing " LUA_QL("script") "\n" + " -l name require library " LUA_QL("name") "\n" + " -v show version information\n" + " -E ignore environment variables\n" + " -- stop handling options\n" + " - stop handling options and execute stdin\n" + , + progname); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) luai_writestringerror("%s: ", pname); + luai_writestringerror("%s\n", msg); +} + + +static int report (lua_State *L, int status) { + if (status != LUA_OK && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + /* force a complete garbage collection in case of errors */ + lua_gc(L, LUA_GCCOLLECT, 0); + } + return status; +} + + +/* the next function is called unprotected, so it must avoid errors */ +static void finalreport (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) + : NULL; + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } +} + + +static int traceback (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg) + luaL_traceback(L, L, msg, 1); + else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ + if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ + lua_pushliteral(L, "(no error message)"); + } + return 1; +} + + +static int docall (lua_State *L, int narg, int nres) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + globalL = L; /* to be available to 'laction' */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, nres, base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + return status; +} + + +static void print_version (void) { + luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + luai_writeline(); +} + + +static int getargs (lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i=n+1; i < argc; i++) + lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i=0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + + +static int dofile (lua_State *L, const char *name) { + int status = luaL_loadfile(L, name); + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + int status = luaL_loadbuffer(L, s, strlen(s), name); + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dolibrary (lua_State *L, const char *name) { + int status; + lua_getglobal(L, "require"); + lua_pushstring(L, name); + status = docall(L, 1, 1); /* call 'require(name)' */ + if (status == LUA_OK) + lua_setglobal(L, name); /* global[name] = require return */ + return report(L, status); +} + + +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + return p; +} + +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + int readstatus = lua_readline(L, b, prmt); + lua_pop(L, 1); /* remove result from 'get_prompt' */ + if (readstatus == 0) + return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[l-1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_freeline(L, b); + return 1; +} + + +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + size_t l; + const char *line = lua_tolstring(L, 1, &l); + status = luaL_loadbuffer(L, line, l, "=stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_saveline(L, 1); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void dotty (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET); + report(L, status); + if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK) + l_message(progname, lua_pushfstring(L, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + luai_writeline(); + progname = oldprogname; +} + + +static int handle_script (lua_State *L, char **argv, int n) { + int status; + const char *fname; + int narg = getargs(L, argv, n); /* collect arguments */ + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == LUA_OK) + status = docall(L, narg, LUA_MULTRET); + else + lua_pop(L, narg); + return report(L, status); +} + + +/* check that argument has no extra characters at the end */ +#define noextrachars(x) {if ((x)[2] != '\0') return -1;} + + +/* indices of various argument indicators in array args */ +#define has_i 0 /* -i */ +#define has_v 1 /* -v */ +#define has_e 2 /* -e */ +#define has_E 3 /* -E */ + +#define num_has 4 /* number of 'has_*' */ + + +static int collectargs (char **argv, int *args) { + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') /* not an option? */ + return i; + switch (argv[i][1]) { /* option */ + case '-': + noextrachars(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'E': + args[has_E] = 1; + break; + case 'i': + noextrachars(argv[i]); + args[has_i] = 1; /* go through */ + case 'v': + noextrachars(argv[i]); + args[has_v] = 1; + break; + case 'e': + args[has_e] = 1; /* go through */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return -(i - 1); /* no next argument or it is another option */ + } + break; + default: /* invalid option; return its index... */ + return -i; /* ...as a negative value */ + } + } + return 0; +} + + +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { /* option */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != LUA_OK) + return 0; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename) != LUA_OK) + return 0; /* stop if file fails */ + break; + } + default: break; + } + } + return 1; +} + + +static int handle_luainit (lua_State *L) { + const char *name = "=" LUA_INITVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, name); +} + + +static int pmain (lua_State *L) { + int argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); + int script; + int args[num_has]; + args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; + if (argv[0] && argv[0][0]) progname = argv[0]; + script = collectargs(argv, args); + if (script < 0) { /* invalid arg? */ + print_usage(argv[-script]); + return 0; + } + if (args[has_v]) print_version(); + if (args[has_E]) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + /* open standard libraries */ + luaL_checkversion(L); + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ + luaL_openlibs(L); /* open libraries */ + lua_gc(L, LUA_GCRESTART, 0); + if (!args[has_E] && handle_luainit(L) != LUA_OK) + return 0; /* error running LUA_INIT */ + /* execute arguments -e and -l */ + if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; + /* execute main script (if there is one) */ + if (script && handle_script(L, argv, script) != LUA_OK) return 0; + if (args[has_i]) /* -i option? */ + dotty(L); + else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ + if (lua_stdin_is_tty()) { + print_version(); + dotty(L); + } + else dofile(L, NULL); /* executes stdin as a file */ + } + lua_pushboolean(L, 1); /* signal no errors */ + return 1; +} + + +int main (int argc, char **argv) { + int status, result; + lua_State *L = luaL_newstate(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + /* call 'pmain' in protected mode */ + lua_pushcfunction(L, &pmain); + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); + result = lua_toboolean(L, -1); /* get result */ + finalreport(L, status); + lua_close(L); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/radio/src/lua/src/lua.h b/radio/src/lua/src/lua.h new file mode 100644 index 000000000..d9ae5c9ea --- /dev/null +++ b/radio/src/lua/src/lua.h @@ -0,0 +1,455 @@ +/* +** $Id: lua.h,v 1.285 2013/03/15 13:04:22 roberto Exp $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "2" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#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_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +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 int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_getglobal) (lua_State *L, const char *var); +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *var); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_getctx) (lua_State *L, int *ctx); + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, + const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, + lua_CFunction k); +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCSETMAJORINC 8 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +#if defined(USE_FATFS) + #include "FatFs/ff.h" + int lua__getc(FIL *f); + #define lua_getc(f) lua__getc(&f) + #define lua_fclose f_close +#else + #include + #define lua_getc getc + #define lua_fclose fclose +#endif + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2013 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/radio/src/lua/src/lua.hpp b/radio/src/lua/src/lua.hpp new file mode 100644 index 000000000..ec417f594 --- /dev/null +++ b/radio/src/lua/src/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/radio/src/lua/src/luac.c b/radio/src/lua/src/luac.c new file mode 100644 index 000000000..b8e179381 --- /dev/null +++ b/radio/src/lua/src/luac.c @@ -0,0 +1,431 @@ +/* +** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#include +#include +#include + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +static void PrintFunction(const Proto* f, int full); +#define luaU_print PrintFunction + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n" + " - stop handling options and process stdin\n" + ,progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i)) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); + f=toproto(L,-1); + for (i=0; ip[i]=toproto(L,i-n-1); + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; + } + f->sizelineinfo=0; + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +static int pmain(lua_State* L) +{ + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=luaL_newstate(); + if (L==NULL) fatal("cannot create state: not enough memory"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,argc); + lua_pushlightuserdata(L,argv); + if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} + +/* +** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" + +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + printf("%c",'"'); + for (i=0; ik[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + case OP_TFORLOOP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); + break; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? getstr(f->source) : "=?"; + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) PrintDebug(f); + for (i=0; ip[i],full); +} diff --git a/radio/src/lua/src/luaconf.h b/radio/src/lua/src/luaconf.h new file mode 100644 index 000000000..87e04e8b8 --- /dev/null +++ b/radio/src/lua/src/luaconf.h @@ -0,0 +1,563 @@ +/* +** $Id: luaconf.h,v 1.176 2013/03/16 21:10:18 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + +// #define LUA_LIB +#define USE_FATFS + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#endif + + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionality listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#define LUA_USE_GMTIME_R +#endif + + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_ENV is the name of the variable that holds the current +@@ environment, used to access global names. +** CHANGE it if you do not like this name. +*/ +#define LUA_ENV "_ENV" + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +@* that are not to be exported to outside modules (LUAI_DDEF for +@* definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +#else /* }{ */ +#define LUAI_FUNC extern +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#endif /* } */ + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ luai_writestring/luai_writeline define how 'print' prints its results. +** They are only used in libraries and the stand-alone program. (The #if +** avoids including 'stdio.h' everywhere.) +*/ + +/* +@@ luai_writestringerror defines how to print error messages. +** (A format string with one argument is enough for Lua...) +*/ + +#if defined(LUA_LIB) || defined(lua_c) +#include +#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) +#define luai_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#else +#define luai_writestring(s,l) +#define luai_writeline() +#define luai_writestringerror(s,p) +#endif + + + +/* +@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, +** strings that are internalized. (Cannot be smaller than reserved words +** or tags for metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#define LUAI_MAXSHORTLEN 40 + + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_ALL controls all compatibility options. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_ALL) /* { */ + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + +/* }================================================================== */ + + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 /* { */ +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L /* }{ */ +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else /* }{ */ +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif /* } */ + + +/* +@@ LUA_INT32 is an signed integer with exactly 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. Probably you do not need to change +** this. +*/ +#if LUAI_BITSINT >= 32 /* { */ +#define LUA_INT32 int +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else /* }{ */ +/* 16-bit ints */ +#define LUA_INT32 long +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif /* } */ + + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua to consume unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + +/* reserve some space for error handling */ +#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) + + + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. +*/ +#if defined(USE_FATFS) +#define LUAL_BUFFERSIZE 512 +#else +#define LUAL_BUFFERSIZE BUFSIZ +#endif + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ + + +/* +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations +*/ +#define l_mathop(x) (x) + + +/* +@@ lua_str2number converts a decimal numeric string to a number. +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does both conversions. C89, however, has no function +** to convert floating hexadecimal strings to numbers. For these +** systems, you can leave 'lua_strx2number' undefined and Lua will +** provide its own implementation. +*/ +#define lua_str2number(s,p) strtod((s), (p)) + +#if defined(LUA_USE_STRTODHEX) +#define lua_strx2number(s,p) strtod((s), (p)) +#endif + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ + +/* the following operations need the math library */ +#if defined(lobject_c) || defined(lvm_c) +#include +#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) +#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) +#endif + +/* these are quite standard operations */ +#if defined(LUA_CORE) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) +#define luai_numisnan(L,a) (!luai_numeq((a), (a))) +#endif + + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER int + +/* +@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. +** It must have at least 32 bits. +*/ +#define LUA_UNSIGNED unsigned LUA_INT32 + + + +/* +** Some tricks with doubles +*/ + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ +/* +** The next definitions activate some tricks to speed up the +** conversion from doubles to integer types, mainly to LUA_UNSIGNED. +** +@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a +** DirectX idiosyncrasy. +** +@@ LUA_IEEE754TRICK uses a trick that should work on any machine +** using IEEE754 with a 32-bit integer type. +** +@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be +** defined when LUA_INTEGER is a 32-bit integer. +** +@@ LUA_IEEEENDIAN is the endianness of doubles in your machine +** (0 for little endian, 1 for big endian); if not defined, Lua will +** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). +** +@@ LUA_NANTRICK controls the use of a trick to pack all types into +** a single double value, using NaN values to represent non-number +** values. The trick only works on 32-bit machines (ints and pointers +** are 32-bit values) with numbers represented as IEEE 754-2008 doubles +** with conventional endianess (12345678 or 87654321), in CPUs that do +** not produce signaling NaN values (all NaNs are quiet). +*/ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/radio/src/lua/src/lualib.h b/radio/src/lua/src/lualib.h new file mode 100644 index 000000000..9fd126bf7 --- /dev/null +++ b/radio/src/lua/src/lualib.h @@ -0,0 +1,55 @@ +/* +** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/radio/src/lua/src/lundump.c b/radio/src/lua/src/lundump.c new file mode 100644 index 000000000..54de011a4 --- /dev/null +++ b/radio/src/lua/src/lundump.c @@ -0,0 +1,258 @@ +/* +** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define lundump_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + const char* name; +} LoadState; + +static l_noret error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} + +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) + +#if !defined(luai_verifycode) +#define luai_verifycode(L,b,f) /* empty */ +#endif + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); +} + +static int LoadChar(LoadState* S) +{ + char x; + LoadVar(S,x); + return x; +} + +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S,x); + if (x<0) error(S,"corrupted"); + return x; +} + +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S,x); + return x; +} + +static TString* LoadString(LoadState* S) +{ + size_t size; + LoadVar(S,size); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + LoadBlock(S,s,size*sizeof(char)); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode(LoadState* S, Proto* f) +{ + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); +} + +static void LoadFunction(LoadState* S, Proto* f); + +static void LoadConstants(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TValue); + f->sizek=n; + for (i=0; ik[i]); + for (i=0; ik[i]; + int t=LoadChar(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o,LoadChar(S)); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: lua_assert(0); + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=NULL; + for (i=0; ip[i]=luaF_newproto(S->L); + LoadFunction(S,f->p[i]); + } +} + +static void LoadUpvalues(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,Upvaldesc); + f->sizeupvalues=n; + for (i=0; iupvalues[i].name=NULL; + for (i=0; iupvalues[i].instack=LoadByte(S); + f->upvalues[i].idx=LoadByte(S); + } +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + f->source=LoadString(S); + n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=NULL; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } + n=LoadInt(S); + for (i=0; iupvalues[i].name=LoadString(S); +} + +static void LoadFunction(LoadState* S, Proto* f) +{ + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadUpvalues(S,f); + LoadDebug(S,f); +} + +/* the code below must be consistent with the code in luaU_header */ +#define N0 LUAC_HEADERSIZE +#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) +#define N2 N1+2 +#define N3 N2+6 + +static void LoadHeader(LoadState* S) +{ + lu_byte h[LUAC_HEADERSIZE]; + lu_byte s[LUAC_HEADERSIZE]; + luaU_header(h); + memcpy(s,h,sizeof(char)); /* first char already read */ + LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); + if (memcmp(h,s,N0)==0) return; + if (memcmp(h,s,N1)!=0) error(S,"not a"); + if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); + if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); +} + +/* +** load precompiled chunk +*/ +Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + Closure* cl; + if (*name=='@' || *name=='=') + S.name=name+1; + else if (*name==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=name; + S.L=L; + S.Z=Z; + S.b=buff; + LoadHeader(&S); + cl=luaF_newLclosure(L,1); + setclLvalue(L,L->top,cl); incr_top(L); + cl->l.p=luaF_newproto(L); + LoadFunction(&S,cl->l.p); + if (cl->l.p->sizeupvalues != 1) + { + Proto* p=cl->l.p; + cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); + cl->l.p=p; + setclLvalue(L,L->top-1,cl); + } + luai_verifycode(L,buff,cl->l.p); + return cl; +} + +#define MYINT(s) (s[0]-'0') +#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) +#define FORMAT 0 /* this is the official format */ + +/* +* make header for precompiled chunks +* if you change the code below be sure to update LoadHeader and FORMAT above +* and LUAC_HEADERSIZE in lundump.h +*/ +void luaU_header (lu_byte* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); + h+=sizeof(LUA_SIGNATURE)-sizeof(char); + *h++=cast_byte(VERSION); + *h++=cast_byte(FORMAT); + *h++=cast_byte(*(char*)&x); /* endianness */ + *h++=cast_byte(sizeof(int)); + *h++=cast_byte(sizeof(size_t)); + *h++=cast_byte(sizeof(Instruction)); + *h++=cast_byte(sizeof(lua_Number)); + *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ + memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); +} diff --git a/radio/src/lua/src/lundump.h b/radio/src/lua/src/lundump.h new file mode 100644 index 000000000..2b8accecb --- /dev/null +++ b/radio/src/lua/src/lundump.h @@ -0,0 +1,28 @@ +/* +** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (lu_byte* h); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + +/* data to catch conversion errors */ +#define LUAC_TAIL "\x19\x93\r\n\x1a\n" + +/* size in bytes of header of binary files */ +#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) + +#endif diff --git a/radio/src/lua/src/lvm.c b/radio/src/lua/src/lvm.c new file mode 100644 index 000000000..657d5c456 --- /dev/null +++ b/radio/src/lua/src/lvm.c @@ -0,0 +1,867 @@ +/* +** $Id: lvm.c,v 2.155 2013/03/16 21:10:18 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define lvm_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; + lua_Number n = nvalue(obj); + int l = lua_number2str(s, n); + setsvalue2s(L, obj, luaS_newlstr(L, s, l)); + return 1; + } +} + + +static void traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); + if (counthook) + resethookcount(L); /* reset count */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } +} + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + setobj2s(L, L->top++, f); /* push function */ + setobj2s(L, L->top++, p1); /* 1st argument */ + setobj2s(L, L->top++, p2); /* 2nd argument */ + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } +} + + +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is not nil? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val, 1); + return; + } + t = tm; /* else repeat with 'tm' */ + } + luaG_runerror(L, "loop in gettable"); +} + + +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = cast(TValue *, luaH_get(h, key)); + /* if previous value is not nil, there must be a previous entry + in the table; moreover, a metamethod has no relevance */ + if (!ttisnil(oldval) || + /* previous value is nil; must check the metamethod */ + ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + /* no metamethod; is there a previous entry in the table? */ + (oldval != luaO_nilobject || + /* no previous entry; must create one. (The next test is + always true; we only need the assignment.) */ + (oldval = luaH_newkey(L, h, key), 1)))) { + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, oldval, val); /* assign new value to that entry */ + invalidateTMcache(h); + luaC_barrierback(L, obj2gco(h), val); + return; + } + /* else will try the metamethod */ + } + else /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + /* there is a metamethod */ + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val, 0); + return; + } + t = tm; /* else repeat with 'tm' */ + } + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + callTM(L, tm, p1, p2, res, 1); + return 1; +} + + +static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TValue *tm1 = fasttm(L, mt1, event); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (!call_binTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); +} + + +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttisnumber(l) && ttisnumber(r)) + return luai_numlt(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) + luaG_ordererror(L, l, r); + return res; +} + + +int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttisnumber(l) && ttisnumber(r)) + return luai_numle(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ + luaG_ordererror(L, l, r); + return !res; +} + + +/* +** equality of Lua values. L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttisequal(t1, t2)); + switch (ttype(t1)) { + 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_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTM(L, tm, t1, t2, L->top, 1); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); + do { + StkId top = L->top; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } + else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ + (void)tostring(L, top - 2); /* result is first operand */ + else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } + else { + /* at least two non-empty string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (i = 1; i < total && tostring(L, top-i-1); i++) { + size_t l = tsvalue(top-i-1)->len; + if (l >= (MAX_SIZET/sizeof(char)) - tl) + luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + n = i; + do { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); + tl += l; + } while (--i > 0); + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ + } while (total > 1); /* repeat until only 1 result left */ +} + + +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttypenv(rb)) { + case LUA_TTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ + return; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + callTM(L, tm, rb, rb, ra, 1); +} + + +void luaV_arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); + setnvalue(ra, res); + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static Closure *getcached (Proto *p, UpVal **encup, StkId base) { + Closure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->l.upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ +} + + +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. Note that the call to 'luaC_barrierproto' must come +** before the assignment to 'p->cache', as the function needs the +** original value of that field. +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + Closure *ncl = luaF_newLclosure(L, nup); + ncl->l.p = p; + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->l.upvals[i] = encup[uv[i].idx]; + } + luaC_barrierproto(L, p, ncl); + p->cache = ncl; /* save it on cache for reuse */ +} + + +/* +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: + case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + /* metamethod should not be called when operand is K */ + lua_assert(!ISK(GETARG_B(inst))); + if (op == OP_LE && /* "<=" using "<" instead? */ + ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) + res = !res; /* invert result */ + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'call_binTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#if !defined luai_runtimecheck +#define luai_runtimecheck(L, c) /* void */ +#endif + + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) \ + (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) + + +/* execute a jump instruction */ +#define dojump(ci,i,e) \ + { int a = GETARG_A(i); \ + if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } + +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } + + +#define Protect(x) { {x;}; base = ci->u.l.base; } + +#define checkGC(L,c) \ + Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ + luaC_step(L); \ + L->top = ci->top;}) /* restore top */ \ + luai_threadyield(L); ) + + +#define arith_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(L, nb, nc)); \ + } \ + else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } + + +#define vmdispatch(o) switch(o) +#define vmcase(l,b) case l: {b} break; +#define vmcasenb(l,b) case l: {b} /* nb = no break */ + +void luaV_execute (lua_State *L) { + CallInfo *ci = L->ci; + LClosure *cl; + TValue *k; + StkId base; + newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); + k = cl->p->k; + base = ci->u.l.base; + /* main loop of interpreter */ + for (;;) { + Instruction i = *(ci->u.l.savedpc++); + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + Protect(traceexec(L)); + } + /* WARNING: several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + 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, + setobjs2s(L, ra, RB(i)); + ) + vmcase(OP_LOADK, + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + ) + vmcase(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, + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + ) + vmcase(OP_LOADNIL, + int b = GETARG_B(i); + do { + setnilvalue(ra++); + } while (b--); + ) + vmcase(OP_GETUPVAL, + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + ) + vmcase(OP_GETTABUP, + int b = GETARG_B(i); + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + ) + vmcase(OP_GETTABLE, + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + ) + vmcase(OP_SETTABUP, + int a = GETARG_A(i); + Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); + ) + vmcase(OP_SETUPVAL, + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + ) + vmcase(OP_SETTABLE, + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + ) + vmcase(OP_NEWTABLE, + int b = GETARG_B(i); + int c = GETARG_C(i); + Table *t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, ra + 1); + ) + vmcase(OP_SELF, + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + ) + vmcase(OP_ADD, + arith_op(luai_numadd, TM_ADD); + ) + vmcase(OP_SUB, + arith_op(luai_numsub, TM_SUB); + ) + vmcase(OP_MUL, + arith_op(luai_nummul, TM_MUL); + ) + vmcase(OP_DIV, + arith_op(luai_numdiv, TM_DIV); + ) + vmcase(OP_MOD, + arith_op(luai_nummod, TM_MOD); + ) + vmcase(OP_POW, + arith_op(luai_numpow, TM_POW); + ) + vmcase(OP_UNM, + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(L, nb)); + } + else { + Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); + } + ) + 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); + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ + rb = b + base; + setobjs2s(L, ra, rb); + 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); + Protect( + if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_LT, + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_LE, + Protect( + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_TEST, + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmcase(OP_TESTSET, + TValue *rb = RB(i); + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else { + setobjs2s(L, ra, rb); + donextjump(ci); + } + ) + vmcase(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 */ + if (luaD_precall(L, ra, nresults)) { /* C function? */ + if (nresults >= 0) L->top = ci->top; /* adjust results */ + base = ci->u.l.base; + } + else { /* Lua function */ + ci = L->ci; + ci->callstatus |= CIST_REENTRY; + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcase(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); + if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ + base = ci->u.l.base; + else { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + 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; + if (cl->p->sizep > 0) luaF_close(L, base); + b = luaD_poscall(L, ra); + if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ + return; /* external invocation: return */ + else { /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcase(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); + if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) + : luai_numle(L, limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + ) + vmcase(OP_FORPREP, + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); + ci->u.l.savedpc += GETARG_sBx(i); + ) + vmcasenb(OP_TFORCALL, + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i), 1)); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + ) + vmcase(OP_TFORLOOP, + l_tforloop: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + } + ) + vmcase(OP_SETLIST, + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; + Table *h; + if (n == 0) n = cast_int(L->top - ra) - 1; + if (c == 0) { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); + } + luai_runtimecheck(L, ttistable(ra)); + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* pre-allocate it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + luaH_setint(L, h, last--, val); + luaC_barrierback(L, obj2gco(h), val); + } + L->top = ci->top; /* correct top (in case of previous open call) */ + ) + vmcase(OP_CLOSURE, + Proto *p = cl->p->p[GETARG_Bx(i)]; + Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + ) + vmcase(OP_VARARG, + int b = GETARG_B(i) - 1; + int j; + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, base - n + j); + } + else { + setnilvalue(ra + j); + } + } + ) + vmcase(OP_EXTRAARG, + lua_assert(0); + ) + } + } +} + diff --git a/radio/src/lua/src/lvm.h b/radio/src/lua/src/lvm.h new file mode 100644 index 000000000..07e25f9c6 --- /dev/null +++ b/radio/src/lua/src/lvm.h @@ -0,0 +1,44 @@ +/* +** $Id: lvm.h,v 2.18 2013/01/08 14:06:55 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) + +#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) + + +/* not to called directly */ +LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); +LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); + +#endif diff --git a/radio/src/lua/src/lzio.c b/radio/src/lua/src/lzio.c new file mode 100644 index 000000000..8b77054e0 --- /dev/null +++ b/radio/src/lua/src/lzio.c @@ -0,0 +1,76 @@ +/* +** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c +#define LUA_CORE + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ + z->p = buff; + return cast_uchar(*(z->p++)); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaZ_resizebuffer(L, buff, n); + } + return buff->buffer; +} + + diff --git a/radio/src/lua/src/lzio.h b/radio/src/lua/src/lzio.h new file mode 100644 index 000000000..08682301e --- /dev/null +++ b/radio/src/lua/src/lzio.h @@ -0,0 +1,65 @@ +/* +** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) + + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif From 330234df01dc2c020e3be1a4381500f95c12dd85 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 15 Jan 2014 17:24:13 +0100 Subject: [PATCH 02/10] Lua interpreter now running inside companion! --- companion/src/CMakeLists.txt | 7 +++- .../opentx/opentxTaranisSimulator.cpp | 33 ++++++++++++++++++- radio/src/Makefile | 2 +- radio/src/lua/src/luaconf.h | 12 ++++--- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 3a8dd26b7..de5e6d1d0 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -80,7 +80,12 @@ IF( Subversion_FOUND ) # Subversion_WC_INFO( ${PROJECT_SOURCE_DIR} C9X ) ENDIF( ) -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/../.. ${PROJECT_SOURCE_DIR}/../../radio/src/fonts/std ) +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${PROJECT_SOURCE_DIR}/../.. + ${PROJECT_SOURCE_DIR}/../../radio/src/fonts/std + ${PROJECT_SOURCE_DIR}/../../radio/src/lua/src +) set(TH9X_CHECKOUT_DIRECTORY ${PROJECT_BINARY_DIR}/firmwares/th9x) add_custom_command( diff --git a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp index fbd65c564..266dd8c7f 100644 --- a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp @@ -49,7 +49,8 @@ #define PPM_CENTER_ADJUSTABLE #define PPM_LIMITS_SYMETRICAL #define FAI_CHOICE - +#define LUA +#define LUA_MODEL_SCRIPTS #define EEPROM_VARIANT 3 #undef min @@ -115,6 +116,36 @@ inline int geteepromsize() { #include "radio/src/translations/tts_pt.cpp" #include "radio/src/translations/tts_sk.cpp" #include "radio/src/translations/tts_pl.cpp" + +#include "radio/src/lua.cpp" +#include "radio/src/lua/src/lapi.c" +#include "radio/src/lua/src/lcode.c" +#include "radio/src/lua/src/lctype.c" +#include "radio/src/lua/src/ldebug.c" +#include "radio/src/lua/src/ldo.c" +#include "radio/src/lua/src/ldump.c" +#include "radio/src/lua/src/lfunc.c" +#include "radio/src/lua/src/lgc.c" +#include "radio/src/lua/src/llex.c" +#include "radio/src/lua/src/lmem.c" +#include "radio/src/lua/src/lobject.c" +#include "radio/src/lua/src/lopcodes.c" +#include "radio/src/lua/src/lparser.c" +#include "radio/src/lua/src/lstate.c" +#include "radio/src/lua/src/lstring.c" +#include "radio/src/lua/src/ltable.c" +#include "radio/src/lua/src/ltm.c" +#include "radio/src/lua/src/lundump.c" +#include "radio/src/lua/src/lvm.c" +#include "radio/src/lua/src/lzio.c" +#include "radio/src/lua/src/lbaselib.c" +#include "radio/src/lua/src/linit.c" +#include "radio/src/lua/src/lmathlib.c" +#include "radio/src/lua/src/loadlib.c" +#include "radio/src/lua/src/lauxlib.c" +#include "radio/src/lua/src/ltablib.c" +#include "radio/src/lua/src/lcorolib.c" + int16_t g_anas[NUM_STICKS+BOARD_X9D_NUM_POTS]; diff --git a/radio/src/Makefile b/radio/src/Makefile index d21c55513..16dfb8b04 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -252,7 +252,7 @@ GVARS = NO # Lua interpreter embedded # Values = NO, NO_MODEL_SCRIPTS, YES -# LUA = NO +LUA = NO # Menu Lock modes # Values = NO, READONLY, NOMENUS diff --git a/radio/src/lua/src/luaconf.h b/radio/src/lua/src/luaconf.h index 87e04e8b8..742295325 100644 --- a/radio/src/lua/src/luaconf.h +++ b/radio/src/lua/src/luaconf.h @@ -12,7 +12,9 @@ #include // #define LUA_LIB -#define USE_FATFS +#if !defined(SIMU) + #define USE_FATFS +#endif /* ** ================================================================== @@ -443,14 +445,14 @@ */ /* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) +//#if defined(lobject_c) || defined(lvm_c) #include #define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) #define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) -#endif +//#endif /* these are quite standard operations */ -#if defined(LUA_CORE) +// #if defined(LUA_CORE) #define luai_numadd(L,a,b) ((a)+(b)) #define luai_numsub(L,a,b) ((a)-(b)) #define luai_nummul(L,a,b) ((a)*(b)) @@ -460,7 +462,7 @@ #define luai_numlt(L,a,b) ((a)<(b)) #define luai_numle(L,a,b) ((a)<=(b)) #define luai_numisnan(L,a) (!luai_numeq((a), (a))) -#endif +// #endif From 7e65fe82c32b9c54a377de3afd4f3470f498c28a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 15 Jan 2014 22:44:53 +0100 Subject: [PATCH 03/10] Companion compilation error on VC++ --- radio/src/lua/src/llimits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/lua/src/llimits.h b/radio/src/lua/src/llimits.h index 1b8c79bda..515faf3b9 100644 --- a/radio/src/lua/src/llimits.h +++ b/radio/src/lua/src/llimits.h @@ -276,7 +276,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; -#if defined(ltable_c) && !defined(luai_hashnum) +//#if defined(ltable_c) && !defined(luai_hashnum) #include #include @@ -285,7 +285,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ lua_number2int(i, n); i += e; } -#endif +//#endif From e15eb9ff7943842863cfb6ff4d844412b179a72e Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 10 Feb 2014 11:26:50 +0100 Subject: [PATCH 04/10] Lua branch updated to 'next' --- radio/src/lua.cpp | 56 ++++++++++++++++++++----------------- radio/src/lua/src/llimits.h | 4 +-- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index 88c58af85..c466a5ac9 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -511,14 +511,15 @@ static int luaModelGetCustomSwitch(lua_State *L) { int idx = luaL_checkunsigned(L, 1); if (idx < NUM_CSW) { - CustomSwData * csw = cswAddress(idx); + LogicalSwitchData * sw = cswAddress(idx); lua_newtable(L); - lua_pushtablenumber(L, "function", csw->func); - lua_pushtablenumber(L, "v1", csw->v1); - lua_pushtablenumber(L, "v2", csw->v2); - lua_pushtablenumber(L, "and", csw->andsw); - lua_pushtablenumber(L, "delay", csw->delay); - lua_pushtablenumber(L, "duration", csw->duration); + lua_pushtablenumber(L, "function", sw->func); + lua_pushtablenumber(L, "v1", sw->v1); + lua_pushtablenumber(L, "v2", sw->v2); + lua_pushtablenumber(L, "v3", sw->v3); + lua_pushtablenumber(L, "and", sw->andsw); + lua_pushtablenumber(L, "delay", sw->delay); + lua_pushtablenumber(L, "duration", sw->duration); } else { lua_pushnil(L); @@ -530,28 +531,31 @@ static int luaModelSetCustomSwitch(lua_State *L) { int idx = luaL_checkunsigned(L, 1); if (idx < NUM_CSW) { - CustomSwData * csw = cswAddress(idx); + LogicalSwitchData * sw = cswAddress(idx); luaL_checktype(L, -1, LUA_TTABLE); for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { luaL_checktype(L, -2, LUA_TSTRING); // key is string const char * key = luaL_checkstring(L, -2); if (!strcmp(key, "function")) { - csw->func = luaL_checkinteger(L, -1); + sw->func = luaL_checkinteger(L, -1); } else if (!strcmp(key, "v1")) { - csw->v1 = luaL_checkinteger(L, -1); + sw->v1 = luaL_checkinteger(L, -1); } else if (!strcmp(key, "v2")) { - csw->v2 = luaL_checkinteger(L, -1); + sw->v2 = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "v3")) { + sw->v3 = luaL_checkinteger(L, -1); } else if (!strcmp(key, "and")) { - csw->andsw = luaL_checkinteger(L, -1); + sw->andsw = luaL_checkinteger(L, -1); } else if (!strcmp(key, "delay")) { - csw->delay = luaL_checkinteger(L, -1); + sw->delay = luaL_checkinteger(L, -1); } else if (!strcmp(key, "duration")) { - csw->duration = luaL_checkinteger(L, -1); + sw->duration = luaL_checkinteger(L, -1); } } } @@ -565,12 +569,12 @@ static int luaModelGetCustomFunction(lua_State *L) if (idx < NUM_CFN) { CustomFnData * cfn = &g_model.funcSw[idx]; lua_newtable(L); - lua_pushtablenumber(L, "switch", cfn->swtch); - lua_pushtablenumber(L, "function", cfn->func); - lua_pushtablezstring(L, "name", cfn->param.name); - lua_pushtablenumber(L, "value", cfn->param.composite.val); - lua_pushtablenumber(L, "mode", cfn->mode); - lua_pushtablenumber(L, "active", cfn->active); + lua_pushtablenumber(L, "switch", CFN_SWITCH(cfn)); + lua_pushtablenumber(L, "function", CFN_FUNC(cfn)); + lua_pushtablezstring(L, "name", cfn->play.name); + lua_pushtablenumber(L, "value", cfn->all.val); + lua_pushtablenumber(L, "mode", cfn->all.mode); + lua_pushtablenumber(L, "active", CFN_ACTIVE(cfn)); } else { lua_pushnil(L); @@ -588,23 +592,23 @@ static int luaModelSetCustomFunction(lua_State *L) luaL_checktype(L, -2, LUA_TSTRING); // key is string const char * key = luaL_checkstring(L, -2); if (!strcmp(key, "switch")) { - cfn->swtch = luaL_checkinteger(L, -1); + CFN_SWITCH(cfn) = luaL_checkinteger(L, -1); } else if (!strcmp(key, "function")) { - cfn->func = luaL_checkinteger(L, -1); + CFN_FUNC(cfn) = luaL_checkinteger(L, -1); } else if (!strcmp(key, "name")) { const char * name = luaL_checkstring(L, -1); - str2zchar(cfn->param.name, name, sizeof(cfn->param.name)); + str2zchar(cfn->play.name, name, sizeof(cfn->play.name)); } else if (!strcmp(key, "value")) { - cfn->param.composite.val = luaL_checkinteger(L, -1); + cfn->all.val = luaL_checkinteger(L, -1); } else if (!strcmp(key, "mode")) { - cfn->mode = luaL_checkinteger(L, -1); + cfn->all.mode = luaL_checkinteger(L, -1); } else if (!strcmp(key, "active")) { - cfn->active = luaL_checkinteger(L, -1); + CFN_ACTIVE(cfn) = luaL_checkinteger(L, -1); } } } diff --git a/radio/src/lua/src/llimits.h b/radio/src/lua/src/llimits.h index 515faf3b9..b278d4880 100644 --- a/radio/src/lua/src/llimits.h +++ b/radio/src/lua/src/llimits.h @@ -276,7 +276,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; -//#if defined(ltable_c) && !defined(luai_hashnum) +#if !defined(luai_hashnum) #include #include @@ -285,7 +285,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ lua_number2int(i, n); i += e; } -//#endif +#endif From d374453c8f8f220ab228397cd6673e8a023087de Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 10 Feb 2014 12:15:24 +0100 Subject: [PATCH 05/10] Lua now uses our fake FatFS when running in simu --- companion/src/CMakeLists.txt | 12 ++++++------ radio/src/lua/src/luaconf.h | 5 +---- radio/src/simpgmspace.cpp | 4 +++- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index de5e6d1d0..538c781ab 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -80,11 +80,14 @@ IF( Subversion_FOUND ) # Subversion_WC_INFO( ${PROJECT_SOURCE_DIR} C9X ) ENDIF( ) +set(RADIO_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/../../radio/src) + include_directories( ${CMAKE_CURRENT_BINARY_DIR} - ${PROJECT_SOURCE_DIR}/../.. - ${PROJECT_SOURCE_DIR}/../../radio/src/fonts/std - ${PROJECT_SOURCE_DIR}/../../radio/src/lua/src + ${RADIO_SRC_DIRECTORY}/../.. + ${RADIO_SRC_DIRECTORY} + ${RADIO_SRC_DIRECTORY}/fonts/std + ${RADIO_SRC_DIRECTORY}/lua/src ) set(TH9X_CHECKOUT_DIRECTORY ${PROJECT_BINARY_DIR}/firmwares/th9x) @@ -114,8 +117,6 @@ add_custom_command( DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/ersky9x/ersky9xsimulator.cpp ) -set(RADIO_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/../../radio/src) - add_custom_command( OUTPUT ${RADIO_SRC_DIRECTORY}/bitmaps/sticks.lbm COMMAND make lbm @@ -306,7 +307,6 @@ ENDIF( ) INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ) - SET( LANGUAGES he pl pt ru de fr it sv cs ) FOREACH( language ${LANGUAGES} ) SET( companion_TS ${companion_TS} translations/companion_${language}.ts ) diff --git a/radio/src/lua/src/luaconf.h b/radio/src/lua/src/luaconf.h index 742295325..2459e6933 100644 --- a/radio/src/lua/src/luaconf.h +++ b/radio/src/lua/src/luaconf.h @@ -11,10 +11,7 @@ #include #include -// #define LUA_LIB -#if !defined(SIMU) - #define USE_FATFS -#endif +#define USE_FATFS /* ** ================================================================== diff --git a/radio/src/simpgmspace.cpp b/radio/src/simpgmspace.cpp index a502dd7f0..cd3fb4803 100644 --- a/radio/src/simpgmspace.cpp +++ b/radio/src/simpgmspace.cpp @@ -534,7 +534,9 @@ FRESULT f_chdir (const TCHAR *name) FRESULT f_opendir (DIR * rep, const TCHAR * name) { - rep->fs = (FATFS *)simu::opendir(convertSimuPath(name)); + char *path = convertSimuPath(name); + TRACE("f_opendir(%s)", path); + rep->fs = (FATFS *)simu::opendir(path); return FR_OK; } From ce6e9fa4a9a792ae1a6c4b929987f05634a2246c Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 10 Feb 2014 14:47:33 +0100 Subject: [PATCH 06/10] Lua EEPROM support in Companion added --- companion/src/eeprominterface.h | 13 +++++++++++++ companion/src/firmwares/opentx/opentxeeprom.cpp | 13 ++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index 06c9ec13f..368354cd4 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -853,6 +853,17 @@ class ModuleData { void clear() { memset(this, 0, sizeof(ModuleData)); } }; +#define C9X_MAX_SCRIPTS 3 +#define C9X_MAX_SCRIPT_INPUTS 10 +class ScriptData { + public: + ScriptData() { clear(); } + char filename[10+1]; + char name[10+1]; + int inputs[C9X_MAX_SCRIPT_INPUTS]; + void clear() { memset(this, 0, sizeof(ScriptData)); } +}; + class ModelData { public: ModelData(); @@ -903,6 +914,8 @@ class ModelData { ModuleData moduleData[C9X_NUM_MODULES+1/*trainer*/]; + ScriptData scriptData[C9X_MAX_SCRIPTS]; + void clear(); bool isempty(); void setDefault(uint8_t id); diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index b36ed2c50..23942d3e8 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2185,10 +2185,17 @@ Open9xModelDataNew::Open9xModelDataNew(ModelData & modelData, BoardEnum board, u } if (IS_TARANIS(board) && version >= 216) { - // TODO ScriptData scriptsData[MAX_SCRIPTS]; - internalField.Append(new SpareBitsField<720>()); - for (int i=0; i<32; i++) + for (int i=0; i<3; i++) { + ScriptData & script = modelData.scriptData[i]; + internalField.Append(new ZCharField<10>(script.filename)); + internalField.Append(new ZCharField<10>(script.name)); + for (int j=0; j<10; j++) { + internalField.Append(new SignedField<8>(script.inputs[j])); + } + } + for (int i=0; i<32; i++) { internalField.Append(new ZCharField<4>(modelData.inputNames[i])); + } } } From cde4fea81790c6ca32412ffe4b96e44ff6c5b672 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 10 Feb 2014 16:05:32 +0100 Subject: [PATCH 07/10] getVersion added to Lua functions --- radio/src/Makefile | 6 ++---- radio/src/lua.cpp | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/radio/src/Makefile b/radio/src/Makefile index 16dfb8b04..44ce5c3ab 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -1082,13 +1082,11 @@ sym: $(TARGET).sym # Build stamp-file stamp_header: - @echo - @echo "Generate Version-stamp:" - @echo "//Automatically generated file (Makefile) - do not edit" > stamp-opentx.h + @echo "// Automatically generated file (Makefile) - do not edit" > stamp-opentx.h @echo "#define DATE_STR \"`date +%Y-%m-%d | tr -d '\r\n'`\"" >> stamp-opentx.h @echo "#define TIME_STR \"`date +%H:%M:%S | tr -d '\r\n'`\"" >> stamp-opentx.h @echo "#define VERS_STR \"$(VERSION)\"" >> stamp-opentx.h - @cat stamp-opentx.h + @echo "#define VERS_NUM $(VERSION)" >> stamp-opentx.h 9x-stamp: @echo "#define DATE_STR \"`date +%Y-%m-%d`\"" > stamp-opentx-9x.txt diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index c466a5ac9..0e18824fa 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -35,6 +35,7 @@ */ #include "opentx.h" +#include "stamp-opentx.h" #if !defined(SIMU) extern "C" { @@ -76,6 +77,12 @@ void hook(lua_State* L, lua_Debug *ar) } } +static int luaGetVersion(lua_State *L) +{ + lua_pushnumber(L, VERS_NUM); + return 1; +} + static int luaGetTime(lua_State *L) { lua_pushunsigned(L, get_tmr10ms()); @@ -507,7 +514,7 @@ static int luaModelDeleteMix(lua_State *L) return 0; } -static int luaModelGetCustomSwitch(lua_State *L) +static int luaModelGetLogicalSwitch(lua_State *L) { int idx = luaL_checkunsigned(L, 1); if (idx < NUM_CSW) { @@ -527,7 +534,7 @@ static int luaModelGetCustomSwitch(lua_State *L) return 1; } -static int luaModelSetCustomSwitch(lua_State *L) +static int luaModelSetLogicalSwitch(lua_State *L) { int idx = luaL_checkunsigned(L, 1); if (idx < NUM_CSW) { @@ -784,8 +791,8 @@ static const luaL_Reg modelLib[] = { { "getMix", luaModelGetMix }, { "insertMix", luaModelInsertMix }, { "deleteMix", luaModelDeleteMix }, - { "getCustomSwitch", luaModelGetCustomSwitch }, - { "setCustomSwitch", luaModelSetCustomSwitch }, + { "getLogicalSwitch", luaModelGetLogicalSwitch }, + { "setLogicalSwitch", luaModelSetLogicalSwitch }, { "getCustomFunction", luaModelGetCustomFunction }, { "setCustomFunction", luaModelSetCustomFunction }, { "getOutput", luaModelGetOutput }, @@ -823,6 +830,7 @@ void luaInit() // Push openTX functions lua_register(L, "getTime", luaGetTime); + lua_register(L, "getVersion", luaGetVersion); lua_register(L, "getValue", luaGetValue); lua_register(L, "playFile", luaPlayFile); lua_register(L, "popupInput", luaPopupInput); From 26d9455b8a2fbc10be144055791a43cae201f7e1 Mon Sep 17 00:00:00 2001 From: Kjell Kernen Date: Wed, 12 Feb 2014 16:11:43 +0100 Subject: [PATCH 08/10] A bunch of new icons for the New Theme --- .../src/images/originals/icons New/add.png | Bin 6773 -> 589 bytes .../originals/icons New/apppreferences.png | Bin 17379 -> 12546 bytes .../src/images/originals/icons New/clear.png | Bin 12443 -> 1716 bytes .../src/images/originals/icons New/copy.png | Bin 3485 -> 1521 bytes .../src/images/originals/icons New/edit.png | Bin 9626 -> 1981 bytes .../src/images/originals/icons New/fuses.png | Bin 11183 -> 6599 bytes .../src/images/originals/icons New/new.png | Bin 2216 -> 2570 bytes .../src/images/originals/icons New/open.png | Bin 2073 -> 20144 bytes .../src/images/originals/icons New/paste.png | Bin 5218 -> 1594 bytes .../originals/icons New/recentdocument.png | Bin 9874 -> 18544 bytes .../src/images/originals/icons New/save.png | Bin 5753 -> 4499 bytes .../src/images/originals/icons New/saveas.png | Bin 6839 -> 10250 bytes companion/src/themes/new/16/add.png | Bin 463 -> 667 bytes .../src/themes/new/16/apppreferences.png | Bin 876 -> 776 bytes companion/src/themes/new/16/clear.png | Bin 733 -> 867 bytes companion/src/themes/new/16/copy.png | Bin 309 -> 530 bytes companion/src/themes/new/16/edit.png | Bin 1041 -> 536 bytes companion/src/themes/new/16/fuses.png | Bin 1015 -> 3443 bytes companion/src/themes/new/16/new.png | Bin 240 -> 600 bytes companion/src/themes/new/16/open.png | Bin 1165 -> 789 bytes companion/src/themes/new/16/paste.png | Bin 469 -> 568 bytes .../src/themes/new/16/recentdocument.png | Bin 812 -> 1106 bytes companion/src/themes/new/16/save.png | Bin 873 -> 3258 bytes companion/src/themes/new/16/saveas.png | Bin 935 -> 774 bytes companion/src/themes/new/24/add.png | Bin 1302 -> 854 bytes .../src/themes/new/24/apppreferences.png | Bin 1625 -> 1517 bytes companion/src/themes/new/24/clear.png | Bin 1681 -> 1225 bytes companion/src/themes/new/24/copy.png | Bin 997 -> 645 bytes companion/src/themes/new/24/edit.png | Bin 1472 -> 898 bytes companion/src/themes/new/24/fuses.png | Bin 1607 -> 4791 bytes companion/src/themes/new/24/new.png | Bin 537 -> 955 bytes companion/src/themes/new/24/open.png | Bin 1765 -> 1270 bytes companion/src/themes/new/24/paste.png | Bin 1234 -> 778 bytes .../src/themes/new/24/recentdocument.png | Bin 865 -> 1439 bytes companion/src/themes/new/24/save.png | Bin 1281 -> 4069 bytes companion/src/themes/new/24/saveas.png | Bin 1429 -> 1268 bytes companion/src/themes/new/32/add.png | Bin 988 -> 933 bytes .../src/themes/new/32/apppreferences.png | Bin 2262 -> 3394 bytes companion/src/themes/new/32/clear.png | Bin 1855 -> 1736 bytes companion/src/themes/new/32/copy.png | Bin 694 -> 976 bytes companion/src/themes/new/32/edit.png | Bin 1939 -> 1135 bytes companion/src/themes/new/32/fuses.png | Bin 2186 -> 5149 bytes companion/src/themes/new/32/new.png | Bin 485 -> 1491 bytes companion/src/themes/new/32/open.png | Bin 2416 -> 2000 bytes companion/src/themes/new/32/paste.png | Bin 910 -> 1054 bytes .../src/themes/new/32/recentdocument.png | Bin 1480 -> 2374 bytes companion/src/themes/new/32/save.png | Bin 1605 -> 3767 bytes companion/src/themes/new/32/saveas.png | Bin 1807 -> 1682 bytes companion/src/themes/new/48/add.png | Bin 1443 -> 589 bytes .../src/themes/new/48/apppreferences.png | Bin 4270 -> 4839 bytes companion/src/themes/new/48/clear.png | Bin 2812 -> 1716 bytes companion/src/themes/new/48/copy.png | Bin 898 -> 1521 bytes companion/src/themes/new/48/edit.png | Bin 3393 -> 1981 bytes companion/src/themes/new/48/fuses.png | Bin 4176 -> 6599 bytes companion/src/themes/new/48/new.png | Bin 611 -> 2570 bytes companion/src/themes/new/48/open.png | Bin 4395 -> 3362 bytes companion/src/themes/new/48/paste.png | Bin 1369 -> 1594 bytes .../src/themes/new/48/recentdocument.png | Bin 2635 -> 4249 bytes companion/src/themes/new/48/save.png | Bin 2625 -> 4499 bytes companion/src/themes/new/48/saveas.png | Bin 2945 -> 2936 bytes 60 files changed, 0 insertions(+), 0 deletions(-) diff --git a/companion/src/images/originals/icons New/add.png b/companion/src/images/originals/icons New/add.png index 9a1ec67d003488bb0114bb921125641a5c3090f4..dbb1e9449a154b599f99a44a0361a9a9d5a81190 100644 GIT binary patch literal 589 zcmV-T0d~8?l-`8)=&fJi-9vK_4@FOk=R)z~mna265HW2HZIfo#-Izk76|&ou>}UptNg&&u zmp8LJvngSW0cOboazPKkn7`R;eBC}k0wY7Q*Jz|5ip zfS&6JPr|nkt}Ds`U#up6ItiHw01=}ywCV?duO+H`S8Gz;F bQ-A>gj7vUFY6VE800000NkvXXu0mjffzJi! literal 6773 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 vq9J$(yKdjM!U_}wF5Fbq7wI*3SpK?Ht05siNU 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 O07;36}a literal 17379 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 atN#ZmQqSJ`&r9_H0000^(6`iC0HR?UO%r zDk0hJMiKaBz<;*;@E}EE9&xXtSu}lWj>>s`;_0LDlZI*8&iP-yoD=YgBXRO7wNflC z8zP>zV!nmy^wEY1)Zup>j8QbEQmLquZleAM7*#BZroW!2azUTi`_fQH2@Ze$tNEm_ zAMh^@kyo;4sbq)}=?^GWS}|$*^t^3}jsgw%1AvbzR0MoQw;C{EKO}HH{Y^$lB#sQW zl;F=#pIWHFAC8e1_j1Vf`tvH2XrM0f?Sd_dwgP}Z2KcF6`y&*Ms8lH3hF=R6sY{$$ z6cT%0h^>?0&;5EjQ-ePg74X?L@b$zcLUoBV8PY24C0YtJ;GYd6=T*u#fnN(3txKGR zMA4Xd>QJ;H!GHhl%wp0PWU0h~8vJ4t__Y$eWJ^^`#A_$fRG^1OV@mWU4&5 zCrCrX9#PB{!)EWYDxq8E zU-Q_lLSw2|PH%qPN2glSVwIc%<~^ zoqeRZl#r#`dnUf&4&I`_|6CzmYYuOx8x<0pwtHPkbdylu>Bi+sTX?$z*_fhA>Cs12 z!ug)S>m2^7))C&xR65xI@*ig8Q$q+ZcI@q9p3^8rFZbNe_?>r$rijL zfw}~P#PB9YOxb97qPZK+;2jIBl^7b9HcSH0G=B>{mEjEDl|Vy+Q92e!cgebk&tPnI z1MhlGj1*J=9>Uwp7-0>UTT6Vb2r4q=WFZiA6T?jvN(H=>d}36h0*3h2T`3a=T%xUI!kn#%%yzHOl}WUdk%l6gd}>WD@8A@nC&InO{Y^n*-UQh ztDwQI!r#LU+c0Lo0VdP66)qvSlxVe}N%aAKt6J^~-df%GlU%$lBv2B(i@jd;QN?O5 z(QHk;laYDRuNTRSC}qPXJYQI|fVlP=C49)8gddF>>l!MuAUNb5khs!mB%U#lXBCr? zrfaUM0Ee%70{lEKwjfy`?WqBq2 zm=fTF0^U=~PV$3a^LzX^r|~!g&kUraV5>UX*g{@TDdhr5HcP^iWiosrejZl~naMkr zi2boK$u!ffyhJ$Li>Iih`}#TNaln7!YHN`!Yl!%E-m2yX-iK-e1I?m#9aDPgG|GJ^vC z6~KSK5mN~vAr(;k)w?8Q^jV=WUl@$b3v-ips)jijhlG)qbG#&sySC%dV0mWPfOk5X zt4S>3qjd?aW~^{Tz)N$pla6|-`0yAO0ck0h6^nryya(|F{0YE+(u?V|kRYCOIzAe$ z!P6~g@V7THYZA1W@UI3B1iDQB3NQeeJTTd6kvwAn0000< KMNUMnLSTZ=_%X=< literal 12443 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 diff --git a/companion/src/images/originals/icons New/copy.png b/companion/src/images/originals/icons New/copy.png index c3bd1a2ccd0944e7499ae952d9356e43094b2424..49e9835c0a7f5f543c249d563e0caaa086ea2db9 100644 GIT binary patch literal 1521 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 diff --git a/companion/src/images/originals/icons New/edit.png b/companion/src/images/originals/icons New/edit.png index 106709caefbb93e52d23e3f14dbd97929696646e..38bb9d67297b183b6380f5313db7bf86da5011b1 100644 GIT binary patch literal 1981 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 KS{0gT-2VWDHGHH1 diff --git a/companion/src/images/originals/icons New/fuses.png b/companion/src/images/originals/icons New/fuses.png index 4354cdcb2d4c5af9a98d1684d99341b26d990a05..f5cf7e6800b13590cf7c6b3f7e4151e1974de6d0 100644 GIT binary patch literal 6599 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 Ef9Y;Vi2wiq diff --git a/companion/src/images/originals/icons New/new.png b/companion/src/images/originals/icons New/new.png index f15f28a4a4b0904b2d1c518048f15ee24e94e569..53dd74e30c212aacbe159a93b49a9ecfbc92e410 100644 GIT binary patch literal 2570 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 WAuSwmy~X`iKw9!j-TO%f%YOlYnDrU} diff --git a/companion/src/images/originals/icons New/open.png b/companion/src/images/originals/icons New/open.png index 45fa2883a71fcb891f1ef7c0c217d71eeae284bc..4bf67c1b058f520bf7c9e08aa51e700dc90f447e 100644 GIT binary patch literal 20144 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 literal 2073 zcmV+!2RP)CWtKz1rEEwa&Ubd$6s{da=&VIP1;2`BM0`Wb;D z{M-!)vd0-ix#k=pmKgFxQgYk(eOi$0QlJD2NbOI5d5567avIIj< zv@<}9dj`!tE;Q@xs8{wNhf{?zUNu9!u=J3D!C+h_ze{}K1V|htI6?j0>T@UYxhDij zhnKMl|M#(rT!AcZ}eF)wgP_d zAX10jekLr}U#(CrCA<(opAbNs2#S{v>vbjZBPMG2>Dlh2!oC#Mk@9m9Zc z2%^^3CBjkLC=!RpAFqNhVw6pZB#Q!^oqj*T-F(Vw$mLX*nO_ zNX-3DeeTpEomGUYnz~IsN92z9JUkMF)7=lf!HB}*Vw`?29z6pA^e+N~guKQ7E$%u) zC{dC3_66}y+`oN81yr%;K@{IH8|1O-3y*riL6}qGd@SEo}8X#Q_kq zZ|eG3QMpHgF(8Pc07FLLD$kpMaaUZZl&Qk=tr>Kq76&g@g}Kbh`}mD}bLg zSob6#9DIaI(-=7VVTPPm{Z+FbtPVT4Iv?2~9(pg}6TG@z0w%t}gOqRBIG>z~1AjdP zW3QR%ZYsA%*Mp?X$w>b?i;UGgQ?+sSsoXX8X`%zES@sOGBngFV;lVB@d3_10@@V;lg>dY2BN>v^RZ2^?j@k8NdQ$X;_ z_a$H}ZfeJ=gha#~If~qTHdcoJ4Lhqwh-3dbkKgY5JsSA}oWGEOlkpdDqpb%S#7{~T>2A7M zsP8QLl$cN`w?OF*Jo#7bDJpj@!Dj^fwz=d)jlRsXTKwbW85}(HH?VT^u<$rb~rBzaiB|lB=W)A?(%51dO$!?mU^ ze8O#IHd*n50bG}w!BKl4^90wps7K`#)>4RXJ_(`usyx1v$_9j`-;Pq{6K%jV&lNRO%>FPb&x$A5bBEmwG~ zsNAo;tlZJ!2;Bu-bsyf#uSL0b05WG_^}?r@soeJn(y81#_yhC8@e_i|9PXV^3ptdy z4Z_G4qZfz6FCzC2|JrSe-C>#48@AYMyIwNBFNyyFX1QPd5r93<00000NkvXXu0mjf DP*&js diff --git a/companion/src/images/originals/icons New/paste.png b/companion/src/images/originals/icons New/paste.png index bdec2e65eb531e53834e68c45b04b41addf49055..2198b77c0694ac7b3d25a0e42054597b632c9089 100644 GIT binary patch literal 1594 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 IJ16CT05(L~fdBvi diff --git a/companion/src/images/originals/icons New/recentdocument.png b/companion/src/images/originals/icons New/recentdocument.png index 567494905ad936b4cd029e6635f774a63d05ce36..87ef05d0e91d9a6ec05c90f9f9dda9c1f3d6d6ee 100644 GIT binary patch literal 18544 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

dS829-aS>3?C`0AD!~WVligTn#0_=3wY|O$LZ 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 literal 9874 zcmV;DCT-b?P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyS! z5*P;<_pV_^^mFW3fyK`cffA+#ZNtGm@L z^}f~e-n)1Hxc606%dDb75~|CmD7v<$>-_FHzw+s1ZpB(?pXFl^&;8DkM@=+8`S|GeBJwOVW^WcLIe)ZyuFTVCoxwW+> ziXxO!Xsrpu5FrFn6qTNfA6H6gA%sY!Qgn254E*_@|M~S>w{G1E7VUJ@s4AIRRM4^EXQ$> zQkIPFI406bDNE1Ak9(d+CX=C|p+P+N+;gm4x$;AI-g)QkrwRzF0C=%4#sa`~-IC#B z&rk^v$8ks`5_q0ReSJM09UZJ&x9+k#@4WK|rveD70C*WsP#F?l$P+k@gX_9@o`>)I z)YaATi(mYLtFF50^1JW8`__{k1XTdMLQfEb!FAm!fQUnZ>$)To2@;6}xm=F^{(jc4 zU%!6KmM!12An;E{5L5y13Ozv#hS=coedR3<1?hB}ef##&*Vo6DS6+GLJ@?#m(t@B0 zfL95EO5;}&#uxyJL;~OU85tQtN=Z*o50_nb*_C(Qb=OT8@$94mK@|Y6LLWFbC9DKN zWf*W>m*L@IJkO(8EYj1{!{wJ>e${>V-M8^%13?u4uR)m_Y}s;y^#sWi6%MKZm?lpUdw>_p z9(>=Q;t7Hvpu4-9_3PJvaP#KP-#n2iVif?>f?-Dgx}5)e54dCYtPHXk?I)k&zb-2XPvywI&Dx4j(?u z<(FUnvDf*{Pul(f3jT^b{y6gVZzI=k$xy9_b0HBnr8v6xSs0EQ$D6L-dJ8~R{ zWHMO_6%!K^B@n#teee6E)>>`Yu;FXg1LS!fJB!?^*`}8d2q8+wujBx~L%wW^Soz+` z$w|7qySe)6t3Q?W{ltf^z4i;%1H5kSWmOV5%_}B>TI-i=E{#1wI-Mq)&C<}&Kx1Pg zp6Aio*~yvbulU%eo4@}JUT4|(_(HX0flXm)D&z%^HIkO{}T_S$PdV?ScrJ;Cvjz@}zawAWUx z{=4jmkwG{(qX0$7WV2|kNhA`bv@mWnt5gh?GMpg@0=l}o*t2I3Q4}$E?p)TdU;hU; z-+c4nM?d<}FI(dmt0eGbHNOJky42Lx(AL&QQ&ST{2t3a#brQv3h;K0fq9}@6%_$TL z1VKP9m*bv$?qSWEHJ{zIY180`Km6gpKPdoET`x`olgT8_&CS%-)}oY}(nTD%n#YEZ zqNuc?q9`ief*>FaLkfigjg5_Tc6M_9`R9Lm!-fsJZn@=_JB!6)t_pyYbj7>95)?5p zoFW<6;gfg(B?dt}bP@w0l}eFHrReVN)?fP4m;T|Vn{N6gX7VUJVE`Bz8swQnqvVTK z68O7mK*jAPax5JQG!aVK%t3238m&wXL8FNx0Xjh#35u>O3Z$EWc3=`1J)tD<>^W5u zI9~9EaRUDLQ(GeT+Puv}Ev&2S8&}GiT4OlEBxS7)DWuR@zh-Ba<@bx{|`$O-=_7 zsFJ{wkQjm>iWJ}w=?J9++LFXb={VV(mf}#A1DvFs;Mm!N%IW0kTvY&^0wAcINS^L> zoFs67r#nW-6{;lgb!P)wA+WUrrRW{Xop=B=Hnnihyt=A&P5?0+JD5800H~6{mnLzQ zoj{Y5lk^=qLZMhBilS1kpUtG1Ib-G&xBgOHL`s2DIwpZ9768@t!fRk~knY~YOcVkp z^Law8aa@;FGHH%g)rtsEg#z6}BRsWlKRQxKpe~!CCY55vvSlTOuo4WfNBpk>U>bJ% z(C{!F-8~FX=J3;LT-T!z<|q^kgh7bsd*p20-*yY4fv^~m%S{jl0f~f%>w6S5Z28&G z@g&S_YGTc*)l+`gNkamM1_yYmW0+hqI4zCux-Ny0K14JLo{#6c6oUfcXc5;3Aa-uuXS z9(6O%#PL&vk)n6_Bp`uJ%`L2&SASX>e`xS1dk=Mx$<{D2?ogZ@Cv-jfj~-=Wbd;o* zB-_wTZQ~q5nV=Aagpoq2h+L#030_(v9EWkOa3ypf9;TQZCFwb|&YVSaOAAMj9AR>N zl)Bk-80_0aO2DP-)-k#-T_u4h!rg1FdGx96xS1M4;ZPVGC7&2ks-qNl5a*>mP``_><``|0gqoO2^<*M3JT# zgyf3>quC_IP;;Q8kNoISmakmJ`1mM=T#mP1df8jQ@Rj1%zy7taU6aXX#Kic-Yf1~M zO5jWEdVt^V*uex2bq$S3AvmyqKb?DavuxGH6jC$k8yqF&yUd-@#FBY4SUh(Ib7$1k zSd$^+CvY8MzGSWN+yqjXLnVk5LMu=TfksM5Ctd2YY1*3WX>ZOlr+qfF7cFQ1^M~l} z>|*r=Z=t8_5bwD3(zk!-)?1%jwrbTpfDc}G-5XB=f7>y{g2$Y|5vlK1(W@K-%=p^z_+^UOX;t+WtT(^2H(vH(}U4 z5NXiLyjIu}ui+ew83N zt`P8MCxK7y+{yCAX92Kp&u(@-@dT}l*V27-h`O3IXS6kQ?$Y_>^96Q2f51!xD{FKV zDsBVU$@OwX7$eeuh=cmjm$l_NO@1)q`x9 z&)E0`&2?GMY;UHuv4&z0@K@LW5nsOH+xT7rfkF$=2!!3ru{%dA`!h)Utk(8nZHz62 zL<;k)QW~W+H{W>=pLpL@1VIs{B9zv+Qi$4`bYki9l_QTl^iX*AsCXkD;~fn1S&2M=o9r0g<=pev$>Xq?M>8XQwRYHO(vD( zlOKFHlao2L7Kpf4Ln{M_*kkI-;SjUK1t26y!xl^%n05U^!07k{f4bohCHYY z0)%uN;a_y|+lIG4`FOPS?3GMTj`N8>{`5n07oXAix^sZRfqtGiIK*V(O{4@CC#lVX zH!{MQBYE=CZKP+PMUXErv#EwTGa5*G2|LAOc5|RYE?%>eNa?amw?@=jAS#S%3@Z>) z5-Yk|gF>K{0gKS({;ryAhMH{J%nB%Nyo*+#wa{7%jc^E~^x5aE8s4+}xyI(ECbZVs z4S)FYAOFP{zj(pr9{@DB%wWy@Hx~(f?3rgM6ns2C$%FUa!-BIfqJMal znN79Ko7qUxca7WD8X?LZSz2p^HNGzGZe@0?iub!Qs}urJ5hBnUsWp)RVSy4uK$e_^ z1gVL%LI6r@v_PVb=a5qRt<5b%2|w9*=->e^`Tfhz-}xV&`QpEQf79Pwvta|by-Y|r zP7?U$8VTFAcP}!TCJKuD>ZkXyV$EAQGB83zZH76m_4uAsB59POx$WT9+Bjvc^-aZW{GVLXXCT1YsUAe zJb&twK!HZ(bL1v-^!4?zcf%^|U&ym1`6y(Q8nG{K~ zDarB$OZk@{Y~}}d-^W)!`!Q;3vSxzU8o(G@l*pa2yRM`LNMYKzOpG_c5Yp5I%r2KU z4N%0Aq109uF0%}zG~q{LJb^%fR!Avz@6mqo_3zx`tUT)s^^Wsai((M^i_cg*5r&c9 z*W1gv=dQWrLZb~lJ*^(#%|Ze@j}DU0O)@$*%7TSwab#?aww4AOYBT)z&;KzUJw5#6 zrp;tS;z)@AdoN1hkW}^unh#J4zVxXLQPT5JT5Cftr3iw+ ztI5{p8XKF$*yxB}arW6)y!%7f)>Z*<%o-RQr&!1%96^0;14l>3sjEqnP5Cya8?`5w zFIWTXk~>!lYy7D*T1x3M53tV~T$Gg`Bl!wqaad?k3MYc{8N#LVp(t|=Gbt>P(m^_c zVh{?)afB37NJk1sN`#Pd$g(SR zJTPqlXqhpK^AdROy$$rn&j}{Anon#Z#me1g#Y}fU-%tm@c2kzbZV2p=MNshO(aOA(j***vB`i; z%BxWPD#RF}(L$Q;9Yjg%7gpuby8M_G^vYr(#(*ZdgD6rAkB)&91SLtCDTs-US`v-T zrnWr6@Pg87Vvv9qLYU-G3L!zZ&z(~k86PJ%Il+vXGv|H!Q=gu9&*se?RSp0Y!iXpc zh?F9gPLnGX$RvH!(Nm%Ci;{triP=W}D|-YbD(d=E=e0$t+ea~)%P}xI#*v{B4i5}5 zS;(6s;VM2&VB)*^$Fath2q|$LiR-wyj)UWv*Exh(JNY0aS13>jBWqLxqCyZ5hEeRDG>%oyWG$2Z;qd;gO zjX>!8zVv-B)KQqIsmV&E)EU5|(*l70qes}bzyFjZfkH|q28YP!%`U8|ZN^37IOTJD z%MuUR?7SrO7=ouNOs=V93X}N)xnj{&?Nt08MWD>pL5g8$NuBK#vVgMc9zvM^7n3T+ zMWS*MNgm_=E7C(Dgw!^rlu}ALGCZmp8X5?~kVGP}XxcnL>&#i4zo_|?^#H%x*1=d1 z;CddO>!F21!f~vIPdT@bt99y_Dqw|M&{o6G7XxyIe7XK_dj^y?rChBw(lG{)iJ-K* zJ|=wS>km?@BM79a2*(DGy-a+SvWg0#%?6Ot#ID-fx+sxw@jM@(VfvK7Q=9~3DpIsG)t63_)i&KT zC1L|2SH_{C1UK6|D1?*(rIhp5HRq_eu002|*6;ZE_0Bm97owDA>7x1a`j38~Acc{P zt!Cg<0T6qDSbqm}P^19-#b^Go%;SZLv-e7?Z=WX^a6A<@8` zSu^M#8f7wHU?P`icx>Fpae=gwU~FhaWh05S_vS%iuT%<uqo=lN@GjIYXdd=tmZDP%nCAswUW$+)T~q)7!$ zfuJP%I3+OH%Af53l5rD>Z7OjpFIP{g`BVsj5<=?9Twc40gp(VO7#JAL`^n_47YvD~ zT?QZoP4)E%DH$CZMrlRT^NcjBYy*Y`infECmDRquJJ=Auh)9)XAQ@L?w2^V0lIu2U z9;IeboAwEbkPgx@ua#2{hc>TqrDFgf9b8wEkP^4zc}IXFz>Oc50wIO!IC#KGWiq&4 zLihF_9?E7iN2bjK96i#8e3Zlig~2;aU6|~lx_HcVi;O7 zXm)pbp5N3HR7nh?LK3!(J_xjsNXMS-BLuCD4ZQQM=P@uaY+e~34R1YwY5By0qbv|P zC2vrceH~NyF|W}Ygw%FkLAydk2fMqyhMBYR5}r8Jb?9Jirf&K|z|2{*dCMtG0s($K z(M5i2nC9kI279}iJ#S&jm|(8kL#YO@5ZaV);{zKh<>oP{j2o6E*KclS2bXtuI_aV7 zYjC{;jw5h{5o&}Lg4_}zG;ZIuq%clN<4z&N0gNVrG|B|!wxw_)2vTCOpRw^V2KxKA zZ@qo<;IxH+Q=J5At*OtXX=rMukk2tRJV??@*gigCuH0cY|2Xz5TM>-3GS8RidrW*5 zq8#_F$m=*34o+@y5?r{7(DdcCbVX zA=J^MN2zUSOpJ|=^8EhigQV|2@S@)Ev{V9xVDX|wL`uAX?)*!ED_b`hHbnwbEr&sP}5aqP}55k6z+xV$T6nFPAhfThxFxTd`eDeT;UW8%HZ z8jRr_LshkPT-r96MUOoBgg>LDg>*X2jvY@QtZ!&~stSN(Q$f$8E}bTkNHD9dja@sQ zMmmxxQfM8KNVrVoi`@9bt+5w-v~t{3S7#@~BO@H@=y-6;Ew}7? zv14S8n*{!5?-9mN>A?_9*Fcf>)>aPe+e2s>d=wcYfBTL*>FDm|lUKioVi*vj2_ju; z(N@~*Ms3}*F7W}g%ZXz(HeTDG9cf#`sVwoD@~$h&?P8|+N0z({_V>ktwCg%taq;=; zV_*4O=Zd#qpgy$zlE{%V`sITUdhPQU%B}=|R;JeA?@@5VqKDk4d3&V!^Spmq( zxsHQz?J_>&-@He}F5kv+$1z0DwdBvS8h}I??|`(iozgH#%wOV2w)(6y^eun$U!zU; z{9JVP_3L@FT8oE=N9sd2p#kyue%>kI;JuCxD6kM_)$vfV%KgOKx736C=ZTGDJqOF zD^x#99^eHGUwKnn>!^QVAaJrZnf?3r5(c68^@9)I-`LV}&&z5eoaRew&B`T4v` z`{R$Y_Tsnm+|FmpmuJz~hEP$S=ocm+3sJ7w$I@+Fz>z|hia1l{U2v>NaN-bPQ$(lK z^;4QKd!Y*hO{r9At+f!MaQFT9*Uo5}p?xpGkM6p&udc5CJ9pf)ap2|t{^JS(NBVks zcyAx$`Qn=b1k!PMw&N%(7R=?~-aVwVHH?prkw_+u_@l~=qS_XB&=rawMy-oagfNO; zxw$izgY9^Cxw=|{?o!ew`AylV~Fv$C$V&s&W@?%#84Z=Yk`z7rRF9LIpF;&WfhW7%|10l|a6 z`Hi#qoYkp4yLKTRN8EPHru%2LxBstOZ@lppT~qM1R03b@i+$Ugb4g`tIIwRoa~CY+ znH}3nIF2=NJlP|OQvpZ1?0mi>9uu@ePucxTL|Mj-heGYoPH9L~S`A^U@rOpo*mdC0 z3-K1Ml+r?o;EC-|X`RYs`+IwIOw#~h35rUkBO_S5;iq) z*4#E`&z;B9Pd?6ym8;qD^!AEkOvTAQLJ~v~xBd8jQc1s}l}na@5^MY=rZ38pu#goE zpQ5s{+^nSU^Ob+P@z~T4t+jR>Cw%0w#~2QxTA?DHN@v8)8^3#WY;^280CN`r00st0 zL_t*Vwr<{h*9SlPQEq#M=LJ>)aEuo?W8ord9m(AJ3)%j}Hdd@$Nq5&l!a||kz##-l z-(%yJ`}p_=t}ur<#qrz@Ziw=cE>pywI1LoK^2Crb>5Es&_xSJ?mvPgNeo~T}wP^*5 z?!NCn=`}QFJ;%`r&l7jt{)3S{yLSD3bw*l_B`Q}&rHy^;mwdwSnAB=Fef zq-V43(ciFk=|XmH|1I+uEv8s3GSJ^o+q{K@L6PCHNrEustOfH3!qAp;MVSa%gHvkh zmK^9lOmkfgEe&;cF3=wNP(EB_3JBi4?jrv9ufD~GtKMm@8X777-(7bm&OYxg;%IL# zH8olBy^S{wJ^A?K|GTZN{TpBWlh42EqvK!g`#E9_Oi9l|I=O4Fzzow&c>%)SuL>86R} z`5RAbCGh3K!Rm8X($d|{!%uBz!5L@p>IjdN`_B=+026YfA@n8S!Po5Ui`P*OJ zci;D4Qwm&-{4Y)lwbrz^wQ=3n@;#)|Sv=3@XFvH#_=V4Z z?*4o}|An9a=ttkb@|tU2)8ARWWX#Ke03ef2^ZqNZ=W5=#t42+MnWbtCI zeeZi2DF%pyq_guNcWu5M6$H;5?mYC(?Y+HE0OIc3ZhPY|AAh9xFc0qOWjt3ry%6Ee zLN?ZO*Sz`__x8Pn6B_?9Ls0`{r8^UY50Qdk>6s_x{tj zZWv*jE+2nc3st*5@B z0XLDLe`JIsgF`q8$8vsi!Hq~Mni?8uoHLhMo=+4-q|zDOgv;RQC_nqfFL-p@qs(h- z=f7S5X%@_10Kkv$**dL%OO*s3=gMTVyzi>3C=?3pc=lNy`}G4jsWi>4Eo5qI5lHg6 z94ZJX77M6JRjLUj+yuVwqoNSUk>qkY1_lQ>xNkoP_V2|NaPfr~@h6}C9J6Q5nnDVz z*A70(mhbzlS-qMyt5=iD9kXZ7{GDvz#V#sc1;9zPQmGV6mn>oFk|ibM4Gj-dC=?09fG~>8 zWRjFPu8Ze+WHTAksnm<+|F4(fUlRcO4j<-$-G>=F-ALeT&MFM&H`;z+Z?9ax(OT0n zFnZzvFuT2-3zy8QTJ!|0A0OU1t)Evd2cKeVx=CPF2|UeL6#%FCI!+SU!>@K9KK+!y z6TFnxboP&(3?y()l>}BvV0BeVV0BeVV0E2_B(V2z55L^q!+5Sx{RZDq63EFx0^8c> zaN&~KRg0Vu68LPD1Xf94l><~)6#&(B;z(dmH^1E7&DdmB34CKopyp8jNl*@Mn=_XS zm$X$aaw14z@2)BdtdhVg2dJ(S1ORg=Vfl)O)%6Ciitk>ZC;)_+Oh!~qabi|Bo7F%b zdvwuj2Gpy3eFA6%+JU)13y`du<&8-KfDxb<=l~7_uUQv%9bw@A1LkXX@-y3^F#rGn07*qoM6N<$ Ef^3By2LJ#7 diff --git a/companion/src/images/originals/icons New/save.png b/companion/src/images/originals/icons New/save.png index 651b2a41fc302ca57261118f3f256d469e373ca9..20352a4f9b93825fd4bd6109d8b360a70524a2a6 100644 GIT binary patch literal 4499 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 literal 5753 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 QcmMzZ07*qoM6N<$g8d-i9smFU literal 6839 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 diff --git a/companion/src/themes/new/16/add.png b/companion/src/themes/new/16/add.png index 6cb5042f2be71e2fbc5bc1beef88d79df0003c0b..b236738251dd8a2596ad69ca1800d6a684721621 100644 GIT binary patch delta 643 zcmV-}0(||?1DgeqBYyx1a7bBm000XU000XU0RWnu7ytkO1ZP1_K>z@;j(q!3lK=n! zAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fdMgRZ;5lKWrRCwBA z{Qv(y10?_;fLK6;TNWFN;NL%gIHcudkIKl)YW@BD_a`$8Gk^QjM^CRkdHBednVI<; zvRZ%uV!>wW-@pIaMZ_eOwe*ZRe*OH(!N$hU@axB4m528paH1Ok5I|TBU}R)q0BU6T z^x-4J?_a+dSXtS?e2_Rg00uHfB~v1{OAiAAkli+`4*u zJ3s)jKotLB`S|85*xAV8fC7GieF`NY2K@f{hY28nAb$n`ZTElOrkXfLB z1Oje;LBV`Jetve4p-fCn3_$sxAK$;92xNZ+=?7wVpn<0W0*D1_`eJ0;fl`!{|&^fK<7UPiKD9p2p~pE dvok<|0RY2){bMWI1lRxo002ovPDHLkV1l-n7lQx* delta 438 zcmV;n0ZIOw1s=3<2~aNv<~^-ULLJkjfkh z&k5Ep^tk=t8fAF8o;@GjOD8V|ABOCYCgs;K3UhEgLlS#m#=Je8lt?X=UgZ!{U^ zCbl9{NoVl*iq2xYd!W;83tN9Bu;@YOZ3!8r(#VqP|1S^-GC;qAU(mLBLHe%>npZD( gi?MNHY&2cS-%8_XA#U^IYybcN07*qoM6N<$f)RYp6951J diff --git a/companion/src/themes/new/16/apppreferences.png b/companion/src/themes/new/16/apppreferences.png index afcc0a5326153df965bcb833254fae3ef2dcd5bf..a39e89ef9c6b64365765325a70bd66ed50891aa0 100644 GIT binary patch delta 763 zcmVeSaefwW^{L9a%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*00Bx+OjJex z|Nj6000000o13MjrLUxNKoP+MDMK|x4G zMM{>IqMMteYHDk4ZfBy~4x8#(&t@-nqHLz`(}b+~eTj=B1^xtgN}p%F^KA<>TY%?(Xw@dxnydoXpJB z)YRJA+Td+%d2n!io}Q+pq`IZ0xuvDMsHnZJuD-9Y!m_fvw6w;xwY;{r$Gf}3z`)JM z#?sKx+SJtD*4E$G*WlUN;M&^Y+uP#Y+~D2agVU|=;-e0 z>FVn0>+kRL^78fc^!N4k`1kkuuq>J_0000-bW%=J009CpFflVTH#avpI5;>%NJvUo zSy@_IT3TtOrmeBr+1c6P;OOY+>GSmU_V)Jn_xJhv`uh6&{QUg<{r&y@{r&#_{{H@P zxZ&gg0Dl18NklllkV+J7Eu$eC6lu_U|G&-w0B|}1 z005QWAQK5`@T&j--6D0lUPn?39RLcgGP7C^hs#w)sa1gRO_TFhrChGG=EVUN|C4Kskb(X7SnAOlY&4}hoi z9FTzitlr6bEf#OK`x@4RIC{K$8{{UF-1qza%dvp1z3rRs$Itld^LBTC2Y`)Y{Ob2F tdi}5o0H{w6WH2ZXPc;Al0vrwy0RMr+BqV$jE=K?W002ovPDHLkV1f=nqw4?w delta 864 zcmV-m1E2he2J8lq8Gi-<001BJ|6u?C00v@9M??T#08sz{6CRFI00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-vj2@V`Huo2o+0008{NklXe9xtglST zTI!_CT|O#zFmv&!tffxM`pT4uh@^izC6$c}NdP62`gr`2fsvow||0d{DNh@LN2?>V)7$~A|XJS zk5@Q2{yw1)G>mTvJn6S27fa-_Dnkc4Sxmmmk@3BVA|Nmr?O^%F zS$YnAMK-IV<$QEK)Qvx2zubO(&1o1;i;JPM+>I9Yg<% zH{M>rAAdg0m3W;!E~DLzU7(<~6EUHq0}usqbg&zMf*`G^oE=*6f@y-LgV=docD=AY z@pOVM^*GaC_R`ls!rI><#3>?90h}V@6e(8Q>FgTi!r5N7)Yo}yB0;0BmE3hpyX^Ni z-i-7qDAchmgXbpBv9kOg-Ja_Jlp6bZZ2vhb6@P=#Xq`ykHe&Cfi2DlW>Ts-*_R3bu zD>welxm?yoL`2uFi>|5n+>q+a01N|yPp(ikVQX=iNEoVBNUy@d zXIcEWf@8Jl17oT#wM|RYeC-bZQGEwZgA*@)_TTzk!I{8V<@o=u5x`vTjWrvk4?$i= q>_=NFPY(FOTZFpn;Zv8(yVz&v;naX7V0000**gBYyx1a7bBm000XU000XU0RWnu7ytkO1ZP1_K>z@;j(q!3lK=n! zAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fdMgRZ;*-1n}RCwBA z{Qv(y10?_;fLK7petT&!=ilG|jBH%Y`G0=>+x7n+!!<@mgnz<+|NgVFbFt+9{`q$c zQ0^v3&hg+=27mx!f+_g>`#*z#1p8z|caeT2eZGwh|NpDO9QWt-TNuoswF8M9kX7gO z{Qm7X$cqfWfKC^bX4U%mj&%}HnFl}su|WO4@5SREw}how)fj-*f?W3*=n_5=W=&yn z7R_(pe>433$G`vz5+&`Jo)AO_xHa|f}%|7U~d8O z?{A1e1O*x+Q1kcC|9`%C^gH91!D;N=eIu$94x<7BzgYr2I|*<=>rHLm+kPsFdIJuF&on_RTgIM9)D0Y0t65wAu%v+{PK_W5-1V<`3ZFP zk3S5*|1$sl#mt%Wn~B~17X$lEkk}uf{68T5^$*L}-;68^L3#lK2o?tS{;_d-|7GR6 z_!p?)?|e>iwDfo@yD`2YWdziga-e_1$h{{8uz;SVFrx4#@bDL}d9AdLV4gouUz z|3;tuUzo>Twd`p3oP$H2_o$-u_81}LxsrVSu~7%9!p009O7 Xb`mW^?oLKU00000NkvXXu0mjfhkB5p delta 710 zcmV;%0y+KT2HgdaBYy&5JQ%+411A5u^X(B){J?GtUe| zG+wQ?I`sW=^W(>*`Li=0|CkNiw(PmNx*86To;DgU0DuF)r+?+;dSP~Ug)=sv8Xa}t zjE`IYfnDp~y?Nbgt!zDdR0ja&)oQDS+1Zum))t1X7PM06o}YXDcH4P&dg=qf`ox4~ zSF3J*a#CLG?m{aC0O=(gKlZfXj*DiwM0;luBBt-%0X_WNG9-**@Q zycr+2l9uJB^Lcp%voHk05VxK@fxovGCo`?#_xoNq2%LqJ6QBKgNvUksP2apJuVAJ% z^k4uT1Yl8eR|xMi2%N=}6CXf)900(&ZCj~K#?2&?Qh$B_4%Kdh1K^y4h|n<%uPcPJ zczhh!EUtCM7_yZLQl^R4;UOpji3r3wI1%(;_3}T{3o|or+Op)u&Q6?4L=Z#}LZC<_ zM>u!aN+s)>U?YMvxt#pgXn=Tx&2QFvid|46i4IqX7_O?wv?- zBN9DGBqZ;2>f&dob9B19dkyZHruV}z;@e&;l^mgzJ4qyOL=w(9l0k690N`CVTQ>%S z=R|~II_(Wi(^-gmzM8dC$-0wDxexPsnM@?`r9anub$@?>#$<$MZarF4$-~|Bu0>JPdf^FtDSpWb407*qoM6N<$f;tUTH~;_u diff --git a/companion/src/themes/new/16/copy.png b/companion/src/themes/new/16/copy.png index f348604335b132b090582a42ecbf7a89bf66a0ac..799b8c317985c5b7c37fcc7f724ef5977c7e8792 100644 GIT binary patch delta 504 zcmVm^gp)e{AZR zkU4qvQ|D*I_$7eY-~aq)`0(>D!|U&V!E!%-{={k_3ye`eVSmYdZ%5MvQ#~~>|L5QT z3~WIB`yWL9+O0bb)0gi2kM1q70TUN&ng8L_r-Wr2_AyLZunsKo3#j=Q)PPybwlKVV z|A8UY)0{zAkRPsj(t<4z1MWU}m{5`$!te#CdgsBj48Q;WVOY0)AD9*w6lTy8dF%TR zr~yBIKmzC|P}92gyTCRxGcYoI`SO+F!nw;>y#)(c7UU2HNqYFWfECP{I+p>Lw<1G> z7+@A-7_e*W9XpM1(QC1+pFFieGRSKnzgZw{nsddI}3jsXB(?EvO6Zz5GxNxP>i=V)GU@ uH7vL?6*g~S1Gus$DCGz<5C*>i0t^7WJ2iJ|`o7x$0000d^YFuP9RcYk;0>5X7!D5Y3RiD~M(hUa-`+x9C-l7le- z0L%;`Vq1ua`@ZL*D42*oZTsSG5XUh9Kq-YqHdBM8HZRt@o`1x3U4&r>-}m=-$RfZP z0$>jS&iFIGd_P^3QlczN-J7O?0obiqP^z*5q9}Ukd7hhqvB6(9yY&jpYy!3)Z#W(+ zJv1i|fb;cdwt*F}d4I*}RB4;V29EPv$2R{O48wpd%g}Wlf*{Z~wg@3igEUR`D-rS3 gX7&kFn>o1wViW(jKuQ!}T>t<807*qoM6N<$f@I`=@&Et; diff --git a/companion/src/themes/new/16/edit.png b/companion/src/themes/new/16/edit.png index 5358d50bbd5ec4a0b36bfa7f584ff07cdeff13b9..2157aca27c8871b956f06334dc8ca2dc59fc9d1d 100644 GIT binary patch delta 522 zcmV+l0`>io2$%$r8Gi-<001BJ|6u?C02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00Fv5L_t(|+G1b;f!c>GB1!jB)kcwNE-B9kxVzCrNlfAYA2kCm?r#i& zA}<+O*nTmvG5?bI{*Bio#?xfQg3XtI;xqsRcAR=Zk|E64oJEQu%(w!FSVNfc#W7Yx z*x4CGHLE55GxEHcvS7zaW3VAP2+Fn`_H`J;Q~`ISt>r1$*E`xCEU zf3<)~xP#%_M}CI47gjQSVrFrGr$l1G=Bau8Y#(n2{9$5Ln7r>BFconGU^Rf1g@u`& zjh&N?jg^Cyg%!wUVPysaCPqdkMkXf4FiR1`JMWpzAHDl`79hX?$Ewz)%?lMd00000 MNkvXXt^-0~f}0KR8vpF=o5)2NWC7+JBrUWXEf*;PfvKp-5Hhj>Es$CTq%55qrj-o@ z5-&{dVnic15ts$*xJ9`a=b&Jb%U9?XXiL9-ZNE||b75cRU%tu7^FHT1zc)E=EumuX zEjQjC0KnmZkIrI3$flp91F%St3YPGg$8i#3B0=YrhZZy5jM#*e0Q~F+0RJ}tcCahH z27n)l0O-;Hpw$B4lGo68CKThAPoGGP#sdF7xB?6B1P2EXvQAA-JjdhloZKwi0>h2~ zCVvI+YYqhQAhB4CMI{o+$jAuRU>188mF?GySt~0mJv}`O3kxEVNFWeE5Y*k>JuwZH z_NpA|WmO{G$JxUBVtv@HX`u{dcS+q#`ilCL-YvSS5sgn9+CF8#2A=Lf1b-no2e->z zTD#8+lX(*d{jMDe&!L>S5Pt3wkDAVmT8jlrd+alcN=C&!%+49Rf(fGipv zMuv~u20q>H_tXd(TfK)&EA^A&S(QrlW)Yf)Af;OUYG&rev{E5iT<>RDpSi=*I=NaS zS83#mHHBh*etBIbffNdj`cKy8Q&&`8r&`ym)H;<)XO_!NJd+6?%CU62Y^xj0W;2SS z&lQ^nNUn#?umOdQ7Q=8J`s5%Yf1=l;dKiUa%bdn)lqwO#iWs+ysLf>ESsN~ucb1zC z1{AfS7Tcz6XIrhdTCEm~1wjxPhPAT!;hwhL-Cd(`%djNh*f43d$ePxm*6{R-Rjq1O zr_msroBvp?Z+AB~W|l2CyCjuDN#(e#`lYPqZ&}Thtmc)h>ZPo5Oja=hI%2 z{O?WJe(41X@n=CN4_9&Bp|!-}!K1`Nd^{0%)xP~(==$R}HVv0?JSM8xdH(!5X6*A~Q#hE${(p{5vcs`v zE-s3m==z$G#>~iy!1>>J+={=TkN0T(tRZzu8oFCHuH9SZ*n$ zr48+O`meRrJiFO-FElw~=%_dGaIg=V?4QbW@^3ug?fIMt&wHAdpBR2M|dCBx)k*D_RhhMhX0q tNTLymmDHlh_kfGJOjg$A_W%lwOra4e?|?PK?Rg9UanbQnosnrp{{h8L4(I>? diff --git a/companion/src/themes/new/16/fuses.png b/companion/src/themes/new/16/fuses.png index 512a067ed1fb8777ac9d9b3949ebc67cec893163..fea12cc6daa5a0e9e93a9a9063e816fc3ae4b359 100644 GIT binary patch literal 3443 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 B(f$Ac diff --git a/companion/src/themes/new/16/new.png b/companion/src/themes/new/16/new.png index bf119555758ce08ea0c192ac458c04dcb774e63f..d3661a19448536ff21d00638827cfc744166e2ff 100644 GIT binary patch delta 575 zcmV-F0>J(70oVkPB!2{RLP=Bz2nYy#2xN!=000SaNLh0L00FxI00FxJI_%@(0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$R)k#D_R5*==lD}&cVHn3h z@0$bL20;o+QHpc287J#j2RC=8cFBLx4k8pws0D`(ML`@Y4u8_sEK2v(A`P|*jhjl) z%MS-7BzH;P-1|7(UA!Evec<7Jxx4S@`P_S_fJ;E0^J(w61 zvOITye7oJ=w<2h*(ORRFn&_8bci8>2%i@(qHuIZ2tUZ{|{>na6J4!TwmH!Xl{<2NO zZ*cIf48ZqB8Gk!!YAmY`KqjLBP)dyrbi$zdyNP$-8v|e8sfEu!RaYGVtu=_CqF2yL zh5HCFcYO}$mEs0)xFi(IijM+Z#?|rUaX9KsV!x7GK`v_COla^K_++un@Z_ICw8jR> z!z|7hLBrP1EwXR2cn&|9q9k|ag#s2jozDIQAnMpIxqkvUj&oZ?-UB!QDs2!=KMRno z5D=e3q#jp%?OXteA$8jU0f0!PAdZ(i-cnB!9O_L_t(IjjfWg4TCTgM9)@4O+`&dn-$V}GDPKRK4n(O0#pp( zbkLYf6I+-949TnfW!>}F$%-WUz9)`(19%u?UI0LTBP1ar+(Se-38coxb0G>etAWz_&gVs8cgu7dgU>rxZZ5!vRs>(RzbWO0O>pGt9V2$@ao-Ya3 z{47XHjGto%rPOu7HvIn$mSs5%Yn|41dV?*ApeTxKf@zvyt;Iagrv)F5x1mmq*#E-- O0000{(WXrhxQLdD36ZNF8W~RZ81psn z$DKR(+4=9apiM<*IRAg|nRC8#&Uen`Ms;96fK#N01~K9daAUcY`IuhESA3Z5J;8sW z=QZ>AT`rBjvu>Up3wH3W@Ij3AUkoGAUUoqc@uDt^KKw;2fG2|(Xzb!5M>-B*aY;jK z%}%uTd9W>j$@i1yxjz92$tZfO_Tp*F;d^+Au=1J~&WMP8`xsFY*BeYY85&p3PCD3q0AodfFg3oD9#;4$*&8QG54z z|8oh04uIS)aXiSZ)E zDvVhI5a4ookXl=09n3R;<#_B(M^LYXQp!*TnpLhr%9C=WroqO-S)=5cYDDtpH*1L* zz^CMD6yBhloM=~g(IQM_z4E+mGk7aIY!;Bq#-S;4_VVrdyr`(gbb3u^{{kOB{FSz>bZApDIP;mR5cb)-3MGNN~rAkhnyMAdsAY>}F0)3ojpk$AVQV8k%tN+DWsf zZaL%~90n1wa&k>7D21^1+AWxrZ5IEZ!Fxrd+(v6uiw7Ed;j68)oT~7*?8vV zkM-BzEI9jk{plOC)^4A_Y~{Q6A0Iz`w(r29xr>(`yZLy>gRgT>Kc0H%)`FeKikmuj z?cM+Up$x$|N6$%j)8-I}=XTJO$tc@3Rexdq7uWgS~j z&pPp-bNl(;oflHeYJ(%98kX;#bl}F6LpMv>`l{xvY2J8Z+QDn33%33L|9_jkTn8}t zyi0=of*E9{UorKP7A$-I=y#-m1Y`Kcf8TVtv+h4X^!tvV(%HX{f1gSF*LPF)i*NeB z{)~SY#4=!ptnD&uzYZyS;lh`U4qNKPp(`uvI6iJPmt%iHVpl`E1{PHSr=uU?g%_4<{xl&OiN#FkmJqN8r#vbNg2 zt9nam!?YLQzJ2wdVUhW1%F4@MzVJ3MwOvj>Gsm?0+?~qLy*-ZW5)2|Y6kL3y>OFnt zteMdbb2E3=96c4fdhMFrgnJueHkaM4ingw1pRrzMu9?N|9lH+Jo_z4&-NToy4}jTM za*BOM)55%Vpr=(!Tq808-nxGO3D+9QW+dm@{>{(JaZG% aQ-e|yQz{EjrUHuv1_n=8KbLh*2~7Z%n;2&R diff --git a/companion/src/themes/new/16/paste.png b/companion/src/themes/new/16/paste.png index 91bf4afd6364c3b611778516dbc67ffd69ebdf07..b434f103c6288b4761766d97bfb6afaa67e4c81a 100644 GIT binary patch delta 544 zcmV+*0^j}B1Gof`BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz z+DSw~RCwBAWWWL@PMmn2k&)5h|Ns9N^7Hcz8SnrWbb*G32Ko2z-y5*Avpf9w@#6pk z0l>I#M&x@SEwKKo2wV_oGm0V@KUnu2i1)!MV}&5x1%Lkh6@PHec4jCwnMKGlhAC6h z7I>WH58c18eyH=Rd=TpMM!%fBy^S|M>Y6>Vm&e z7odh6!^zjq41dP9u?(hqYGD4)zyBH7fcW=6i2U~-U<3XEZ34w6s^6}C_hfkRRi5Ge zhJ6fE7OVq{{Q_$Kg=7HS1%LmrVL0H(Ek1^lRA+`SK-D`Bo@My`_YcFm?fbxVWM~k? zfFCd~U~$2(U%wb+rNkIse*MD`66nV82Wac>fB%8>e}Ax7ATId9!14?11vZS32bm7` zH&Da6^}E0}|N8qIO#1``pt|7iUlyqI8R3Bm@*m9K9zHH$e}ilXx#Abx1yBQi{9tBa zVPS%$Ex07ifL&Ynpt!)^%MZnX4~LIF5y0@me;F{XCCtvC73YmLfq}dLvW^poWzi*_ i!t-u25E%gg0t^78z!h6YUsM+W0000Aw z!<+Y+@4T5Y0xFeC5?mLH#W6<6_*zQ%Mc45-$z&1$(=_>@DmnveTuPr?j< zm3$R|{MIh@dfiX1C*HFB;S1H`cDRE<@Votuo&0MqFMiVb+vU1@!$0c^5bU0e2J||= zcrhVN%o$j3w)_pv?>4KOd#FtYl*3#uw=oP5K|}+ZsmTZc*=%;`q(-AbCX=DnY88}H z3?SnGf`E9Sb$@>jQ6v%}l}ZtfMhi-*gCPfK56~bw6wquo{n)nc0&HyTq$d2R^`YgrkEhz1#nv<>lHZ08UQNM>=>?N;N4F5pf*n(QsW?L`2HvviMgB mwP!q==2<|kR>QKak$^kyki`mem7Wg(0000WM00$%h5LOfzl>h($0s^N94v_!=0{{RP0e=ZZ3OITR44DoPkN^Mx z0000000#gCCIAv(2oN6#88iR@02(N~CO4-B9cCFYS_K|v8ZuM>2`mQ>CI}fv5hFbk zHj*@6m<$|93?M=fAy5z}Nnm`*0}??96Ff3o+gokHNMg-znb9O;LqpSDR$~HblNn1=~<8EU!3`Ao$YFq+HIlnZkpt8o9S_w;c}VbbfD;VtNMAS^nkGW zgQn|;oXd)>?vSzUlZlm-z4Vu{?3cRonYr$py7ZlnnSY+M=AW_Iq_yIt!0M*S{HVzA zs>AQCxYw`E^s&L|vbE8(w$ih=)3mg}waN3gzvZ~g>$=0-ySv7`%j~|#;=jh_z{=*q z%ILzw&BMXQ!^6zP#Ms5k)5y>0%Dv0V%+<`u)6LA@&dAcv%h=A$-_O$N(b3t`&C=7* z;MCFN*MGsq*w@|I*xuRL=G(;4+}PaQ*VC<<=@=q=IH0* z=;-6)>gMX}&`|NhL({`vX-{{Q~}|Ns5>|Ns8~|Nr>So4x=508(^PPE!B?0000000000 z0000000000000sf7aJW#MMg$iTxxfBcXxS?j*^n2qphv7v$V9r!^Fhd+S=RX<>~6` z>VNX}_V@Sq`T6<${QUg={r>*`{#Zdn>;M1&{z*hZR2Ufr!A(!XFc<*fw|l!X9Q%L) zii?35gE8Jrj2eHtSC5`dcF|xM*<_%yb!CNZta+^Yv1pId>Qj}bNoHK#ZJyfG^nnq{_k6R6moE#T w2KkVAFk*G}vrS_FVi_hf%VFwRiY);A1LnMYbdrzlf&c&j07*qoM6N<$f{_(TU;qFB delta 782 zcmY+Adq`7p6vuya>eiFUutgUAVM#3E&KEd?(lnDEl+CCM!F-m1J#R=A2XS=I(3vwoT_YY>%{g?{?L0^j8PI9KK)92hKUu;`Zofsrtj? z4P0Rq06w<`4`ky;@;H36IzNs=Wgzse#dN z2#T9$FN1tTmd5eSBSOAHg@JYK(H z1{<9;87;Wl|2yRHct@sD)b7;J;6~iK9O4#(?3XbkHSeaJE+a;osUN;2mUPTd5;SIa z3>u~k80lSNar>Okj82pE&?NHq(^uUL5e#wu#o&;^ID(k-cJ58_eB+JK(lMJyn7Fhxt4vC_0{-EsgJ+74v4@^TLrO~{*mZHUx=H+Iccg2lq_Q@r_hH*0I`T|(Kp8D^epV*N zZc&z(Rt$@_{^*GkX4Hss69k!Un&xD2Z*PBJ&F%FMnv$TV>RL_D<4^Bj4)iv}3+oj? z92p&Tuc0wduZ`$#s6U)tqEMY^Z~Yu0tS^d_j3mVG+bi8K+*FWPt1)$TsS4E1-B)&q z+a47hJ`yA7l1RYiGFc-*9@X<(?^WfTSCtg1O6A3srF;WPkSrw;k|oO06|yvWa=JV< vNeap25cDj)F6%#_;#x_0S@nNFsyroC4yFDBoZhDv9sqfwoKxAIS<1RU^+lv^ diff --git a/companion/src/themes/new/16/save.png b/companion/src/themes/new/16/save.png index fbcbc53a435ee3991e15747ca3dd1d0f598cf24a..cd0162b619357cfe6196d594c2d1a7ccfacbae18 100644 GIT binary patch literal 3258 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 diff --git a/companion/src/themes/new/16/saveas.png b/companion/src/themes/new/16/saveas.png index 2e4ba2b82d40328f1711b65fb0f15638b801dce7..3c3045a47cace8eba1cc3d4c075b4f6a46ae3e93 100644 GIT binary patch delta 761 zcmV+BGIs_AqQpdz;Mx1e&nTGVebB~Kmrg7_m%YRvYzvpwl=L-L`o`1Ud z?0uPy1z_&XnSOP0(yRA+a(dcbT3U)rr4pr53GY4idY$$4b>>f>?p|JA?#`SD(-&WQ zPL`Li{ptXMYHA{}iKHfyc<*IwY)mF5CZt?0OQX?{)zwwWRVydb?BwFiz2eT@AN(hm zKU{JE76M|1g?~T@fnu>pk|e}&OdQ8VQA7xVw3ze8d`5HcKJ}eWc;(#3-yIs5jh?FF zy{Awp5JeH*dup{B=g+-HJXm9E>mEH{rQVzn00DSnVId?*BE>=hGh;kWan2zk7$6dO z?*-$VJ9mjI1=fCa+`JhbWk66RNfOdD1rdT73V$HN>+>ycf7{^6*(yK&HH#A= zs6IT&Osy7HZrrf_{e2q@2G;F%t=(>0tJSifZ+&F%zIn>-eD%IBVu%q(0&gOKMrd7h)HSP1eT0#&8o@6+jY$g=}_yE`mA^BCigpJ%W2 z_edDWF&YA9c8nl|5kaL=;rrVwl*c_UzV$gEBk>VI$aBK+6~fTq;NXCbjSaRM%GtAv zwA-CSTrcz$25B{B~sE zos;5E*O}^j${NV>KsM?+>_)DETm#aI@liA)kUyHu53aB6Rc|Hx{(+j$6rZa_dB7e1 rM1m91C~|q^B>(+EIdAsje*pI{NRNvMYx0*200000NkvXXu0mjfiEwG` literal 935 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl-tmOGnnF#-9E#X;^) z4C~IxyaaL-l0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP+w<& zPlzi}!T$5-qhsQ2tZj~6x_jpO!z=fm*;rXyn3w~(r>;G?a`)M-N3YCH&2sY!vvcwe zp1OSV;Y%|UQ$sz&|Eu->&tw21At9lPXw&}-ML}Gk6$~IjNl8gKcS4+~y0S7*Tv6sh0 z?YVsGLEofll_~E3=L`7w_*K_6p1g3irM=tT%^m39>yva6lT!8_J+tq~shYYbUmrg= zS9eEy$NFU3|8u$TwsYudX@-P`#l|Isg+&Ag2KjjVczJr=*^v2vp>RdGwvL8oOiWyG za7c1WT0v3C$*sLdS68Q`rpZW2hlfW-Mn)GFm*y81XJ+RF1O*2Lh2#|!g-1q*g@yb2 z`fF%t{Qv)dTh?58px6Or$7JlMyGzDL5xY>?k-K;oBz82Ih+L^ zk;OpT1B~5HX4?T7hdo^!LnJOICp0j*sim>095{3;?esau$Av|OpKsi}Y5k$8vgQv{ z)3-8(2O26mN?OMh-aW}-XVhCKG%4s3k5S$`xd1_b{rt!Ua+dP(2G`HqD+I(bYAlct z;W1HGG10L(6zwUgv0#yuq^PX0wD|l9Gp4Lz+vIMmYN~6itY@rktsc&-vS8)Z>C@)L z2SkL#1g+vN>+*|?s&sWt4c)p4K2~6r?au0R#{vl7R;Q{`H&aq({ht-yrWn z!wn#SU_M|3rwVKq{3nzXF)ct&5C8!Lvw-W@&z~r{l~5djEdGx(h`<(rOHhCS0$cFu z)2H6AUw^-9p=$x=4@NF-E_VSTVgCRB|Dgs0Fi79Lesu!KeTd;LNb#~8!~+N*umwOH zoBo1g9?hx$fj(kkWw`{5G+mUk2%1uU{ruGlu1Q1~h{(;LQ6bl%@J|Heh0|XFJ z#Wlz<^tu~YibDqg0mMQm(*Ou&dxmy_y8jl13&;VK}-hPz=Vna1I4*`*nLGM#1(Jc_``qe z_Fw+%*M9MTVis565R{6*WiAs72ZNYFESLreAQpse%ve+ct$$!*{`>LMFNP2Ae=sn! z04@FZpMm-7Z|q(MJDQb2!L5^lg@d2r^~I$O00G2=A_)vDEcibYkOmnJ3LX$|Z{Pd^2MZ%J!~(8A-x=)ujV4v4`ltU$woVjxGnc=3bb`HL4|2QYywW`aaM z$Oj-dvT$=U{9)!51BQw?Kmf4-v;UvJAa8@yImFeBjEEEjbS1-YVCMP(4Do;9cmm}G zNJN7i@t+Zqe?a_y(8&G$_un5-!~z7Mq1ti)0DnP{rLFs4w=6+2O1TafH6ss zCyFHY4OxB(B#QZ%DqK?u3FGx|yb|_1h%qVa2NtiPJpsh>`Sb6O{ECv?Ou+09NrsFJ zKmYs(Tfhn`iAot8^O-T@csVlZ~y=O z`+p4(KrFjv6vT4~Nd^N$i4~Sc|NV!AJ&^h#u4-zf>l$wK_Vo)$W(N5NX!x768!mmi zf9e=eA<$2Z=oydk%j0t=|Ns5|7$AUH-rWTjxpx_G7Q39x|LPeSV~rR=t_KAP(8bKa zQu5>N!$)77nxBQQum%wT0mOo@IOmbJV1E!dN@V!==PM$dnV_kQm4lT5KLF=6fB?d2 z0iUcTgS<;812ZcZsEh_jEE5wVrJ;lg9sm$PEVv9;aPI;-ftlgozh8)=8x#l35Q`Xz zGoJw7bSo3jhKL#R5J#D~RFDP{Sbw8`L}`R}*hO1AjmO z!Gnlj(UCzBY&bJ8-~9$fA~?M=v9JM?J39jl=N|@Uc1TKM29`Czq{u>y1pomAR>UqK z#~`ff&+z5hX<&-^g>WITWc$g&vh5!K-}wJ*+`_+s{6CB=3_tF_{_^GV*<(<@{Ksbj zKmb81KVXjh4@@cl!Nmt7W@2Mvmn#9fToi87zrTO~{r&L>$ofdg0)PMm02lvA=7OLr QF#rGn07*qoM6N<$g1&q$r~m)} diff --git a/companion/src/themes/new/24/apppreferences.png b/companion/src/themes/new/24/apppreferences.png index f979f3c96b217fbafde644bc42ff489cd35627ef..8d81a5191fe91b560f126d71d3f7149ee0eafc49 100644 GIT binary patch delta 1493 zcmV;`1uFX44DAb$Du4d~{{a7>y{D4^000SaNLh0L00VXa00VXbebs`@00007bV*G` z2i^h<4+%L@ZBJVO00nwUL_t(Y$IVr3OjB1Fer|hjds|wh9~7iiL@5Y@nL0=2h97Zp zaT>BL%c5BnmuMD#jV&4%GBwkw(abPi7RQt+GFhT=>Qv&#rhgJf1o3kYDDok*6eoq! z+xC{W_ug~%V`X8?x$tAj-sB`F?|IMj6@Y` z2HM+OJ#oJdfHF~H6@bhwTehz)E8DmdKmvf7LqkG@QcCyl|7ug*ms?YFd@F!_0EUSW zSeu*goQcIG+JE2g^#XW){`>{6dOY3;rIa2z^zEkr=3cmP^`I;()aMff0J#$(FqM|R zzg`q0G#ZttD2~KpF^S5uLS3?dA#f)fFLThVlL%g1I9F7dF z+x=@RfWRo|sHLAfcWKw+#YL;y+8#7!W@gOMYBh$Aj!x9p9*5881H&+27=RE8l}d#r zOBP|-vZdfSmfpM9dMPh2=cPy_8cR#FEd$U3fR0sBW_kJ6a-EJ(N=;49pcI;xmOD6e z<}6s2BY%3mQA|iMFg&jp4Tec7gTWB%@9*b&dLAM#FOP9J>{)~mjiL~3G%B^-xY2YQ zfHIbVR97FqRZvivnwFL_&F}Z4zP&_E6WK=DLH@syUsW`2S8HAFJ$lAci`i*XD{x^&!1T& zNeUQ-0nh7Wk`!#>IMv?q>Ns%Vz|WLMYFL&f7K<67kO-sEV7_?q>ZTJXzW<`2;JM{v zGk=&ofBu5EEEbbZ6eAGDFcK4u5QK1)=lPzBii(k^Nzh=>wIwAb@g|cAvMeDG5E-X4 zXDOu=IXN?L-M@eLPXbz3ccmpcImKx(80{>}CCr{Z1%#+nfxwXYADhKwNwQeX)NW73 zg9nc>JRC+aDD+B_6n44V{~}X8fENHvDt|BEv!b=-TfMlV^LU`2b0MNuh$NG}Ki0B8Y3#x|Po`t=5m z=e18ZZ!Y^L8jbW86)l(>42o((2sn;obUI$m^BR^A!h}L$csv6jL_tS~>&B{8#rq#U z>bcw13m!Sfn* zcX!wQ>gprs0Vd>dI5N`H9kzo9EAIgK34jovbkDTpY}l~z2!K}rl=k%W z4EX(ix_b5M&jGw_v)MLYzE1q(-4!c}D*!B-=-4y?SPq~lp6Qypy1J&8mX?l%3m5JI vU;&T?p!iwSjF|wTIi86cfD6DK{2%OhCs}StW+r3y00000NkvXXu0mjfJzlwd delta 1602 zcmV-I2EF<13)u{iDt}%8Q2+oF9*$A~000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^h+4jmW;wh~nU00rhrL_t(Y$BmYKOqJIez<=j`U+#qq@=@;s3oeva@#vS!pQg_nOTRZtEnI>BZ*C$H?2Ylh$7@2 zde^bB=%Wfu6tPh*qWHnUih+)!Y779kLFU!&QU*h!x-vJb2nM{w)Waz*9RpBq~k$(}pkr2xo7j5J2a4)XJd_*kz``bA6 zw-QEfoo095V_d5JfPXc8hBI+1@$s8bO7TVA5ejmIm}q^G!#ra8CydA_^#Yc6Rh}yx zQ3ea+y@-VA?{DM!m%rhsujCP7-wGn^-OcPzFMcnT2;B#!2du@cu^B$Ty)%`b zjz6R822X4)q`BoheLZb>rboc^qNzZpfp~40LjC17Qnnw$m03u-GaG>WWBsht`iL+b zi1pt$Uf019?#1KnCogXwIkp@IM=RWc@fJ?yz3bhY_({PZi+>p{LhF zM*fGGW|)zIT7L4wSZp?cAXq^V>wk=<>t;2UU&Qpn(za*4UhL~~P|9FSay~iVt)*iy zgU-$|W<4`>cHXCbFoUH0TAUm5(RG99gd8TPJWKV-1D0P5T|Ol^@T`5dGv=JXOP6K6 z{CR;`@<77j1rZUM@$^Z1%R4gT>02|tES2R2D~v#Q?Ag%3PWxgd?b+a-?SE80eT4@RM8vWznV1}w%C`}Jmp&Wl+2mf6 z({tT%hy9&OuAV|po_KT7xO|uNUeaW`9jUKk?P}jarrVL;OPW-c?~;khVL5r?O}X+h z66j7i{LpteaBF>;zf;NOkAIPhGQ{8cK)Y&@vGH~h5$Wr1m%8I?=PSyPhL4ay&*rlK z`DD&@#~!v!Uny8ItH)=3FzxsY>Dx=VP+LiAR0$h5tS0F`OHofT!ka;Uc>+Os{jb~raRd!bNWd!{d+-* zM9gd?6bYb|J%} ALI3~& diff --git a/companion/src/themes/new/24/clear.png b/companion/src/themes/new/24/clear.png index 8414751d58e9f0ba703e56f217472eb3c15595e7..92d92c9869f888e13b3f19c6dc3d6b8b48228961 100644 GIT binary patch delta 1124 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 IM6N<$f}p#!v;Y7A diff --git a/companion/src/themes/new/24/fuses.png b/companion/src/themes/new/24/fuses.png index 38ce749a13421ee0e143a2652e9db793cc6f563e..2620abd66c1bc8f4c64dfa2ccb7d6d6954369b86 100644 GIT binary patch literal 4791 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 RVnF}^002ovPDHLkV1g)qGHn0= literal 1607 zcmY*YeLT}^6#tE8Yi#+Dm*n<#BUkJa3QeUu;bv%5uD85Z_ujNkmTtOyk`#$(KGmI~ z(x*uats$|}RdU0X%6#T+BCngtye!Oq_tgEX^Z7mJJkL4jd!FZfpXZn1@9RkJ zA$ogJ>0nL247@hzj(aVy!7MrKPIE_)vc@gg3!|{c#M3=@BBlSDe_5=F_M+1eB+(K< zPM<}Pd2pQ`L6GBi2r?FdAgCW*#nI6b;E)NxgoFfZYwM>^ zpSHHP3IqbsadB}Xkw~FXq@<)685x~BckbQ0cj@WrP<&`;XncG;Dk=)#d-v`IRAy!- zXb{K*XINNRO-&6rVY|-GP5?qpKR-VRfdmH!!x^9y=&r7=qN1Yc=xAqWXDk*A(a_LP zNWO640yNUw+nbY6+6%`fl-@lKHjKt&duyqkbXY8S+I9KoF z9^L%>{G&&Y5(or57IWngZv2k6`sLcrTV}uju+HUjWilC!Mk{12eaSHcihvUeg@VCg z?%ur%oVaYjOY?PRy5jkN8m6VC(dl#uK|#p0wYB}#Teq8w8?E6B837BO_|H zdT?+Mu1}>>_4oIWjg4tE8aN(wJv%$QxVYHR&;Xp*)zx)(cf-SIYHE^5Bpn?cLZJ|t zZ*OmhTWEh#JU2HdX)Kw28;YuDl(kx_*N&(x9sP6z1sTsmXL!K#{QSJSN)PRe(F`TY z<#MG`xv;Q+_Qar{1=G{hnrad%@kHkyspXg9Euk;W(WwGdU5C~iq61L&+2RvC+82UK zsPPq2C3N+eP4^8zkoBCV{gj`Br#ozPa@1KkW0fiZWBztEsrJ10CyV884y+VRdD0YP z!KPW0yV(=gddXA!ygq9br*&{Alm~WAkKZ}834dbxFmc%ju?W{_Nv4 zp5!DST}Z>(jEZ+09IjiTWnvRP`ew_%`Bt3Xlf^fimgGL(g^80mkZ#UtE|)C~XfAT% zL>kW8`coG2&(sq_6T>n3zKOv#hP;KpNL$4T*n3qB{Z%~mByF1;euK%E-vSf0+mqU< z(6&4Si=`~DU*f@feI2|0IkF8BE_qYk1Fc%4BX(%}G~4j?jaP0JIOB#%WQNWvea_WO z2M{vZN*EAC4fF}sYP^!yX<mtq6T`%BK(E{l^hpKYn8EawX!wPNsEa}yyLKgd2LR?x+ zLuX4*>hpK9kM|6Fw~4JZ0_DuqGUueBpa_3E?xml0wyxUFCfk^YU0=JdPo0*TyXW>u zf17;`Iqc~%C*v>*S<{#sy|klrgQZ1LI`7UZXBOGk?fa>Q7Jlrt2wz5c^798F!-Py~ zYUXZ+^atD2^sD;=dqpQ?;*65tZ;G5MRI4fc`%J{!QIS0T$3*T1T1$jVD6Di#68B<` z#Sbe=6$N3fr*0{Pic^!yc3JWo=HD;8IXucq2ctuS!cnGFRA|phi4@CS;)i==++`g7 zu<}p!ulzEN9fE$03`%54ltwIGW@+fmTvJE;4l%bvCT8xKZEv9ESH)t_^EU=JRx`R7 zMC1zpa-}AFV>#TB1=}Nt9TUku=o)?OAQ)tmoxP*2oxQESOQ8K`R|gmPHrm;{+S&Q< pk#7G6aFiMI+o6-+0GwPMom}ml{s#;xI2`~$yghuWr8^_e{09o}5gPyi diff --git a/companion/src/themes/new/24/new.png b/companion/src/themes/new/24/new.png index 192f3a238c01c13b170e60faa4aa0cb305c58a75..5e419a3b48b8351277ddc6aa73c0c92029fa6d55 100644 GIT binary patch delta 933 zcmV;W16ur<1iJ^2B!32COGiWi{{a60|De66lK=n!32;bRa{vGXb^rhab^(3Wg3JH_ z00(qQO+^RZ0t^l%JBN@j?f?J-NJ&INR7l6omeFflbri=xzk8E3w#`0%(NRPv3?KJ0rM?z2>R#%fFc1X674{DZ1NW-FjBf25c7NCu>=?C>RMV#RW>ecW z*==&~{T&~YdvkM_#?B`X9Dcuh?&W*F-}5`alPKCIB0P_&Ysw@^-Y|_%v+-l>9>!%!$?(0^K6uMERzF;=aZD-LIWI7@0c#rapy^G9WqYiDKv`0U3?j-^NVuJ}Fo zR`0C?Ck&sIVHiDKDb@9Sy>y*5y+(F8OR@P7Yj-6O_PDmfU-FRLOIZ@>#3*s5Vx0u4 z3)ENO@0C(0;AZhAVhVQ_Z<9$Tp=!g2EsWn+AMj|WNPnfVha?0HCSp+qKA6!ffl`!e zC7j0&ThrDvM>ChN2K(3-3Jx>eRibb?RLH}z!6Sp6*63qK40w@bpuh+B*#{*GsZv1d zPzvjm#n6l*`vMI84TUSM7Ju(+1;?OlgEtC5siPoNnlAS3n9(LMk(+=RJk5Z51rj42 z*2yd+Pk+Lb5zt8>#y3HNE~X*SXcy&kd2&NJ@L+8lw)Q#+)@}It5p3-O34W!{SHV5l z-r1S;+52l)S-7jJ%_`%|y04 zx5Kec7xhrlHQWxEBxmSa@8E2ucKrfcT&y(zPn3FirD+q96c| zfc82A+qNl}%hc<2n$0F!Yb?vE0Gsx%2T;(4BE zt$#&pEsKkb!QS&cnV+AtGnvdgewo8=gebPW*Uw`puC=CCs|6*xe}BQbe0lPNjg5_k zof-MjO9Q&ai(3x!|i z`i^a$(>%|kTD3MWUHbUU($ex=^m0Dq{~qaI1(bo(K|cHk1W0L*Tv^_Y00000NkvXX Hu0mjf$I8Cd delta 511 zcmV004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0004xNkla03d+C91y;7=3! z1=)+Bl)%o;PPSp#QW8J_!7aFO;lkI44uZ4fY9;B$KxWB!2{$NklZV!S1Gw|=sx&7be{AXsFloA_xF$Hi`Fn>HnjfYna?CnMk z-FhiL`E3ysy3+s-JB#?r$O#itbC=acvPOA%{+vSh&UBKA-*y7sp*bapU! z&Gji*p3W)eD2{jINJR+8-hRu6OT$fw?D`qTZTG9`%d(`hgMF^%o)~CazXElg?#BDI z%{X?bXDfy->_Q?riGO`HyHVRx3||nRMFwRb*!mPK1Dxqb-~Fu^c;dNwj9#h4v>QW` z-$9P0QRlBlxZQ`+YJ3~r%H`@8y)U6{j9X9r=6G8hH{cqphC9cp_G8wct*BvuYD`=Y<` z6}rDmEE<_X6I~mIhhg;zR}3xN!RD$qcq<-*X_^QIgYbAf`dLLF5WvNY=kP*jJ$^a= zEyn*Gd6AZ$QVMzwym@^0mdYy4$hNcj!z3LFSBDfiWPfI75gGmw@yS5~+5C!t z&kk~K9Dkd=S(Js#$ak`lFKPl(tA*ZlN$Zrd`lk1A{^a2v1u#03jKbw%s@WV|$EKNX zej&GYa0Bg};=p>smoNev4QVQ(+U+9Bio+ z*t)GPqCSU!rKCQ^P$^ObgrgPeGGoi<5~jZrsekbi)%;y6PyhbKzLvhXOo$QF`8iMeJjWr00b0GRMVQe>Rlo3ShZJm;9l*1dvYNRjt2Qe{e2kl9R6owr!zFO1{*K6cAH(C?z5fM%ADJ z1PbhBA-~jbPMvJ#UJ99cH&W&|^8m5vwKtPhZup3m9)95e_|Utq9ewAcu^-5p{Ofwd g|5a?{^^X7p07tZb-BaovsQ>@~07*qoM6N<$f){&CGynhq delta 1714 zcmV;j22J_)3FQrtB!2{FK}|sb0M^*lPgpVl0004VQb$4nuFf3k0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv0RI600RN!9r;`8x z010qNS#tmY07w7;07w8v$!k6U00p&4L_t(Y$DNf~Y*gnJ$A5o!?w#>?7TYs`7qFoL z0vIQbV*?2|ZJL%eDX5C_(u%ZASCJ}Fm7=skY87>PXdbFcfmE#^Nt-ka0t9s{Y?eTp zwls-tHe);{1}}q$csw(n<<89Amp+(S5v48VNZ;f4`=9ea-}#Qft%U&0yR)r*Q(a@z zV_r$J4tE`R9)B1D76K_CbBk<3z=PlZ-c!4F?)lTq-^XXHvxym7lB8EQZ0LMp>((a* zfgju|eC6^LD}VW`U9ZND4qsIdUrf3^17mLgM9Tf@*SP(xp)w`1!{dr2mqo z7svwyL*W%|Yu0R9+1md26Wf2;Hxj6CZn@*}?>_y^meu#(f4l2A;-|l`d9&ybRMakQt~Yc|EX|}Sq?0Jw zY1&&>vwyg;fj}UL<2YEBg<%-(=~Jgifd_#qV2=a@J3srtqs^`D+rIhqv#o|yDd{Dd zfDb||?^vpu4#nxKC~_XHnB%qu5!yO8AxRRB<6syDhG9@D6`7ozG#eHz^1pX}_&5Gw zNc_>0Th~cIQ|HEqw|()k@3g6w;}P@%evgZ3+J9JvL8&N{OD0$tt>&JNyQrKA&gs!XU|XnvVNEN3gC*oU|ln(rE_&dMG(Qa`7bz zz<4q-1EMlT-L@mCYMJkKgaV&JKkuSFSKNHilSH zN&Chx;RK?LXto`31@+YO{<1#BBlRng=;mtuoF`p_)gwrwoS zLQxco#Uf|VoS~qqv~;W|(zujF$s&`OMmG!`+a?t7(SM{X)wOreK45t6nVPyG6bl7X zlM@J*L3KEcuIp%;hAhjBjC@Gq>PIYZZed-=eWVqObBQ#ns$v)hj^hyYdr6NBWPf}1 z{_#!V^-s=$U>LekF3KdYCa9|p;`8|^6!MIZk25)$AP}9;hKCdmM^Nswk>);=%=LW+;wj!(WYg@Wt04L zfl|4QEXz2KgXr;4;T3793Ao+A-+y`e-6Mzg0OS8Aplhm7EadUH4)dc?`g(gg(SMFD zPyG-r6y^QVX$->vz%)&CT}KpLYW$*^nTTb7w(a@;k=TVdf&GAey?|h7nxK?R=&FjU zD)gQ@&FY7~%*DhEp|CMGtpJioV1C%|&csJbM~@#mf8^l)lf|NZ80ftoK7Ut%Vd#Qd zE`wt+6pOK7RU4*QNhBCV5CqEQGL~f#@cXD1UF(CMgYgr8IWRC18~Ouq3P|4wK39RM z8-k&0xVDWQnuot(8C5kAY}>|h90C;*qQ@|c69egIpWFW4baJX2I1VKK*8-XSO$Cs= zULuX3qIT8Ycq&8qd|pglCw~(5Gcj~7(|5e*^52ejA1lgo7cc^pZ)QVD02LK}YNGR4 zu;NY%mPmad2$o4iG|iruem8#dSoc2@@rkZ$KBoZpX5b$SWF*Hp-?C=iXNITCQZy1E zh-QA&_wJR~e)~f2oi1)?EMh^ieffC@{DjeWn2RZ(w=6)Fy0000b zbVXQnWMOn=I%9HWVRU5xGB7bTEif@HF*#H*HaasoIx{&dFflqXFi=t7KL7v#C3Hnt zbYx+4WjbwdWNBu3039+gF*GeOF)cAUR53L=G&MRfH7hVNIxsNi?vvM%Atwp|07*qo IM6N<$f~gZ8mH+?% diff --git a/companion/src/themes/new/24/paste.png b/companion/src/themes/new/24/paste.png index c726c08d439d62848dd2881d6060b853779d57b4..c5444dd670ce61c927ddcbf6cc613891dad24798 100644 GIT binary patch delta 754 zcmVPgzB@guV{JI>60n14z3!*t;B_U+8PH^1NS z&8`9gBbUovR#kPJKbxlcIF(ABh9-yRH<8I?HdQK>@kk_+;V~g318W#cZIDiz=5-!y=)5jX=JRqFtTrQ0`kIS*)LYpT=gi!rhvQGqE zU5UWcBogv`sefb@e0FzE_tgMn6Bdg%MKCoI%A(DWVAlB*(}Z7xj!St5rQoQzD6`=s%tYJ55l3?HGi>rrSc1~N#PI6Q9%|>RbZO5*IwxEO+ruiUaNapa>Vu%o{u(G;p7hos03lP(%0QTsj`i^=1 zS%(|(7=QdI{}hRM+cRdw=?!8baS)(74KyNAqGVMgRZ+ delta 1214 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 dxSV_azgjSWu>t-Pa|{~zqgJQ)B0 diff --git a/companion/src/themes/new/24/save.png b/companion/src/themes/new/24/save.png index bec9b6c13f6e497e9b35a2dcdaeac262ee2cdcd6..173dc986dc03ff5adbb21d775cccaed06a959f30 100644 GIT binary patch literal 4069 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 literal 1281 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAv7|ftIx;ZaWVy5H788)qSRCZ; z#IWw1%u66gA=x9ymw};5je((|g@NH0P^jSr14F3+1H-EX1_rAc3=HB0b9M#VFfcHg z2l#}z0u|WV*xFj#965jU*rmHCuH27_O|Y@Hu{5^?a*toWckafcYxkdnxp#ovGuIzp zx%bS{+``Pn^ytMqKsBeYJ-B@LshP29Zhm1_PTrQi$4re)4D}3wCVP4N80mu;($X?U z`UZMBx{QpB`Z~Hm5p@j>J#8H=bqye!g@r|1Llel*R@YEhRt7S7czD!RR6)vARFxDJ zfebM*adl-CIcXV?EH^ih1Oi1xB_<$XWCXH-Gz%*$kO9;SB-z>7fg})ca&kgMAY1_f z0SE&~^78WW@$tjCK(|5I_ny63zIwflmCfC!ZyvsQcmLU&pupfePhQWNzXa&Z?cl<7cU1HGS}n}6=w-K)1BI@mdchDD@jX3br^A}uWw z=>3AC(i;z+A3t}czOfY;o^kPsDXHn}w(j12;8<~KB``EhOwFol8}B`Rvu?}I%&c5j zXV-+p14MfU|6%?bRV{`Hf zl9E#u6cmGkL-GoW(lfISjf}Omb&`@(EG(@;L&Jg5YVY7=W@c_{Yv=9lV`*vi|Nnol z_sY|OffZ8{3m$uRVI$t!L6s5fcdY#*^o~nWJw-u|0j7#a{oRhEL+_*B+71 zpL2Mxh)&c8+QXRS?e4P2>(Zn5Kn`btM`SUO_5fqIli7Aa1p%Hejv*T7lM@^mdwh5z z7>v2KrLEc94AjNV{e5y|^jB%f?{7$`adL7>nl!<{Da0kj$HtP8DJV!a;n1X@OPMb@ z4JJ&~ROS|(KKcBqbDjIVw(a3Ea4e%f)T$k}W)*N(=Wm@hUA`7Z?@E zD!y*r%C#4+FnMRZzH-&v!KGMgc31Fcty!gtQD357MJG2L%6%(4_h_L4XD#!FmW6@g z;pI;L`SJf-It4mCj|u3iP2RoC=j|*rSrx#S9XS~I;tb(-GkC>EB};cK>RZ1uQtvsoocqEAQ_4$$hQ4 z)jX%9u(Y{-{cp7eeP4;o|82=Uy*>B)$FI)48vkWKFF$)nQb3|b zZv8>U-DT}&_QK%{M8Xk}m!5P07nMMG|WN@iLmiUw0F6H_Y#Q;3FV?bP0l+XkKB5clo diff --git a/companion/src/themes/new/24/saveas.png b/companion/src/themes/new/24/saveas.png index 83df4c639504bbd5a2c66ca0fc938d8260177b7f..478c4d2cbb892d3c5e60c5cbb249758c194985b6 100644 GIT binary patch delta 1259 zcmV%781muHGc;6cs$aW#Nlwrwf_EoOifK891f$bvQlFhGUucBucNB@Eo0A~b9!|0 zhexsmx-JX`rMa%_lE5P2h?&Gq#7x3-er9K9F*!MjP$-08dAWS~aP>0Us_)^{$&;ez z)kD*%sqqd4*%TNVg2!w|(l{fQhr!vLPNyWWNTiRDDu1KCGKm8%I!+I1IJh^0zW%f4 zpLk_@!IEgRLOkc_nUH?6By0@IBa;}mK$xJ^vx4r&Jvjc^Kj?j7181*n$8@4t`lwqY zVPGhVS!W@E8Prb1GS=4CB9%&^s!Tzx{}&uNF@qzWNeuj2h1>UhwAaWd;3utV@KGTR z^WE=bV}Dp(S;@(x5P?FZDI%yQf>7NyJXAJZ^CrUR*!_ZN_dLCa5 zM^IjDptEBi{*3R%j&@*UV*{TL4I#F)Bu{0Izyf=6_il9T-=75}2g~@@S|jE@!HG|A zLCdIk`CvO-pLSV;Hl){zg z!zKx`HLyu!>AOV^Yg~?v;iqpt#K2_-K04Y8fBkFFP4KP$xl2gxheySfNLadCkyyrs zTS+YA=3)b0e-0?A?}nlH3jFdiFt*+UQ-3o{qQ%9ICsE!#*er|$PEfmuL?UQ!e+*tPwSdvlTz|?| zyWsBxn|;p4UpPKRlmQ1XB!QcHeq%!ed|t04U?*;HH8nK_MYQW~kC?x9#l^)4lDv)7 z5vJznWzSTtsJsN|TAGCS`j_yK9@{t@2FdWqwaNZ2n9HommdO}%eGMM!yux1Owe|Jn zm8(}#mv$k#I1i2F%WgJob3ik)qhu~?23Z%~{B~PP&&40awL3b04L4-){3lpd6>z%U zt<>+GWGbbvk~fp9ls=n-dnxVDwn*y9f=y8}Y_vxs{WTuRhyF1UX)Trdd2V7N{x4V3 VQZ@t$d$Rxl002ovPDHLkV1k+)Z2JHJ literal 1429 zcmY*X2~bm46n%*ahy-L@fB{C?BD7&iOhU*ffe?cP5*9-UyFh@@0D%Ar2sITPsoE+< zi)B}fR8$=3AlMNUcMxksT|mSTkdeiR)>4_e^7}9|o$=0p=bm%_J^%fG|JxrK9&EA7 zZWRE)B81Nq!EC#{R<3~f@bn+IVZvnwh6Muf2&d~D!$OTI6a{lZyVl_u6pm?pQ5XQF zn*b==1He02Dw_j9O$NY_0svAAfQ_=TXB!IuY<;9q90VKuS!}i+>&DQd{(IxM9!w-A zrLg>1Oa>Fmf%|&x=+wx>>?f&%^3KC25A-ukhOZBee)Fyl_WV9Fd4GJ`he}5~7-$^^ ztp$p_{H&bZu1o!NDvjbrL0dMUZC+>{+zNyWgj6yGJ;yaldwYlEP;d0~7f?bY27@uy z-Q3-c6==cXa8uvmAz^xNa&vKkgg_v;xe_6P=;cm6er|K(w&1w6t9Pzl85*DbIF_*~!{pq{vB{YbehB=8?3~=n!!?t$FAi1Lz-gcjcsQAC zMV@wKeE9Jbjz1?_5}PT{YC3UBCX)~Rz(VV>$^!N1P1RU zktQW2$HgT`qGO^&V%^oMrK<^Oqsd+w!;9n*8Y&bD!eV0L@(a}ygAGgiru%2*dHID5 z8r{XwDIp;#Cs&!AyuIP@H-)MqX70wkuVl-GCiGTy6e?WOWVc81MBv`ZM0Z(?NtQa5hE1@^Tw5#=ax^F znUWt@2s8iF+B%r+4;zX@c!6T~p|lhZ=75k83#jHKdq2}}$!<1`i1<3Z%04heZ9gD>Fp652;;0d zDPv#KSlwM%GFx2hcBHy?OJX+VLUE{FGM{eMWmUtiS*1xyQ&*wYT|Q-$8W_z;EO19T_xsxY5$1gaq+yaTlWax zd{fPcl@96eY2L4PV5#2hYw+V;yS~;n|Mh5}W}xzzZ;7F+hCy4W**TP>?_8Yk)4bO< zT~^*53IH4W%4^CHuNA~I9XNc0b5JmUZrHOeW@Aqg+k=IrH#_I$#A*JKh*gBri~arM zeQS?Z?ISw55?g(x0!PBh(_di$EuuyE;!YI@{tKciC{~r8s>(pp3Nl~WKCz;|& zVTvg}2$cyh5}AUK$&uS80zNY+^3vt9lFtlughofmbfaPB<&O`c0fYpF^V+#7yZ-~B CH6M=v diff --git a/companion/src/themes/new/32/add.png b/companion/src/themes/new/32/add.png index e83f4c1a067027d5521f69f5d8476455f560a6e0..ecd9f6a9feb78c84d812d36a363bf2e8fb22634c 100644 GIT binary patch delta 912 zcmV;B18@A?2c-v)BYyx1a7bBm000XU000XU0RWnu7ytkO1ZP1_K>z@;j(q!3lK=n! zAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fdMgRZ<8%ab#RCwBA z{Qv(y!$1On0AgYoU;q$6EHH*!78^muz|cxjP*I%4$<6-fKY!MsV`O`9`{DW@-@gYj zGBOf0Z`ZV63;+SdLW*nu{rjhDVPnfEC?d!TWMjxPGqWASV)bt|NlWA`wzt!VZ=ack_HGM z(i{K`g1>+NF@OC1^ABqXFf#sQAk_r`0YrKT0OS7OKkQNP?;jIboRI|c00M|a2QV`H z`STl$v6mnJ!H^UH5I`h{z`y^X5cr291VB;npMjJh00Sj+>tBZ7KYwEeGf>aJpZ^$) zEQ~qWIG6))`Iwo7h2j3qhYaUWp4$v^06+l29q{+h-#>3(d;w;&zjzBG5P`Fp1#12I z9e*-pW`Aa8`2O`510xf}41fS)LBt(UKQMcNvKTD^$nD6*I6wfgAeV5U1V(EIfP9K< z2S5O^AhOqgVE+EafUT0DCIDq)P&C6L5g>qAkX`oo&mWpQ09=xS(it=z0R#|I6o5j2 z_6`7MPZT=<0*D2v6k`Duv4kB!sF?dtgaiJ9a(@!oZh!!SJK+1bZ}s=@+{ITA0W&{? znS_kA0w^otGW_MU=Rbb__^|_M!GAo3-y5LX6Ce&i03jE}eZXkwBjCM>z)~=e5m!T& z2~->Ydkr)vkk}{z2q04H0uEq-g|i+26;Qw;mKhpPMAZiX0Yp}9$ncK=w*yEt4}LQ35P2;k20T%~0BR8t-yi@8Aky0dz&0V{KSn$uz(7)i1R#J& zPXoXZz*!qYLx2NGmw%C00M|q2b}x!`!~qoKR7I417^{a3^?-%CIAQ^ m#)0k~0|d~3_l^Mq3;>%jWwX>){xkpp00{s|MNUMnLSTaU!foIxpDW7h-@JO2%!gwJtB1Vbm!5xH-EQ*W1w4PT)!xR@wxHV z2e;qj%y=~XBjQ)Hn%z&n+XOxX_JPSOC4dNL#v}HA-sj(gy2p+L&R$&yQGhkz=_@Bt zS1ka4{&h$~7m>{3{N)Z&1sDOk=(vk3pc=q3u%tBTrI3YjmnR@`a8b#LmlcR)q5`WS zP-cAs77a8K)4&VMPU1xT8C1XR@s9?Ea;_a{6k z^I>ixW?&RZv%e$9ymZn>JVuQL#ux1!4{1Bv;f3 zP~U5oW}TQ1>pc-bgt~*SGpq^Esv{DM3Lw#+Br|AY2qduVldxn8f=TgmVK!A`v}Uv> zIIpM^oPQJ4Yv`Q@0tFGGQCbRt*JrB553(k&Et0QijWL@xL4L0|9{|+p06dXW4FD+& zJpseK(&=!`@I?d)9iVBA$)v+X&;*(eCmAe*&nuAmz==_jjy806@Nhmbgq0m12v;*+MxnnGu_$!^xmes zbTMRoHXaStP~3a->O1_D3`mPmxG=MW2aiJn=J=;1upEZj!4Z>x_I809==`H^KHMgl z!dfhi|7{z$ez>1JLW`Z#dfT9d6Nam#Lfcz&bB>%;azj pf1EBuK!LNsnCB;Nb~qMP;Xk`yM+@wix@8$WCaiLza;(Get4kLbf4mStBM}MV7J~YATU@CSw~i*|$uV zLDsQ{vNa4QS@NU4|NZVc?|sib=RWUt-{;(WpIn2RvY!$<1polp&CQIhkG0B)ureRd z2>RcTjuqoQBl8=q$0Lf>{qgadEzr#F9st0kdLneS>#`>(!Qjg`gRcj828X%c^#Fv0 zg(-Xc-?``J8t9=MaMug{Q&$K8INfA!YIVNp_%mrKIcRt=!l`Tq7va(j;d-8#fm!F?ak&cm<@8P1vSzx6+ z?rfSiaV}{t284fEO|7@gy7tA9KH@X=|onAK%an7Tpz+#S#QNuu=5cB5*!oFl{U54y8%iQmaJMe|( z=2}UPSz+(bP{Aj=gcdsGz*8(TygoeKF&E}G+uN%%6B9>Te*V10$CHt+Xxtr-5sZKN z>Gu*r6$*v^1M+zID(Q2I%+kx$xkAVCFJ*D`Y-~r}3ks=e+}hg_mTcYL%chL{XSc7h zICEj1oU*a)5a4%Bm7rfFaW&I$eBX*+1g|!m$UYX^TN(_Q+RL=anvw>o>+1Hv3w6kr z5#`Eu)OiYTQu&*$tt&e^PHmV51~Ua&S*)pG=4H{ZOpmrXHC%uiCDkmf`c9P#n)?$I zA1Ww~!a^-Icc!G^GhS*Tr+?9=1+u=g%Enc`i>n{h4Qylfg@tgQ_4GOueIZ8y78f^D zDNcVJgX@>&R1vP*g-k`)r99Ejdi!g@N2i&As}%79YZT8Uj?UrRa?lTyAAWOZYWK=s z7{^@KxhNI4o+xT}Ne+n5Hkh`(J%Cz$`FFF#eFJGYR~8%68Q7-+p@QL$%5 z*vugdEGNcodOEsi^cR#i9qFL;*XC(rY6pWbjtRZ+luam|14d#_A?Xn52KIh6?#?U3 zkbLg2=s+TKd6}UQ!u^`$@e+pKUaW8b3s$^q8y`O69@kt(5Lf$`#6%NZvGf}#d@L5W zAB>DM;kJNVvvBQKafs@?AboZB6cu%>9zotc0QI-!1Bk z&}cMKz)3{o#8;_JF@P_9eNBFmC(-x_1FcycJ=DgpT)IT@;sZGesG%Ww9cmg>YLa=o z4DYv>Y-_I3(dfkKXfnAvy5VX;PR{6xO_^;k%l|T*Sa}G=jzpC!AsyNoU8k0g{WmgoLZ2N}zZb-mit1OxbDJN~J7O&`r-CsmUhm z;P)gX_HjxN6 z=es^QNkAR&zT;6PC345CNa6ekF#e$hAwkX@g(Y96XISWtV@b2U_3`#?>l=vC0YQV7 zbLUcV8-d#73Q0_eb(i7$f39$@0sQtDb0onOSyQM`d?>3%eOzLZ6{K?h{Pkzqq0;B& zWXjB0fx*nWW$0zbF*wdLYWj|m6HXcy8E=bB4Aq+D z=H9fihrxghK6f0#YqgDng0z#<5EVauFydp5TINtFlsyJ zh>351{b`ySpwrONB578aK(#m!Sm21w+O$!;CM-+CXj z9mhr{&6){=p%9VXaZ~XJ&*$EeHotk994gDc!-Ol|_V)H6UJ>|nu+=XkYBUSr*E;6u zOi2s#NwOOoTm4Oy(Z8wsmz!u4tKJHT`|lAS93wC3>ZaDKN8WgQaB#}jF5=nZ0`EX7 z6`YcgYtDK5U+V0ouzy7VS2wabFp}cT^+H1N{K4w>RBQc0KYx)ZKUUUDhh+X5-*a<=XB$lNt~ zoJka!Sh4pua4H5-&#)I4NF>a+7ehd4^?&ntKy_EHExlI2edKxZ#8U5N48cL0DbLE>LAg0-rj52zn7i;;`enx~(=}>Bxmp`VQ zHG}uLmB2wfL3C_N?t+3H;9i>zG-GmyMP!JAUpafQO84>?B2h@Q;2N`s6-!79-G|s% zi&NcaDs9?@crK~`-rfCk`LunGL+BfPvaP0OZP%GINVt}h4r&*Qke2yA zblR%VLFQsre4+MrVvKYB*U$cw0s=v=vFs9ouCg+wQ}1oRi@{(pr&88H0?or%I`mX=rJI<5GL&y}hPj$$z)K$dn% zU(z0uj%(>V;_jwTh<0J8e0cI4SL_HO6#EEBZz(MjZl4Pei>Rxvjsi4m4yJo4JkmKl zoS`k%q@52KyU2}}BY;Y;*7ak;8F_^!$b-n&JsbG{-9KHgHpe_N7 z#>VW$V%773lU%2dNj+3q?q*{Xaxj9at&K6B3^%ZwG(#X(?d--chyE_>q z|4zmtqOFDPsh(EQg4tbhu+H7)P?>7d&=6#K3DAlfCcW}#@}6t$SZ3ic4lB@)$)iaQ zi>N%E$;zr(YfaGc1l#XI0Dyt`{5mdww(Bjazx|>fzl#}K(wLKLvRw)ycH*B+G6aioGLYFxVCwC z_yII{n+@1LGNKVg$3;K4v(p>AtAgt^k!(`%@usspQ$3hDPTW!z^G$7zXb^+UNat^5 z@r`kztMghlz=~TN;k@}`37wlGbo^H1u&1G3swO|%)EYfgMpfgVVrwLXVsY%KYi}x2 zjM^<3MvN{F9l5CGMbx*r%yYDIe^nLgUC?EIptrTXts{*;^@|PNXB3AfEvPN&%+5;m zn^S2X!jf0L+!q`Tzr5imC2_e_1gC!vRi5zmFR5#?AjhU!8RU1|&4RdTIKQ0{{iIu9 z>V}c2s{D#*SLo9V#TRzo2NZl39%pE2IXY#S(xoSyQ z<=H#2yuOZ2N=kY^x*Qzm)j%dVSyiPb!2L_M zQlvHn(vKoNR29IM4sa^p#JQkzCjvk1tGlk_{m6axSX*hP!E_lSX3gj;wyaFNy$4f2xXdgIV@O^U?fk;#Ky*^k|8K?P*Y6# z!rc7F=H_PbX@4xfex{$oP*7%yNXdJt7?NX*1hVxj*gk<9GDOFPr^+SogM;+v`@D w!zPCz0rSE~3S&x{$3NQjB#Yb0<|2qKl%W&flMlP}c2Swg+6951J literal 2262 zcmV;{2r2i8P)c5{J*K!Qqhk#G%bG0CUP_x6u(*<_R0;+fgm zGv|EgdERq*pZ9&?BAeO$Ookb0uaIcRdlEf!Rt%qr5fCv0B8E>SdiJbDJKvK?dxi8q zmvOPU>i-fCRu?mF&P!;SOHdjh)`Y}Y5C2ES`zDzE^~An39G~m z9d|Q%VzSrcE#5RO?a1)Dcq$L$}tL0mRV3 zi~{NH=3w=*Z#2N@|En?wtMkQ{UyB){>-1i>ZCXg{=UWlO0v00xrk|d(pOJmpq6Emy zqD36{9tAT1rfw0NIwzX8vTf5sx;h#VGl;1s)S3hT%r|^*t5F8nGS`YJv?D>zcI?CR z={D}D2qEK(sHuK{Xs8Fo0zcQ|Av%8?EJ&WQD2oreO0pM6{ieu!H7?Gzq3G^8rI0pjh9M&%^Dfm zc2)mGc5b{>ni|%~?kx)>81W^||EAI@QD2qBd{q)W|K{!_FEDz4Uu@bYA60R?T3hx) z#$sm8xhKiUw$|SlkOVYs`fUmF0lk;EHm~EYzpZ0H@3mY?*+-EFf&+Z` zuML!ymB!yl5DcAIj6VS=v-jDIm}K;;xbF%Ig%F8`sNK7R<#!xO0&McsQoVfxj#w|N ze|Q}zMO9S|QAalAw>`@h?y{usf4P1Ezj*XkT+VS8vWhc^;IIWVm44>AhaC>v%cGPH zINo%Cl)SYRPQM+1ryiM2iTg5cy7BwCT;q}yF%*oj=ebZ|T8PHg1n zo30rqGDG-=VLq%O!CNo`5chZFf)DGowl$JhxGJ&plDXNeDlf$~E@rt~{K_x`xSTOo ztt{cXD<{)&rVfDbUA2<>{f%G_VOpMKd6Ocv+^(tMJP`p=L?U7O`_6H`yPNK>yUEJG z1&49~P`!NvkK9)TrayjJLy{{O`bsflP7w_sZy5!7zCDgPmmOuOw^AjZ7_F$dwb_iBlWUd$EU4;j&LdB#Ij0#fdm% zg53s=U>kvOAF0kP)~!?SmnXD+WZPBs zTW&3%6_;fYWt~`3fKXx?Vk+G3*)%u4NXf$AB`~tH++=6Dfd|>MXMv@v3han}adFuQ zA%>1pfXOiO3lB>TiRgBTn;(Mrdw_fa^bgqcN)$j=?Rg7Vc*^V)`4 zJoeys5yWDVHtb>s&nY5Pety>+ z0)fvt_2of6+Vui|KczEo@d|EPv6=B{S;Sm!LO~xcr`=+^Kpwve5i9=2Vg}JvH)+l+ z0A7E24gH}dfP{e4YS(Onq& zF#oqSL5u*GPfh3aN$V)DaF@{)8c&P2lUT%W#d$-I$NK=Wh#zlr2kpKIfB|ViH!QM^%U<`YTLL?^a_vCT&j}9l@WyhI1ydQ7C?mxub z*=Y#iZPAIQU(MXo=Mv-zDPFgLC-3gWIZnkhBoG9Jjg*|9Whwyu*roNz;Nsz_V%>jq zuD$DPT#gB2KH@;QkLJb~5x`yYG^z1BAN5^ufEU(Jr1GKEM5+d$*(TPf%<5PQK)C&y zV!c@t-DCZl_b55;-83rZA3U&CB1S~MsYQ&496YdX)OcO(8}jZ(CAvowzef|jSxLBk zX>qcpEt9Kt52AaJXC6;ZNc;hxRIZyZRj(kA-ivJ9c=srhSO0joJa#Wq^$JqCZoc>f z$qC6lw>w4mAbt-LXvwJ_`?$QRqI;0W9mwtRv_n(SjOodT2H*5s~NDm&)Ot)?C1wCS%qGp_6WfMDvVrYdd1#ZH3qV;bisoVU}H;toz4L zKx^(oe1+dw3cBRbjE)TV3DQNrl#c8;$xY!7{z9fdeL@<-U zM=l;3(@?hbdRt2IQm5m kyC&WKmX`Au-^Jkm7i?Y$TPJu@KmY&$07*qoM6N<$f>j4b2LJ#7 diff --git a/companion/src/themes/new/32/clear.png b/companion/src/themes/new/32/clear.png index 9f63a08c2823267a997dd86a443dffd962dd6aa9..89031abab785adb16ddbd3a835a04de2bfa7e03b 100644 GIT binary patch delta 1721 zcmV;q21fb64#*9VBYyx1a7bBm000XU000XU0RWnu7ytkO1ZP1_K>z@;j(q!3lK=n! zAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fdMgRZ?K1oDDRCwBA z{Qv(y!$1On0AgYoU;q$6EHK7?dugl+{{8*$%*enXz{t$F4u8lcHn{{8=7tE|u41X2T1`}^NN zh}_5D3@SQ2jEw*OcR#rHg#nl*`j8zD5I`sn`1==Vxe~`Lbv+*Dub+Q2{P^_`?%-bx z{}?{J|I47L!UH7%`zK=kxti{Cy z458jfH-En}0uyvUD1C$E0Rjl_fPeq~J4i^g%}~?kX8!!;7sK~o|G`0soPK`(VPJR* zG)zI60~8Vscdvf?1rk@*=57Fqy@gqhrtb$(&%ZxF$E$KO{Q3E}`}xBk*MY*@Kym;9 z1a|-iSU4`3*P z(tild0!DnL5>WEZ)8GH!0WD`@VrWN}0|+1%beDo1@!}6COSK3|FasTd&*=Yfjkw$j zl6mv;FT;mdf2*08Q7s1nfB?c;4giCw_5G{Apc1V`K#U3OJ5uW`SXKj>^YQI}P_VaS zQwI=0I7>p1BR;d<`^!gP)a=fel!)eg8vTIB>EsGVrl5 zF??bC&p}8nKmf7evm6+VP4a>aHN0GZ8Q%Q($ME+b{?rcB2g)HL-2WL^{xdZ`dVkNr z4Aj(sOCLZ0vEVVONrwMlEjQagh8LfKCE0(7<-~*msCaw6aGnCl;Z0_W2P zY-#}lhy_Q+YLemkTg%1#2Wa_!V9^gM+Zjnp1Al=gfgB;q@s~k{ho%0>S7wj__2{Mm z1P}{0%cVK~)N(TZW_bC9G@qjbV1JRu@DfOfu>WI_;$W?N_Jajv3`$4<1Q4b^6wUw;M)tpUja z1Q4it!#@^|Iv~3X>_Zj~R$z;$ z1*i{u%>*jPfo1{q{r$(xo_`4xI0%yh2q3gv@PFPvR(7EJ|1*G1B34vK{D&Yepyh0w zH9$qJNcviVV&Gbo>Dw2m0~k>)=jQqSpOrlW$e)L7BR~MLU}@UU`_Ibp|1THAEXL2D zfMwc0xc&dQc^Lk4aHClc*Vp=wg9}`XGJOR(0#Q@`q430uVrW zNq z&PPB7ACSF)=*<8Be=<7*4>z#k$@mq>-i1#oKmaigbnh4-fCjvG3=m)dU{#+iy9A`{ P00000NkvXXu0mjfes4K6 delta 1841 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 delta 671 zcmV;Q0$}~n2et)}BYy&YNkl7{;HdEg6iI7~S1iyLLDjOV{3bv32dO zlPw=1U&%|sPvD&*CPj9!&Fyv@jxnU$P;gVAI-?^Kl$^74R-i(|=r68HVAu+ika2tNl!ZgkAjYgwTsZ`EE_=21d08&u~%;)n=0E58*-EQ|uu~=*whViCe zulEpO&e$dJ6Mu^@ZUunF7t|8G`}{K&gdhlzWf`4LC#R}v1HfyJ<9e>^&dWi~z{%m> z$^gk^62svTrfEVDgn1?ah#bewGZD#zt4I(80DvS(uq+Fc$pqu^I0xV!fJRyCA$k1voj}gRY;&f+EY<@ArYLvU8CD!hZ&2)o3)j5%UG`cB}Vaeyu!N zR8ccQ8~ zAWjKr@_z;3c|NcM>5C|OA#X9{}ge4QWd$On!a6*fM~PfaCM#=H|)(G=-iAY}-buRDxw$ z{}+H*zc+jlQzH;rUidX5YefKT0JsB&AI=cjAQ%p%e*xFWL9=@VDQW-!002ovPDHLk FV1hqYJJv&8c?}6Z+4SUMyjUBEX;LF?AcqHD<$&HFD1TQt?hcQGy}fgmN~M;z zcd+-{ot??d?tVY}o0;FvaM)m}56{)4jFkfjdJRlswUzno$4khvk&WWXXUzjC>7*f* zUjjrI8s5>f@fXHtZ}tO;tO7g`-*?Oa<8!o@V1Ck%+40F!Q>KdDoO%CMx7)pv4FGnd z_{v=`60>(OKYta#9j6Bq6=wX*7h7Jcsp`s>2N((viW;j8N^U-sSQJZ(am@VT!Bkl} zCdx$W3<8ehP*J#Iz3|>gZJKw%$4B>kKI8Kv5nV)NW*#%n+wc^XV6N%_Iy*bz^Z8)6 z+fh)qTRL`lpOlwh{F9d5!P3-PBoKtA{O}Kt<1c*yTz_Si=;-Kx!{I<*Umu#An<2|G zZrpM=9IfW9nvMZ=s)hUu9ZTMOm@pLLa$E;N5YXG(i|+1jw70jzVzEF`6ttcV;N<>r z!?kakzSV3DtQUID9r@Z$iaN|@GZKjesGHH)*oc;v7IbxWVXx>zZN(T?B5wG7BEsPk z>xuWjYk$)$4%lyd9qN~smX_8J4GqC$GGTdnd954jOg%Vp_#XIz^HAg{cH~T8b(NPa zrw@sj?4veK08|^K_QshyaaW~Tip63W85zM_=M8J(Z1N@z7z>X;G@aQV1o?l(4~_xb z%QaP^)8&?4l?2pO2q@b1%9{A*5IIuQHatN#tA8B4e#3U^MWa|%&PuG3L_D^dH3;&! zhTmP&w!Oxkq9AZtg&Ra=9oqYzG;CIDN5 z;GYUXGMzSBLy)ZmkBlK?HDcC@*8WE!$W}vWMi4xW6OVx)+xe0F2cb&~0=h!!&Ep3i zf`1^}{hg)@0giy^%OQsoQqT9ppJ)b<4g|xo;ERqUG#Q3I7{mv!S6jcbjfFJ>coKvv z&gAHjj07Nr^8nhGQk3B@FS|xG1=t9YOCcC4q`KYk%t6G1(+Iis;B)h!6LjiAZ1Ib} zVcYtmR8#x3@3%JB_?&g|Zy7B8a@Vha!hiJ(i%?KTIJAT$UE+_0NWG?GU^7oVU#u79 zNK9IEPa`QSNU29kZHwTdZO-uSh1x6Eu8-c$3cxzV+qK147^G$u+8s$HDY^r3TsXf65qe=5mQgcWc*vlh^w}dOz2UV(B~u5z z5vG1LkT@F%Gdmnt2Y03oKwqv3(_I=T(41GrY2s)##bG%LpmN+NVIFYMDWFo^-vazw gTGx!yr2Hem0Po(l>faW3nE(I)07*qoM6N<$g7G010RR91 delta 1924 zcmV-~2YdMM2$K(xB!2{FK}|sb0NDiGvf2Uw0004VQb$4nuFf3k0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv0RI600RN!9r;`8x z010qNS#tmY07w7;07w8v$!k6U00xLjL_t(o!@ZVmY+F|u$A5q4-0SOW$BCVHH*p$w zYnv^hFKn$^)(@1vX)Cx`7Iy!;aR%pi%Xb8$ysoMvN z_5sSesp`~qq^TRVO`9cY-t5FUwsY?}hYwC0XR*VOMjz|w>K;G$IludVo^$Sl`q?+{ z)yEFJ;vIbAJAZ)S2AlLP>uX|iaEDB`{o<|HUVUcs=FQfP1h5`x6{}ohZ@toU53;Fk z)B5%6+fu32YePdr=7s?5e|M-i+qU|aoKxGCOeU$TtGn%{fu ztM6^can?GHlU&`Jrh9qshR1frYxh3ad+bI)09aDW)qg+y_V#1%Kj#|#H`|!^A2qpC zUw#UZHv#~_3fipv`x6|!`YVh+W*am3eUm%&#ivf3II(SXbo3|XFz3&of9T4UD-Te% za|Q+mews?9ww4DS931@Z@#Dw4sx4ancB<%e;nREg?)edpj`jQKv(FN4?)X8g{^S0c znVCC*aDQ3gkB^OwZ2|&wQ(|;<^tQ{FFMonkY5}ZlHhX6(mAaiOTl|Ca>Y~TMU3+-s z{0K+K`+ZdJFG(hfw^$?3M9Ts*HZ~^5$HxQZfz#=<7#bRK%H~8SlMw?018y~dY6p)D z2I&0jz74N;Stq+1R@m6Lev9cTUY)Fc>=MB6@PF{9E?&GSH*VbcMj#MSb8|cT`}?nM z*|Ozr%d)gmO7`{jeM2er=GwJu&%SxCc>1e%cO9gxurnLHAtW-zP13VYbsO)up1(YkS>zV_!Qb7$E}GndFdtU^&uiX_fyPj#+|Pq zq%0-U7>qKY4QM?tvY5|uog=VY63MyLFMkbSMS}6JxFY2FNIQ&L`6M!Ekxm_=-n>L( zk0OL57ru9q5*3S02x_8WHMK0CD`veUKubilhi!q(``|cOmJREk#1fD`cZitzJ>edO zH3PZY`&i1Zfz>$B(H>hqUIOrz0uZf1-8M1lW2a{@p)lI>O2Q@f5cMJ5e~6fQnSWr9 zVkQj}?yi#b%3#!d3KnQ0AkkFQ_D<>SC@cxk5tZ?HYY3?%rlk&J+w&5~_n{n%Oz*FW znLknAqlp+vA$I?g3X}>lkN|=}c1eKxplp*;VtF1q7+mBaH$06Hg3Nmdi0Z?*YYbxA zrWo5*b#Z`}Sh!h6<28C}WV|Xs^nde@I6*_x)U+Zn?cq)NWdQ*x5mI2fpT^aY={-Qy z{DsgOMJ}(Ha_=kchU;t3LqvtJB6mH!eERU?162WP?|v}8B4*2`Mi)8hpc~!l6@JHl zW^KvT>F2>5A+n~PK=`xRk!2NCxYY=p_U=yLAAqR{V8>b$tu9C@kwPG>>VI9D5Q5O= zXAwd$aq15U`(~oI7ZEiYX$KbhCn6wgnv;~iL#lEO*ls*9<1ubD_CyhXe0E+)0m71C z$BI}!D(7NsHLg9t=AmIg4gy{FBkDF`AHhGjKNDsasj z@7RI2ek()&{4<%8uh9INhkuDRHZSmR0$RfE@~frvdldnK!fuaRKE~Y69r~t z1+-GAIf&BFl!loHQ=Si|h%NJk>XPi-`4Hn1MQm#!KvY<5l+J>RyMI7*22H#p5iMmS z8-tsg7daVIxmW$*+g7s9dbdHwy6SZ1+-N0l(Iiy+^&2S>LM$3m%8KK|SRx{X9p9dW z${nw)Gpe<$%05)k|HTq93qflV5Q|a}{Me)6{MF&unKL7$`wJH+dfrD0P?(%W{X5VJ z$VC8##@dr-^SnD6!hdcEW5qUNU2>3)Km05UK!G%YYOEipM%F*Z6gIXW{iD=;xSFfhf*n(P1o z03~!qSaf7zbY(hiZ)9m^c>ppnF*GeOF)cAUR53L=G&MRfH7hVNIxsNi?vvL50000< KMNUMnLSTX%XOV6I diff --git a/companion/src/themes/new/32/fuses.png b/companion/src/themes/new/32/fuses.png index c0bb8bf4ce7c011db93cc118ba23107a505479c1..e229989bbb930f9b6fde0ba9ba0b1b0caf2e39a6 100644 GIT binary patch literal 5149 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 LNkvXXu0mjfLjSB> delta 2173 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 delta 460 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 diff --git a/companion/src/themes/new/32/paste.png b/companion/src/themes/new/32/paste.png index d5c13a9b6fdee054eb4a6b313c81880b95cb3836..c89889787b2804eed3c89a2a784b53ab3ad065ed 100644 GIT binary patch delta 1034 zcmV+l1oiul2c8I!BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU# zz)3_wRCwCFSKCVzQ5^ow?oyN)Mqp6ZiV5ONT7pPe>XK0zUeel>An73_K{mpN{s13> z3Q(FviA0NQ(WlH6+;}1dD@1mECKlYPhwA-{=V1iHzl)b z#(TrV)w;32e-sX!yJN|U3n2{OCiJLhXERgQbYc9eZj4Y-!g!Y;AQGha;>hL5YBov0 zi2hxIfL8%P7(mDg|Ef)eTHtG}RGr8M7#KQ>tz>f{f`8D6+Po}#x88-DVc}0Hc*+VO zKR0Jpu-9%qqYRiONTq_`2Ag2xjyhO;JqTr zmrR6VDWTDbNb-WnfFLnoC4mL?%NZ4L>7oaIEPn=+M9OLbRIN3XV}lWy327Aw0#33F zIfk6pxqJIo9j!XOm9dr$)eE$(@QeY(Ty4h#@`JQ~0l-A7mEJ}pB1r>5P#8$g1Jpe1 zppg>Zygw=eVR9l6FcM`zQqRVS-9O{4Q9Zz?=mAISuI+s%5}iUtwWH0|Q`WK#A zsm87%-P1XNv)u)_ad8Y%|c@aEQqyzb7RR zsAVXEXgInrq2AgGkz*7FEKft6NCFK5hJTI6B!jLj)!k9M4+K`0A*K_4B9~kI*pAy`#zoT8J3;=HzXA*ZRet2U^eH0a00000NkvXXt^-0~ Ef(<(2F#rGn delta 888 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 literal 1605 zcmZ8h2~bmK5Pk{wr3ghtEoUJRNJs+Vhy)T$AR#0|4h}gIj&KuBwP-zvf-P97rA0)} z5fLv$q)tJGtDJHP$PtbN6d?#oM@AX7mj1}JGj?bGZ@=At_wAc+-@G4uSe{zyd(|Nb z(xTHSY~YQzj;aDcN@Y$LaEj4nCK-YxiZgXna1g`N*q-iC&EWp!t;z@*n+ZY3Eg|JEwn*fTOk2KA+5I&i9i4X%oh5+I4ElGfZDZsXglA_}0-2XvAVN2F+ z+b#zDza)6_zn5S5;pyl8egQzMCsPZOXUp^Q*A>@qPR_~amR`*+ykvT_fNtZmCE4Pu zf-A*OrHivKRwZ+bl!H_!ykq5^-)0t8a(}#(n3NKqAUY+^9-WdAU5G%sP<~iUY4z8o()gXTd4vRhdpGqZCh=jBc9J>Q)c`yBEm z9w2&p(Cjd{py1FD@Y3Ot0Re$Lo*$dd4GauQN=ZveJHlXig9YL74u^w+X`Zx@5I*=4 zuxMKi4b4!#z}uV27lbFLrdyg@=<4W@$nI=5CsG(~puY!*udlBk931N5N!QZa!C){W zg;A_SzPh@)rlw{*oUNjZx`r76*d471iyt%954sPI~;&P|d&oLn)k8{O3nw zdn^Sxil;P6o)M>??>w)K}C6`kGl@_a85{Lz0E$@V{4>PyRI(v4R1_RU0%f|@3Od8864!F zS5sbbpRQCz;@xeixvs|~9}UWHRQAq_IuXL~#1@GMYec9*_^VQBLG!6}GmG>Uc{^9m zOjs^CXL{8!!;7=QJy{4p8#{U;x}QQDDk9#f)v0cMqI#=!GE%hG^d7UUq@j-*gscO? z)$Q67V%M64+GS||{nW9zLU@`+HJou9zdl~0;B`+{n=%@8PK+AIm?b-qw9bZFyunwl)zhSV{=s@8!|dns*iGklgKxZrQc`7^tA-}qo$*VX$q-p2SMqB4)*x_dgEYOOGhUHGY2R0lTI_d!&|j3 zZ{LYoqm(cc~a`+dQ2bkRBP9E+j;x3W0-g7_2=CgGFJTxmX8+oio7>V~xQQ rFqqEXqSY@N5|bihqcXl|z!U881Pp$=VexhT1ZaThR2HSiT_FAkZq!rX diff --git a/companion/src/themes/new/32/saveas.png b/companion/src/themes/new/32/saveas.png index e2af8d1fa16a2feccd875cf155d2d32c4bc25e1e..03c95363248b2c535717b73a0257d74c5a822a3b 100644 GIT binary patch delta 1664 zcmV-`27mdF4w4O!C4X~5NmK|32nc)#WQYI&21!XoK~z}7#aC-=R7Dj2?%lhOcByT* zw4|kND6~L9~@#v0o6$(%WjtSKJpbgDr`@rdB&&6?#{ykLQo`c|tIcDo%mn+>uo z>!N8IB9REf;V=dV2X#?Z744m!zwE26y&y@_qtUsF>)9nmp4LB)XY8%*mf5SH6z+r> zDQ1c?^D1kKl7G$mAfZP!bSxH&?wA9hmfn#b0jR93H0M-TSEJYKEob9$?qmJky(lVK z>yn*!q1ss$I(Dl4ifjU42FQp3#uVd)2|!Vl7#2j~bLk;w$Q~a*F|z~N_C7qneGf)v z$e3Eb{>Q47!Br*z-HG6k)5<~7%E%~zAOKtl5C$fdkxD~1r6CpH_8X*95g982Wj!8t;bjPgafXc`9Vd>mVtlQm+dDA64Fna(y zj!lf5Il28N%@boFx_=~`31dHLOsnTC@O|b~ivY~@Vmd{cU6{Wp7f>Uw6)F=QQ&;p_WpxuC7i`LBFRF>HaUU@zn-MS_rQ^brUV!8BPEDkD=gUd?iE%C zJUFn~i|V=@wDdSB!A*vS17JoZwn~+??#|8_MQX2mJZ4--LL7+3(rjVu+T=vdCj+=} z$%D6_>&IK)x=`PqL9|06wn$%=69dp!C4A%#%mC#nY8Voo+bj{hwnjqT&jEaQ&Vx5L z_mo(GP66Tsee zLHz9-i>u+WC@qdIsEx7O=k@aXASI1~X_F@5^V(W7z3AZuNi0r7eHHSx-8k`e2#1cV z*tyz@(rNRNGVTS;TRNm43Wcz8%NF=qkbfqO0siEV9vze0@s35&LA&?k^!F#R?^6Yv zmZf0kjLEQ#*~+p)jnSnH%1BGo0VK@=$%t;Q(A?Y%FQZKaA-4IpAJF{!VN@L&fo1nf zxN}MYE(ezZ4UMKARn5Y}LbEi-#8V6dM#|w+y~fkFctUBc7Nc> zM1}XX>aqO6 zEOgi_G2o^t4M_u)qQ9V^AUYNCE09d8vc!vOFAUSR{QEG4i!C(-6b{VOtSgc<(d_G@7=gAz4LKhZIm^Tc- z=uxAj((&Vw?Q)rPb#-;=41b7GEjmsV_3icOz{lctFnvNLwNmy%lx0B8!-D+_6?*DvF5B$u$!hKzn#co#PGwSNE#luZjFXoH{t0000< KMNUMnLSTZ(XC?3e delta 1790 zcmV z0Dy!50Qvv`0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000JJOGiWi{{a60|De66lK=n! z32;bRa{vGUNB{r;NB~C3Yd!z~1_Vh&K~z}7#g=PqRL32~e}8lL-d(S;yj{+Jx7KR1KkRnu;%}sz_C;D2m!ht&&tJiW>4E4^q@1hkzjs z#Kf{8DQoQwgnS86?4Drd@Z?8X{rmO+-?0N}*&5Bb|GFC(QiEz>Id#QSOASK>f@ zOQ%y4+9n~y4u{>iFWX@lSq=jsChEVdavlHJ_ZGuLLw`CN&j3HYVFzlP+BJvGezy=} zyWP+?I~|70>9C_|Q=4}9y#u`Y`d*|oO-ovfPoMFgpOph2pYh*rH;iq%ZrkQ`7`Hkd zc66II<0V?Z;Qvp4?raP&+Is zx8J$${(n_>+_4rzzwv6j=IDge?0V$=_zLu8e@!rPMpI}+)rbJXd zv>74bHg_r~M~_#L3}w##H)1y`Edb!fc3&H*R0@D@zmHHja#I547rDuvlf#qWFGdVC zW_DGJUDT&v(gMz=QmNYZb{_!JG&$q_*9{RXrRePF%NNiZVcz+2>DPpl06)RU`)4qHVMIuo?s5#8uJ%6F` z)013^MNvwjl)@$?&u=LpFV=8%SlH_=q`J+uG=Hw^ufyT6bv*|FUJC{TzYm8)IeB?5 zE(CiC1Oj|>(Zcb9{{8_@9RDZYQw<~%39PF#&cvn)D76P*Fp~xf3BMY`}cA1-Tef6&tsbA_>423ESu!npX8ApJ~ck* zizmOqnStzd&61ql+&$4~6uAD+XsNF2?GHb)RTzejloDMxh>wmSr9?^#OUkQld8KV# zYj0g^@z~lBgxdfJL>)Zz<`R;om4ErogPlF+4#Kqq73?yc6~9Ct%S70Mvvkk^e^Z`r5>J_pI_*5xvsm`x__ZlSX4xD zNeS86*$5#pO_O7%x|lad(DS*;JKi}+OOci3q@}ruK!1?Yc>Eaf2=Mt-0svGzKDx22 zy!=b#b8>PhE-59;>6~yYN~KbS!(sdblCFUyrnK<2wQ=-F4WV$T(WYrXla}?nH2Gwk zFpV4_uyJG6T-RJz#>TVAFMr4Tvbt4Rz@O`!0-2S?p(KJn&#WUGeGxjiD!#Pg%HZ^b}NU&p@2g`#n(-m z2@QCGD^a@pe@Xnc<99!OwdGblKXa`B001R)MObuXVRU6WV{&C-bY%cCFflYOFflDL zIaDz=Ix{&sGcYSKF*-0X#mSoN0000bbVXQnWMOn=I&E)cX=Zrd~8?l-`8)=&fJi-9vK_4@FOk=R)z~mna26 z5HW2HZIfo#-Izk76|&ou>}UptNg&&ump8LJvngSW0cOboa(_V&z?i?;YviSW;NYkR zx7Y0!zpP6RwGNMKjhm~slH=W$`xAhQggI0{Ic>nkb|Kanr$2$q^NTunzR7R;vr_Z?BA-}Qo;l3Nhg1JTl7UHOQ7DzCk)Lfyq<{c*U9T_jD?dpED zyt%Uugv5UfV`mDZ4-ZC;7wh?A$%I15;A%?E;|yHr+;sxKe=Vo&R|kggla+H`S8Gz;FQ-A>gj7vUFY6VE800000NkvXXu0mjf D{GINkl z-3@-ca*si-!|&W^|0_?Sc26DxT0jT5|FE9Z5D-BFf8Oi{;3fPTfX=|(egqgx;W`-s zkGBcj-V#8nn}55A1-4~NB_SjH3R4q!MNrohJb@)jVh>z|I2x84g4RS;DTO79Kwx&2 zYb2_nBqyMf%p!rv9bgj*2`Z8{a!P3FlDHZKBs7+Um}hkKY#K|G0~WYjc})nMfM4PO zq>4b$eE~#FGE4MKZIHwgm(gk{wN)3yr^(JuVnIYkgMar7lDM>%Hi^Z5eAktl_IDrw z2}hA+9FqY54kX|z%@FWbQX-(O#1dL|;OLoY(4UCN9HOSIHxI&GM>Ssjss?)pH*`6H zBc_AgIC%V<1;gBt9xAa0S-n=~{quKz`}(8nmrkw#c?SB_+sBX0&6vZ;DARVXVAEFj zXA{|hSARItBEqwKGhTcD#ahh;EyK?bwW$H7R@)ozp8Xs6{l zQ7_vwz8ipFuimHAEgQgexS4n0Yjxdfy$)UgRe#AZFEs770iwd^F{L+RP+P1x1QQ*N z$})h*fH9ZE8{N_>*{%M=f)^zeC1|ZFHIx8oG$yLz3B+?%z?Bk|xu=vylu#m7KAA&N zMgV(gvvC~aaMoAGf-g$Qi;|**LdO6_`LR+>;GwjvEKB3F)PfYy&2^MQ%`z&r)sJx2 zs(*!XR+P}oOY*`TU6cjuBT*+1jYko2F1=sZ92*3rk`8s?1d|8X8W;>px_z@E3Y3Jv zo8VP=ZN|t0h!B(UW!e&`$)%aNR${gyLAO`Z?U&WWkrXUgHU~c<62qnBu~_V3GtBzE zffz8zTni5bJq;o3l8B^qi4u2xB3HZ9qY7q;4dk$3ybWwT&|17UAv{&vP z-v9E`bn>{z*!o{+Snq4HQZs3y;=@}_{M^2bpTGT^_MJQe8iJoZ__&Me@Vf8kYb>I% zV!cc6-RmJglY-u$;72~J1nh)WPj+;UvC44 z^f};u*bW`+lTte)(YsMy^e^0A-FRc-K#Pe^i7lyN_Z5VEy-U8a>JB3*d?z8Wdga22 zb7zV#_sq7QZya`PHA3hvUthX<{zG>dN#Q$HR5M_j>QMA3qYp*lVI;{vd!&?Q28^@$ gp(r|xq;UEl!2?e1!w6|z01E&B07*qoM6N<$f>a`>i~s-t diff --git a/companion/src/themes/new/48/apppreferences.png b/companion/src/themes/new/48/apppreferences.png index 8a94b21f816e5e4c7639162b281b43f0ae35a67e..be06b9a3f5aed65ae06c72065c2775fe411b39ba 100644 GIT binary patch literal 4839 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 Q`v3p{07*qoM6N<$g3U%=`Tzg` diff --git a/companion/src/themes/new/48/clear.png b/companion/src/themes/new/48/clear.png index 6c10e115087899c4a32a99ab210f831340f46e94..445702cc8560ed0f7b7f43929eabc810695daa4e 100644 GIT binary patch delta 1701 zcmV;W23q<26|@bIBYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU& zR!KxbRCwC#n%i#_RUF5EGiPSEdujL9Zfgk$5yVSC7N5iz1cDMnAYL9Y{ssDMOq*?D zVwP+Zeb)cL#F%Jmj6oC;eel6Z)dxW!K&k@0Y9v0>W#`Y8DZl+@2t zvq|p2dow2oe}9L+%VX?4F-nP7M@a3HKXfV~+3iLV_+`L!4=7YxF=_hrylsh& z0uA^BfR8Fv1bjue8Zco$Byc_bO-4v0jtsVx;LlH=TByMvj*%Dla>(`i^D2{Qpf2(4 zf-Q-*0)RgT_^Dm{BNUCOR4CnsUkeqfOPpC05_?{Vt&`x-{dzi6gFh4%@Yyx+^~5DY zb%`?>(tj%LC0YtJ;GYd6=T*u#fnN(3txKGRMA4Xd>QJ;H!GHhl%wp0PWU0h~8vJ4t z__Y$eWJ^^`#A_$fRG^1OV@mWU4&5Cx1vo!yZx06~kulvMQl*i63)RE*TU2 zzApgy=fb4ggl|ajHs)iLThi&m`2uNGD}MK2*K8ynQB;}A_}I;y=4epSaV+FDiun~v z>>HrzpYkbwKk>`}Dd@HqmhHpyRK>${nh9`|R$uejtwLj}S59w!+()X%`A92D0ulzR zy?@I9l5q%MPpCRHbD>On)p`fH|Gtw(Jf?W0^yZy?q_~ujrP_NYzTpnuqQC!KAzf<@ zZ>Jj-5}USrT}gD4P~Yjs11w9Q79eX0tuye@UwqmfPd4;7Q7>Yx&(v7@Fqq~*=Ts8xf{;l9Sf|L z7#fx~Oajm}e+xa8;SAoDKtqC2Iu=KF$-0NnU~F{*?|My)6jT5n!rRLjVGWmCOMI*d zDl+9{ArN#E!%Y=R1-z7eVpO66hWQ+ZdDEo;U&KT_G6f*<#|?{?tMnd9;oY7I2!D7F zB_E5MRKV=C8~F7S5?z?Z987a2;iMZ)`Bf{qGiFke!)x8cuaiKXy12lotlO8cJCLRP zij~|E(Kj5vnZ%{60tv~Mgq^8G%E#gRHOiyGE@7}Sd$b?SCBm4>2T`3a=T%xUI!kn# z%%yzHOl}WUdk%l6gd}>WD@8A@n1Agh+D)fZKG{re>#Lx_uEO8L4cjngzX2xGwG}QQ zx0GnLph@)seydvU3f@}X_>)|`EhJD9yok)~^|ssM+tdIJ1BE`PQlSs?AH z79C3%I0`%iWtB`ON^_>;<}M7&D463_j~|P4g-jm6!C{yZ;DZ9*Q_4>AgJ1J|{5PlZ zI0MfNq@!S~I@;JmUQQ|H0!cPY!jfe&d?9`wR|}cRJC=z3u`$Us)2zHiINOV-sHFS) zIp%S|f8lCtkt}P9Eki=9c7Ld_fDdwbHm>9rCY#Rr!-Hc438k3BO5f}VZv+NF*c#sM zKqe&QV!pKmhaU*z%*NT`{AAmD9UT%9ET3&DVW}Q6g982)z<<6GQwbp<6;S-uyCh`v zS)njr7>vscbCY(ehB+9AgprnWyd;dfw&T!Xd1lyvcRHD?Ni5-`b$@E)%Q4+OeQ{|Ybwm^?7qYLPr+00000NkvXXu0mjf!f7?T delta 2805 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 Bw&DN) delta 3390 zcmV-E4Z-rg55XFcB!2{FK}|sb0NDiGvf2Uw0004VQb$4nuFf3k0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv0RI600RN!9r;`8x z010qNS#tmY07w7;07w8v$!k6U01P%sL_t(&-qo3HY#hgV$A5n_yL-EP?|c(qj+7{w zk|;ax1#!}rB&4)B?J``wepluqssoTPF;+Hrv;Ixq&D>2e0 zZGggtWvQ(rS9K)El}m}F$;zThTYM48d*yNOZfE-8?#R=Lq^O{%oB`%`cXnp(|9_tU z%=7H7DBQcV#edkh|I>7BYEUD?XOF*d;-7x)}hb^ zU(sGczSF*oz}63n+1c5?ef#!p+O}=m@slS{7H&4kReuTm;NtXqyX-=2sB!DAna=IP zvI2B>cauyeZ*6XF?%KY6`^zUzoOs`oFw!MTKbR_w=9|0v78blt%d&_>A|w(C;d$Q9 zJ)1^b9)IS<3xK-WV3#ET_@3uw1_lP+h(scNj^iW>g#yh@4Rps(iMH0J-GBJ8>3C~! z?B8GfF@Nv7g>6)hC9QRKVq)Svu(h?drL#5tEF1EVA%Zj5ZAU(^qbnV0b4Oo!zmcdC z&_KcSyyTTDS1#P1xOmH+z`w0GrH_>#MMSbP&~ndh+dF4s4}Wv~c%}dQvPhsI7+}xo zzu@FMUqNM_L#r3jdgK?ip8UGb{Kp3$d*rjYLw`dt`P1<% zCz4a>+$^Y(Q|Qcdgg1Wb_dav@j)yOfT)4}!touhsM!M_g85|tk3*0v`F|ivkYww*s zdw;euo6UaG^Spb2U_GA6$;sa~P4lxrd^v*GBTyxg{+|i@k9>_kAJ6fx$w`=>(df5M zq36G6L^gclb6X-W-L17YhK7ck>p+U}@$rCCii;O7HUU=c?*IW6z#F_Nh~+7Vkay;De4*N?y8jN%Zve*vF0?bB2e9o&Ns*6>(md zVWm%W$DN0N^*g^c`E-2ZrD&`f+y*eV?n4Cc^3$`IhiAi|_bQ~t)YMet#Kc6G<2d6z zJw0=VVffX_78VxlR4TRQ_19m|9)CP|aNM%25}<_;D5d1(%a^yDJ$u$Xbm-8CZQGs@ zLVx*(sc$|0`#YatnP6(Jfq(`w#XBDQo$ReTx-R}lqz3;1tu?{HS1~phjcDV?d&zv8 zq;oF_i=nKKH#J3R!=}z&)9e&t$xfpMgUiFiOq+q2w4Io&?8rh0(%Pi|(tjAqLXkN$ z(3>#I3QHCPU$t-h;tB7}7cSJ3SPKC}q|I<*?uM9Kps?*r*uEw`{EvXf9X^A(SrZNa z1|s)8Qtl_YV`Dp|u4aS~NO`sQdt)}6_UvJ=QUs(x)QF(L)O_d{cH{d$hhrIwV>?=H zj8L!-7zVr>CJ?>*ucG02Ab%PO6aW_*KZmnLk$&s@pf&E$8O&ZuB=}*({4r9Y`?2li zvvDcGG=nStm+QLJdJG`ZY+*LEZlt`hZ=8U$p|`mqD4i=;iU5R?f?WIG5cdS>(eI(5sSD^837FwfbBn8O(=3BA42fY#FkIA*hjE1>)BjzxE|ajfNh0ncjNDPO(cdk@ z5!c`FR_fCk10&YZE`RK>t-Y+ECKp>%z9Af^qt(?&DUnhlVCmd+(S45*+;K12q#!>B z#S3Rq*?%Dz$PvvvgCP|{h-GVa9$Asva@DmYiI!lKwc!KNdWWsW143FxN60Ud&Xl+F zV9Fz(@vrXH{g;^Yn(W2r%LW=chqYDXgbqRaDAU3F@s$Z$mw)Z2HCpS+rns~Y#BzcX zur6lD&Bm@+p=|WUt#mCO5Yi5GG+EU@1}!BTadnk0YR6v_y!BqPNyyJ>3Ipd*^T%! zPY@P@?3>3>T7Sd&Hwg5WXp9^n?0tiUhR>iYe|sbAVq=pj0$n>c)Du{f2jaG9cZ`Z= zwMN+XHTqquCUV!Kg!>LNpAqC!;0^ZUXO0sPS8!9`MhbsL&DYOYZEp{O(U|C@ZYNp` z0V8gUR@W>~E_{D+5wEo9gyCZBdW1;dr^uxtpVSlv`hW4WFJq}u+~l{A^2Qc&A_Owp zl&DwDS|lVbMEmU20%-vUQH~rpP=>6_{~R_*KOT=p}ZjSW~m*p%M{C7*L5Xiv~;w$ z+AO)VSVWlSidwx!7FH1ZwyzNT`NQP1kWXnAE(}mi{}@kg!S}Muj;(KNa=>-nW@BAX zm>LINpFl9))oL#VF{u>7an`)}gb)Zbh`sk|Vt>1jkk1Kn=@3(+`!TF8N|_mi;F_`Z z^EsxZ*%q#|<4|iYf$K>~2+M74u|Vs}m<10^3#|pUUe@|r@rs%sfyCYOBuYfM_@jOp z`4PSsA$sdCQwX@YO^H=NlqXGu499HjUPtAH+*$~LFgj$$W4u&;pJk1uQH{+gnXf@v zb$^#cNQp2+<-BqfAO%Pq)V4>6#LkmD{VZ4h>jb4-iqOve%*}_utcxu*77{>Q2uns< z+o*Y#zODzrNc63D*%Yp{q%BwOiw z?Rn+vnyR&4^}4oAYmH@DIF3Vb`vIJR6pudoC{I206sEa6tgfg4oDLvRQI%emfPcMy zcd*T(u~e!6(F*b&z80ur`C2c6)8%Vj_EyznYVjJhV)33*3a^l7e%`}0O+NCGyEu68 zPJE?Tv}(*21Wh|JQzozm2?-|{_lxn#snVhZtc;?N(kRnkl14RA6%wSlD#=8GmK7-} zh4vLfgJqZmEE_2d49eTB6@aO!0)IjjmxYt@6mc`qHdYR167W|i;EP~;P)0X)$Cld0 zEa+(lb4`it|7j`unsp&FXteHa@+VJ^0{-fOOhh|6Y<>0XKf|~w-~lW{u+9Oq`Sy)e zg7B&Y)PiVVXV)cKrJMVGV}0B}$aP&*!L7b zA*4VU<<~x3z4le>i=62La0n8GY-53B(Il7nv}m|IZL8ge6e)1KDBBf599#< ze*rjPP@j-}vx5Kt03~!qSaf7zbY(hYa%Ew3WdJfTF*GeOF)cAUR53O>GdVgjIV&(R zIxsL2bl5@w001R)MK@SKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}000i+Nkl2#+b>AroRXa7id40-TUXUkL7)zy7(o!{qse!t&2zjF>n2*EeG(fEe9 zZ@d6@x(9n7edNEbHrrh^O&f|VO9nC8R7L%(EX&UV@cj)LDVF2@jpMjIIoa9fuI_HP zBFk$wZQY_~@n%rd<-jkWedc_r{YgdX^n+>+K zGzg*y|G)s=dHoG79*_M9-+!$l z%SXOqe$i|;_pQ6>#x#@J3_~}d8#)YK2O$KWmd~|w9UTYm-@N4x8UUP`nS^24XLs%2 zXPem5&U^1WASV+4(%je-GjtugrolfjfO8%XR@K$fwlv$p@$Y{X)3P9nyNl+{vskQF z&@>H(VZhL%gBKf#;aq!rSWYCqf8H!qRGq~w`}gq^do>KhqpGSg9w-`#z$^#^fb)XW$P}WcYZj~ZnMGBLO+0Tx zDrD)T2v2LPkw_#C-m_)%JCoLd!Tx?D)9FNMS$R>K-Tv{e{ri~Iv-+R@WVu-|KU%(M z5j%b~iD4ibi5LKSrUSa1(WfZtW{%_5&7D7=q8S=ALxZMi7`le$<0tgiGiUt?N&4QT zbzso%Z-|6K`JrIYwP0a6&6`XWjSUU&?b^R@6;0E%7OUm(t#{mE>1=NwPX>#cleyXQQ3G8$HJWMnb{ z|4=C*q-m;fNqOKxVU&b_v81%rlAV`}k?08gg9AA7?t6-^>n}_3_$C0sO6cvjrMF2S2*f95U!QRU%=IXa?Z``$i-wh`}`|N0GS(()=2w#laH1GhBh{xe@I;pB z>i#4ii&g1|9!jJt0s!imu?_VAfQNpve`6pJcy&ol4Js-tvG>7xWI8hujf63C=FGxN zg$FRXnETlikJ~AlZYnJ+%VIfJpebrBVd+#@O!NvN$aJ|7@cT)_v5!wk@%S?5hrg<2 zY36^EZ`S% z639zS)by{|lo<#FUcF}VVz_d0@IQZe5jnXzQ^J2K0jZY$hgsC)_!XMV7%C%kA>z+H z$50e?JI8a6%`Yv@uv)Fu#29yFyKwM(D_}8GMt+u+UbcQ694;q*``B+0Ui94&M`@MS zX0_t*Ylo1Vmz#pm3kHLe7Q-(sV7m6;zK3V=CezXR3+89r($c=@BN z`!39IW{#E}!vXy9*#qzvt;c}Ep9f#RZTplfd8$gjkbo=NQvP`R{a!_umz+I)rYjr@ z850xTQFRM=gT*hO_zeIc&_9R|4!(twd1=UNJ&f7u+(qH9IEgRQ6IndZyXO`c7nr4? z(b`F{;)91bK}~2-R0EFm1eVS(MmP{0)hVW9$Ug)ov*=rjv!ZV7!MAQ(j~OCB0bpqw0|668 z^aw;N2U!7pT`@%E7y!)qT8>pN1ztA{w=0Lm?AiG!uBZVa21Y^w*k+9GZwfLPB;q`J zhGZB9LH`gBpbx5S0cVOKU9kNivU+Q)VHj7u8M;yrRBMLj&dz0VRbd|HT)h~FUV06` z*z+V_`u$;awlw0@#~-5Z_B)a1;NVPSL9sy9-`$D+As(D52BBi(>-W7C_^*o@N)?CG z530>9U^K_%_^z+bF0~Qe|n7tH<>`Ihv zsRU6Z%*f8YZqFk>e~u7xHvn=u+s-fJfofS(+_SC{ke8Q(yg4O!^VPS<;H_3Os%z$< z^<*0)Nr9&5&@=-BkuWIN?6FSlnOP{WsNf3c%)V0)gqH!(7aHZSNW=@m)!LcpIJx%fam$King!28#y^S%%ZBQDp3?$Q!~=V;{I|4RFBAUcS*4w zIoVmTJDm9N-Q)0i{Qv-)&5Ww5BKSOAh(#52_Q#-T1~Tm?3?-uAXnKw6C|Vf`h29V? zVtlL|Pr?OHoRjwD9h3+AOGD=PzLOB&oq zPNKUjFb023-&ab8G3bx4Z3%jP@aaLfS9nenl^1wGxtB)ouy6@~D5 zdJr2?&^Z`~q8V_00l!Ys^|1q}JrC^A6h&Fz+tYh05C|9(%Wy@O(bwILpx=+e*@foy zH{Ix{S-IlQ+`PQkd7f`0gcMzlfa+j8?5-%yfX!wD%bRfG({t$S9Ug-(FE2oMdk^9< z1>V8YWX-ah;7>$gVwgHb*WaFW=dfd^EX(q>KCjOgkH@DB55q7J35C$(^C1z7p|reA zShaR-p=c40?RveDPct z`n-LJNea6BacDY0R{AKsnPqQ~HSLXy%?f*W?Cj7~wSHh=ATj>`SUj$uJ#)4t7!2Mh zNm70|6u#Eu@fMYg;2V%Jk2Z!yQlL&b$>K)WXZy8SVR#N#h|gV3x0oeY@VN6 z7 zfl>I4lBOQIoCWCNoez!}hH)Ymivbh`oft5P@jigz3Av%`y8d(|5;3G$3^YaC9@w*+ znIwP^fT1bq8bQwN1(4#(D7?jlWh)lJKM;f@tLO!d#a%svZA9W zn1HSm6u8ph8}>uwxLf0@`r4J&Ld?nhQ6+?Ymkm9wBhd?MB|5UG`o-E^UpqqEGOX&f|4Q^e8YZNIR3V{ zs{UpCIoIX3hj%`x0eIi%^%0ZVjFJWOT^z@~3BZ+n#maHq?;H+Ckst^Nhr=q*^9@tx zz}_Ru+W^)zw{_AmS#&9`Am|^4BFpec73c;*<-$2=>GHzL^WTlB$}3+6e(b7BQSSA5 zy}q`V7F5;LaJ4H}*4oq4&+t6oBM3r!et!OUW?ePQuBs|JJniw3X!M>7Zt5Rc&aVaV z*7B-FdY{M30KiB>L&?>}c)#IOSb6@A5k>hE0OL|2_a0HEeRluu9|J%+$8m2I%`M8v zD=1*2;qZBjTr3ttyQe*9v)eas{-=Nb-FX54q$LkwO{vSen~RxcS7*|{U$ea0;6{@M zZ+vhRy;1gGUpgxtimA|&0^;L@C;)UqhQbYK@yaxbX4%tq<1h>DWUg{NV^Ew zLQ}v1(tCY#-~09UtTTI^b7t?e*37rR{Y{LynLa%YCk+4q^o9ny7NAG`H=tDD-G=Nq z3Un0STBce6P&KGT8A}4^kU$H4ZJ=`W`hOE%cLNJk0KnV;09-f#oPbNXKLGFq%(ChN z0Lb?MaMeGv`L-IkLFHzwuM1rMcjdN~B!Vkf{0(daL2vNCLvQH5Ish=F!8rx-!!l43uYAm8C6Vf?1TmIsCmk0#`GU z&sJwo+UL%R*pAb(;;l;x0)fC8>1u6Q^zV|yaA}40+P9XC=Cxx2XV5s zwe^Vcy7Ja4HBabP;_Lnwvb#?V71vT~6O8bV5n%ik?AH7D>bzbsXM(gq;=vWd`QVv?YvqP3O4Gj&yWU=R3 z;5Y7+O>N7g&N151Of%u{-@j7@1O_s~wC!Z%LKxvl-Fx!sVX-kW$5$(?TS7_y7I8@} zp|I`*J88eU_H)lBhuII4q}-V`QG#8YIueNy#^F>&HJQSfU@;ykYJ3!QJ)I=#0mlt=1j?UqUD9_2i&*`aj2BLVLAH|M%apis>i6(%yf3`cO z0l_utoQcK{u%Jnd;YZihe(jTs%B} z!@_7Fz|Gs{cuSK957y5`MMcZHdwO`LNa(7FhzQZMuGXj9{Jy@vNHKBoON!1A1qjgj z?e9ULr>Ex%Jr#M8b(y=IoE#x9FE4CuA0v*%U`!gs=eGxVoO#&T2;uo6M?<$+DbtJj z5{G===oQdjxiT@l6fjXVwzs#Jke{FbPknv81#qX6pd>4d`!_Z=7XJb?rP-&yn%Kmx zC0HpI?6X&tSg&3UUi4B*760hkLuHg_9uDTzVgdkp)3MQrGDlz@jg&zk=F2N89+J-= z90s>#eZ7+V-ACST7Q2bc&i^oCoGN7si|f<(Nq@e6wEZg(R()@>cyD}sJo(}SOq&-< zcJ{JTsJN_*mg-erkB@vk`PRv4%S7)Uq|rwc>!C=qNSIep{ytWtnn7zlc;V8`BpF3dH7B!k7mzI}T7Z(@b3JD9BVAZ(M zK|$Rlv^L(7ABBR;oA!9f=5=)N6ciLl6-+3PPfi9_R#j~}*x1-K{P?>;HBRHgYSTDr zzpu&)n1+U)70)pN00v`Wi7x_60Mq7#4i0wr z^`!}Dx{hh%=6?r8p-_KTSJO*BeE1+GBBD&%$BdC(0}u?Ikt9Q`l|3qTWawe_-IE_b zevAwa4bg(%K_Mn4X6;%eNiod?#SrCg-Rqt6tk~GdNX*FC*mx;~`~3WTUYUU=f($%> zt|zyogj!Nk@~w2onQTX6qjKuXF^k*;cQ)T<-)rIKJ7iEGwa-l@_+Z^u-_Fi1Qm6oWO{|Loh;k(Ae6U7S!P1D4L?poxFE*H)F_siT5H;AX{85tcEE(T|~wR69ohoLt$6J&U&-U1(91+)K?vL zd2vqlYN3o{C%cKM(Gfy{yB`qn@7M3&eQoP}Zl_z|>F8-`Y11+@!!7XPyigZgcCes9 zoYB+M`#gAnUjNY`UDebS!c$CK$s8n4ZJGGNEYtLKdyyuprwe5IuMZR(iGE*ZW^`^O zYE@XjVtOg(Jv#q6O>Q|eGt;r6qM`-(;>vI@P*@)X|ETI__)qL+Thw%wb57Ue>$?2R zdiwf#<{~b#X-xPly60)KbzG$t*aNn8(%RZE`S@#Ni7sc;&bM&Yr0wnP<1(8nry_F^ zkizGKTKJNUCg$cCD|*ABE26qarUvm|YTfhrvl@oV-)0FN4_l9yGfG=qTip_ebbtCO zEhxVQOLP&9G{j<6@2MSgaHu2Wp?Ao8l1^1ui-c}QFYGX}-+M9nlj_t!#-m+oa4Ipjmuc-) zSi^gz7BwHgRpD+2<Iv7~PGu#i^%0d-1*ePUR)rVURi+j2+Ia%fB6?83lDKbw1;OvX!vxI9{Wz!H|kUnmvB zG~lFd0OxZM;%kd%USUpK*$es>*dVr8lkBoKT>(ok7J%~I4o^T7S#Yqjvx9Y)-n_lh zviX*ghUR4AlWW5dut1($T3I=Yh>3lY$ry1a|I;6T-g2~pS$;>n{2ZDN+nnU}QcpO7 zgIOJbU(!Pu8Z3@OXU33<(`Pv=qP&ppkHXe*Vsybt|qP ze}jH6FXvZRKQ8?EaqCXTNDzglbmhY+s|*|C`nKJqtt!5*%xe?7xSWSnWEPM^6@S8I zWYDX%qmPDl&xqJ*ub;XTI0!D)33G3|#&g&VY`r9qlsPJ_;|2!}L|9{oR~0X?8pm0x z!TESRsat6-be9@Dg$c(zbGVaDB`{Z(V35CI#JU{g=*}vkfGglOmxRDOm=`#)7LB3k z-R0!p7XvAuOqqR`e+Fl@-#-{CcWg-+9US}`GWYDzGrG@hTpne7@M+lDkc9$re0=-? zk8d)!w5*%-C2%)g*?F$)i#g(cW0B5YqE-01@!BUOS;AvpH*%2?Y2Fx~atBhbEny{m$2x98RPK`ESD-8v$NAThn({pG>a8{VXQ z?JG5uq0^GCSA#rU4KVEGO^yl9K{fsj9ox;xm{U@X-mGB;WfCSrTkH5giR-p9nw0`q z4YF+CpSB+Xt+p)2Iecb~a%?vU5NPbuZ(PHXBc?-VgUeg3EQfbl5k7$3B`wo^V4oA` z2C-H9P3zo`61Td%Xes%^xJYxUH|$ZP8JXsUQAHxnZEf#KOGx~5baJ}j!Ge8Y2b5G{ zC{SpAgFaQ`cELn6IvSe*bnpu&WqG$0OxJd25*L%hc(RpO%7X_HU^VaRlnfV z!*l%Xv8fiJu=}qkz(`G(0x58Y)cbZ4skaz-J?QriJ#M0c;{OagdkpHFzX6db{w6LC zyVJ7S?hfk2TM7yaf4lcorcQqbj>(86uZ|>(+pNBN^~#&JY9O9R-w`xtXJQvs0#A3AhB-RMswyk{hZ2P)OK#=Nt_3vtZfJ5sa4wH` z3W`Q%t+lByB!p;WXci0SIjD6R05#qzNI83cr$~5WESrQLE&Pd?Kj!q$ z$xzgId;4x?9R+U3VnvB-$TUNdGBP6KnYxOKD88y{0DKK7D=RBWAt9j<9UYxxAl;vf zkjaGuKGLVR!lxVy<6+b{{t#LfJH5%v&v8p?67JUn%nUmotv|l%yyhUr9@i&+Ez-8P zro7jy_M6N@wzHcv_Qb|z8V>Q|l}D|@M?6kXaadWt&jp$O(MQr|h8Y2|H#CCGw)Lxm zKc={yXllD6t%?z-UJW9iw8{h-?~fd|{v;&Ww?xTt{jhF}?3lar&#jZNXjLf9WY^y1 zepdtu_s=EeWujA}li?68_-8GIzIhkz;fnS|x(9fI4v yafA#KfqGH00pGH0urI{e*w!Ii8EjTV0hC^w^G~X<^KTCKgJRO diff --git a/companion/src/themes/new/48/new.png b/companion/src/themes/new/48/new.png index 3315820aeff59a5b4292e7f2c91ad5df26669d02..53dd74e30c212aacbe159a93b49a9ecfbc92e410 100644 GIT binary patch delta 2561 zcmV+c3jX!u1d0@pBYyw{b3#c}2nYxWdO`YD8sZ?FeV}odsohulOGCTkqrLJrLxH@;o+Q6?cfKwgf8RKL?!o ziICXAXE~26i4p5v+sjR#x`~U|U5qNLr*;d#!{e3NS9s+0N0>Ec!KO%&>&3Ul!FB{R z;C3OzXt`Xj-mU&E=HKN0X_6v@;13f|vE!v3_)(wBMt?5jsmqC^k~T+an@%4C|V zAxRQtzs%Dop61Z8LttW~bECLT{I0sR+HA{m*&#bS3rI+kgd~9^NtJn{>r-Q+>qC== zxcRl4@l~ITMlNFeS=%X!A_cF2k;`#@_h;x*V*ps5#oPHeNu*NvNNgY3j^P`;dhFFG z9#2S5N`Fzl$X+3YP@9`g)PQUZx)I=ov0{0E8Ecx`|F#o5Vsp;$Ic(dojf|T?l|h#T z+2Sn(s-HBsW!{YR5(d8d*UcG z{9>y&8@(XlnGc_VM7Z8`Fiqi~S$h3060$~2ftU=%v_ow+6hiR9M24c7#}2^sq2RmZ zHIumw9z=j7Fv}$^2s8n|L=_MM*L4|p#(zUSyMYwPdg`NA? z3~^xRzZP6U03v{&zA(zexl!B%PzG$)sV(r=1tuM;08qAV@PM^|54ezwrZ}@_q-EKV zC555X>CYt86p9rVIwF8Zq-7Ad1>cMiASxM1Rn(A#0OVEZpQ_bM05P=IL0p?oJAYLH zkYyPKC0s2GJn~+S59Z!K&4mV%!^n~nW+CA-lb<@}KA}fa@N(fg4xj^ZWVKxjuo!$R z&~D(FEIfDTBm;@iZ8F6vuKeXj*7QTk zhoTRL50(bbrqC5p0E3flvkobZUrZI82FYxn&kwLL4lBZlHp$>zr}M z8SL!dNmN9`ETn;5hMWQOC73ON5md594S`|+*%HheFl$2A03lb>r-#We_&JboAH>aw zGyu<{d$KH(NF+FS!?|4d)_-+8I`k-k6hI8D68Jv2GDHOY=Ex|iND2waJ2?shTmy3D zFp$NXN*b1MIl!-Zmm`3ww#~VT^+9#v z$45s|&(UVd3 zZQO^MFvIpD16~A*MkPknN~Kl8w2KDBfdVd%@f45odte;M2_gKB73c(fb*^a|0|Nud zvW$LAXVZ~Q>`(6J=!T<|N6L@`dVzeUXNmw;crWTlIdAGb#%>w=Gjluz{2Ry$A-q;c z%F`66f~{>cPP=XZzJEIEy3WAB0J^Rdi^Uk67$o~2+e$06Iu-IjmV7X4+CIbv$I+MmYcuyljFya z|4ax`=){FYqZn9@yEGzD1)t01nVLFD$ujBg>ZZTHpMiDj&~=>?6BEImyLLTvoE*``EUPVHgyP1-iT9b>Jr_C%FH?`}e*4{EPRs1HU8!?b?T>s8UUf)pTiDHl>n@ zVVWe9$vW^4?H)aN@Q(-YSPJ-#gLoybRI5O_Y=2|hHf7spaB!gNHjM5bJ-Bc0zUze$ z#g(=atNP_}ZI$&r52q5usZ@$cB+A6(gt-5^59~eo^ntrN0l(@Bv?HuRe5;=tTmfwSgnlm}fDeJ^Rtml$feHy_b-qt&&{NN5o-41+KX5kj0Tp+x{d2ys~7muR=!AAlSn;;y4bKq-aeIEU@~ z5{*XVTdUQ24}ZKMM#8#stdW?eNx58RHk+~8YzTsY^?Hqz64!O9*Xw!URtWL2)9L&G zHbCS^rbR#qf$O^LcKZQXDMc8DY`0s2AV5lq=Xv=s3~zyVz>NKf{SR6MU@u{s=HEap z3){9S6bbVHm7dE7&*Yqkj)NwE_V1`5a;zajFFti$&}? zsTPn@#-5XEfm6r?bdw3_CKJ$2CZL-K-$oPtOu8_4Uuy-+GMkc3nUWL4-6T^UGn-&AJcS#_fi3M9GECApY@ZQExD zb8R98Mnt0#-EQ|V1(arvZ diff --git a/companion/src/themes/new/48/open.png b/companion/src/themes/new/48/open.png index 04aebb09f5b2653eae1be9d0f3188b9b3b4b78a9..590e37acf7472914c14c8027035b10bc78e4b8e6 100644 GIT binary patch delta 3326 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 IM6N<$g8W~0`2YX_ delta 4372 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

;Xuk~V%275&b%s4M4R`7Mt?7# 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 delta 2619 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 delta 2616 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 aq5lGv6YiBFz3uh@0000 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 jIaDz Date: Thu, 13 Feb 2014 00:05:22 +0100 Subject: [PATCH 09/10] Companion menu selections are now marked the propper way for each operating system. Previously they were marked in nonstandard ways or not at all. --- companion/src/mainwindow.cpp | 166 +++++++++++++++++++++++++++++------ companion/src/mainwindow.h | 4 + 2 files changed, 142 insertions(+), 28 deletions(-) diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 5a9ec02ab..85eed8af1 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -1583,8 +1583,7 @@ void MainWindow::updateMenus() burnToAct->setEnabled(hasMdiChild); separatorAct->setVisible(hasMdiChild); - bool hasSelection = (activeMdiChild() && - activeMdiChild()->hasSelection()); + bool hasSelection = (activeMdiChild() && activeMdiChild()->hasSelection()); cutAct->setEnabled(hasSelection); copyAct->setEnabled(hasSelection); simulateAct->setEnabled(hasSelection); @@ -1593,6 +1592,9 @@ void MainWindow::updateMenus() compareAct->setEnabled(activeMdiChild()); updateRecentFileActions(); updateProfilesActions(); + updateLanguageActions(); + updateIconSizeActions(); + updateIconThemeActions(); QSettings settings; setWindowTitle(tr("OpenTX Companion - FW: %1 - Profile: %2").arg(GetCurrentFirmware()->name).arg(settings.value("profileId").toString())); @@ -1766,9 +1768,13 @@ void MainWindow::createActions() } updateRecentFileActions(); + QActionGroup *profilesAlignmentGroup = new QActionGroup(this); + for (int i=0; isetVisible(false); + profileActs[i]->setCheckable(true); + profilesAlignmentGroup->addAction(profileActs[i]); connect(profileActs[i], SIGNAL(triggered()), this, SLOT(loadProfile())); } updateProfilesActions(); @@ -1776,86 +1782,138 @@ void MainWindow::createActions() createProfileAct->setStatusTip(tr("Create a new Radio Setting Profile")); connect(createProfileAct, SIGNAL(triggered()), this, SLOT(createProfile())); + QActionGroup *themeAlignmentGroup = new QActionGroup(this); + classicThemeAct = new QAction(tr("Classical"), this); + classicThemeAct->setCheckable(true); classicThemeAct->setStatusTip(tr("The classical Companion icon theme")); + themeAlignmentGroup->addAction(classicThemeAct); connect(classicThemeAct, SIGNAL(triggered()), this, SLOT(setClassicTheme())); + newThemeAct = new QAction(tr("New"), this); + newThemeAct->setCheckable(true); newThemeAct->setStatusTip(tr("The Companion 2.0 colored icon theme")); + themeAlignmentGroup->addAction(newThemeAct); connect(newThemeAct, SIGNAL(triggered()), this, SLOT(setNewTheme())); + monoThemeAct = new QAction("Monochrome",this); + monoThemeAct->setCheckable(true); monoThemeAct->setStatusTip(tr("A monochrome black icon theme")); + themeAlignmentGroup->addAction(monoThemeAct); connect(monoThemeAct, SIGNAL(triggered()), this, SLOT(setMonochromeTheme())); + monoWhiteThemeAct = new QAction("MonoWhite",this); + monoWhiteThemeAct->setCheckable(true); monoWhiteThemeAct->setStatusTip(tr("A monochrome white icon theme")); + themeAlignmentGroup->addAction(monoWhiteThemeAct); connect(monoWhiteThemeAct, SIGNAL(triggered()), this, SLOT(setMonoWhiteTheme())); + monoBlueThemeAct = new QAction("MonoBlue",this); + monoBlueThemeAct->setCheckable(true); monoBlueThemeAct->setStatusTip(tr("A monochrome blue icon theme")); + themeAlignmentGroup->addAction(monoBlueThemeAct); connect(monoBlueThemeAct, SIGNAL(triggered()), this, SLOT(setMonoBlueTheme())); + QActionGroup *iconAlignmentGroup = new QActionGroup(this); + smallIconAct = new QAction(tr("Small"),this); smallIconAct->setStatusTip(tr("Use small toolbar icons")); + smallIconAct->setCheckable(true); + iconAlignmentGroup->addAction(smallIconAct); connect(smallIconAct, SIGNAL(triggered()), this, SLOT(setSmallIconThemeSize())); + normalIconAct = new QAction(this); normalIconAct->setStatusTip(tr("Use normal size toolbar icons")); normalIconAct->setText(tr("Normal")); + normalIconAct->setCheckable(true); + iconAlignmentGroup->addAction(normalIconAct); connect(normalIconAct, SIGNAL(triggered()), this, SLOT(setNormalIconThemeSize())); + bigIconAct = new QAction(this); bigIconAct->setStatusTip(tr("Use big toolbar icons")); bigIconAct->setText(tr("Big")); + bigIconAct->setCheckable(true); + iconAlignmentGroup->addAction(bigIconAct); connect(bigIconAct, SIGNAL(triggered()), this, SLOT(setBigIconThemeSize())); + hugeIconAct = new QAction(this); hugeIconAct->setStatusTip(tr("Use huge toolbar icons")); hugeIconAct->setText(tr("Huge")); + hugeIconAct->setCheckable(true); + iconAlignmentGroup->addAction(hugeIconAct); connect(hugeIconAct, SIGNAL(triggered()), this, SLOT(setHugeIconThemeSize())); + QActionGroup *languageAlignmentGroup = new QActionGroup(this); + defaultLanguageAct = new QAction(tr("System default language"),this); defaultLanguageAct->setStatusTip(tr("Use system default language in menus")); + defaultLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(defaultLanguageAct); connect(defaultLanguageAct, SIGNAL(triggered()), this, SLOT(setDefaultLanguage())); czechLanguageAct = new QAction(tr("Czech"),this); czechLanguageAct->setStatusTip(tr("Use Czech in menus")); + czechLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(czechLanguageAct); connect(czechLanguageAct, SIGNAL(triggered()), this, SLOT(setCZLanguage())); germanLanguageAct = new QAction(tr("German"),this); germanLanguageAct->setStatusTip(tr("Use German in menus")); + germanLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(germanLanguageAct); connect(germanLanguageAct, SIGNAL(triggered()), this, SLOT(setDELanguage())); englishLanguageAct = new QAction(tr("English"),this); englishLanguageAct->setStatusTip(tr("Use English in menus")); + englishLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(englishLanguageAct); connect(englishLanguageAct, SIGNAL(triggered()), this, SLOT(setENLanguage())); frenchLanguageAct = new QAction(tr("French"),this); frenchLanguageAct->setStatusTip(tr("Use French in menus")); + frenchLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(frenchLanguageAct); connect(frenchLanguageAct, SIGNAL(triggered()), this, SLOT(setFRLanguage())); italianLanguageAct = new QAction(tr("Italian"),this); italianLanguageAct->setStatusTip(tr("Use Italian in menus")); + italianLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(italianLanguageAct); connect(italianLanguageAct, SIGNAL(triggered()), this, SLOT(setITLanguage())); hebrewLanguageAct = new QAction(tr("Hebrew"),this); hebrewLanguageAct->setStatusTip(tr("Use Hebrew in menus")); + hebrewLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(hebrewLanguageAct); connect(hebrewLanguageAct, SIGNAL(triggered()), this, SLOT(setHELanguage())); polishLanguageAct = new QAction(tr("Polish"),this); polishLanguageAct->setStatusTip(tr("Use Polish in menus")); + polishLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(polishLanguageAct); connect(polishLanguageAct, SIGNAL(triggered()), this, SLOT(setPLLanguage())); portugueseLanguageAct = new QAction(tr("Portuguese"),this); portugueseLanguageAct->setStatusTip(tr("Use Portuguese in menus")); + portugueseLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(portugueseLanguageAct); connect(portugueseLanguageAct, SIGNAL(triggered()), this, SLOT(setPTLanguage())); swedishLanguageAct = new QAction(tr("Swedish"),this); swedishLanguageAct->setStatusTip(tr("Use Swedish in menus")); + swedishLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(swedishLanguageAct); connect(swedishLanguageAct, SIGNAL(triggered()), this, SLOT(setSELanguage())); russianLanguageAct = new QAction(tr("Russian"),this); russianLanguageAct->setStatusTip(tr("Use Russian in menus")); + russianLanguageAct->setCheckable(true); + languageAlignmentGroup->addAction(russianLanguageAct); connect(russianLanguageAct, SIGNAL(triggered()), this, SLOT(setRULanguage())); openDocumentURLAct = new QAction(tr("Manuals and other Documents"),this); openDocumentURLAct->setStatusTip(tr("Open the OpenTX document page in a web browser")); connect(openDocumentURLAct, SIGNAL(triggered()), this, SLOT(openDocumentURL())); - } void MainWindow::createMenus() @@ -1904,6 +1962,8 @@ void MainWindow::createMenus() languageMenu->addAction(portugueseLanguageAct); languageMenu->addAction(swedishLanguageAct); languageMenu->addAction(russianLanguageAct); + + settingsMenu->addMenu(themeMenu); themeMenu->addAction(classicThemeAct); themeMenu->addAction(newThemeAct); @@ -2113,36 +2173,86 @@ void MainWindow::updateRecentFileActions() } for ( j = numRecentFiles; j < MaxRecentFiles; ++j) recentFileActs[j]->setVisible(false); - - // separatorAct->setVisible(numRecentFiles > 0); +} + +void MainWindow::updateIconSizeActions() +{ + QSettings settings; + int size = settings.value("icon_size","0").toInt(); + switch (size){ + case 0: smallIconAct->setChecked(true); break; + case 1: normalIconAct->setChecked(true); break; + case 2: bigIconAct->setChecked(true); break; + case 3: hugeIconAct->setChecked(true); break; + } +} + +void MainWindow::updateLanguageActions() +{ + QSettings settings; + QString langId = settings.value("locale","").toString(); + + if (langId=="") + defaultLanguageAct->setChecked(true); + else if (langId=="cs_CZ") + czechLanguageAct->setChecked(true); + else if (langId=="de_DE") + germanLanguageAct->setChecked(true); + else if (langId=="en") + englishLanguageAct->setChecked(true); + else if (langId=="fr_FR") + frenchLanguageAct->setChecked(true); + else if (langId=="it_IT") + italianLanguageAct->setChecked(true); + else if (langId=="he_IL") + hebrewLanguageAct->setChecked(true); + else if (langId=="pl_PL") + polishLanguageAct->setChecked(true); + else if (langId=="pt_PT") + portugueseLanguageAct->setChecked(true); + else if (langId=="ru_RU") + russianLanguageAct->setChecked(true); + else if (langId=="sv_SE") + swedishLanguageAct->setChecked(true); +} + +void MainWindow::updateIconThemeActions() +{ + QSettings settings; + int size = settings.value("theme","1").toInt(); + switch (size){ + case 0: classicThemeAct->setChecked(true); break; + case 1: newThemeAct->setChecked(true); break; + case 2: monoWhiteThemeAct->setChecked(true); break; + case 3: monoThemeAct->setChecked(true); break; + case 4: monoBlueThemeAct->setChecked(true); break; + } } void MainWindow::updateProfilesActions() - { - int i; - QSettings settings; - int activeProfile = settings.value("profileId").toInt(); +{ + int i; + QSettings settings; + int activeProfile = settings.value("profileId").toInt(); - settings.beginGroup("Profiles"); - for (i=0; isetText(text); - profileActs[i]->setData(i+1); - profileActs[i]->setVisible(true); - if ((i+1) == activeProfile) - profileActs[i]->setIcon(CompanionIcon("arrow-right.png")); - else - profileActs[i]->setIcon(CompanionIcon("")); - - } else { - profileActs[i]->setVisible(false); - } - settings.endGroup(); + settings.beginGroup("Profiles"); + for (i=0; isetText(text); + profileActs[i]->setData(i+1); + profileActs[i]->setVisible(true); + if ((i+1) == activeProfile) + profileActs[i]->setChecked(true); + } + else { + profileActs[i]->setVisible(false); } + settings.endGroup(); + } } void MainWindow::createProfile() diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h index 2881d70d0..e01b0e6c3 100644 --- a/companion/src/mainwindow.h +++ b/companion/src/mainwindow.h @@ -163,6 +163,10 @@ private: void readSettings(); void updateRecentFileActions(); void updateProfilesActions(); + void updateIconSizeActions(); + void updateLanguageActions(); + void updateIconThemeActions(); + int getFileType(const QString &fullFileName); QString FindTaranisPath(); QString Theme; From d2dd9fa6f8a4610cfe33ae364acb637aa266e06c Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Thu, 13 Feb 2014 16:04:05 +0100 Subject: [PATCH 10/10] Ignore list --- radio/src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/.gitignore b/radio/src/.gitignore index 34089378a..3a16d35fe 100644 --- a/radio/src/.gitignore +++ b/radio/src/.gitignore @@ -13,3 +13,4 @@ /SCRIPTS /SOUNDS /LOGS +/*.bat