From ed4411602cdd97ade38d443539ab97b310611157 Mon Sep 17 00:00:00 2001 From: danpetry Date: Wed, 28 Mar 2018 17:45:53 +0200 Subject: [PATCH] pkg/lua: Provide better integration with RIOT - Remove file related functions from loader. * All packages must be builtin. - Remove os.tmpname. - Interface with TLSF. - Don't abort() when out of memory. --- examples/lua/main.c | 55 ---- examples/{lua => lua_basic}/Makefile | 8 +- examples/{lua => lua_basic}/README.md | 0 examples/lua_basic/main.c | 61 ++++ examples/{lua => lua_basic}/main.lua | 0 pkg/lua/Makefile | 3 +- pkg/lua/Makefile.dep | 3 + pkg/lua/Makefile.include | 2 + pkg/lua/Makefile.lua | 12 +- pkg/lua/contrib/Makefile | 3 + pkg/lua/contrib/binsearch.c | 51 ++++ pkg/lua/contrib/binsearch.h | 139 +++++++++ pkg/lua/contrib/lua_loadlib.c | 263 ++++++++++++++++ pkg/lua/contrib/lua_run.c | 283 ++++++++++++++++++ pkg/lua/doc.txt | 148 ++++++++- pkg/lua/include/lua_builtin.h | 84 ++++++ pkg/lua/include/lua_loadlib.h | 58 ++++ pkg/lua/include/lua_run.h | 223 ++++++++++++++ ...endency-on-nonexistent-RIOT-syscalls.patch | Bin 1768 -> 0 bytes .../patches/0001-Remove-luaL_newstate.patch | Bin 0 -> 1800 bytes ...RSIZE-to-be-defined-in-the-command-l.patch | Bin 0 -> 803 bytes ...ke-size-of-LoadF-buffer-configurable.patch | Bin 0 -> 706 bytes pkg/lua/patches/0004-Remove-os.tmpname.patch | Bin 0 -> 2507 bytes ...Do-not-allocate-buffers-on-the-stack.patch | Bin 0 -> 5206 bytes .../patches/0006-Cleanup-test-module.patch | Bin 0 -> 13937 bytes .../patches/0007-Add-a-proper-makefile.patch | Bin 0 -> 11026 bytes ...o-32-bit-build-and-small-buffer-size.patch | Bin 0 -> 1080 bytes 27 files changed, 1328 insertions(+), 68 deletions(-) delete mode 100644 examples/lua/main.c rename examples/{lua => lua_basic}/Makefile (93%) rename examples/{lua => lua_basic}/README.md (100%) create mode 100644 examples/lua_basic/main.c rename examples/{lua => lua_basic}/main.lua (100%) create mode 100644 pkg/lua/Makefile.dep create mode 100644 pkg/lua/contrib/Makefile create mode 100644 pkg/lua/contrib/binsearch.c create mode 100644 pkg/lua/contrib/binsearch.h create mode 100644 pkg/lua/contrib/lua_loadlib.c create mode 100644 pkg/lua/contrib/lua_run.c create mode 100644 pkg/lua/include/lua_builtin.h create mode 100644 pkg/lua/include/lua_loadlib.h create mode 100644 pkg/lua/include/lua_run.h delete mode 100644 pkg/lua/patches/0001-Remove-dependency-on-nonexistent-RIOT-syscalls.patch create mode 100644 pkg/lua/patches/0001-Remove-luaL_newstate.patch create mode 100644 pkg/lua/patches/0002-Allow-LUAL_BUFFERSIZE-to-be-defined-in-the-command-l.patch create mode 100644 pkg/lua/patches/0003-Make-size-of-LoadF-buffer-configurable.patch create mode 100644 pkg/lua/patches/0004-Remove-os.tmpname.patch create mode 100644 pkg/lua/patches/0005-Do-not-allocate-buffers-on-the-stack.patch create mode 100644 pkg/lua/patches/0006-Cleanup-test-module.patch create mode 100644 pkg/lua/patches/0007-Add-a-proper-makefile.patch create mode 100644 pkg/lua/patches/0008-Default-to-32-bit-build-and-small-buffer-size.patch diff --git a/examples/lua/main.c b/examples/lua/main.c deleted file mode 100644 index 22458153e0..0000000000 --- a/examples/lua/main.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2018 FU Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup examples - * @{ - * - * @file - * @brief Basic lua example application - * - * @author Daniel Petry - * - * @} - */ - -#include -#include -#include "lauxlib.h" -#include "lualib.h" - -#include "main.lua.h" - -int lua_run_script(const char *buffer, size_t buffer_len) -{ - - lua_State *L = luaL_newstate(); - - if (L == NULL) { - puts("cannot create state: not enough memory"); - return ENOMEM; - } - - luaL_openlibs(L); - luaL_loadbuffer(L, buffer, buffer_len, "lua input script"); - - if (lua_pcall(L, 0, 0, 0) != LUA_OK){ - puts("Lua script running failed"); - return EINTR; - } - - lua_close(L); - return 0; -} - -int main(void) -{ - puts("Lua RIOT build"); - lua_run_script(main_lua, main_lua_len); - return 0; -} diff --git a/examples/lua/Makefile b/examples/lua_basic/Makefile similarity index 93% rename from examples/lua/Makefile rename to examples/lua_basic/Makefile index 57c5c89fd3..91a55145f5 100644 --- a/examples/lua/Makefile +++ b/examples/lua_basic/Makefile @@ -1,4 +1,4 @@ -APPLICATION = lua +APPLICATION = lua_basic # If no BOARD is found in the environment, use this default: BOARD ?= native @@ -29,12 +29,10 @@ DEVELHELP ?= 1 # Change this to 0 show compiler invocation lines by default: QUIET ?= 1 -USEMODULE += ps - ifneq ($(BOARD),native) # This stack size is large enough to run Lua print() functions of # various lengths. Other functions untested. - CFLAGS += -DTHREAD_STACKSIZE_MAIN=4096 + CFLAGS += -DTHREAD_STACKSIZE_MAIN='(THREAD_STACKSIZE_DEFAULT+2048)' endif USEPKG += lua @@ -61,6 +59,6 @@ $(LUA_PATH)/: $(LUA_H): | $(LUA_PATH)/ $(LUA_H): $(LUA_PATH)/%.lua.h: %.lua - xxd -i $< | sed 's/^unsigned/const/g' > $@ + xxd -i $< | sed 's/^unsigned/const unsigned/g' > $@ $(RIOTBUILD_CONFIG_HEADER_C): $(LUA_H) diff --git a/examples/lua/README.md b/examples/lua_basic/README.md similarity index 100% rename from examples/lua/README.md rename to examples/lua_basic/README.md diff --git a/examples/lua_basic/main.c b/examples/lua_basic/main.c new file mode 100644 index 0000000000..0763ab4dae --- /dev/null +++ b/examples/lua_basic/main.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 FU Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Basic lua example application + * + * @author Daniel Petry + * + * @} + */ + +#include +#include + +#include "lauxlib.h" +#include "lualib.h" +#include "lua_run.h" + +#include "main.lua.h" + +#define LUA_MEM_SIZE (11000) +static char lua_mem[LUA_MEM_SIZE] __attribute__ ((aligned(__BIGGEST_ALIGNMENT__))); + +int lua_run_script(const uint8_t *buffer, size_t buffer_len) +{ + lua_State *L = lua_riot_newstate(lua_mem, sizeof(lua_mem), NULL); + + if (L == NULL) { + puts("cannot create state: not enough memory"); + return ENOMEM; + } + + lua_riot_openlibs(L, LUAR_LOAD_BASE); + luaL_loadbuffer(L, (const char *)buffer, buffer_len, "lua input script"); + + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts("Lua script running failed"); + return EINTR; + } + + lua_close(L); + return 0; +} + +int main(void) +{ + puts("Lua RIOT build"); + lua_run_script(main_lua, main_lua_len); + puts("Lua interpreter exited"); + + return 0; +} diff --git a/examples/lua/main.lua b/examples/lua_basic/main.lua similarity index 100% rename from examples/lua/main.lua rename to examples/lua_basic/main.lua diff --git a/pkg/lua/Makefile b/pkg/lua/Makefile index d2f1a775de..69170baa95 100644 --- a/pkg/lua/Makefile +++ b/pkg/lua/Makefile @@ -1,11 +1,12 @@ PKG_NAME=lua PKG_URL=https://github.com/lua/lua.git +# tag: v5-3-4 PKG_VERSION=e354c6355e7f48e087678ec49e340ca0696725b1 PKG_LICENSE=MIT .PHONY: all -all: +all: Makefile.lua @cp Makefile.lua $(PKG_BUILDDIR) "$(MAKE)" -C $(PKG_BUILDDIR) -f Makefile.lua diff --git a/pkg/lua/Makefile.dep b/pkg/lua/Makefile.dep new file mode 100644 index 0000000000..2079d072aa --- /dev/null +++ b/pkg/lua/Makefile.dep @@ -0,0 +1,3 @@ +USEPKG += tlsf +USEMODULE += lua-contrib +USEMODULE += printf_float diff --git a/pkg/lua/Makefile.include b/pkg/lua/Makefile.include index 9fb515a3b4..ab9d3759b2 100644 --- a/pkg/lua/Makefile.include +++ b/pkg/lua/Makefile.include @@ -1 +1,3 @@ INCLUDES += -I$(PKGDIRBASE)/lua +INCLUDES += -I$(RIOTPKG)/lua/include +DIRS += $(RIOTPKG)/lua/contrib diff --git a/pkg/lua/Makefile.lua b/pkg/lua/Makefile.lua index f0bd4d8a38..b22984b2a1 100644 --- a/pkg/lua/Makefile.lua +++ b/pkg/lua/Makefile.lua @@ -1,9 +1,9 @@ -SRC := $(filter-out lua.c luac.c,$(wildcard *.c)) +SRC := $(filter-out loadlib.c lua.c luac.c,$(wildcard *.c)) -# This builds for native using POSIX system calls and some extra libraries, and -# removes a compiler warning that warns against using tmpnam(). -ifeq ($(BOARD),native) - CFLAGS += -DLUA_USE_LINUX -endif +CFLAGS += -fstack-usage -fconserve-stack \ + -DLUA_MAXCAPTURES=16 \ + -DL_MAXLENNUM=50 +# Enable these options to debug stack usage +# -Wstack-usage=128 -Wno-error=stack-usage=128 include $(RIOTBASE)/Makefile.base diff --git a/pkg/lua/contrib/Makefile b/pkg/lua/contrib/Makefile new file mode 100644 index 0000000000..50d6799441 --- /dev/null +++ b/pkg/lua/contrib/Makefile @@ -0,0 +1,3 @@ +MODULE = lua-contrib + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/lua/contrib/binsearch.c b/pkg/lua/contrib/binsearch.c new file mode 100644 index 0000000000..2aa7f96264 --- /dev/null +++ b/pkg/lua/contrib/binsearch.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @file + * + * @brief Generic binary search for tables containing strings. + * @author Juan Carrano + * + */ + +#include + +#include "binsearch.h" + +int binsearch_str(const void *start, size_t offset, size_t stride, size_t nmemb, + const char *str, size_t n) +{ + const uint8_t *cstart = (((const uint8_t *)start) + offset); + size_t lo = 0, hi = nmemb; + + while (lo < hi) { + size_t mid = (lo + hi) / 2; + const char *target = *((const char *const *)(cstart + mid * stride)); + int cmp = strncmp(str, target, n); + + if (cmp == 0) { + return mid; + } + else if (cmp < 0) { + hi = mid; + } + else { /* (cmp > 0) */ + lo = mid + 1; + } + } + return (-ENOENT); +} + +const void *binsearch_str_p(const void *start, size_t offset, size_t stride, + size_t nmemb, const char *str, size_t n) +{ + int ix = binsearch_str(start, offset, stride, nmemb, str, n); + + return (ix == (-ENOENT)) ? NULL : (const uint8_t *)start + ix * stride; +} diff --git a/pkg/lua/contrib/binsearch.h b/pkg/lua/contrib/binsearch.h new file mode 100644 index 0000000000..9be7ca3db4 --- /dev/null +++ b/pkg/lua/contrib/binsearch.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @internal + * @{ + * @file + * + * @brief Generic binary search for tables containing strings. + * @author Juan Carrano + * + * It is often the case that one has an array of structs, where one of the + * members of the struct is a string pointer containing a key that must be + * searched. If the array is sorted by this key and of known length, a binary + * search can be performed. + * + * To make the code generic we must reinterpret the structure array + * as an array of pointers to string with a stride (separation in bytes between + * elements) and offset (position of the first element relative to the start of + * the array) given by the struct definition. + * + * For example, given the following struct and array definitions and assuming + * a 32 bit platform with strict aligment: + * struct s1 { + * int a; // Takes up 4 bytes + * char *name; // Takes up 4 bytes + * char m; // Takes up 1 byte + * }; + * struct s1 my_table[] = {......}; + * + * Then each element of my_table will be aligned to 12 bytes. The address of the + * "name" field of the first elements will be 4 bytes more than the address of + * "my_table". With this two numbers we can compute the address of the i-th + * "name" field as: + * [address of my_table] + offset + i*stride + * Where stride=12 bytes and offset = 4 bytes. + */ + +#ifndef BINSEARCH_H +#define BINSEARCH_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Produce a compiler error if x is not an lvalue. + */ +#define _ENSURE_LVALUE(x) ((void)sizeof(&(x))) + +/** + * UNSAFE MACRO: Difference in bytes between the addresses of two consecutive + * array elements. + */ +#define _ARRAY_STRIDE(arr) ((size_t)((uint8_t *)((arr) + 1) - (uint8_t *)(arr))) + +/** + * UNSAFE MACRO: Offset in bytes from the start of the array to member "member" + * of the first element. + */ +#define _ARRAY_MEMBER_OFFS(arr, member) \ + ((size_t)((uint8_t *)(&((arr)->member)) - (uint8_t *)(arr))) + +/** + * Find the index of the array element that contains "str" in + * member "member". + * + * A compile-time error will be raised if arr is not an lvalue. This ensures the + * macro is safe. + * + * @return Index of the array element containing the string. + * @return (-ENOENT) if it is not found. + */ +#define BINSEARCH_STR(arr, nmemb, member, str, n) \ + (_ENSURE_LVALUE(arr), \ + (binsearch_str((arr), _ARRAY_MEMBER_OFFS(arr, member), _ARRAY_STRIDE(arr), \ + (nmemb), (str), (n))) \ + ) + +/** + * Find a pointer of the array element that contains "str" in + * member "member". + * + * @return Address of the element containing the string (as a void pointer). + * @return Null if it is not found. + */ +#define BINSEARCH_STR_P(arr, nmemb, member, str, n) \ + (_ENSURE_LVALUE(arr), \ + (binsearch_str_p((arr), _ARRAY_MEMBER_OFFS(arr, member), _ARRAY_STRIDE(arr), \ + (nmemb), (str), (n))) \ + ) + +/** + * Search for an array element containing a string. + * + * This does NOT check for NULL pointers, though start can be NULL of the size + * (nmemb) is zero. + * + * @param start Pointer to start of array. The array must be ordered + * according to the search string. + * @param offset Offset of member containing string within structure. This + * can be determined using offsetof. + * @param stride Difference in bytes between the addresses of two consecutive + * array elements. + * @param nmemb Number of elements in the array. + * @param str String that will be compared against. + * @param n Compare up to n characters (see strncmp()) + * + * @return Index of the array element containing the string. + * @return (-ENOENT) if it is not found. + */ +int binsearch_str(const void *start, size_t offset, size_t stride, size_t nmemb, + const char *str, size_t n); + +/** + * Like binsearch_str but returns the pointer to the element. + * + * @return Address of the element containing the string. + * @return Null if it is not found. + */ +const void *binsearch_str_p(const void *start, size_t offset, size_t stride, + size_t nmemb, const char *str, size_t n); + + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* BINSEARCH_H */ diff --git a/pkg/lua/contrib/lua_loadlib.c b/pkg/lua/contrib/lua_loadlib.c new file mode 100644 index 0000000000..cedc2d1938 --- /dev/null +++ b/pkg/lua/contrib/lua_loadlib.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 1994-2017 Lua.org, PUC-Rio. + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_lua + * @{ + * @file + * + * @brief Replacement for the lua "package" module. + * @author Juan Carrano + * @author Roberto Ierusalimschy + * + * This file replaces the loadlib.c that comes with lua. It removes support + * for files (both lua files and c shared objects) and dynamic loading since + * none of these are present in RIOT. + * + * Instead, modules are searched in statically defined tables. In the case + * of C modules, the table contains pointers to C functions that act as module + * loaders. For pure Lua modules, the source code must be given as a string + * embedded in the application binary. + * + */ + +#define loadlib_c +#define LUA_LIB + +#include "lprefix.h" + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#include "binsearch.h" + +#include "lua_builtin.h" +#include "lua_loadlib.h" + +/* ======================== 'searchers' functions =========================== */ + +static int _ll_searcher_builtin_lua(lua_State *L, const char *name) +{ + const struct lua_riot_builtin_lua *lmodule = + BINSEARCH_STR_P(lua_riot_builtin_lua_table, + lua_riot_builtin_lua_table_len, + name, name, LUAR_MAX_MODULE_NAME); + + if (lmodule != NULL) { + int load_result = luaL_loadbuffer(L, (const char *)lmodule->code, + lmodule->code_size, + lmodule->name); + if (load_result == LUA_OK) { + lua_pushstring(L, name); /* will be 2nd argument to module */ + } + + return load_result; + } + else { + return LUAR_MODULE_NOTFOUND; + } +} + +/** + * Search in the list of pure lua modules. + * + * If the module is found, the source code is compiled and the compiled chunk + * is placed on the lua stack, followed by the module name (as a string). + */ +static int searcher_builtin_lua(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + int load_result = _ll_searcher_builtin_lua(L, name); + + switch (load_result) { + case LUA_OK: + return 2; /* there are two elements in the stack */ + case LUAR_MODULE_NOTFOUND: + return luaL_error(L, "Module '%s' not found in Lua-builtins", + lua_tostring(L, 1)); + default: + return luaL_error(L, "error loading module '%s' from Lua-builtins: \n%s", + lua_tostring(L, 1), lua_tostring(L, 2)); + } +} + +static int _ll_searcher_builtin_c(lua_State *L, const char *name) +{ + const struct lua_riot_builtin_c *cmodule = + BINSEARCH_STR_P(lua_riot_builtin_c_table, + lua_riot_builtin_c_table_len, + name, name, LUAR_MAX_MODULE_NAME); + + if (cmodule != NULL) { + lua_pushcfunction(L, cmodule->luaopen); + lua_pushstring(L, name); /* will be 2nd argument to module */ + return LUA_OK; + } + else { + return LUAR_MODULE_NOTFOUND; + } +} + +/** + * Search in the list of C lua modules. + * + * If the module is found, the loader function is loaded with lua_pushcfunction + * and is returned. + */ +static int searcher_builtin_c(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + int load_result = _ll_searcher_builtin_c(L, name); + + if (load_result == LUA_OK) { + return 2; + } + else { + return luaL_error(L, "Module '%s' not found in C-builtins", + lua_tostring(L, 1)); + } +} + +int lua_riot_getloader(lua_State *L, const char *name) +{ + int load_result; + + load_result = _ll_searcher_builtin_lua(L, name); + + if (load_result == LUAR_MODULE_NOTFOUND) { + load_result = _ll_searcher_builtin_c(L, name); + } + + return load_result; +} + +/* ======================== 'require' function ============================= */ + +static int searcher_preload(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + if (lua_getfield(L, -1, name) == LUA_TNIL) { /* 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); + /* push 'package.searchers' to index 3 in the stack */ + if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) { + luaL_error(L, "'package.searchers' must be a table"); + } + /* iterate over available searchers to find a loader */ + for (i = 1;; i++) { + if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' 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, LUA_LOADED_TABLE); + 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 */ + } + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no 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; +} + +/* ====================== 'package' module loader =========================== */ + +static const luaL_Reg pk_funcs[] = { + /* placeholders */ + { "preload", NULL }, + { "searchers", NULL }, + { "loaded", NULL }, + { NULL, NULL } +}; + + +static const luaL_Reg ll_funcs[] = { + { "require", ll_require }, + { NULL, NULL } +}; + +LUAMOD_API int luaopen_package(lua_State *L) +{ + static const lua_CFunction searchers[] = + { searcher_preload, searcher_builtin_lua, searcher_builtin_c, NULL }; + int i; + + luaL_newlib(L, pk_funcs); /* create 'package' table */ + + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers) / sizeof(searchers[0]) - 1, 0); + /* fill it with predefined 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); + } + + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ + + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_setfield(L, -2, "loaded"); + + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + 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/pkg/lua/contrib/lua_run.c b/pkg/lua/contrib/lua_run.c new file mode 100644 index 0000000000..fcb57f1689 --- /dev/null +++ b/pkg/lua/contrib/lua_run.c @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_lua + * @{ + * @file + * + * @brief Convenience functions for running Lua code. + * @author Juan Carrano + * + */ + +#define LUA_LIB + +#include "lprefix.h" + +#include +#include + +#include "kernel_defines.h" +#include "tlsf.h" + +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +#include "lua_run.h" +#include "lua_loadlib.h" + +const char *lua_riot_str_errors[] = { + "No errors", + "Error setting up the interpreter", + "Error while loading a builtin library", + "Cannot find the specified module", + "Compilation / syntax error", + "Unprotected error (uncaught exception)", + "Out of memory", + "Internal interpreter error", + "Unknown error" +}; + +/* The lua docs state the behavior in these cases: + * + * 1. ptr=?, size=0 -> free(ptr) + therefore ptr=NULL, size=0 -> NOP + * 2. ptr=? , size!=0 -> realloc(ptr, size) + * + * The TLSF code for realloc says: + * / * Zero-size requests are treated as free. * / + * if (ptr && size == 0) + * { + * tlsf_free(tlsf, ptr); + * } + * / * Requests with NULL pointers are treated as malloc. * / + * else if (!ptr) + * { + * p = tlsf_malloc(tlsf, size); + * } + * + * Therefore it is safe to use tlsf_realloc here. + */ +static void *lua_tlsf_alloc(void *ud, void *ptr, size_t osize, size_t nsize) +{ + tlsf_t tlsf = ud; + + (void)osize; + + return tlsf_realloc(tlsf, ptr, nsize); +} + +LUALIB_API lua_State *lua_riot_newstate(void *memory, size_t mem_size, + lua_CFunction panicf) +{ + lua_State *L; + + #ifdef LUA_DEBUG + Memcontrol *mc = memory; + #endif + + /* If we are using the lua debug module, let's reserve a space for the + * memcontrol block directly. We don't use the allocator because we lose + * the pointer, so we won't be able to free it and we will get a false + * positive if we try to check for memory leaks. + */ + #ifdef LUA_DEBUG + memory = (Memcontrol *)memory + 1; + mem_size -= (uint8_t *)memory - (uint8_t *)mc; + #endif + + tlsf_t tlsf = tlsf_create_with_pool(memory, mem_size); + + #ifdef LUA_DEBUG + luaB_init_memcontrol(mc, lua_tlsf_alloc, tlsf); + L = luaB_newstate(mc); + #else + L = lua_newstate(lua_tlsf_alloc, tlsf); + #endif + + if (L != NULL) { + lua_atpanic(L, panicf); + } + + return L; +} + +static const luaL_Reg loadedlibs[LUAR_LOAD_O_ALL] = { + { "_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_MATHLIBNAME, luaopen_math }, + { LUA_UTF8LIBNAME, luaopen_utf8 }, + { LUA_DBLIBNAME, luaopen_debug }, +}; + +LUALIB_API int lua_riot_openlibs(lua_State *L, uint16_t modmask) +{ + int lib_index; + + #ifdef LUA_DEBUG + luaL_requiref(L, LUA_TESTLIBNAME, luaB_opentests, 1); + lua_pop(L, 1); + #endif + + for (lib_index = 0; lib_index < LUAR_LOAD_O_ALL; + lib_index++, modmask >>= 1) { + const luaL_Reg *lib = loadedlibs + lib_index; + + if (!(modmask & 1)) { + continue; + } + /* TODO: how can the loading fail? */ + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib from stack (it is already global) */ + } + + return lib_index; +} + +/** + * Jump back to a save point (defined with setjmp). + * + * @note This function never returns! + */ +NORETURN static int _jump_back(lua_State *L) +{ + jmp_buf *jump_buffer = *(jmp_buf **)lua_getextraspace(L); + + /* FIXME: I dont think it's OK to print a message */ + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + + /* TODO: try to return some info about the error object. */ + + longjmp(*jump_buffer, 1); +} + +static int lua_riot_do_module_or_buf(const uint8_t *buf, size_t buflen, + const char *modname, void *memory, size_t mem_size, + uint16_t modmask, int *retval) +{ + jmp_buf jump_buffer; + lua_State *volatile L = NULL; + volatile int tmp_retval = 0; /* we need to make it volatile because of the + setjmp/longjmp */ + volatile int status = LUAR_EXIT; + int compilation_result; + + if (setjmp(jump_buffer)) { /* We'll teleport back here if something goes wrong*/ + status = LUAR_INTERNAL_ERR; + goto lua_riot_do_error; + } + + L = lua_riot_newstate(memory, mem_size, _jump_back); + if (L == NULL) { + status = LUAR_STARTUP_ERR; + goto lua_riot_do_error; + } + + /* lua_getextraspace() gives us a pointer to an are large enough to hold a + * pointer. + * + * We store a pointer to the jump buffer in that area. + * + * lua_getextraspace() is therefore a pointer to a pointer to jump_buffer. + */ + *(jmp_buf **)lua_getextraspace(L) = &jump_buffer; + + tmp_retval = lua_riot_openlibs(L, modmask); + if (tmp_retval != LUAR_LOAD_O_ALL) { + status = LUAR_LOAD_ERR; + goto lua_riot_do_error; + } + + if (buf == NULL) { + compilation_result = lua_riot_getloader(L, modname); + } + else { + compilation_result = luaL_loadbufferx(L, (const char *)buf, + buflen, modname, "t"); + } + + switch (compilation_result) { + case LUAR_MODULE_NOTFOUND: + status = LUAR_NOMODULE; + goto lua_riot_do_error; + case LUA_ERRSYNTAX: + status = LUAR_COMPILE_ERR; + goto lua_riot_do_error; + case LUA_ERRMEM: /* fallthrough */ + case LUA_ERRGCMM: /* fallthrough */ + default: + status = LUAR_MEMORY_ERR; + goto lua_riot_do_error; + case LUA_OK: + break; + } + + if (buf != NULL) { + lua_pushstring(L, modname); + } + + switch (lua_pcall(L, 1, 1, 0)) { + case LUA_ERRRUN: /* fallthrough */ + case LUA_ERRGCMM: /* fallthrough */ + default: + status = LUAR_RUNTIME_ERR; + puts(lua_tostring(L, -1)); + goto lua_riot_do_error; + case LUA_ERRMEM: + status = LUAR_MEMORY_ERR; + goto lua_riot_do_error; + case LUA_OK: + break; + } + + tmp_retval = lua_tonumber(L, 1); + +lua_riot_do_error: + + if (L != NULL) { + lua_riot_close(L); + } + + if (retval != NULL) { + *retval = tmp_retval; + } + + return status; +} + + +LUALIB_API int lua_riot_do_module(const char *modname, void *memory, size_t mem_size, + uint16_t modmask, int *retval) +{ + return lua_riot_do_module_or_buf(NULL, 0, modname, memory, mem_size, modmask, + retval); +} + +LUALIB_API int lua_riot_do_buffer(const uint8_t *buf, size_t buflen, void *memory, + size_t mem_size, uint16_t modmask, int *retval) +{ + return lua_riot_do_module_or_buf(buf, buflen, "=BUFFER", memory, mem_size, + modmask, retval); +} + +#define MAX_ERR_STRING ((sizeof(lua_riot_str_errors) / sizeof(*lua_riot_str_errors)) - 1) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +LUALIB_API const char *lua_riot_strerror(int errn) +{ + return lua_riot_str_errors[MIN((unsigned int)errn, MAX_ERR_STRING)]; +} + +/** @} */ diff --git a/pkg/lua/doc.txt b/pkg/lua/doc.txt index 944d45c632..50d6293ed4 100644 --- a/pkg/lua/doc.txt +++ b/pkg/lua/doc.txt @@ -1,6 +1,152 @@ /** * @defgroup pkg_lua Lua ported to RIOT * @ingroup pkg - * @brief Provides Lua support for RIOT + * @brief Provides a Lua interpreter for RIOT * @see https://github.com/lua/lua + * @see sys_lua + * + * # Lua programming language support + * + * ## Introduction + * + * This package embeds a [Lua 5.3](https://www.lua.org/) interpreter into RIOT. + * With a few exceptions, all the APIs mentioned in the + * [official documentation](https://www.lua.org/manual/5.3/) are available in + * this package too. + * + * ## Running Lua code. + * + * lua_run.h contains functions that make it easy to setup the interpreter and + * catch errors in a safe way. The functions from Lua's auxlib can still be used + * but then you must supply your own allocator and panic routines, load the + * builtin modules, etc. + * + * To run a chunk of code stored in an array use: + * ``` + * lua_riot_do_buffer(const char *buf, size_t buflen, void *memory, + * size_t mem_size, uint16_t modmask, int *retval); + * ``` + * The interpreter will not use the global heap for allocations, instead the + * user must supply a memory buffer. + * + * To save some memory, some builtin modules can be left out. `modmask` specifies + * which builtins to load. Note that if a builtin is not loaded by C code, then + * it cannot be loaded by Lua code later. + * + * `lua_riot_do_buffer` takes care of setting up the Lua state, registering a panic + * handler that does not crash the application, configuring an allocator, loading + * libraries, etc. + * + * To run a module as a script use `lua_riot_do_module`. This is roughly equivalent + * to executing: + * ``` + * require('modulename') + * ``` + * + * ## Memory requirements + * + * While generally efficient, the Lua interpreter was not really designed for + * constrained devices. + * + * A basic interpreter session typically requires about 12kB RAM. The stack + * but it depends on the functions used (string handling tends to use more stack). + * It also depends on the platform. + * + * There is currently no easy way to determine the stack needs other than trial + * and error. Future versions of the package will include instrumentation to + * this end. + * + * ## Adding your own modules. + * + * `lua_loadlib.c` contains two loaders, one for modules written in Lua and + * another one for C extensions. + * + * An index to the modules is stored in a table (there are two, one for each + * kind of module). The tables are indexed by the module name and must be sorted + * in ascending order by this key. + * + * The definitions for the table types are in `lua_builtin.h`. The loader module + * containes empty tables, defined as weak symbols so they can be ovewritten + * by the application. The variables that must be defined are: + * + * ``` + * /** Table containing all built in pure lua modules */ + * const struct lua_riot_builtin_lua *const lua_riot_builtin_lua_table; + * /** Number of elements of lua_riot_builtin_lua_table */ + * const size_t lua_riot_builtin_lua_table_len; + * + * /** Table containing all built in c lua modules */ + * const struct lua_riot_builtin_c *const lua_riot_builtin_c_table; + * /** Number of elements of lua_riot_builtin_c_table */ + * const size_t lua_riot_builtin_c_table_len; + * ``` + * + * Currently, these must be defined manually in the application code. In the + * future a script will generate this tables, populating them with both RIOT + * modules and the user modules. + * + * + * ## Customizations + * + * The upstream Lua code is used without with the following modifications. + * + * Modifications that affect the API: + * + * - lua.c (the main interface to the interpreter) is replaced by our own + * stripped-down version. The REPL is no longer included. + * - loadlib.c (the "package" module) is replaced by our own (simplified) + * loader. All the code dealing with files and dynamic loading has been + * removed. + * - os.tmpname() is removed as it caused compiler warnings and it is not + * really possible to use it right. Use io.tmpfile() instead. + * - The test module has been modified to allow it run in the RIOT environment. + * This is not a public API, though. + * + * Other modifications: + * + * - There is a patch changing the Makefile. This updated makefile is not used + * in the package, but is provided to aid development in a PC. + * - Some patches to reduce stack and memory usage. + * + * ### Patches + * + * A version of Lua with the patches applied is available at + * https://github.com/riot-appstore/lua. It can be downloaded and compiled in + * desktop computer, and the official test suite (https://www.lua.org/tests/) + * can then be run. + * + * Alternatively, the patches in this package can be directly applied to the + * official distribution. + * + * The updated makefile creates two standalone executables. Tests should be run + * with the debug executable. + * + * ## TODO + * + * The following features are missing and will be eventually added: + * + * - Load source code incrementally. It can be done now, but then the rest of the + * interpreter setup must be loaded manually. + * - Bindings to access RIOT functionality. + * - Support in the build system for easily including application-specific + * modules. + * - Instrumentation to measure stack consumption (and maybe prevent overflow). + * - Support for "frozen tables" (i.e. tables that live in ROM). + * - Provide a better way of supplying data to a script and getting back results. + * - Specify a function to call inside a module (????) + * - Expand this readme into a proper manual. + * + */ + +/* These are docs for the future (when we have the script to compile module tables) */ +/* + * # Running Lua and C code + * + * see \ref sys_lua for information on how to access RIOT modules from within + * Lua. + * + * While it is possible to include your application specific modules and run + * arbitrary Lua code only just using this interpreter, the \ref sys_lua module + * provides an automated way of handling Lua modules. + * */ diff --git a/pkg/lua/include/lua_builtin.h b/pkg/lua/include/lua_builtin.h new file mode 100644 index 0000000000..fcfec30bdf --- /dev/null +++ b/pkg/lua/include/lua_builtin.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_lua + * @{ + * @file + * + * @brief Definitions for including built-in modules. + * @author Juan Carrano + * + * The modules must be placed in the tables lua_riot_builtin_lua_table (for lua + * source code) and lua_riot_builtin_c_table (for C extensions) and the lengths + * of these tables must be in lua_riot_builtin_lua_table_len and + * lua_riot_builtin_c_table_len. + * + * These symbols are defined as weak, so there if they are not defined elsewhere + * they will default to zero (or NULL), that is, empty tables. + */ + +#ifndef LUA_BUILTIN_H +#define LUA_BUILTIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Avoid compilation errors where there are no external modules defined */ +/** + * Attribute to make symbols weak. + * + * @todo This should be made part of RIOT. + */ +#define WEAK __attribute__((weak)) + +/** + * Only the first `LUAR_MAX_MODULE_NAME` characters of a module name + * will be considered when performing a lookup. + */ +#define LUAR_MAX_MODULE_NAME 64 + +/** + * Entry describing a pure lua module whose source is built into the + * application binary. + */ +struct lua_riot_builtin_lua { + const char *name; /*!< Name of the module */ + const uint8_t *code; /*!< Lua source code buffer*/ + size_t code_size; /*!< Size of the source code buffer. */ +}; + +/** + * Entry describing a c lua module built into the + * application binary. + */ +struct lua_riot_builtin_c { + const char *name; /*!< Name of the module */ + int (*luaopen)(lua_State *); /*!< Loader function. It must place the module + * table at the top of the lua stack. + * @todo Add better docs. + */ +}; + +/** Table containing all built in pure lua modules */ +extern WEAK const struct lua_riot_builtin_lua *const lua_riot_builtin_lua_table; +/** Number of elements of lua_riot_builtin_lua_table */ +extern WEAK const size_t lua_riot_builtin_lua_table_len; + +/** Table containing all built in c lua modules */ +extern WEAK const struct lua_riot_builtin_c *const lua_riot_builtin_c_table; +/** Number of elements of lua_riot_builtin_c_table */ +extern WEAK const size_t lua_riot_builtin_c_table_len; + +#ifdef __cplusplus +extern "C" } +#endif + +#endif /* LUA_BUILTIN_H */ + +/** @} */ diff --git a/pkg/lua/include/lua_loadlib.h b/pkg/lua/include/lua_loadlib.h new file mode 100644 index 0000000000..f2ce87e14e --- /dev/null +++ b/pkg/lua/include/lua_loadlib.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_lua + * @{ + * @file + * + * @brief Lightweight C interface to the package loader. + * @author Juan Carrano + * + */ + +#ifndef LUA_LOADLIB_H +#define LUA_LOADLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Error code for when a modules is not found. + * + * The numeric value is chosen so that there is no collision with Lua's + * own error codes. + */ +#define LUAR_MODULE_NOTFOUND 50 + +/** + * Load a module as a chunk. + * + * This function is a lightweight "require". It does not require the "package" + * module to be loaded and does not register the module. + * Only the builtin tables are searched. + * + * Upon sucessful execution, the compiled chunk will be at the top of the lua + * stack. + * + * @param L Initialized Lua interpreter state. + * @param name Name of the module. + * + * @return Same as lua_load. If the module is a C-module, then this will + * always succeed and return LUA_OK. + */ +int lua_riot_getloader(lua_State *L, const char *name); + +#ifdef __cplusplus +extern "C" +} +#endif + +#endif /* LUA_LOADLIB_H */ + +/** @} */ diff --git a/pkg/lua/include/lua_run.h b/pkg/lua/include/lua_run.h new file mode 100644 index 0000000000..dcdbde42f9 --- /dev/null +++ b/pkg/lua/include/lua_run.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_lua + * @file + * @{ + * + * @brief Convenience functions for running Lua code. + * @author Juan Carrano + * + * This functions make it easy to create and use new Lua context: + * It provides: + * + * - Easy to use routines for executing modules as scrips. + * - Control over which modules get loaded. + * - Support for using a local heap allocator. + * - Out of memory handling via setjmp/longjmp. + * + * This library is not strictly required, as all of the functionality could be + * implemented in terms of the public lua api, but it covers most of the use + * cases, and thus avoids code repetition in applications. + * + */ + +#ifndef LUA_RUN_H +#define LUA_RUN_H + +#include + +#include "lua.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Convert a library index into a bit mask. + */ +#define LUAR_LOAD_FLAG(n) (((uint16_t)1) << (n)) + +/** + * Order in which the builtin libraries are loaded. + */ +enum LUAR_LOAD_ORDER { + LUAR_LOAD_O_BASE, + LUAR_LOAD_O_PACKAGE, + LUAR_LOAD_O_CORO, + LUAR_LOAD_O_TABLE, + LUAR_LOAD_O_IO, + LUAR_LOAD_O_OS, + LUAR_LOAD_O_STRING, + LUAR_LOAD_O_MATH, + LUAR_LOAD_O_UTF8, + LUAR_LOAD_O_DEBUG, + LUAR_LOAD_O_ALL, +}; + +/** Load the base globals (_G) */ +#define LUAR_LOAD_BASE LUAR_LOAD_FLAG(LUAR_LOAD_O_BASE) +/** Load ´package´ */ +#define LUAR_LOAD_PACKAGE LUAR_LOAD_FLAG(LUAR_LOAD_O_PACKAGE) +/** Load ´coroutine´ */ +#define LUAR_LOAD_CORO LUAR_LOAD_FLAG(LUAR_LOAD_O_CORO) +/** Load ´table´ */ +#define LUAR_LOAD_TABLE LUAR_LOAD_FLAG(LUAR_LOAD_O_TABLE) +/** Load ´io´ */ +#define LUAR_LOAD_IO LUAR_LOAD_FLAG(LUAR_LOAD_O_IO) +/** Load ´os´ */ +#define LUAR_LOAD_OS LUAR_LOAD_FLAG(LUAR_LOAD_O_OS) +/** Load ´string´ */ +#define LUAR_LOAD_STRING LUAR_LOAD_FLAG(LUAR_LOAD_O_STRING) +/** Load ´math´ */ +#define LUAR_LOAD_MATH LUAR_LOAD_FLAG(LUAR_LOAD_O_MATH) +/** Load ´utf8´ */ +#define LUAR_LOAD_UTF8 LUAR_LOAD_FLAG(LUAR_LOAD_O_UTF8) +/** Load ´debug´ */ +#define LUAR_LOAD_DEBUG LUAR_LOAD_FLAG(LUAR_LOAD_O_DEBUG) + +/* TODO: maybe we can implement a "restricted base" package containing a subset + * of base that is safe. */ + +#define LUAR_LOAD_ALL (0xFFFF) /** Load all standard modules */ +#define LUAR_LOAD_NONE (0x0000) /** Do not load any modules */ + +/** Errors that can be raised when running lua code. */ +enum LUAR_ERRORS { + LUAR_EXIT, /** The program exited without error. */ + LUAR_STARTUP_ERR, /** Error setting up the interpreter. */ + LUAR_LOAD_ERR, /** Error while loading libraries. */ + LUAR_NOMODULE, /** The specified module could not be found. */ + LUAR_COMPILE_ERR, /** The Lua code failed to compile. */ + LUAR_RUNTIME_ERR, /** Error in code execution. */ + LUAR_MEMORY_ERR, /** Lua could not allocate enough memory */ + LUAR_INTERNAL_ERR /** Error inside the Lua VM. + * Right now, if this happens, you may leak memory from + * the heap. If your program is the only one using the + * dynamic allocation, just clean the heap. + */ +}; + +/** + * Human-readable description of the errors + */ +extern const char *lua_riot_str_errors[]; + +/** + * Return a string describing an error from LUAR_ERRORS. + * + * @param errn Error number as returned by lua_riot_do_buffer() or + * lua_riot_do_buffer() + * + * @return A string describing the error, or "Unknown error". + */ +LUALIB_API const char *lua_riot_strerror(int errn); + +/** + * Initialize a lua state and set the panic handler. + * + * @todo Use a per-state allocator + * + * @param memory Pointer to memory region that will be used as heap for + * the allocator. Currently this functionality is not + * supported and this must be set to NULL. + * @param mem_size Size of the memory region that will be used as heap. + * Currently this functionality is not supported and this + * must be set to 0. + * @param panicf Function to be passed to lua_atpanic. If set to NULL, + * a generic function that does nothing will be used. + * + * @return the new state, or NULL if there is a memory allocation error. + */ +LUALIB_API lua_State *lua_riot_newstate(void *memory, size_t mem_size, + lua_CFunction panicf); + +/** + * Terminate the lua state. + * + * You must call this function if you want the finalizers (the __gc metamethods) + * to be called. + */ +#ifndef LUA_DEBUG + #define lua_riot_close lua_close +#else + #define lua_riot_close luaB_close +#endif /* LUA_DEBUG */ + +/** + * Open builtin libraries. + * + * This is like luaL_openlibs but it allows selecting which libraries will + * be loaded. + * + * Libraries are loaded in the order specified by the LUAR_LOAD_ORDER enum. If + * there is an error the load sequence is aborted and the index of the library + * that failed is reported. + * + * If debuging is enabled (compile with the LUA_DEBUG macro), then the test + * library will be unconditionally loaded. + * + * @param L Lua state + * @param modmask Binary mask that indicates which modules should be + * loaded. The mask is made from a combination of the + * LUAR_LOAD_* macros. + * + * @return The index of the library that failed to load, or LUAR_LOAD_O_ALL + * if all libraries were loaded. + */ +LUALIB_API int lua_riot_openlibs(lua_State *L, uint16_t modmask); + +/** + * Initialize the interpreter and run a built-in module in protected mode. + * + * In addition to running code in protected mode, this also sets a panic + * function that long-jumps back to this function, in case there is an internal + * interpreter error (LUAR_INTERNAL_ERR). + * Right now the only things that the application can are either to abort(), + * or to manually reset the heap (only if there's no other thread using it). + * + * @param modname name of the module. + * @param memory @see lua_riot_newstate() + * @param mem_size @see lua_riot_newstate() + * @param modmask @see lua_riot_newstate() + * @param[out] retval Value returned by the lua code, if it is a number, + * or zero if no value is returned or the value is not + * a number. If retval is null, the value is not stored. + * + * @return An error code ( @see LUAR_ERRORS). LUAR_EXIT indicates no error. + */ +LUALIB_API int lua_riot_do_module(const char *modname, void *memory, size_t mem_size, + uint16_t modmask, int *retval); + +/** + * Initialize the interpreter and run a user supplied buffer in protected mode. + * + * Only text data (i.e. lua source code) can be loaded by this function. The + * lua interpreter is not robust against corrupt binary code. + * + * @see lua_riot_do_module() for more information on internal errors. + * + * @param buf Text data (lua source code). + * @param buflen Size of the text data in bytes. If buf is + * a zero-terminated string, the zero must not be counted. + * @param memory @see lua_riot_newstate() + * @param mem_size @see lua_riot_newstate() + * @param modmask @see lua_riot_newstate() + * @param[out] retval @see lua_riot_do_module() + * @return @see lua_riot_do_module(). + */ +LUALIB_API int lua_riot_do_buffer(const uint8_t *buf, size_t buflen, void *memory, + size_t mem_size, uint16_t modmask, int *retval); + +#ifdef __cplusplus +extern "C" } +#endif + +/** @} */ + +#endif /* LUA_RUN_H */ diff --git a/pkg/lua/patches/0001-Remove-dependency-on-nonexistent-RIOT-syscalls.patch b/pkg/lua/patches/0001-Remove-dependency-on-nonexistent-RIOT-syscalls.patch deleted file mode 100644 index b4017f538264e4e7e8ce76d855242587e2152ac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1768 zcmb_cU2oe)5PS}Q#ngGQJ}8RRx70Xr;3lY1B{pmqeJBdyNG_$TsXKvpw5=x1Z_nOI z792b1Qy~E)_x9%YW@qO^rPoMDlO#)fG0`Y3vVM|IQqk*E*6$_BAQpl~H0;wf$49Mj zO&cU*#PQ7k(Tn3G_`onTrf9O))X&d5xC9@TzL2W2Ux`h>KNs-Z&Ta;zFM-EKA*_2zv zsDxcn1-s%y1U821T<=h!>NPVI1)WYOK&eeB(LasL@ty#jXC03``@s{in1L0rKjc0a}gcD|VJpB=~OX3;0!wb58z^tExmzhkH zYs;oKtDPcU!3_`i$t$$!H#VBh?$hAe{Nn7l>&4~!tHt&Ev+w9j{(mCASMXsdScH%7 zdkqgKle8Gbc@#}1(_uOq_Md6^kiQr4;oEWD>kq@EkG6jfpXs<(8~=#a z*g`~AvAOX)$&5#|)eZboP6cXZhBLsGe9{iUK5 ziVtP=u}!gdo!mW;E}UHnHWjDX2#xasTU{g9>e%95DBD%Um$6RR`-&CY=TV5Su`57$ zn5EYFW0g&gbc1%#e$8}9MKAod(L~Jacr6S3w9CmG&rP`b>J{_-*;DIMRaVwH;f6 diff --git a/pkg/lua/patches/0001-Remove-luaL_newstate.patch b/pkg/lua/patches/0001-Remove-luaL_newstate.patch new file mode 100644 index 0000000000000000000000000000000000000000..f7059b62a91d6b7228b5bdd53edd06c4f2bdbcf7 GIT binary patch literal 1800 zcma)6ZEu@M5dOZuVp{1=5CZ`ljO|=bann}yiAGV~e7P4{3oJ1`yjaVUrs?&+cV?jp zPNGw>WzR0p%sl(d%)V9i4n*NkBVYKD??-W-M!XmcKMjldBrL}Ba2ids@igEuysss! z#U6qfe1BoSF!ud`y~QvK_@m_#&bd-t*6`aWFYC;+qIFZDs#1En_?^AxS}fpWD;yYy zu-q#Q5zHW%E+(_ZB!-cXA=$c3KZ#5);IGT&$Mbg(9MArN4`Nr}2&h_~Y^3BexkV(55y|kkC@axGw&n6#zc$e9E% zGR72eFS%MKt5=)lJyM z%N%2EcvaOISlzNk0Xl21l><$ACpH>t`oCXETG{ZGxzM@UZGO^Q26+N-d<3%A&^7{d z922rEz%rh2dJ2B;4p1l|EX-w}5C}jC-6{zeS4m=azR|X*8gcMi3B#Hk9q9NV8nN{0 z&sRzfdoJ;$2P*ZMNx09d)S}U<#KJ38E9>Ru@?v$qfL88Rt+5A@y?FzrgbY)Ht|4hT zP(`d?8vAeg(&>m1_s0+A&~=xK_3hXj^@KG z^!j&I8GsTvrJ=c>8LKb2VP&5!+vlbwHR((oq_=rs)?$Cfkba-y5MC zoSn^~?2ZY4(eCg%0EFCkQ*%cZLFu{hxZb%p}Sb|(~8UVqu+Xk!CDJHy+-3~u`w4)SS~&Ev@P;y4e&d6+*x!`nwQyk#`Q zv$->a5&k|NUus5b!(>y{JWt!A5bD-`EYWbt2{RB0$M+|mVF1Z@IJ3i@U7ZV(aL`VN zyt-EXUs??XVD2CURjj{)x)c7mo-q!!26fOuPI6dDEpX_5Xd>j3q{OVuZ%w)(H7O_+^jp@ipEtA-oJWmuZyu&s9fEq!{ z@#97$r4n*3RS2ZJ0l~6VnD6)unY|L2t#GZfK0`a3Lcri<0-&3r!le0~0PhQ=c!6lAQU z0@k6~5OQBt+7;lY6bcapfk4^n+&dF)@Eb$)*#s1fEjfLo-I|I+#;w~@-B|Cooqkt{ z!Wx4hSlb4A@XU}s`@*_{?x9p-(sZQ5kP;OanUqjc#>3&R`O8|tjq$R6GC?pJCWk6Q z|M845nF#cH*jBnMsYccs!^fR(%L2yNIYFbM%GVFz44>=Wz`F=Y=NseUdSXBL1?$GWE5k@txNzt{dEZ#qA{EqdMOJIlU0cMYwn?sj?peRBLQ d0{n_6kB1)g@aN>eZ6^(Q@sEipRHIM{@fRap;%5K= literal 0 HcmV?d00001 diff --git a/pkg/lua/patches/0003-Make-size-of-LoadF-buffer-configurable.patch b/pkg/lua/patches/0003-Make-size-of-LoadF-buffer-configurable.patch new file mode 100644 index 0000000000000000000000000000000000000000..0237936119a67584045049349469fdc4fd791e1a GIT binary patch literal 706 zcmaixU2mH(6o&8pE8fc{1cLbp37w{-UC}a8san>XRaIp0aYjc?n2 zC7*NrK1au|Gt)eykSj_SBv<9ikD@r>ahS-(LP?(|BH*-I3K558h}%YEM@R4kzMl>o zf$wvc*)}OYbwcA>7$bCpcTZk9hHKTi1(~|io}~BegJ>!3Tg{N*R=nB{d>5y}-^dqA*H4Z&}Eoh=l_8{Y4b@gPgO>aU7iU>owd(7|#+o<6#T={U+aD?KgK@ z{AenPx)b@n(}ol-Y`ovK)<8`2nVr5xJ0A9Sf?o{n>ye~Yo?6qD?LU)j9fMe30`n8H}Po5H6i4kQ>=7j0ImuK7j22(WxgKY&>`hY=gB`yYL_<)D2`)s%U`Z$V( rl|VISkoL$xTf{j>`d98Pm)(4}=*|CF{2AYJ$zYdtl?5J8JkHo(U6jrH literal 0 HcmV?d00001 diff --git a/pkg/lua/patches/0004-Remove-os.tmpname.patch b/pkg/lua/patches/0004-Remove-os.tmpname.patch new file mode 100644 index 0000000000000000000000000000000000000000..c94f3490e433d96a494c83a1906238ab7757ab01 GIT binary patch literal 2507 zcmb_dZByGg5dMsQ#Wwe$d9jl?Z$K!WQV!<02`$sWOy@WzBirjl#gTK84CFZe`>kXf z0_DpM=P-li-F@`z?xWSQ%9aoffAlQa(ckKS4*X;)Em|({6d(I^sa;3P;;KPr0RJ?vlaz8|s3fYeFBm0#b99t+4 zw&9eo2_e{lpg$h&j=LjhbqSG8^Y8~oW(=2S2j_>s!JxBq1>bO)-5_MTZI&y^m)K_P z#DLJiVU-z_M(`ALmaB-o5(x9T_8{W9Mh#K6T!|DF+;Sy_oNKsUpd=rW#jo(5L_UFbF71${|{CImg(uI5DPZL?(6J zZ!l(SMbL9fpLZTN3?E;apaR}O9QVSozrE9Lk9PSm8IrJqZg(^oFygck$y%)zY(#(h z1pe->HyA>T{*8dvR3IZFFk*=_1L-VUV03L)P)~C{o01u!IiZe7;-uycxM$F5!o&WX zA82+M(9iEQncr-}{hJZ@9nN7U6EV*fB}S($$rQXV)c$_#?4Q?E^@QiC@nDj3D>My- z2jE?VD^m#D$<&>V8!l3-KF=ByI+Q}88kX1E;BwV=AK#vVO`*g5Uqk}$h^3GiyG9iJ z8e3HQds{fa@TpuT7YDP8>Cwz_e&HpfG>;KJa1jYM@ci`b%fadAi{t6Z zA4gmLUIqS0;K}Ly==5xIaDLRF?SDe3j9ax1(d}6Me0NWcyit<4H+Qz?BCC4nA?XVK zWImLSHY!@J$*@7Nf^Y0?dLrysJ*bDzO;p1=!n=L&g9b!&oUo41J!~+!>^qk|cyRnM z)wo5ERe4owdOw+dg+r?xA%#1!t_?p|p{nDg%982`%ct(Ur#Y6YC#XqD^5Q{^nh!d8L@w67Bfd(opg z(*1q&N^QUrdI4KF+jdThk^i(~&}fkU?2M=6tQx^G0x42Auz{{ymn9Lg9qaG*JZe~f z(0kUfLKP1G8_sQ`>GHh1qMpZu4w-;0q o>VoZ(Ow^D2TG@1GrOR|GnSd z9Y}zp(-}`>4*?$b7Q5em`#4^w$%^cWZ3jXKXDBBlw?7oV(?53I$Ss0ErWwJid?_i*h4G&Me z#f3$!Ba1BhE{wgX@Fg7p_ulfrYFAdGa24hmR_Ulkc|r@Bb9m+=V~1XAFepO{S^UP~ zWYBSJY7ZyF&IB*zQ0JjXACu6hRxF>~r}285r$j^WRrod z=_VxEi;4y*3X}n(bDDPF&d#j1)z(imIp9zCtx|V>PIi;<$ty13CamV9Qv@Z5wNVTC80Mjf z;H%%G`z4nUW@JWBGE9B2YLPLwA&hr4vKO}5ro%(_bnB8*M*NfLN#RCiIo0mNY(*HS z-*Fr;rtfe9V(HI_yLQlICOlIPe*RqMDpg(9KBxfC<}yu_w1MP4FyY9P1T{Hb$O8mf zd5a)>spKM{);GBghq^4l(DLSOjv531RO?9qP)QGnObY;UHLF+|;AbGlBaG`_S$ zMw#4%t1K|jsC%3|UsKAj(Hadn(59>=t{L9?xnT_HFlMg$j6p;;B?**i&8Cj2m#m*D zNy9}Li-^1=&SkuP`4?>iD}hf&sX-8nnw+IeXPOGbJ_>$&G_qCQuM$C(VU_>F_tD|F zgmN{mB|l8aazoHe6@Utrwi?z&wgk3Cl<%teqoM&ox%%^FZm}?c!?MLl`!>-?@ z>v3H}cPBs_NkX3Rzr9T5m~#i%9XyojQ$q-JWJM!TaRy}3-;mEH?Ql`;Ts1JW#w|_7 z1m9z9u*(f5CE1es^x^vY>cid5zpu)z<|(B2m|W@4rOiryXJD$^y|-J>=A{CaULb^O zSEo=(Nzd=~T*ncCHxc`%)8)=|x>R}N z3{SXD@#UDaCVyT_3`-ap)523@=cX*F$e2vvi%x5H5vi#l(#6_{#QJ$$tZL6}T6ByCUdjsNR zFm%Vhd(!KP$@s*#$GaeIJj(NSh!z65`64UaI_I0$AR~GN?Kiu5@4U1({R3*3ks0dy^++N<_{B*ms|Nh-{ zcGaOlXYYRKIe@)r2S-5>dwfzl;-i)%`Du;grSy4jKt?L+R=IuXGP!piFb~+NLv&uX zBa$(HchGeC{oG$f>@Abjz(KTbx6deAce^^s*<-lINXa5w_SDM0gX6E_ufD#<9_Q8- zPO`P+HLt7H@jMOERj#Y~Y_0-Q7E_pv7{QM$;ED>%_w1ZYOupwFZr0O=sFGBEYetg$ zjo9rZfHvW2iSsU|WMenxU46%PY~W;sTcrrjM6>zT-Q{LVQ?{XLaIQ5tNTq1Ijdw7w zoxxzF(AC%1=wh6H+>5QL0eO;(NR#1jh(}KKR96m^2Q$X#g23smo4#Vu zQacTc)zA`$QDbJ>)k>s~d`QmZTBNKMu_{)W-ZDKdzy2s{d@UkvBDM^IgSW*EC06>XFaEfBd4f zH}JL8z;9n_JetknZ6%#B6&@VGISl>lZDemSbT7~aR#g2DBZY2ew5QL(kBRI~*eBdgzY J#y!Wf{s$(>{y+c# literal 0 HcmV?d00001 diff --git a/pkg/lua/patches/0006-Cleanup-test-module.patch b/pkg/lua/patches/0006-Cleanup-test-module.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d22dd9fcf6ab79d6313ff454aa73a859ad2b5bb GIT binary patch literal 13937 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 csV`1075ogkw2DItIg8%>k literal 0 HcmV?d00001 diff --git a/pkg/lua/patches/0007-Add-a-proper-makefile.patch b/pkg/lua/patches/0007-Add-a-proper-makefile.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6eb73d24706a9e450dbde6c537ffe56600ac198 GIT binary patch literal 11026 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 literal 0 HcmV?d00001