diff --git a/components/base_nodemcu/Makefile.projbuild b/components/base_nodemcu/Makefile.projbuild index e2d8ad64b5..1a205a9bfd 100644 --- a/components/base_nodemcu/Makefile.projbuild +++ b/components/base_nodemcu/Makefile.projbuild @@ -1,8 +1,14 @@ BASE_NODEMCU_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) BASE_NODEMCU_BUILD_DIR:=$(BUILD_DIR_BASE)/base_nodemcu +ifeq ($(CONFIG_LUA_EMBED_LFS),y) + NODEMCU_LD_SCRIPT:= nodemcu_rodata_lfs.ld +else + NODEMCU_LD_SCRIPT:= nodemcu_rodata.ld +endif + $(BUILD_DIR_BASE)/$(PROJECT_NAME).elf: $(BASE_NODEMCU_BUILD_DIR)/ld_patched $(BASE_NODEMCU_BUILD_DIR)/ld_patched: $(BUILD_DIR_BASE)/esp32/esp32.project.ld - "$(BASE_NODEMCU_DIR)/add_rodata_ld.sh" "$<" "$(BASE_NODEMCU_DIR)/ld/nodemcu_rodata.ld" + "$(BASE_NODEMCU_DIR)/add_rodata_ld.sh" "$<" "$(BASE_NODEMCU_DIR)/ld/$(NODEMCU_LD_SCRIPT)" touch $@ diff --git a/components/base_nodemcu/c_stdlib.c b/components/base_nodemcu/c_stdlib.c deleted file mode 100644 index 5bc5729dc8..0000000000 --- a/components/base_nodemcu/c_stdlib.c +++ /dev/null @@ -1,26 +0,0 @@ -#ifdef LUA_CROSS_COMPILER - -#include -#include -#include -#define true 1 -#define false 0 - -#else - -#include -#include -#include - -const char *lua_init_value = "@init.lua"; - -const char *c_getenv(const char *__string) -{ - if (strcmp(__string, "LUA_INIT") == 0) - { - return lua_init_value; - } - return NULL; -} - -#endif diff --git a/components/base_nodemcu/include/c_stdlib.h b/components/base_nodemcu/include/c_stdlib.h deleted file mode 100644 index 24cbcd3d2e..0000000000 --- a/components/base_nodemcu/include/c_stdlib.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SDK_OVERRIDES_STDLIB_H_ -#define _SDK_OVERRIDES_STDLIB_H_ - -extern const char *c_getenv (const char *); - -#endif diff --git a/components/base_nodemcu/include/module.h b/components/base_nodemcu/include/module.h index 3ddde95cf1..4f1165a19f 100644 --- a/components/base_nodemcu/include/module.h +++ b/components/base_nodemcu/include/module.h @@ -1,8 +1,8 @@ #ifndef __MODULE_H__ #define __MODULE_H__ -#include "lrodefs.h" #include "sdkconfig.h" +#include "lrotable.h" /* Registering a module within NodeMCU is really easy these days! * @@ -36,37 +36,37 @@ #define MODULE_PASTE_(x,y) x##y #define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(x,y) -#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(s))) - +#ifdef LUA_CROSS_COMPILER +#ifdef _MSC_VER +//on msvc it is necessary to go through more pre-processor hoops to get the +//section name built; string merging does not happen in the _declspecs. +//NOTE: linker magic is invoked via the magical '$' character. Caveat editor. +#define __TOKIFY(s) .rodata1$##s +#define __TOTOK(s) __TOKIFY(s) +#define __STRINGIFY(x) #x +#define __TOSTRING(x) __STRINGIFY(x) +#define __ROSECNAME(s) __TOSTRING(__TOTOK(s)) +#define LOCK_IN_SECTION(s) __declspec ( allocate( __ROSECNAME(s) ) ) +#else +#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".rodata1." #s))) +#endif +#else +#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s))) +#endif /* For the ROM table, we name the variable according to ( | denotes concat): * cfgname | _module_selected | CONFIG_LUA_MODULE_##cfgname * where the CONFIG_LUA_MODULE_XYZ macro is first expanded to yield either * an empty string (or 1) if the module has been enabled, or the literal * CONFIG_LUA_MODULE_XYZ in the case it hasn't. Thus, the name of the variable * ends up looking either like XYZ_module_enabled, or if not enabled, - * XYZ_module_enabledLUA_USE_MODULES_XYZ. This forms the basis for + * XYZ_module_enabledCONFIG_LUA_MODULE_XYZ. This forms the basis for * letting the build system detect automatically (via nm) which modules need * to be linked in. */ #define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \ - const LOCK_IN_SECTION(".lua_libs") \ - luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \ - const LOCK_IN_SECTION(".lua_rotable") \ - luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_LUA_MODULE_,cfgname))) \ - = { luaname, map } - - -/* System module registration support, not using CONFIG_LUA_MODULE_XYZ. */ -#define BUILTIN_LIB_INIT(name, luaname, initfunc) \ - const LOCK_IN_SECTION(".lua_libs") \ - luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc } - -#define BUILTIN_LIB(name, luaname, map) \ - const LOCK_IN_SECTION(".lua_rotable") \ - luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map } - -#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2) -# error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)" -#endif - + const LOCK_IN_SECTION(libs) \ + luaR_entry MODULE_PASTE_(lua_lib_,cfgname) = { luaname, LRO_FUNCVAL(initfunc) }; \ + const LOCK_IN_SECTION(rotable) \ + luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_LUA_MODULE_,cfgname))) \ + = {luaname, LRO_ROVAL(map ## _map)} #endif diff --git a/components/base_nodemcu/include/nodemcu_esp_event.h b/components/base_nodemcu/include/nodemcu_esp_event.h index 2a2f21840a..b83a85dc87 100644 --- a/components/base_nodemcu/include/nodemcu_esp_event.h +++ b/components/base_nodemcu/include/nodemcu_esp_event.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * Copyright 2016-2019 Dius Computing Pty Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,8 @@ #include "esp_event.h" #include "module.h" +#include +#include /** * Similarly to how a NodeMCU module is registered, a module can register @@ -66,7 +68,10 @@ typedef struct { extern nodemcu_esp_event_reg_t esp_event_cb_table; #define NODEMCU_ESP_EVENT(evcode, func) \ - static const LOCK_IN_SECTION(".esp_event_cb_table") \ + static const LOCK_IN_SECTION(esp_event_cb_table) \ nodemcu_esp_event_reg_t MODULE_PASTE_(func,evcode) = { evcode, func }; +_Static_assert(_Alignof(nodemcu_esp_event_reg_t) == 4, "Unexpected alignment of event registration - update linker script snippets to match!"); +_Static_assert(sizeof(nodemcu_esp_event_reg_t) == 8, "Unexpected size of array member - update the linker script snippets to match!"); + #endif diff --git a/components/base_nodemcu/ld/nodemcu_rodata.ld b/components/base_nodemcu/ld/nodemcu_rodata.ld index 50458c44cf..e63f75a2fd 100644 --- a/components/base_nodemcu/ld/nodemcu_rodata.ld +++ b/components/base_nodemcu/ld/nodemcu_rodata.ld @@ -1,17 +1,29 @@ /* ----- Begin NodeMCU link-time arrays ------- */ - . = ALIGN(4); + /* Don't change the alignment here without also updating the _Static_assert + * over in linit.c! */ + . = ALIGN(8); /* Link-time arrays containing the defs for the included modules */ - lua_libs = ABSOLUTE(.); + lua_libs_map = ABSOLUTE(.); KEEP(*(.lua_libs)) - LONG(0) LONG(0) /* Null-terminate the array */ - lua_rotable = ABSOLUTE(.); + /* Null-terminate the array, 24 bytes */ + LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) + + /* Don't change the alignment here without also updating the _Static_assert + * over in linit.c! */ + . = ALIGN(8); + lua_rotables_map = ABSOLUTE(.); KEEP(*(.lua_rotable)) - LONG(0) LONG(0) /* Null-terminate the array */ + /* Null-terminate the array, 24 bytes */ + LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) + + /* Don't change the alignment here without also updating the _Static_assert + * over in nodemcu_esp_event.h! */ + . = ALIGN(4); esp_event_cb_table = ABSOLUTE(.); - KEEP(*(.esp_event_cb_table)) - LONG(0) LONG(0) /* Null-terminate the array */ + KEEP(*(.lua_esp_event_cb_table)) + LONG(0) LONG(0) /* Null-terminate the array, 8 bytes */ /* ----- End NodeMCU link-time arrays ------- */ diff --git a/components/base_nodemcu/ld/nodemcu_rodata_lfs.ld b/components/base_nodemcu/ld/nodemcu_rodata_lfs.ld new file mode 100644 index 0000000000..3420fa6a85 --- /dev/null +++ b/components/base_nodemcu/ld/nodemcu_rodata_lfs.ld @@ -0,0 +1,37 @@ + + /* ----- Begin NodeMCU link-time arrays ------- */ + + /* Don't change the alignment here without also updating the _Static_assert + * over in linit.c! */ + . = ALIGN(8); + /* Link-time arrays containing the defs for the included modules */ + lua_libs_map = ABSOLUTE(.); + KEEP(*(.lua_libs)) + /* Null-terminate the array, 24 bytes */ + LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) + + /* Don't change the alignment here without also updating the _Static_assert + * over in linit.c! */ + . = ALIGN(8); + lua_rotables_map = ABSOLUTE(.); + KEEP(*(.lua_rotable)) + /* Null-terminate the array, 24 bytes */ + LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) LONG(0) + + /* Don't change the alignment here without also updating the _Static_assert + * over in nodemcu_esp_event.h! */ + . = ALIGN(4); + esp_event_cb_table = ABSOLUTE(.); + KEEP(*(.lua_esp_event_cb_table)) + LONG(0) LONG(0) /* Null-terminate the array, 8 bytes */ + + /* ----- End NodeMCU link-time arrays ------- */ + + /* ----- NodeMCU embedded LFS reserved area --------- */ + + . = ALIGN(4096); /* flash page alignment needed */ + lua_flash_store_reserved = ABSOLUTE(.); + KEEP(*(.lfs.reserved)) + + /* ----- End NodeMCU embedded LFS reserved area ----- */ + diff --git a/components/base_nodemcu/linit.c b/components/base_nodemcu/linit.c index 2b751f6aa3..17c03459a7 100644 --- a/components/base_nodemcu/linit.c +++ b/components/base_nodemcu/linit.c @@ -15,64 +15,111 @@ #include "lauxlib.h" #include "luaconf.h" #include "module.h" -#include "sdkconfig.h" +#include "lstate.h" +#include +#include -BUILTIN_LIB_INIT( BASE, "", luaopen_base); -BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package); - -#if defined(LUA_USE_BUILTIN_IO) -BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io); -#endif - -#if defined (CONFIG_LUA_BUILTIN_STRING) -extern const luaR_entry strlib[]; -BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string); -BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib); +LROT_EXTERN(strlib); +LROT_EXTERN(tab_funcs); +LROT_EXTERN(dblib); +LROT_EXTERN(co_funcs); +LROT_EXTERN(math); +#if defined(LUA_CROSS_COMPILER) +LROT_EXTERN(oslib); +//LROT_EXTERN(iolib); #endif +/* + * The NodeMCU Lua initalisation has been adapted to use linker-based module + * registration. This uses a PSECT naming convention to allow the ROTable and + * initialisation function entries to be collected by the linker into two + * consoliated ROTables. This significantly simplifies adding new modules and + * configuring builds with a small subset of the total modules. + * + * This linker-based approach is not practical for cross compiler builds which + * must link on a range of platforms, and where we don't have control of PSECT + * placement. However unlike the target builds, the luac.cross builds only + * used a small and fixed list of libraries and so in this case the table can + * be defined in this source file, so in this case all library ROTables are + * defined here, avoiding the need for linker magic is avoided on host builds. + * + * Note that a separate ROTable is defined in lbaselib.c for the base functions + * and there is a metatable index cascade from _G to this base function table to + * the master rotables table. In the target build, the linker marshals the + * table, hence the LROT_BREAK() macros which don't 0 terminate the lists. + */ -#if defined(CONFIG_LUA_BUILTIN_TABLE) -extern const luaR_entry tab_funcs[]; -BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table); -BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs); +#ifdef _MSC_VER +//MSVC requires us to declare these sections before we refer to them +#pragma section(__ROSECNAME(A), read) +#pragma section(__ROSECNAME(zzzzzzzz), read) +#pragma section(__ROSECNAME(libs), read) +#pragma section(__ROSECNAME(rotable), read) +//These help us to find the beginning and ending of the RO data. NOTE: linker +//magic is used; the section names are lexically sorted, so 'a' and 'z' are +//important to keep the other sections lexically between these two dummy +//variables. Check your mapfile output if you need to fiddle with this stuff. +const LOCK_IN_SECTION(A) char _ro_start[1] = {0}; +const LOCK_IN_SECTION(zzzzzzzz) char _ro_end[1] = {0}; #endif -#if defined(CONFIG_LUA_BUILTIN_DEBUG) -extern const luaR_entry dblib[]; -BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug); -BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib); +LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(rotable) lua_rotables) + LROT_TABENTRY( string, strlib ) + LROT_TABENTRY( table, tab_funcs ) + LROT_TABENTRY( debug, dblib) + LROT_TABENTRY( coroutine, co_funcs ) + LROT_TABENTRY( math, math ) + LROT_TABENTRY( ROM, lua_rotables ) +#ifdef LUA_CROSS_COMPILER + LROT_TABENTRY( os, oslib ) + //LROT_TABENTRY( io, iolib ) +LROT_END(lua_rotables, NULL, 0) +#else +LROT_BREAK(lua_rotables) #endif -#if defined(LUA_USE_BUILTIN_OS) -extern const luaR_entry syslib[]; -BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib); +LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(libs) lua_libs) + LROT_FUNCENTRY( _, luaopen_base ) + LROT_FUNCENTRY( package, luaopen_package ) + LROT_FUNCENTRY( string, luaopen_string ) + LROT_FUNCENTRY( table, luaopen_table ) + LROT_FUNCENTRY( debug, luaopen_debug ) +#ifndef LUA_CROSS_COMPILER +LROT_BREAK(lua_rotables) +#else + LROT_FUNCENTRY( io, luaopen_io ) +LROT_END( lua_libs, NULL, 0) #endif -#if defined(CONFIG_LUA_BUILTIN_COROUTINE) -extern const luaR_entry co_funcs[]; -BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs); +#ifndef LUA_CROSS_COMPILER +extern void luaL_dbgbreak(void); #endif -#if defined(CONFIG_LUA_BUILTIN_MATH) -extern const luaR_entry math_map[]; -BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map); -#endif +void luaL_openlibs (lua_State *L) { -#ifdef LUA_CROSS_COMPILER -const luaL_Reg lua_libs[] = {{NULL, NULL}}; -const luaR_table lua_rotable[] = {{NULL, NULL}}; -#else -extern const luaL_Reg lua_libs[]; + lua_pushrotable(L, LROT_TABLEREF(lua_libs)); + lua_pushnil(L); /* first key */ + /* loop round and open libraries */ +#ifndef LUA_CROSS_COMPILER +// luaL_dbgbreak(); // This is a test point for debugging library start ups #endif - -void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lua_libs; - for (; lib->name; lib++) { - if (lib->func) - { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); + while (lua_next(L, -2) != 0) { + if (lua_islightfunction(L,-1) && + fvalue(L->top-1)) { // only process function entries + lua_pushvalue(L, -2); + lua_call(L, 1, 0); // call luaopen_XXX(libname) + } else { + lua_pop(L, 1); } } + lua_pop(L, 1); //cleanup stack } +#ifndef LUA_CROSS_COMPILER +# ifdef LUA_NUMBER_INTEGRAL +# define COMPARE <= +# else +# define COMPARE == +# endif +_Static_assert(_Alignof(luaR_entry) COMPARE 8, "Unexpected alignment of module registration - update the linker script snippets to match!"); +_Static_assert(sizeof(luaR_entry) COMPARE 24, "Unexpect size of array member - update the linker script snippets to match!"); +#endif diff --git a/components/base_nodemcu/uart.c b/components/base_nodemcu/uart.c index 218b3c9c76..51ed4619eb 100644 --- a/components/base_nodemcu/uart.c +++ b/components/base_nodemcu/uart.c @@ -260,30 +260,29 @@ static int uart_getconfig(lua_State* L) { } // Module function map -static const LUA_REG_TYPE uart_map[] = { - { LSTRKEY( "setup" ), LFUNCVAL( uart_setup ) }, - { LSTRKEY( "write" ), LFUNCVAL( uart_write ) }, - { LSTRKEY( "start" ), LFUNCVAL( uart_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( uart_stop ) }, - { LSTRKEY( "on" ), LFUNCVAL( uart_on ) }, - { LSTRKEY( "setmode" ), LFUNCVAL( uart_setmode ) }, - { LSTRKEY( "getconfig" ), LFUNCVAL( uart_getconfig ) }, - { LSTRKEY( "STOPBITS_1" ), LNUMVAL( PLATFORM_UART_STOPBITS_1 ) }, - { LSTRKEY( "STOPBITS_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) }, - { LSTRKEY( "STOPBITS_2" ), LNUMVAL( PLATFORM_UART_STOPBITS_2 ) }, - { LSTRKEY( "PARITY_NONE" ), LNUMVAL( PLATFORM_UART_PARITY_NONE ) }, - { LSTRKEY( "PARITY_EVEN" ), LNUMVAL( PLATFORM_UART_PARITY_EVEN ) }, - { LSTRKEY( "PARITY_ODD" ), LNUMVAL( PLATFORM_UART_PARITY_ODD ) }, - { LSTRKEY( "FLOWCTRL_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) }, - { LSTRKEY( "FLOWCTRL_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) }, - { LSTRKEY( "FLOWCTRL_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) }, - { LSTRKEY( "MODE_UART" ), LNUMVAL( PLATFORM_UART_MODE_UART ) }, - { LSTRKEY( "MODE_RS485_COLLISION_DETECT" ), LNUMVAL( PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) }, - { LSTRKEY( "MODE_RS485_APP_CONTROL" ), LNUMVAL( PLATFORM_UART_MODE_RS485_APP_CONTROL ) }, - { LSTRKEY( "MODE_RS485_HALF_DUPLEX" ), LNUMVAL( PLATFORM_UART_MODE_HALF_DUPLEX ) }, - { LSTRKEY( "MODE_IRDA" ), LNUMVAL( PLATFORM_UART_MODE_IRDA ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(uart) + LROT_FUNCENTRY( setup, uart_setup ) + LROT_FUNCENTRY( write, uart_write ) + LROT_FUNCENTRY( start, uart_start ) + LROT_FUNCENTRY( stop, uart_stop ) + LROT_FUNCENTRY( on, uart_on ) + LROT_FUNCENTRY( setmode, uart_setmode ) + LROT_FUNCENTRY( getconfig, uart_getconfig ) + LROT_NUMENTRY( STOPBITS_1, PLATFORM_UART_STOPBITS_1 ) + LROT_NUMENTRY( STOPBITS_1_5, PLATFORM_UART_STOPBITS_1_5 ) + LROT_NUMENTRY( STOPBITS_2, PLATFORM_UART_STOPBITS_2 ) + LROT_NUMENTRY( PARITY_NONE, PLATFORM_UART_PARITY_NONE ) + LROT_NUMENTRY( PARITY_EVEN, PLATFORM_UART_PARITY_EVEN ) + LROT_NUMENTRY( PARITY_ODD, PLATFORM_UART_PARITY_ODD ) + LROT_NUMENTRY( FLOWCTRL_NONE, PLATFORM_UART_FLOW_NONE ) + LROT_NUMENTRY( FLOWCTRL_CTS, PLATFORM_UART_FLOW_CTS ) + LROT_NUMENTRY( FLOWCTRL_RTS, PLATFORM_UART_FLOW_RTS ) + LROT_NUMENTRY( MODE_UART, PLATFORM_UART_MODE_UART ) + LROT_NUMENTRY( MODE_RS485_COLLISION_DETECT, PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) + LROT_NUMENTRY( MODE_RS485_APP_CONTROL, PLATFORM_UART_MODE_RS485_APP_CONTROL ) + LROT_NUMENTRY( MODE_RS485_HALF_DUPLEX, PLATFORM_UART_MODE_HALF_DUPLEX ) + LROT_NUMENTRY( MODE_IRDA, PLATFORM_UART_MODE_IRDA ) +LROT_END(uart, NULL, 0) int luaopen_uart( lua_State *L ) { uart_status_t *us; @@ -297,4 +296,4 @@ int luaopen_uart( lua_State *L ) { return 0; } -NODEMCU_MODULE(UART, "uart", uart_map, luaopen_uart); +NODEMCU_MODULE(UART, "uart", uart, luaopen_uart); diff --git a/components/embedded_lfs/component.mk b/components/embedded_lfs/component.mk new file mode 100644 index 0000000000..70e62d1ea5 --- /dev/null +++ b/components/embedded_lfs/component.mk @@ -0,0 +1,19 @@ +SHELL:=/bin/bash + +ifeq ($(CONFIG_LUA_EMBED_LFS),y) + +COMPONENT_OBJS := $(COMPONENT_BUILD_DIR)/luac_out.o +COMPONENT_EXTRA_CLEAN := $(COMPONENT_OBJS) $(COMPONENT_BUILD_DIR)/luac_out.o.bin +COMPONENT_ADD_LINKER_DEPS := $(COMPONENT_BUILD_DIR)/luac_out.o +EMBEDDED_LFS_DATA:= $(BUILD_DIR_BASE)/luac.out + +$(COMPONENT_BUILD_DIR)/luac_out.o: $(EMBEDDED_LFS_DATA) + echo "embedding luac.out into object file $@..." + dd if=/dev/zero bs=1 count=$$(( $(CONFIG_LUA_EMBEDDED_FLASH_STORE) )) of="$@.bin" status=none + dd if="$(EMBEDDED_LFS_DATA)" conv=notrunc of="$@.bin" status=none + cd $(dir $@) && $(OBJCOPY) --input-target binary --output-target elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.lfs.reserved --redefine-sym _binary_luac_out_o_bin_start=lua_flash_store_reserved "$(notdir $@.bin)" "$@" + +$(EMBEDDED_LFS_DATA): + touch $@ + +endif diff --git a/components/lua/lapi.c b/components/lua/lapi.c index 4f7d1c4f36..371c09fa42 100644 --- a/components/lua/lapi.c +++ b/components/lua/lapi.c @@ -10,9 +10,9 @@ #include "lua.h" -//#include C_HEADER_ASSERT -#include C_HEADER_MATH -#include C_HEADER_STRING +//#include +#include +#include #include "lapi.h" #include "ldebug.h" #include "ldo.h" @@ -213,7 +213,7 @@ LUA_API void lua_replace (lua_State *L, int idx) { if (!func) luaG_runerror(L, "attempt to set environment on lightfunction"); else { - api_check(L, ttistable(L->top - 1)); + api_check(L, ttistable(L->top - 1)); func->c.env = hvalue(L->top - 1); luaC_barrier(L, func, L->top - 1); } @@ -411,9 +411,10 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: return lua_touserdata(L, idx); - case LUA_TROTABLE: + case LUA_TROTABLE: + return rvalue(o); case LUA_TLIGHTFUNCTION: - return pvalue(o); + return fvalue(o); default: return NULL; } } @@ -458,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { } -LUA_API void lua_pushrolstring (lua_State *L, const char *s, size_t len) { - lua_lock(L); - luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newrolstr(L, s, len)); - api_incr_top(L); - lua_unlock(L); -} - - LUA_API void lua_pushstring (lua_State *L, const char *s) { if (s == NULL) lua_pushnil(L); @@ -593,7 +585,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) { t = index2adr(L, idx); api_check(L, ttistable(t) || ttisrotable(t)); res = ttistable(t) ? luaH_get(hvalue(t), L->top - 1) : luaH_get_ro(rvalue(t), L->top - 1); - setobj2s(L, L->top - 1, res); + setobj2s(L, L->top - 1, res); lua_unlock(L); } @@ -633,7 +625,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { break; case LUA_TROTABLE: mt = (Table*)luaR_getmeta(rvalue(obj)); - break; + break; default: mt = G(L)->mt[ttype(obj)]; break; diff --git a/components/lua/lauxlib.c b/components/lua/lauxlib.c index c45772061e..3b50babf32 100644 --- a/components/lua/lauxlib.c +++ b/components/lua/lauxlib.c @@ -7,12 +7,13 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_CTYPE -#include C_HEADER_ERRNO -#include C_HEADER_STDIO -#include C_HEADER_STDLIB -#include C_HEADER_STRING +#include +#include +#include +#include +#include #ifndef LUA_CROSS_COMPILER +#include "esp_system.h" #include "vfs.h" #else #endif @@ -44,6 +45,149 @@ #define LUA_USECCLOSURES 0 #define LUA_USELIGHTFUNCTIONS 1 +//#define DEBUG_ALLOCATOR +#ifdef DEBUG_ALLOCATOR +#ifdef LUA_CROSS_COMPILER +static void break_hook(void) {} +#define ASSERT(s) if (!(s)) {break_hook();} +#else +#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);} +#endif + +/* +** {====================================================================== +** Diagnosticd version for realloc. This is enabled only if the +** DEBUG_ALLOCATOR is defined. It is a cutdown version of the allocator +** used in the Lua Test Suite -- a compromise between the ability catch +** most alloc/free errors and overruns and working within the RAM limits +** of the ESP8266 architecture. ONLY FOR HEAVY HACKERS +** ======================================================================= +*/ +#define this_realloc debug_realloc +#define MARK 0x55 /* 01010101 (a nice pattern) */ +#define MARKSIZE 2*sizeof(size_t) /* size of marks after each block */ +#define fillmem(mem,size) memset(mem, ~MARK, size) + +typedef union MemHeader MemHeader; +union MemHeader { + L_Umaxalign a; /* ensures maximum alignment for Header */ + struct { + size_t size; + MemHeader *next; + size_t mark[2]; + }; +}; + +typedef struct Memcontrol { /* memory-allocator control variables */ + MemHeader *start; + lu_int32 numblocks; + lu_int32 total; + lu_int32 maxmem; + lu_int32 memlimit; +} Memcontrol; +static Memcontrol mc = {NULL,0,0,0,32768*64}; +static size_t marker[2] = {0,0}; + +static void scanBlocks (void) { + MemHeader *p = mc.start; + int i; + char s,e; + for (i=0; p ;i++) { + s = memcmp(p->mark, marker, MARKSIZE) ? '<' : ' '; + e = memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE) ? '>' : ' '; + printf("%4u %p %8lu %c %c\n", i, p, p->size, s, e); + ASSERT(p->next); + p = p->next; + } +} + +static int checkBlocks (void) { + MemHeader *p = mc.start; + while(p) { + if (memcmp(p->mark, marker, MARKSIZE) || + memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE)) { + scanBlocks(); + return 0; + } + p = p->next; + } + return 1; +} + + +static void freeblock (MemHeader *block) { + if (block) { + MemHeader *p = mc.start; + MemHeader *next = block->next; + size_t size = block->size; + ASSERT(checkBlocks()); + if (p == block) { + mc.start = next; + } else { + while (p->next != block) { + ASSERT(p); + p = p->next; + } + p->next = next; + } + fillmem(block, sizeof(MemHeader) + size + MARKSIZE); /* erase block */ + free(block); /* actually free block */ + mc.numblocks--; /* update counts */ + mc.total -= size; + } +} + +void *debug_realloc (void *b, size_t oldsize, size_t size) { + MemHeader *block = cast(MemHeader *, b); + ASSERT(checkBlocks()); + if (!marker[0]) memset(marker, MARK, MARKSIZE); + if (block == NULL) { + oldsize = 0; + } else { + block--; /* go to real header */ + ASSERT(!memcmp(block->mark, marker, MARKSIZE)) + ASSERT(oldsize == block->size); + ASSERT(!memcmp(cast(char *, b)+oldsize, marker, MARKSIZE)); + } + if (size == 0) { + freeblock(block); + return NULL; + } else if (size > oldsize && mc.total+size-oldsize > mc.memlimit) + return NULL; /* fake a memory allocation error */ + else { + MemHeader *newblock; + size_t commonsize = (oldsize < size) ? oldsize : size; + size_t realsize = sizeof(MemHeader) + size + MARKSIZE; + newblock = cast(MemHeader *, malloc(realsize)); /* alloc a new block */ + if (newblock == NULL) + return NULL; /* really out of memory? */ + if (block) { + memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */ + freeblock(block); /* erase (and check) old copy */ + } + /* initialize new part of the block with something weird */ + if (size > commonsize) + fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize); + /* initialize marks after block */ + memset(newblock->mark, MARK, MARKSIZE); + newblock->size = size; + newblock->next = mc.start; + mc.start = newblock; + memset(cast(char *, newblock + 1)+ size, MARK, MARKSIZE); + mc.total += size; + if (mc.total > mc.maxmem) + mc.maxmem = mc.total; + mc.numblocks++; + return (newblock + 1); + } +} + + +/* }====================================================================== */ +#else +#define this_realloc(p,os,s) realloc(p,s) +#endif /* DEBUG_ALLOCATOR */ + /* ** {====================================================== ** Error-report functions @@ -173,7 +317,7 @@ LUALIB_API void luaL_checkanyfunction (lua_State *L, int narg) { if (lua_type(L, narg) != LUA_TFUNCTION && lua_type(L, narg) != LUA_TLIGHTFUNCTION) { const char *msg = lua_pushfstring(L, "function or lightfunction expected, got %s", luaL_typename(L, narg)); - luaL_argerror(L, narg, msg); + luaL_argerror(L, narg, msg); } } @@ -181,7 +325,7 @@ LUALIB_API void luaL_checkanytable (lua_State *L, int narg) { if (lua_type(L, narg) != LUA_TTABLE && lua_type(L, narg) != LUA_TROTABLE) { const char *msg = lua_pushfstring(L, "table or rotable expected, got %s", luaL_typename(L, narg)); - luaL_argerror(L, narg, msg); + luaL_argerror(L, narg, msg); } } @@ -270,11 +414,7 @@ LUALIB_API void (luaL_register) (lua_State *L, const char *libname, LUALIB_API void (luaL_register_light) (lua_State *L, const char *libname, const luaL_Reg *l) { -#if LUA_OPTIMIZE_MEMORY > 0 luaI_openlib(L, libname, l, 0, LUA_USELIGHTFUNCTIONS); -#else - luaI_openlib(L, libname, l, 0, LUA_USECCLOSURES); -#endif } static int libsize (const luaL_Reg *l) { @@ -411,14 +551,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx, if (e == NULL) e = fname + strlen(fname); lua_pushlstring(L, fname, e - fname); lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - /* If looking for a global variable, check the rotables too */ - void *ptable = luaR_findglobal(fname, e - fname); - if (ptable) { - lua_pop(L, 1); - lua_pushrotable(L, ptable); - } - } + 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 */ @@ -632,8 +765,9 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; - lf.extraline = 0; + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {} + + lf.extraline = 0; } ungetc(c, lf.f); status = lua_load(L, getF, &lf, lua_tostring(L, -1)); @@ -700,12 +834,12 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) { lf.f = vfs_open(filename, "r"); if (!lf.f) return errfsfile(L, "open", fnameindex); } - // if(vfs_size(lf.f)>LUAL_BUFFERSIZE) + // if(fs_size(lf.f)>LUAL_BUFFERSIZE) // return luaL_error(L, "file is too big"); c = vfs_getc(lf.f); if (c == '#') { /* Unix exec. file? */ lf.extraline = 1; - while ((c = vfs_getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ + while ((c = vfs_getc(lf.f)) != VFS_EOF && c != '\n') ; /* skip first line */ if (c == '\n') c = vfs_getc(lf.f); } if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ @@ -713,7 +847,7 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) { lf.f = vfs_open(filename, "r"); /* reopen in binary mode */ if (!lf.f) return errfsfile(L, "reopen", fnameindex); /* skip eventual `#!...' */ - while ((c = vfs_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + while ((c = vfs_getc(lf.f)) != VFS_EOF && c != LUA_SIGNATURE[0]) ; lf.extraline = 0; } vfs_ungetc(c, lf.f); @@ -786,11 +920,20 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { void *nptr; if (nsize == 0) { +#ifdef DEBUG_ALLOCATOR + return (void *)this_realloc(ptr, osize, nsize); +#else free(ptr); return NULL; +#endif } if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */ luaC_fullgc(L); +#ifndef LUA_CROSS_COMPILER + if (L != NULL && (mode & EGC_ON_MEM_LIMIT) && G(L)->memlimit < 0 && + (esp_get_free_heap_size() < (-G(L)->memlimit))) + luaC_fullgc(L); +#endif if(nsize > osize && L != NULL) { #if defined(LUA_STRESS_EMERGENCY_GC) luaC_fullgc(L); @@ -798,16 +941,19 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize)) return NULL; } - nptr = (void *)realloc(ptr, nsize); + nptr = (void *)this_realloc(ptr, osize, nsize); if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) { luaC_fullgc(L); /* emergency full collection. */ - nptr = (void *)realloc(ptr, nsize); /* try allocation again */ + nptr = (void *)this_realloc(ptr, osize, nsize); /* try allocation again */ } return nptr; } LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) { - printf("ASSERT@%s(%d): %s\n", file, line, message); + printf("ASSERT@%s(%d): %s\n", file, line, message); +#if defined(LUA_CROSS_COMPILER) + exit(1); +#endif } static int panic (lua_State *L) { diff --git a/components/lua/lbaselib.c b/components/lua/lbaselib.c index 878079a860..e0121522f9 100644 --- a/components/lua/lbaselib.c +++ b/components/lua/lbaselib.c @@ -11,9 +11,9 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDIO -#include C_HEADER_STRING -#include C_HEADER_STDLIB +#include +#include +#include #include "lauxlib.h" #include "lualib.h" #include "lrotable.h" @@ -462,73 +462,59 @@ static int luaB_newproxy (lua_State *L) { return 1; } -#define LUA_BASELIB_FUNCLIST\ - {LSTRKEY("assert"), LFUNCVAL(luaB_assert)},\ - {LSTRKEY("collectgarbage"), LFUNCVAL(luaB_collectgarbage)},\ - {LSTRKEY("dofile"), LFUNCVAL(luaB_dofile)},\ - {LSTRKEY("error"), LFUNCVAL(luaB_error)},\ - {LSTRKEY("gcinfo"), LFUNCVAL(luaB_gcinfo)},\ - {LSTRKEY("getfenv"), LFUNCVAL(luaB_getfenv)},\ - {LSTRKEY("getmetatable"), LFUNCVAL(luaB_getmetatable)},\ - {LSTRKEY("loadfile"), LFUNCVAL(luaB_loadfile)},\ - {LSTRKEY("load"), LFUNCVAL(luaB_load)},\ - {LSTRKEY("loadstring"), LFUNCVAL(luaB_loadstring)},\ - {LSTRKEY("next"), LFUNCVAL(luaB_next)},\ - {LSTRKEY("pcall"), LFUNCVAL(luaB_pcall)},\ - {LSTRKEY("print"), LFUNCVAL(luaB_print)},\ - {LSTRKEY("rawequal"), LFUNCVAL(luaB_rawequal)},\ - {LSTRKEY("rawget"), LFUNCVAL(luaB_rawget)},\ - {LSTRKEY("rawset"), LFUNCVAL(luaB_rawset)},\ - {LSTRKEY("select"), LFUNCVAL(luaB_select)},\ - {LSTRKEY("setfenv"), LFUNCVAL(luaB_setfenv)},\ - {LSTRKEY("setmetatable"), LFUNCVAL(luaB_setmetatable)},\ - {LSTRKEY("tonumber"), LFUNCVAL(luaB_tonumber)},\ - {LSTRKEY("tostring"), LFUNCVAL(luaB_tostring)},\ - {LSTRKEY("type"), LFUNCVAL(luaB_type)},\ - {LSTRKEY("unpack"), LFUNCVAL(luaB_unpack)},\ - {LSTRKEY("xpcall"), LFUNCVAL(luaB_xpcall)} - -#if LUA_OPTIMIZE_MEMORY == 2 -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 2 -#include "lrodefs.h" -const LUA_REG_TYPE base_funcs_list[] = { - LUA_BASELIB_FUNCLIST, - {LNILKEY, LNILVAL} -}; -#endif - +#include "lrotable.h" -static int luaB_index(lua_State *L) { -#if LUA_OPTIMIZE_MEMORY == 2 - int fres; - if ((fres = luaR_findfunction(L, base_funcs_list)) != 0) - return fres; -#endif - const char *keyname = luaL_checkstring(L, 2); - if (!strcmp(keyname, "_VERSION")) { - lua_pushliteral(L, LUA_VERSION); - return 1; - } - void *res = luaR_findglobal(keyname, strlen(keyname)); - if (!res) - return 0; - else { - lua_pushrotable(L, res); - return 1; - } -} +LROT_EXTERN(lua_rotable_base); -static const luaL_Reg base_funcs[] = { -#if LUA_OPTIMIZE_MEMORY != 2 -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 0 -#include "lrodefs.h" - LUA_BASELIB_FUNCLIST, -#endif - {"__index", luaB_index}, - {NULL, NULL} -}; +/* + * Separate ROTables are used for the base functions and library ROTables, with + * the base functions ROTable declared below. The library ROTable is chained + * from this using its __index meta-method. + * + * ESP builds use specific linker directives to marshal all the ROTable entries + * for the library modules into a single ROTable in the PSECT ".lua_rotable". + * This is not practical on Posix builds using a standard GNU link, so the + * equivalent ROTable for the core libraries defined in linit.c for the cross- + * compiler build. + */ + +LROT_EXTERN(lua_rotables); + +LROT_PUBLIC_BEGIN(base_func_meta) + LROT_TABENTRY( __index, lua_rotables ) +LROT_END(base_func, base_func_meta, LROT_MASK_INDEX) + +LROT_PUBLIC_BEGIN(base_func) + LROT_FUNCENTRY(assert, luaB_assert) + LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage) + LROT_FUNCENTRY(dofile, luaB_dofile) + LROT_FUNCENTRY(error, luaB_error) + LROT_FUNCENTRY(gcinfo, luaB_gcinfo) + LROT_FUNCENTRY(getfenv, luaB_getfenv) + LROT_FUNCENTRY(getmetatable, luaB_getmetatable) + LROT_FUNCENTRY(loadfile, luaB_loadfile) + LROT_FUNCENTRY(load, luaB_load) + LROT_FUNCENTRY(loadstring, luaB_loadstring) + LROT_FUNCENTRY(next, luaB_next) + LROT_FUNCENTRY(pcall, luaB_pcall) + LROT_FUNCENTRY(print, luaB_print) + LROT_FUNCENTRY(rawequal, luaB_rawequal) + LROT_FUNCENTRY(rawget, luaB_rawget) + LROT_FUNCENTRY(rawset, luaB_rawset) + LROT_FUNCENTRY(select, luaB_select) + LROT_FUNCENTRY(setfenv, luaB_setfenv) + LROT_FUNCENTRY(setmetatable, luaB_setmetatable) + LROT_FUNCENTRY(tonumber, luaB_tonumber) + LROT_FUNCENTRY(tostring, luaB_tostring) + LROT_FUNCENTRY(type, luaB_type) + LROT_FUNCENTRY(unpack, luaB_unpack) + LROT_FUNCENTRY(xpcall, luaB_xpcall) + LROT_TABENTRY(__metatable, base_func_meta) +LROT_END(base_func, base_func_meta, LROT_MASK_INDEX) + +LROT_BEGIN(G_meta) + LROT_TABENTRY( __index, base_func ) +LROT_END(G_meta, NULL, 0) /* @@ -659,18 +645,14 @@ static int luaB_corunning (lua_State *L) { return 1; } -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE co_funcs[] = { - {LSTRKEY("create"), LFUNCVAL(luaB_cocreate)}, - {LSTRKEY("resume"), LFUNCVAL(luaB_coresume)}, - {LSTRKEY("running"), LFUNCVAL(luaB_corunning)}, - {LSTRKEY("status"), LFUNCVAL(luaB_costatus)}, - {LSTRKEY("wrap"), LFUNCVAL(luaB_cowrap)}, - {LSTRKEY("yield"), LFUNCVAL(luaB_yield)}, - {LNILKEY, LNILVAL} -}; +LROT_PUBLIC_BEGIN(co_funcs) + LROT_FUNCENTRY( create, luaB_cocreate ) + LROT_FUNCENTRY( resume, luaB_coresume ) + LROT_FUNCENTRY( running, luaB_corunning ) + LROT_FUNCENTRY( status, luaB_costatus ) + LROT_FUNCENTRY( wrap, luaB_cowrap ) + LROT_FUNCENTRY( yield, luaB_yield ) +LROT_END (co_funcs, NULL, 0) /* }====================================================== */ @@ -682,20 +664,18 @@ static void auxopen (lua_State *L, const char *name, lua_setfield(L, -2, name); } - static void base_open (lua_State *L) { /* set global _G */ lua_pushvalue(L, LUA_GLOBALSINDEX); lua_setglobal(L, "_G"); + /* open lib into global table */ - luaL_register_light(L, "_G", base_funcs); -#if LUA_OPTIMIZE_MEMORY > 0 - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); -#else + luaL_register_light(L, "_G", &((luaL_Reg) {0})); + lua_pushrotable(L, LROT_TABLEREF(G_meta)); + lua_setmetatable(L, LUA_GLOBALSINDEX); + lua_pushliteral(L, LUA_VERSION); lua_setglobal(L, "_VERSION"); /* set global _VERSION */ -#endif /* `ipairs' and `pairs' need auxliliary functions as upvalues */ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "pairs", luaB_pairs, luaB_next); @@ -712,10 +692,5 @@ static void base_open (lua_State *L) { LUALIB_API int luaopen_base (lua_State *L) { base_open(L); -#if LUA_OPTIMIZE_MEMORY == 0 - luaL_register(L, LUA_COLIBNAME, co_funcs); - return 2; -#else return 1; -#endif } diff --git a/components/lua/lcode.c b/components/lua/lcode.c index a5e0a8e78c..5fa535ce42 100644 --- a/components/lua/lcode.c +++ b/components/lua/lcode.c @@ -10,7 +10,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDLIB +#include #include "lcode.h" #include "ldebug.h" diff --git a/components/lua/ldblib.c b/components/lua/ldblib.c index b57512ce77..4b8062850f 100644 --- a/components/lua/ldblib.c +++ b/components/lua/ldblib.c @@ -10,12 +10,14 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDIO -#include C_HEADER_STDLIB -#include C_HEADER_STRING +#include +#include +#include #include "lauxlib.h" #include "lualib.h" +#include "lstring.h" +#include "lflash.h" #include "lrotable.h" #include "sdkconfig.h" @@ -25,6 +27,39 @@ static int db_getregistry (lua_State *L) { return 1; } +static int db_getstrings (lua_State *L) { + size_t i,n=0; + stringtable *tb; + GCObject *o; +#ifndef LUA_CROSS_COMPILER + const char *opt = lua_tolstring (L, 1, &n); + if (n==3 && memcmp(opt, "ROM", 4) == 0) { + if (G(L)->ROstrt.hash == NULL) + return 0; + tb = &G(L)->ROstrt; + } + else +#endif + tb = &G(L)->strt; + lua_settop(L, 0); + lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */ + for (i=0, n=1; isize; i++) { + for(o = tb->hash[i]; o; o=o->gch.next) { + TString *ts =cast(TString *, o); + lua_pushnil(L); + setsvalue2s(L, L->top-1, ts); + lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */ + } + } + lua_getfield(L, LUA_GLOBALSINDEX, "table"); + lua_getfield(L, -1, "sort"); /* look up table.sort function */ + lua_replace(L, -2); /* dump the table table */ + lua_pushvalue(L, -2); /* duplicate the strt_copy ref */ + lua_call(L, 1, 0); /* table.sort(strt_copy) */ + return 1; +} + + #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL static int db_getmetatable (lua_State *L) { @@ -384,33 +419,30 @@ static int db_errorfb (lua_State *L) { return 1; } -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE dblib[] = { +LROT_PUBLIC_BEGIN(dblib) #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL #if defined(LUA_CROSS_COMPILER) - {LSTRKEY("debug"), LFUNCVAL(db_debug)}, -#endif // defined(LUA_CROSS_COMPILER) - {LSTRKEY("getfenv"), LFUNCVAL(db_getfenv)}, - {LSTRKEY("gethook"), LFUNCVAL(db_gethook)}, - {LSTRKEY("getinfo"), LFUNCVAL(db_getinfo)}, - {LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)}, + LROT_FUNCENTRY( debug, db_debug ) +#endif + LROT_FUNCENTRY( getfenv, db_getfenv ) + LROT_FUNCENTRY( gethook, db_gethook ) + LROT_FUNCENTRY( getinfo, db_getinfo ) + LROT_FUNCENTRY( getlocal, db_getlocal ) #endif - {LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)}, + LROT_FUNCENTRY( getregistry, db_getregistry ) + LROT_FUNCENTRY( getstrings, db_getstrings ) #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL - {LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)}, - {LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)}, - {LSTRKEY("setfenv"), LFUNCVAL(db_setfenv)}, - {LSTRKEY("sethook"), LFUNCVAL(db_sethook)}, - {LSTRKEY("setlocal"), LFUNCVAL(db_setlocal)}, - {LSTRKEY("setmetatable"), LFUNCVAL(db_setmetatable)}, - {LSTRKEY("setupvalue"), LFUNCVAL(db_setupvalue)}, + LROT_FUNCENTRY( getmetatable, db_getmetatable ) + LROT_FUNCENTRY( getupvalue, db_getupvalue ) + LROT_FUNCENTRY( setfenv, db_setfenv ) + LROT_FUNCENTRY( sethook, db_sethook ) + LROT_FUNCENTRY( setlocal, db_setlocal ) + LROT_FUNCENTRY( setmetatable, db_setmetatable ) + LROT_FUNCENTRY( setupvalue, db_setupvalue ) #endif - {LSTRKEY("traceback"), LFUNCVAL(db_errorfb)}, - {LNILKEY, LNILVAL} -}; + LROT_FUNCENTRY( traceback, db_errorfb ) +LROT_END(dblib, NULL, 0) LUALIB_API int luaopen_debug (lua_State *L) { - LREGISTER(L, LUA_DBLIBNAME, dblib); + return 0; } diff --git a/components/lua/ldebug.c b/components/lua/ldebug.c index 0bdc094fc3..eab0ef62b2 100644 --- a/components/lua/ldebug.c +++ b/components/lua/ldebug.c @@ -10,7 +10,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lapi.h" #include "lcode.h" diff --git a/components/lua/ldo.c b/components/lua/ldo.c index 9a2ddd0e76..7694ab8fbb 100644 --- a/components/lua/ldo.c +++ b/components/lua/ldo.c @@ -11,7 +11,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "ldebug.h" #include "ldo.h" @@ -106,7 +106,7 @@ void luaD_throw (lua_State *L, int errcode) { lua_unlock(L); G(L)->panic(L); } - // c_exit(EXIT_FAILURE); + // exit(EXIT_FAILURE); } } @@ -144,8 +144,11 @@ static void correctstack (lua_State *L, TValue *oldstack) { void luaD_reallocstack (lua_State *L, int newsize) { TValue *oldstack = L->stack; int realsize = newsize + 1 + EXTRA_STACK; + int block_status = is_block_gc(L); lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + set_block_gc(L); /* The GC MUST be blocked during stack reallocaiton */ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + if (!block_status) unset_block_gc(L); /* Honour the previous block status */ L->stacksize = realsize; L->stack_last = L->stack+newsize; correctstack(L, oldstack); diff --git a/components/lua/ldump.c b/components/lua/ldump.c index 4f50319e7d..db2a036202 100644 --- a/components/lua/ldump.c +++ b/components/lua/ldump.c @@ -9,7 +9,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lobject.h" #include "lstate.h" @@ -47,7 +47,7 @@ static void DumpChar(int y, DumpState* D) static void Align4(DumpState *D) { - while(D->wrote&3) + while(D->wrote&3 && D->status==0) DumpChar(0,D); } diff --git a/components/lua/legc.c b/components/lua/legc.c index bbef290055..c0bf07a6f2 100644 --- a/components/lua/legc.c +++ b/components/lua/legc.c @@ -3,9 +3,9 @@ #include "legc.h" #include "lstate.h" -void legc_set_mode(lua_State *L, int mode, unsigned limit) { - global_State *g = G(L); - +void legc_set_mode(lua_State *L, int mode, int limit) { + global_State *g = G(L); + g->egcmode = mode; g->memlimit = limit; } diff --git a/components/lua/legc.h b/components/lua/legc.h index a0d9dde317..c85ebb6b25 100644 --- a/components/lua/legc.h +++ b/components/lua/legc.h @@ -11,7 +11,7 @@ #define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit #define EGC_ALWAYS 4 // always run EGC before an allocation -void legc_set_mode(lua_State *L, int mode, unsigned limit); +void legc_set_mode(lua_State *L, int mode, int limit); #endif diff --git a/components/lua/lflash.c b/components/lua/lflash.c new file mode 100644 index 0000000000..8cd226484b --- /dev/null +++ b/components/lua/lflash.c @@ -0,0 +1,610 @@ +/* +** $Id: lflash.c +** See Copyright Notice in lua.h +*/ + +#define lflash_c +#define LUA_CORE +#define LUAC_CROSS_FILE +#include "lua.h" + +#include "lobject.h" +#include "lauxlib.h" +#include "lstate.h" +#include "lfunc.h" +#include "lflash.h" +#include "platform.h" +#include "vfs.h" +#include "uzlib.h" +#include "platform_wdt.h" + +#include "esp_partition.h" +#include +#include +#include +#include + +/* + * Flash memory is a fixed memory addressable block that is serially allocated by the + * luac build process and the out image can be downloaded into SPIFSS and loaded into + * flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build + * process. + */ + +static const char *flashAddr; +static uint32_t flashSize; +static uint32_t flashAddrPhys; +static uint32_t flashSector; +static uint32_t curOffset; + +#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t)))) +#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1)) +#define ALL_SET (~0) +#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE +#define FLASH_PAGES (flashSize/FLASH_PAGE_SIZE) +#define READ_BLOCKSIZE 1024 +#define WRITE_BLOCKSIZE 2048 +#define DICTIONARY_WINDOW 16384 +#define WORDSIZE (sizeof(int)) +#define BITS_PER_WORD 32 +#define WRITE_BLOCKS ((DICTIONARY_WINDOW/WRITE_BLOCKSIZE)+1) +#define WRITE_BLOCK_WORDS (WRITE_BLOCKSIZE/WORDSIZE) + +struct INPUT { + int fd; + int len; + uint8_t block[READ_BLOCKSIZE]; + uint8_t *inPtr; + int bytesRead; + int left; + void *inflate_state; +} *in; + +typedef struct { + uint8_t byte[WRITE_BLOCKSIZE]; +} outBlock; + +struct OUTPUT { + lua_State *L; + lu_int32 flash_sig; + int len; + outBlock *block[WRITE_BLOCKS]; + outBlock buffer; + int ndx; + uint32_t crc; + int (*fullBlkCB) (void); + int flashLen; + int flagsLen; + int flagsNdx; + uint32_t *flags; + const char *error; +} *out; + + +#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE + extern const char lua_flash_store_reserved[0]; +#endif + + +#ifdef NODE_DEBUG +extern void printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void dumpStrt(stringtable *tb, const char *type) { + int i,j; + GCObject *o; + + NODE_DBG("\nDumping %s String table\n\n========================\n", type); + NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size); + for (i=0; isize; i++) + for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) { + TString *ts =cast(TString *, o); + NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n", + i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, + ts_isreadonly(ts) ? "R" : " ", getstr(ts)); + } +} + +LUA_API void dumpStrings(lua_State *L) { + dumpStrt(&G(L)->strt, "RAM"); + if (G(L)->ROstrt.hash) + dumpStrt(&G(L)->ROstrt, "ROM"); +} +#endif + +#ifndef CONFIG_LUA_EMBEDDED_FLASH_STORE +/* ===================================================================================== + * The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase + * wrap writing to flash. The last two are platform dependent. Also note that any + * writes are suppressed if the global writeToFlash is false. This is used in + * phase I where the pass is used to size the structures in flash. + */ +static void flashSetPosition(uint32_t offset){ + NODE_DBG("flashSetPosition(%04x)\n", offset); + curOffset = offset; +} + + +static void flashBlock(const void* b, size_t size) { + NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,(unsigned int)b,size); + lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0); + platform_flash_write(b, flashAddrPhys+curOffset, size); + curOffset += size; +} + + +static void flashErase(uint32_t start, uint32_t end){ + int i; + if (start == -1) start = FLASH_PAGES - 1; + if (end == -1) end = FLASH_PAGES - 1; + NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end); + for (i = start; i<=end; i++) + platform_flash_erase_sector( flashSector + i ); +} + +static int loadLFS (lua_State *L); +static int loadLFSgc (lua_State *L); +static int procFirstPass (void); +#endif + +/* ===================================================================================== + * luaN_init(), luaN_reload_reboot() and luaN_index() are exported via lflash.h. + * The first is the startup hook used in lstate.c and the last two are + * implementations of the node.flash API calls. + */ + +/* + * Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed + */ +LUAI_FUNC void luaN_init (lua_State *L) { +#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE + flashSize = CONFIG_LUA_EMBEDDED_FLASH_STORE; + flashAddr = lua_flash_store_reserved; + flashAddrPhys = spi_flash_cache2phys(lua_flash_store_reserved); + if (flashAddrPhys == SPI_FLASH_CACHE2PHYS_FAIL) { + NODE_ERR("spi_flash_cache2phys failed\n"); + return; + } +#else + const esp_partition_t *part = esp_partition_find_first( + PLATFORM_PARTITION_TYPE_NODEMCU, + PLATFORM_PARTITION_SUBTYPE_NODEMCU_LFS, + NULL); + if (!part) + return; // Nothing to do if the size is zero + + flashSize = part->size; // in bytes + flashAddrPhys = part->address; + flashAddr = spi_flash_phys2cache(flashAddrPhys, SPI_FLASH_MMAP_DATA); + if (!flashAddr) { + spi_flash_mmap_handle_t ignored; + esp_err_t err = spi_flash_mmap( + flashAddrPhys, flashSize, SPI_FLASH_MMAP_DATA, + cast(const void **, &flashAddr), &ignored); + if (err != ESP_OK) { + NODE_ERR("Unable to access LFS partition - is it 64kB aligned as it needs to be?\n"); + return; + } + } +#endif + G(L)->LFSsize = flashSize; + flashSector = platform_flash_get_sector_of_address(flashAddrPhys); + + FlashHeader *fh = cast(FlashHeader *, flashAddr); + curOffset = 0; + + /* + * For the LFS to be valid, its signature has to be correct for this build + * variant, the ROhash and main proto fields must be defined and the main proto + * address be within the LFS address bounds. (This last check is primarily to + * detect the direct imaging of an absolute LFS with the wrong base address. + */ + + if (fh->flash_sig == 0 || fh->flash_sig == ~0 ) { + NODE_ERR("No LFS image loaded\n"); + return; + } + + if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) { + NODE_ERR("Flash sig not correct: %u vs %u\n", + fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG); + return; + } + + if (fh->pROhash == ALL_SET || + ((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) { + NODE_ERR("Flash size check failed: %x vs 0xFFFFFFFF; size: %u\n", + fh->mainProto - cast(FlashAddr, fh), fh->flash_size); + return; + } + + G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash); + G(L)->ROstrt.nuse = fh->nROuse ; + G(L)->ROstrt.size = fh->nROsize; + G(L)->ROpvmain = cast(Proto *,fh->mainProto); +} + +/* + * Library function called by node.flashreload(filename). + */ +LUALIB_API int luaN_reload_reboot (lua_State *L) { +#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE + // Updating the LFS section is disabled for now because any changes to the + // image requires updating its checksum to prevent boot failure. + lua_pushstring(L, "Not allowed to write to LFS section"); + return 1; +#else + // luaL_dbgbreak(); + const char *fn = lua_tostring(L, 1), *msg = ""; + int status; + + if (G(L)->LFSsize == 0) { + lua_pushstring(L, "No LFS partition allocated"); + return 1; + } + + + /* + * Do a protected call of loadLFS. + * + * - This will normally rewrite the LFS and reboot, with no return. + * - If an error occurs then it is sent to the UART. + * - If this occured in the 1st pass, the previous LFS is unchanged so it is + * safe to return to the calling Lua. + * - If in the 1st pass, then the ESP is rebooted. + */ + status = lua_cpcall(L, &loadLFS, cast(void *,fn)); + + if (!out || out->fullBlkCB == procFirstPass) { + /* + * Never entered the 2nd pass, so it is safe to return the error. Note + * that I've gone to some trouble to ensure that all dynamically allocated + * working areas have been freed, so that we have no memory leaks. + */ + if (status == LUA_ERRMEM) + msg = "Memory allocation error"; + else if (out && out->error) + msg = out->error; + else + msg = "Unknown Error"; + + /* We can clean up and return error */ + lua_cpcall(L, &loadLFSgc, NULL); + lua_settop(L, 0); + lua_pushstring(L, msg); + return 1; + } + + if (status == 0) { + /* Successful LFS rewrite */ + msg = "LFS region updated. Restarting."; + } else { + /* We have errored during the second pass so clear the LFS and reboot */ + if (status == LUA_ERRMEM) + msg = "Memory allocation error"; + else if (out->error) + msg = out->error; + else + msg = "Unknown Error"; + + flashErase(0,-1); + } + NODE_ERR("%s\n", msg); + + esp_restart(); + return 0; +#endif // CONFIG_LUA_EMBEDDED_FLASH_STORE +} + + +/* + * If the arg is a valid LFS module name then return the LClosure + * pointing to it. Otherwise return: + * - The Unix time that the LFS was built + * - The base address and length of the LFS + * - An array of the module names in the LFS + */ +LUAI_FUNC int luaN_index (lua_State *L) { + int n = lua_gettop(L); + + /* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */ + if (!(G(L)->ROpvmain)) { + lua_settop(L, 0); + lua_pushnil(L); + if (G(L)->LFSsize) { + lua_pushinteger(L, (lua_Integer) flashAddr); + lua_pushinteger(L, flashAddrPhys); + lua_pushinteger(L, G(L)->LFSsize); + return 4; + } else { + return 1; + } + } + + /* Push the LClosure of the LFS index function */ + Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L))); + cl->l.p = G(L)->ROpvmain; + lua_settop(L, n+1); + setclvalue(L, L->top-1, cl); + + /* Move it infront of the arguments and call the index function */ + lua_insert(L, 1); + lua_call(L, n, LUA_MULTRET); + + /* Return it if the response if a single value (the function) */ + if (lua_gettop(L) == 1) + return 1; + + lua_assert(lua_gettop(L) == 2); + + /* Otherwise add the base address of the LFS, and its size bewteen the */ + /* Unix time and the module list, then return all 4 params. */ + lua_pushinteger(L, (lua_Integer) flashAddr); + lua_insert(L, 2); + lua_pushinteger(L, flashAddrPhys); + lua_insert(L, 3); + lua_pushinteger(L, cast(FlashHeader *, flashAddr)->flash_size); + lua_insert(L, 4); + return 5; +} + +#ifndef CONFIG_LUA_EMBEDDED_FLASH_STORE +/* ===================================================================================== + * The following routines use my uzlib which was based on pfalcon's inflate and + * deflate routines. The standard NodeMCU make also makes two host tools uz_zip + * and uz_unzip which also use these and luac.cross uses the deflate. As discussed + * below, The main action routine loadLFS() calls uzlib_inflate() to do the actual + * stream inflation but uses three supplied CBs to abstract input and output + * stream handling. + * + * ESP8266 RAM limitations and heap fragmentation are a key implementation + * constraint and hence these routines use a number of ~2K buffers (11) as + * working storage. + * + * The inflate is done twice, in order to limit storage use and avoid forward / + * backward reference issues. However this has a major advantage that the LFS + * is scanned with the headers, CRC, etc. validated BEFORE the write to flash + * is started, so the only real chance of failure during the second pass + * write is if a power fail occurs during the pass. + */ + +static void flash_error(const char *err) { + if (out) + out->error = err; + if (in && in->inflate_state) + uz_free(in->inflate_state); + lua_pushnil(out->L); /* can't use it on a cpcall anyway */ + lua_error(out->L); +} + +/* + * uzlib_inflate does a stream inflate on an RFC 1951 encoded data stream. + * It uses three application-specific CBs passed in the call to do the work: + * + * - get_byte() CB to return next byte in input stream + * - put_byte() CB to output byte to output buffer + * - recall_byte() CB to output byte to retrieve a historic byte from + * the output buffer. + * + * Note that put_byte() also triggers secondary CBs to do further processing. + */ +static uint8_t get_byte (void) { + if (--in->left < 0) { + /* Read next input block */ + int remaining = in->len - in->bytesRead; + int wanted = remaining >= READ_BLOCKSIZE ? READ_BLOCKSIZE : remaining; + + if (vfs_read(in->fd, in->block, wanted) != wanted) + flash_error("read error on LFS image file"); + + platform_wdt_feed(); + + in->bytesRead += wanted; + in->inPtr = in->block; + in->left = wanted-1; + } + return *in->inPtr++; +} + + +static void put_byte (uint8_t value) { + int offset = out->ndx % WRITE_BLOCKSIZE; /* counts from 0 */ + + out->block[0]->byte[offset++] = value; + out->ndx++; + + if (offset == WRITE_BLOCKSIZE || out->ndx == out->len) { + if (out->fullBlkCB) + out->fullBlkCB(); + /* circular shift the block pointers (redundant on last block, but so what) */ + outBlock *nextBlock = out->block[WRITE_BLOCKS - 1]; + memmove(out->block+1, out->block, (WRITE_BLOCKS-1)*sizeof(void*)); + out->block[0] = nextBlock ; + } +} + + +static uint8_t recall_byte (uint offset) { + if(offset > DICTIONARY_WINDOW || offset >= out->ndx) + flash_error("invalid dictionary offset on inflate"); + /* ndx starts at 1. Need relative to 0 */ + uint n = out->ndx - offset; + uint pos = n % WRITE_BLOCKSIZE; + uint blockNo = out->ndx / WRITE_BLOCKSIZE - n / WRITE_BLOCKSIZE; + return out->block[blockNo]->byte[pos]; +} + +/* + * On the first pass the break index is set to call this process at the end + * of each completed output buffer. + * - On the first call, the Flash Header is checked. + * - On each call the CRC is rolled up for that buffer. + * - Once the flags array is in-buffer this is also captured. + * This logic is slightly complicated by the last buffer is typically short. + */ +int procFirstPass (void) { + int len = (out->ndx % WRITE_BLOCKSIZE) ? + out->ndx % WRITE_BLOCKSIZE : WRITE_BLOCKSIZE; + if (out->ndx <= WRITE_BLOCKSIZE) { + /* Process the flash header and cache the FlashHeader fields we need */ + FlashHeader *fh = cast(FlashHeader *, out->block[0]); + out->flashLen = fh->flash_size; /* in bytes */ + out->flagsLen = (out->len-fh->flash_size)/WORDSIZE; /* in words */ + out->flash_sig = fh->flash_sig; + + if ((fh->flash_sig & FLASH_FORMAT_MASK) != FLASH_FORMAT_VERSION) + flash_error("Incorrect LFS header version"); + if ((fh->flash_sig & FLASH_SIG_B2_MASK) != FLASH_SIG_B2) + flash_error("Incorrect LFS build type"); + if ((fh->flash_sig & ~FLASH_SIG_ABSOLUTE) != FLASH_SIG) + flash_error("incorrect LFS header signature"); + if (fh->flash_size > flashSize) + flash_error("LFS Image too big for configured LFS region"); + if ((fh->flash_size & 0x3) || + fh->flash_size > flashSize || + out->flagsLen != 1 + (out->flashLen/WORDSIZE - 1) / BITS_PER_WORD) + flash_error("LFS length mismatch"); + out->flags = luaM_newvector(out->L, out->flagsLen, uint); + } + + /* update running CRC */ + out->crc = uzlib_crc32(out->block[0], len, out->crc); + + /* copy out any flag vector */ + if (out->ndx > out->flashLen) { + int start = out->flashLen - (out->ndx - len); + if (start < 0) start = 0; + memcpy(out->flags + out->flagsNdx, out->block[0]->byte + start, len - start); + out->flagsNdx += (len -start) / WORDSIZE; /* flashLen and len are word aligned */ + } + + return 1; +} + + +int procSecondPass (void) { + /* + * The length rules are different for the second pass since this only processes + * upto the flashLen and not the full image. This also works in word units. + * (We've already validated these are word multiples.) + */ + int i, len = (out->ndx > out->flashLen) ? + (out->flashLen % WRITE_BLOCKSIZE) / WORDSIZE : + WRITE_BLOCKSIZE / WORDSIZE; + uint32_t *buf = (uint32_t *) out->buffer.byte; + uint32_t flags = 0; + /* + * Relocate all the addresses tagged in out->flags. This can't be done in + * place because the out->blocks are still in use as dictionary content so + * first copy the block to a working buffer and do the relocation in this. + */ + memcpy(out->buffer.byte, out->block[0]->byte, WRITE_BLOCKSIZE); + for (i=0; i>=1 ) { + if ((i&31)==0) + flags = out->flags[out->flagsNdx++]; + if (flags&1) + buf[i] = WORDSIZE*buf[i] + cast(uint32_t, flashAddr); // mapped, not phys + } + /* + * On first block, set the flash_sig has the in progress bit set and this + * is not cleared until end. + */ + if (out->ndx <= WRITE_BLOCKSIZE) + buf[0] = out->flash_sig | FLASH_SIG_IN_PROGRESS; + + flashBlock(buf, len*WORDSIZE); + + if (out->ndx >= out->flashLen) { + /* we're done so disable CB and rewrite flash sig to complete flash */ + flashSetPosition(0); + flashBlock(&out->flash_sig, WORDSIZE); + out->fullBlkCB = NULL; + } + + return 1; +} + +/* + * loadLFS)() is protected called from luaN_reload_reboot so that it can recover + * from out of memory and other thrown errors. loadLFSgc() GCs any resources. + */ +static int loadLFS (lua_State *L) { + const char *fn = cast(const char *, lua_touserdata(L, 1)); + int i, res; + uint32_t crc; + + /* Allocate and zero in and out structures */ + + in = NULL; out = NULL; + in = luaM_new(L, struct INPUT); + memset(in, 0, sizeof(*in)); + out = luaM_new(L, struct OUTPUT); + memset(out, 0, sizeof(*out)); + out->L = L; + out->fullBlkCB = procFirstPass; + out->crc = ~0; + + /* Open LFS image/ file, read unpacked length from last 4 byte and rewind */ + if (!(in->fd = vfs_open(fn, "r"))) + flash_error("LFS image file not found"); + in->len = vfs_size(in->fd); + if (in->len <= 200 || /* size of an empty luac output */ + vfs_lseek(in->fd, in->len-4, VFS_SEEK_SET) != in->len-4 || + vfs_read(in->fd, &out->len, sizeof(uint)) != sizeof(uint)) + flash_error("read error on LFS image file"); + vfs_lseek(in->fd, 0, VFS_SEEK_SET); + + /* Allocate the out buffers */ + for(i = 0; i < WRITE_BLOCKS; i++) + out->block[i] = luaM_new(L, outBlock); + + /* first inflate pass */ + if (uzlib_inflate (get_byte, put_byte, recall_byte, + in->len, &crc, &in->inflate_state) < 0) + flash_error("read error on LFS image file"); + + if (crc != ~out->crc) + flash_error("checksum error on LFS image file"); + + out->fullBlkCB = procSecondPass; + out->flagsNdx = 0; + out->ndx = 0; + in->bytesRead = in->left = 0; + /* + * Once we have completed the 1st pass then the LFS image has passed the + * basic signature, crc and length checks, so now we can reset the counts + * to do the actual write to flash on the second pass. + */ + vfs_lseek(in->fd, 0, VFS_SEEK_SET); + flashErase(0,(out->flashLen - 1)/FLASH_PAGE_SIZE); + flashSetPosition(0); + + res = uzlib_inflate(get_byte, put_byte, recall_byte, + in->len, &crc, &in->inflate_state); + if (res < 0) { // UZLIB_OK == 0, UZLIB_DONE == 1 + const char *err[] = {"Data_error during decompression", + "Chksum_error during decompression", + "Dictionary error during decompression", + "Memory_error during decompression"}; + flash_error(err[UZLIB_DATA_ERROR - res]); + } + return 0; +} + + +static int loadLFSgc (lua_State *L) { + int i; + if (out) { + for (i = 0; i < WRITE_BLOCKS; i++) + if (out->block[i]) + luaM_free(L, out->block[i]); + if (out->flags) + luaM_freearray(L, out->flags, out->flagsLen, uint32_t); + luaM_free(L, out); + } + if (in) { + if (in->fd) + vfs_close(in->fd); + luaM_free(L, in); + } + return 0; +} +#endif diff --git a/components/lua/lflash.h b/components/lua/lflash.h new file mode 100644 index 0000000000..722d0f3605 --- /dev/null +++ b/components/lua/lflash.h @@ -0,0 +1,50 @@ +/* +** lflashe.h +** See Copyright Notice in lua.h +*/ + +#ifndef lflash_h +#define lflash_h + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + +#ifdef LUA_NUMBER_INTEGRAL +# define FLASH_SIG_B1 0x02 +#else +# define FLASH_SIG_B1 0x00 +#endif +#define FLASH_FORMAT_VERSION (1 << 8) +#define FLASH_FORMAT_MASK 0xF00 +#ifdef LUA_PACK_TVALUES +#ifdef LUA_NUMBER_INTEGRAL +#error "LUA_PACK_TVALUES is only valid for Floating point builds" +#endif +# define FLASH_SIG_B2 0x04 +#else +# define FLASH_SIG_B2 0x00 +#endif +# define FLASH_SIG_B2_MASK 0x04 +#define FLASH_SIG_ABSOLUTE 0x01 +#define FLASH_SIG_IN_PROGRESS 0x08 +#define FLASH_SIG (0xfafaa050 | FLASH_FORMAT_VERSION |FLASH_SIG_B2 | FLASH_SIG_B1) + +typedef lu_int32 FlashAddr; +typedef struct { + lu_int32 flash_sig; /* a stabdard fingerprint identifying an LFS image */ + lu_int32 flash_size; /* Size of LFS image */ + FlashAddr mainProto; /* address of main Proto in Proto hierarchy */ + FlashAddr pROhash; /* address of ROstrt hash */ + lu_int32 nROuse; /* number of elements in ROstrt */ + int nROsize; /* size of ROstrt */ + lu_int32 fill1; /* reserved */ + lu_int32 fill2; /* reserved */ +} FlashHeader; + +LUAI_FUNC void luaN_init (lua_State *L); +LUAI_FUNC int luaN_flashSetup (lua_State *L); +LUAI_FUNC int luaN_reload_reboot (lua_State *L); +LUAI_FUNC int luaN_index (lua_State *L); +#endif + diff --git a/components/lua/lfunc.c b/components/lua/lfunc.c index 104643f6f6..a9c6e2d964 100644 --- a/components/lua/lfunc.c +++ b/components/lua/lfunc.c @@ -9,7 +9,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lfunc.h" #include "lgc.h" @@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->k, f->sizek, TValue); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); - if (!proto_is_readonly(f)) { + if (!proto_isreadonly(f)) { luaM_freearray(L, f->code, f->sizecode, Instruction); #ifdef LUA_OPTIMIZE_DEBUG if (f->packedlineinfo) { diff --git a/components/lua/lfunc.h b/components/lua/lfunc.h index 1450bb7d91..2dc7266b6a 100644 --- a/components/lua/lfunc.h +++ b/components/lua/lfunc.h @@ -18,9 +18,6 @@ #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ cast(int, sizeof(TValue *)*((n)-1))) -#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT) -#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT) - LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); diff --git a/components/lua/lgc.c b/components/lua/lgc.c index c1da493513..044f66abf0 100644 --- a/components/lua/lgc.c +++ b/components/lua/lgc.c @@ -9,7 +9,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "ldebug.h" #include "ldo.h" @@ -37,10 +37,10 @@ #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) +#define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);} -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define isfinalized(u) testbit(getmarked(u), FINALIZEDBIT) #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) @@ -61,15 +61,21 @@ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) + if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n))) +// The gkey is always in RAM so it can be marked as DEAD even though it +// refers to an LFS object. setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ } static void reallymarkobject (global_State *g, GCObject *o) { + /* don't mark LFS Protos (or strings) */ + if (gettt(&o->gch) == LUA_TPROTO && isLFSobject(&(o->gch))) + return; + lua_assert(iswhite(o) && !isdead(g, o)); white2gray(o); - switch (o->gch.tt) { + switch (gettt(&o->gch)) { case LUA_TSTRING: { return; } @@ -159,10 +165,14 @@ static int traversetable (global_State *g, Table *h) { int i; int weakkey = 0; int weakvalue = 0; - const TValue *mode; - if (h->metatable && !luaR_isrotable(h->metatable)) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); + const TValue *mode = luaO_nilobject; + + if (h->metatable) { + if (!luaR_isrotable(h->metatable)) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + } + if (mode && ttisstring(mode)) { /* is there a weak mode? */ weakkey = (strchr(svalue(mode), 'k') != NULL); weakvalue = (strchr(svalue(mode), 'v') != NULL); @@ -180,6 +190,8 @@ static int traversetable (global_State *g, Table *h) { while (i--) markvalue(g, &h->array[i]); } + if (luaH_isdummy (h->node)) + return weakkey || weakvalue; i = sizenode(h); while (i--) { Node *n = gnode(h, i); @@ -202,6 +214,8 @@ static int traversetable (global_State *g, Table *h) { */ static void traverseproto (global_State *g, Proto *f) { int i; + if (isLFSobject(f)) + return; /* don't traverse Protos in LFS */ if (f->source) stringmark(f->source); for (i=0; isizek; i++) /* mark literals */ markvalue(g, &f->k[i]); @@ -282,7 +296,7 @@ static l_mem propagatemark (global_State *g) { GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); - switch (o->gch.tt) { + switch (gettt(&o->gch)) { case LUA_TTABLE: { Table *h = gco2h(o); g->gray = h->gclist; @@ -317,7 +331,7 @@ static l_mem propagatemark (global_State *g) { sizeof(TValue) * p->sizek + sizeof(LocVar) * p->sizelocvars + sizeof(TString *) * p->sizeupvalues + - (proto_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode + + (proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode + #ifdef LUA_OPTIMIZE_DEBUG (p->packedlineinfo ? strlen(cast(char *, p->packedlineinfo))+1 : @@ -387,8 +401,11 @@ static void cleartable (GCObject *l) { static void freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + switch (gettt(&o->gch)) { + case LUA_TPROTO: + lua_assert(!isLFSobject(&(o->gch))); + luaF_freeproto(L, gco2p(o)); + break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; @@ -398,6 +415,7 @@ static void freeobj (lua_State *L, GCObject *o) { break; } case LUA_TSTRING: { + lua_assert(!isLFSobject(&(o->gch))); G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; @@ -420,6 +438,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { + lua_assert(!isLFSobject(&(curr->gch)) || curr->gch.tt == LUA_TTHREAD); if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ sweepwholelist(L, &gco2th(curr)->openupval); if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ @@ -538,7 +557,7 @@ static void atomic (lua_State *L) { size_t udsize; /* total size of userdata to be finalized */ /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); - /* traverse objects cautch by write barrier and by 'remarkupvals' */ + /* traverse objects caucht by write barrier and by 'remarkupvals' */ propagateall(g); /* remark weak tables */ g->gray = g->weak; @@ -694,10 +713,10 @@ void luaC_barrierf (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 != GCSfinalize && g->gcstate != GCSpause); - lua_assert(ttype(&o->gch) != LUA_TTABLE); + lua_assert(o->gch.tt != LUA_TTABLE); /* must keep invariant? */ if (g->gcstate == GCSpropagate) - reallymarkobject(g, v); /* restore invariant */ + reallymarkobject(g, v); /* Restore invariant */ else /* don't mind */ makewhite(g, o); /* mark as white just to avoid other barriers */ } diff --git a/components/lua/lgc.h b/components/lua/lgc.h index 9c26932b46..bf47909bd2 100644 --- a/components/lua/lgc.h +++ b/components/lua/lgc.h @@ -79,6 +79,7 @@ #define VALUEWEAKBIT 4 #define FIXEDBIT 5 #define SFIXEDBIT 6 +#define LFSBIT 6 #define READONLYBIT 7 #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) @@ -100,6 +101,13 @@ #define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT) #define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT) #define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT) +#ifndef LUA_CROSS_COMPILER +#define isLFSobject(x) testbit(getmarked(x), LFSBIT) +#define stringfix(s) if (!test2bits(getmarked(&(s)->tsv), FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);} +#else +#define isLFSobject(x) (0) +#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);} +#endif #define luaC_checkGC(L) { \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ diff --git a/components/lua/liolib.c b/components/lua/liolib.c deleted file mode 100644 index ad4d5d4b34..0000000000 --- a/components/lua/liolib.c +++ /dev/null @@ -1,662 +0,0 @@ -/* -** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -// #include -#include -#include -#include -#include "vfs.h" - -#define liolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" -#include "lrotable.h" - - -#define IO_INPUT 1 -#define IO_OUTPUT 2 -#define IO_STDERR 0 - -#if LUA_OPTIMIZE_MEMORY != 2 -#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_ENVIRONINDEX, f) -#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_ENVIRONINDEX, f) -#else -#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX, liolib_keys[f]) -#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[f]) - -/* "Pseudo-random" keys for the registry */ -static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int)&luaL_argerror}; -#endif - -static const char *const fnames[] = {"input", "output"}; - -static int pushresult (lua_State *L, int i, const char *filename) { - int en = vfs_ferrno(0); /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (filename) - lua_pushfstring(L, "%s: err(%d)", filename, en); - else - lua_pushfstring(L, "err(%d)", en); - lua_pushinteger(L, en); - return 3; - } -} - - -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: err(%d)", filename, vfs_ferrno(0)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} - - -#define tofilep(L) ((int *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - - -static int io_type (lua_State *L) { - void *ud; - luaL_checkany(L, 1); - ud = lua_touserdata(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); - if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) - lua_pushnil(L); /* not a file */ - else if (*((int *)ud) < FS_OPEN_OK) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static int tofile (lua_State *L) { - int *f = tofilep(L); - if (*f < FS_OPEN_OK) - luaL_error(L, "attempt to use a closed file"); - return *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 int *newfile (lua_State *L) { - int *pf = (int *)lua_newuserdata(L, sizeof(int)); - *pf = FS_OPEN_OK - 1; /* file handle is currently `closed' */ - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - return pf; -} - - -#if LUA_OPTIMIZE_MEMORY != 2 -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - -#if 0 -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - int *p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = FS_OPEN_OK - 1; - return pushresult(L, ok, NULL); -} -#endif - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - int *p = tofilep(L); - int ok = (vfs_close(*p) == 0); - *p = FS_OPEN_OK - 1; - return pushresult(L, ok, NULL); -} -#endif - -static int aux_close (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY != 2 - lua_getfenv(L, 1); - lua_getfield(L, -1, "__close"); - return (lua_tocfunction(L, -1))(L); -#else - int *p = tofilep(L); - if(*p == fileno(stdin) || *p == fileno(stdout) || *p == fileno(stderr)) - { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; - } - int ok = (vfs_close(*p) == 0); - *p = FS_OPEN_OK - 1; - return pushresult(L, ok, NULL); -#endif -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) - LUA_IO_GETFIELD(IO_OUTPUT); - tofile(L); /* make sure argument is a file */ - return aux_close(L); -} - - -static int io_gc (lua_State *L) { - int f = *tofilep(L); - /* ignore closed files */ - if (f != FS_OPEN_OK - 1) - aux_close(L); - return 0; -} - - -static int io_tostring (lua_State *L) { - int f = *tofilep(L); - if (f == FS_OPEN_OK - 1) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%i)", f); - return 1; -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - int *pf = newfile(L); - *pf = vfs_open(filename, mode); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; -} - - -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -#if 0 -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - int *pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - int *pf = newfile(L); - *pf = tmpfile(); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, NULL) : 1; -} -#endif - -static int getiofile (lua_State *L, int findex) { - int *pf; - LUA_IO_GETFIELD(findex); - pf = (int *)lua_touserdata(L, -1); - if (pf == NULL || *pf == FS_OPEN_OK - 1){ - luaL_error(L, "default %s file is closed", fnames[findex - 1]); - return FS_OPEN_OK - 1; - } - return *pf; -} - - -static int g_iofile (lua_State *L, int f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) { - int *pf = newfile(L); - *pf = vfs_open(filename, mode); - if (*pf == FS_OPEN_OK - 1) - fileerror(L, 1, filename); - } - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - LUA_IO_SETFIELD(f); - } - /* return current value */ - LUA_IO_GETFIELD(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 idx, int toclose) { - lua_pushvalue(L, idx); - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 2); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - /* will iterate over default input */ - LUA_IO_GETFIELD(IO_INPUT); - return f_lines(L); - } - else { - const char *filename = luaL_checkstring(L, 1); - int *pf = newfile(L); - *pf = vfs_open(filename, "r"); - if (*pf == FS_OPEN_OK - 1) - fileerror(L, 1, filename); - aux_lines(L, lua_gettop(L), 1); - return 1; - } -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - -#if 0 -static int read_number (lua_State *L, int f) { - lua_Number d; - if (vfs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} -#endif - -static int test_eof (lua_State *L, int f) { - int c = vfs_getc(f); - vfs_ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - -#if 0 -static int read_line (lua_State *L, int f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (vfs_gets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(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 - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} -#else -static int read_line (lua_State *L, int f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - char *p = luaL_prepbuffer(&b); - signed char c = EOF; - int i = 0; - do{ - c = (signed char)vfs_getc(f); - if(c==EOF){ - break; - } - p[i++] = c; - }while((c!=EOF) && (c!='\n') && (i0 && p[i-1] == '\n') - i--; /* do not include `eol' */ - - if(i==0){ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ - } - - luaL_addsize(&b, i); - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ -} -#endif - -static int read_chars (lua_State *L, int f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ - luaL_Buffer b; - luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { - char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = vfs_read(f, p, rlen); - luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); -} - - -static int g_read (lua_State *L, int f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - //vfs_clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); - 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]) { -#if 0 - case 'n': /* number */ - success = read_number(L, f); - break; -#endif - case 'l': /* line */ - success = read_line(L, f); - break; - case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (vfs_ferrno(f)) - return pushresult(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) { - int *pf = (int *)lua_touserdata(L, lua_upvalueindex(1)); - int sucess; - if (pf == NULL || *pf == FS_OPEN_OK - 1){ /* file is already closed? */ - luaL_error(L, "file is already closed"); - return 0; - } - sucess = read_line(L, *pf); - if (vfs_ferrno(*pf)) - return luaL_error(L, "err(%d)", vfs_ferrno(*pf)); - if (sucess) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(2))) { /* 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, int f, int arg) { - int nargs = lua_gettop(L) - 1; - int status = 1; - for (; nargs--; arg++) { -#if 0 - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - vfs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else -#endif - { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (vfs_write(f, s, l) == l); - } - } - return pushresult(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) { - return g_write(L, tofile(L), 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - int f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = vfs_lseek(f, offset, mode[op]); - if (op) - return pushresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, vfs_tell(f)); - return 1; - } -} - -#if 0 -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - int 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 pushresult(L, res == 0, NULL); -} -#endif - - -static int io_flush (lua_State *L) { - return pushresult(L, vfs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return pushresult(L, vfs_flush(tofile(L)) == 0, NULL); -} - -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 2 -#include "lrodefs.h" -#if LUA_OPTIMIZE_MEMORY == 2 -const LUA_REG_TYPE iolib_funcs[] = { -#else -const LUA_REG_TYPE iolib[] = { -#endif - {LSTRKEY("close"), LFUNCVAL(io_close)}, - {LSTRKEY("flush"), LFUNCVAL(io_flush)}, - {LSTRKEY("input"), LFUNCVAL(io_input)}, - {LSTRKEY("lines"), LFUNCVAL(io_lines)}, - {LSTRKEY("open"), LFUNCVAL(io_open)}, - {LSTRKEY("output"), LFUNCVAL(io_output)}, - // {LSTRKEY("popen"), LFUNCVAL(io_popen)}, - {LSTRKEY("read"), LFUNCVAL(io_read)}, - // {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)}, - {LSTRKEY("type"), LFUNCVAL(io_type)}, - {LSTRKEY("write"), LFUNCVAL(io_write)}, - {LNILKEY, LNILVAL} -}; - -#if LUA_OPTIMIZE_MEMORY == 2 -static int luaL_index(lua_State *L) -{ - return luaR_findfunction(L, iolib_funcs); -} - -const luaL_Reg iolib[] = { - {"__index", luaL_index}, - {NULL, NULL} -}; -#endif - -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE flib[] = { - {LSTRKEY("close"), LFUNCVAL(io_close)}, - {LSTRKEY("flush"), LFUNCVAL(f_flush)}, - {LSTRKEY("lines"), LFUNCVAL(f_lines)}, - {LSTRKEY("read"), LFUNCVAL(f_read)}, - {LSTRKEY("seek"), LFUNCVAL(f_seek)}, - // {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)}, - {LSTRKEY("write"), LFUNCVAL(f_write)}, - {LSTRKEY("__gc"), LFUNCVAL(io_gc)}, - {LSTRKEY("__tostring"), LFUNCVAL(io_tostring)}, -#if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("__index"), LROVAL(flib)}, -#endif - {LNILKEY, LNILVAL} -}; - -static void createmeta (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY == 0 - 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_register(L, NULL, flib); /* file methods */ -#else - luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ -#endif -} - - -#if 0 -static void createstdfile (lua_State *L, int f, int k, const char *fname) { - *newfile(L) = f; -#if LUA_OPTIMIZE_MEMORY != 2 - if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); - } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); -#else - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[k]); - lua_setfield(L, -2, fname); -#endif -} -#endif - -#if LUA_OPTIMIZE_MEMORY != 2 -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); -} -#endif - -LUALIB_API int luaopen_io (lua_State *L) { - createmeta(L); -#if LUA_OPTIMIZE_MEMORY != 2 - /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); - newfenv(L, io_noclose); /* close function for default files */ -#else - luaL_register_light(L, LUA_IOLIBNAME, iolib); - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); -#endif -#if 0 - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, IO_STDERR, "stderr"); - -#if LUA_OPTIMIZE_MEMORY != 2 - lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ -#endif -#endif - return 1; -} diff --git a/components/lua/llex.c b/components/lua/llex.c index 538a822a1f..4a8edbc383 100644 --- a/components/lua/llex.c +++ b/components/lua/llex.c @@ -10,9 +10,9 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_CTYPE -#include C_HEADER_LOCALE -#include C_HEADER_STRING +#include +#include +#include #include "ldo.h" #include "llex.h" diff --git a/components/lua/lmathlib.c b/components/lua/lmathlib.c index 342df2ecef..26967652b9 100644 --- a/components/lua/lmathlib.c +++ b/components/lua/lmathlib.c @@ -10,8 +10,8 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDLIB -#include C_HEADER_MATH +#include +#include #include "lauxlib.h" #include "lualib.h" @@ -309,92 +309,57 @@ static int math_randomseed (lua_State *L) { return 0; } - - -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE math_map[] = { +LROT_PUBLIC_BEGIN(math) #ifdef LUA_NUMBER_INTEGRAL - {LSTRKEY("abs"), LFUNCVAL(math_abs)}, - {LSTRKEY("ceil"), LFUNCVAL(math_identity)}, - {LSTRKEY("floor"), LFUNCVAL(math_identity)}, - {LSTRKEY("max"), LFUNCVAL(math_max)}, - {LSTRKEY("min"), LFUNCVAL(math_min)}, - {LSTRKEY("pow"), LFUNCVAL(math_pow)}, - {LSTRKEY("random"), LFUNCVAL(math_random)}, - {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)}, - {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)}, -#if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("huge"), LNUMVAL(LONG_MAX)}, -#endif + LROT_FUNCENTRY( abs, math_abs ) + LROT_FUNCENTRY( ceil, math_identity ) + LROT_FUNCENTRY( floor, math_identity ) + LROT_FUNCENTRY( max, math_max ) + LROT_FUNCENTRY( min, math_min ) + LROT_FUNCENTRY( pow, math_pow ) + LROT_FUNCENTRY( random, math_random ) + LROT_FUNCENTRY( randomseed, math_randomseed ) + LROT_FUNCENTRY( sqrt, math_sqrt ) + LROT_NUMENTRY( huge, INT_MAX ) #else - {LSTRKEY("abs"), LFUNCVAL(math_abs)}, - // {LSTRKEY("acos"), LFUNCVAL(math_acos)}, - // {LSTRKEY("asin"), LFUNCVAL(math_asin)}, - // {LSTRKEY("atan2"), LFUNCVAL(math_atan2)}, - // {LSTRKEY("atan"), LFUNCVAL(math_atan)}, - {LSTRKEY("ceil"), LFUNCVAL(math_ceil)}, - // {LSTRKEY("cosh"), LFUNCVAL(math_cosh)}, - // {LSTRKEY("cos"), LFUNCVAL(math_cos)}, - // {LSTRKEY("deg"), LFUNCVAL(math_deg)}, - // {LSTRKEY("exp"), LFUNCVAL(math_exp)}, - {LSTRKEY("floor"), LFUNCVAL(math_floor)}, - // {LSTRKEY("fmod"), LFUNCVAL(math_fmod)}, -#if LUA_OPTIMIZE_MEMORY > 0 && defined(LUA_COMPAT_MOD) - // {LSTRKEY("mod"), LFUNCVAL(math_fmod)}, -#endif - // {LSTRKEY("frexp"), LFUNCVAL(math_frexp)}, - // {LSTRKEY("ldexp"), LFUNCVAL(math_ldexp)}, - // {LSTRKEY("log10"), LFUNCVAL(math_log10)}, - // {LSTRKEY("log"), LFUNCVAL(math_log)}, - {LSTRKEY("max"), LFUNCVAL(math_max)}, - {LSTRKEY("min"), LFUNCVAL(math_min)}, - // {LSTRKEY("modf"), LFUNCVAL(math_modf)}, - {LSTRKEY("pow"), LFUNCVAL(math_pow)}, - // {LSTRKEY("rad"), LFUNCVAL(math_rad)}, - {LSTRKEY("random"), LFUNCVAL(math_random)}, - {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)}, - // {LSTRKEY("sinh"), LFUNCVAL(math_sinh)}, - // {LSTRKEY("sin"), LFUNCVAL(math_sin)}, - {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)}, - // {LSTRKEY("tanh"), LFUNCVAL(math_tanh)}, - // {LSTRKEY("tan"), LFUNCVAL(math_tan)}, -#if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("pi"), LNUMVAL(PI)}, - {LSTRKEY("huge"), LNUMVAL(HUGE_VAL)}, -#endif // #if LUA_OPTIMIZE_MEMORY > 0 + LROT_FUNCENTRY( abs, math_abs ) +// LROT_FUNCENTRY( acos, math_acos ) +// LROT_FUNCENTRY( asin, math_asin ) +// LROT_FUNCENTRY( atan2, math_atan2 ) +// LROT_FUNCENTRY( atan, math_atan ) + LROT_FUNCENTRY( ceil, math_ceil ) +// LROT_FUNCENTRY( cosh, math_cosh ) +// LROT_FUNCENTRY( cos, math_cos ) +// LROT_FUNCENTRY( deg, math_deg ) +// LROT_FUNCENTRY( exp, math_exp ) + LROT_FUNCENTRY( floor, math_floor ) +// LROT_FUNCENTRY( fmod, math_fmod ) +// LROT_FUNCENTRY( mod, math_fmod ) +// LROT_FUNCENTRY( frexp, math_frexp ) +// LROT_FUNCENTRY( ldexp, math_ldexp ) +// LROT_FUNCENTRY( log10, math_log10 ) +// LROT_FUNCENTRY( log, math_log ) + LROT_FUNCENTRY( max, math_max ) + LROT_FUNCENTRY( min, math_min ) +// LROT_FUNCENTRY( modf, math_modf ) + LROT_FUNCENTRY( pow, math_pow ) +// LROT_FUNCENTRY( rad, math_rad ) + LROT_FUNCENTRY( random, math_random ) + LROT_FUNCENTRY( randomseed, math_randomseed ) +// LROT_FUNCENTRY( sinh, math_sinh ) +// LROT_FUNCENTRY( sin, math_sin ) + LROT_FUNCENTRY( sqrt, math_sqrt ) +// LROT_FUNCENTRY( tanh, math_tanh ) +// LROT_FUNCENTRY( tan, math_tan ) + LROT_NUMENTRY( pi, PI ) + LROT_NUMENTRY( huge, HUGE_VAL ) #endif // #ifdef LUA_NUMBER_INTEGRAL - {LNILKEY, LNILVAL} -}; +LROT_END(math, NULL, 0) /* ** Open math library */ - -#if defined LUA_NUMBER_INTEGRAL -# include /* for LONG_MAX */ -#endif - LUALIB_API int luaopen_math (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY > 0 return 0; -#else - luaL_register(L, LUA_MATHLIBNAME, math_map); -# if defined LUA_NUMBER_INTEGRAL - lua_pushnumber(L, LONG_MAX); - lua_setfield(L, -2, "huge"); -# else - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); -# if defined(LUA_COMPAT_MOD) - lua_getfield(L, -1, "fmod"); - lua_setfield(L, -2, "mod"); -# endif -# endif - return 1; -#endif } diff --git a/components/lua/loadlib.c b/components/lua/loadlib.c index 63ceb595e2..ab56776bf8 100644 --- a/components/lua/loadlib.c +++ b/components/lua/loadlib.c @@ -20,7 +20,6 @@ #ifndef LUA_CROSS_COMPILER #include "vfs.h" -#include "c_stdlib.h" // for c_getenv #endif #include "lauxlib.h" @@ -334,9 +333,9 @@ static int ll_loadlib (lua_State *L) { */ #ifdef LUA_CROSS_COMPILER static int readable (const char *filename) { - FILE *f = c_fopen(filename, "r"); /* try to open file */ + FILE *f = fopen(filename, "r"); /* try to open file */ if (f == NULL) return 0; /* open failed */ - c_fclose(f); + fclose(f); return 1; } #else @@ -363,7 +362,9 @@ static const char * findfile (lua_State *L, const char *name, const char *pname) { const char *path; name = luaL_gsub(L, name, ".", LUA_DIRSEP); - lua_getfield(L, LUA_ENVIRONINDEX, pname); + lua_getfield(L, LUA_GLOBALSINDEX, "package"); + lua_getfield(L, -1, pname); + lua_remove(L, -2); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); @@ -449,7 +450,9 @@ static int loader_Croot (lua_State *L) { static int loader_preload (lua_State *L) { const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + lua_getfield(L, LUA_GLOBALSINDEX, "package"); + lua_getfield(L, -1, "preload"); + lua_remove(L, -2); if (!lua_istable(L, -1)) luaL_error(L, LUA_QL("package.preload") " must be a table"); lua_getfield(L, -1, name); @@ -475,13 +478,16 @@ static int ll_require (lua_State *L) { return 1; /* package is already loaded */ } /* Is this a readonly table? */ - void *res = luaR_findglobal(name, strlen(name)); - if (res) { - lua_pushrotable(L, res); + lua_getfield(L, LUA_GLOBALSINDEX, name); + if(lua_isrotable(L,-1)) { return 1; + } else { + lua_pop(L, 1); } /* else must load it; iterate over available loaders */ - lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + lua_getfield(L, LUA_GLOBALSINDEX, "package"); + lua_getfield(L, -1, "loaders"); + lua_remove(L, -2); if (!lua_istable(L, -1)) luaL_error(L, LUA_QL("package.loaders") " must be a table"); lua_pushliteral(L, ""); /* error message accumulator */ @@ -564,8 +570,13 @@ static void modinit (lua_State *L, const char *modname) { static int ll_module (lua_State *L) { const char *modname = luaL_checkstring(L, 1); - if (luaR_findglobal(modname, strlen(modname))) + /* Is this a readonly table? */ + lua_getfield(L, LUA_GLOBALSINDEX, modname); + if(lua_isrotable(L,-1)) { return 0; + } else { + lua_pop(L, 1); + } int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ @@ -614,7 +625,7 @@ static int ll_seeall (lua_State *L) { static void setpath (lua_State *L, const char *fieldname, const char *envname, const char *def) { - const char *path = c_getenv(envname); + const char *path = NULL; /* getenv(envname) not used in NodeMCU */; if (path == NULL) /* no environment variable? */ lua_pushstring(L, def); /* use default */ else { @@ -646,34 +657,20 @@ static const luaL_Reg ll_funcs[] = { static const lua_CFunction loaders[] = {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; -#if LUA_OPTIMIZE_MEMORY > 0 -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE lmt[] = { - {LRO_STRKEY("__gc"), LRO_FUNCVAL(gctm)}, - {LRO_NILKEY, LRO_NILVAL} -}; -#endif +LROT_PUBLIC_BEGIN(lmt) + LROT_FUNCENTRY(__gc,gctm) +LROT_END(lmt,lmt, LROT_MASK_GC) LUALIB_API int luaopen_package (lua_State *L) { int i; /* create new type _LOADLIB */ -#if LUA_OPTIMIZE_MEMORY == 0 - luaL_newmetatable(L, "_LOADLIB"); - lua_pushlightfunction(L, gctm); - lua_setfield(L, -2, "__gc"); -#else - luaL_rometatable(L, "_LOADLIB", (void*)lmt); -#endif + luaL_rometatable(L, "_LOADLIB",LROT_TABLEREF(lmt)); /* create `package' table */ luaL_register_light(L, LUA_LOADLIBNAME, pk_funcs); -#if defined(LUA_COMPAT_LOADLIB) +#if defined(LUA_COMPAT_LOADLIB) lua_getfield(L, -1, "loadlib"); lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); #endif - lua_pushvalue(L, -1); - lua_replace(L, LUA_ENVIRONINDEX); /* create `loaders' table */ lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); /* fill it with pre-defined loaders */ diff --git a/components/lua/lobject.c b/components/lua/lobject.c index 7504ac196b..93f1202a8f 100644 --- a/components/lua/lobject.c +++ b/components/lua/lobject.c @@ -54,6 +54,7 @@ int luaO_fb2int (int x) { int luaO_log2 (unsigned int x) { +#ifdef LUA_CROSS_COMPILER 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, @@ -67,6 +68,12 @@ int luaO_log2 (unsigned int x) { int l = -1; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; +#else + /* Use Normalization Shift Amount Unsigned: 0x1=>31 up to 0xffffffff =>0 + * See Xtensa Instruction Set Architecture (ISA) Refman P 462 */ + asm volatile ("nsau %0, %1;" :"=r"(x) : "r"(x)); + return 31 - x; +#endif } diff --git a/components/lua/lobject.h b/components/lua/lobject.h index dd31e01574..3f76bfe1df 100644 --- a/components/lua/lobject.h +++ b/components/lua/lobject.h @@ -19,10 +19,8 @@ #define NUM_TAGS (LAST_TAG+1) -/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */ -#define READONLYMASK 128 - - +#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */ +#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */ /* ** Extra tags for non-values */ @@ -30,6 +28,21 @@ #define LUA_TUPVAL (LAST_TAG+2) #define LUA_TDEADKEY (LAST_TAG+3) +#ifdef __XTENSA__ +/* +** force aligned access to critical fields in Flash-based structures +** wo is the offset of aligned word in bytes 0,4,8,.. +** bo is the field within the word in bits 0..31 +*/ +#define GET_BYTE_FN(name,t,wo,bo) \ +static inline lu_byte get ## name(void *o) { \ + lu_byte res; /* extract named field */ \ + asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\ + return res; } +#else +#define GET_BYTE_FN(name,t,wo,bo) \ +static inline lu_byte get ## name(void *o) { return ((t *)o)->name; } +#endif /* ** Union of all collectable objects @@ -51,86 +64,46 @@ typedef struct GCheader { CommonHeader; } GCheader; +/* +** Word aligned inline access functions for the CommonHeader tt and marked fields. +** Note that these MUST be consistent with the CommonHeader definition above. Arg +** 3 is a word offset (4 bytes in this case) and arg 4 the bit offset in the word. +*/ +GET_BYTE_FN(tt,GCheader,4,0) +GET_BYTE_FN(marked,GCheader,4,8) - +#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL) +# error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines" +#endif /* ** Union of all Lua values */ -#if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) -typedef union { - struct { - int _pad0; - GCObject *gc; - }; - struct { - int _pad1; - void *p; - }; - lua_Number n; - struct { - int _pad2; - int b; - }; -} Value; -#else // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) typedef union { GCObject *gc; void *p; lua_Number n; int b; } Value; -#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) /* ** Tagged Values */ -#ifndef LUA_PACK_VALUE #define TValuefields Value value; int tt #define LUA_TVALUE_NIL {NULL}, LUA_TNIL +#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER) +#pragma pack(4) +#endif typedef struct lua_TValue { TValuefields; } TValue; -#else // #ifndef LUA_PACK_VALUE -#ifdef ELUA_ENDIAN_LITTLE -#define TValuefields union { \ - struct { \ - int _pad0; \ - int tt_sig; \ - } _ts; \ - struct { \ - int _pad; \ - short tt; \ - short sig; \ - } _t; \ - Value value; \ -} -#define LUA_TVALUE_NIL {0, add_sig(LUA_TNIL)} -#else // #ifdef ELUA_ENDIAN_LITTLE -#define TValuefields union { \ - struct { \ - int tt_sig; \ - int _pad0; \ - } _ts; \ - struct { \ - short sig; \ - short tt; \ - int _pad; \ - } _t; \ - Value value; \ -} -#define LUA_TVALUE_NIL {add_sig(LUA_TNIL), 0} -#endif // #ifdef ELUA_ENDIAN_LITTLE -#define LUA_NOTNUMBER_SIG (-1) -#define add_sig(tt) ( 0xffff0000 | (tt) ) - -typedef TValuefields TValue; -#endif // #ifndef LUA_PACK_VALUE +#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER) +#pragma pack() +#endif /* Macros to test type */ -#ifndef LUA_PACK_VALUE #define ttisnil(o) (ttype(o) == LUA_TNIL) #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisstring(o) (ttype(o) == LUA_TSTRING) @@ -142,27 +115,11 @@ typedef TValuefields TValue; #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) #define ttisrotable(o) (ttype(o) == LUA_TROTABLE) #define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION) -#else // #ifndef LUA_PACK_VALUE -#define ttisnil(o) (ttype_sig(o) == add_sig(LUA_TNIL)) -#define ttisnumber(o) ((o)->_t.sig != LUA_NOTNUMBER_SIG) -#define ttisstring(o) (ttype_sig(o) == add_sig(LUA_TSTRING)) -#define ttistable(o) (ttype_sig(o) == add_sig(LUA_TTABLE)) -#define ttisfunction(o) (ttype_sig(o) == add_sig(LUA_TFUNCTION)) -#define ttisboolean(o) (ttype_sig(o) == add_sig(LUA_TBOOLEAN)) -#define ttisuserdata(o) (ttype_sig(o) == add_sig(LUA_TUSERDATA)) -#define ttisthread(o) (ttype_sig(o) == add_sig(LUA_TTHREAD)) -#define ttislightuserdata(o) (ttype_sig(o) == add_sig(LUA_TLIGHTUSERDATA)) -#define ttisrotable(o) (ttype_sig(o) == add_sig(LUA_TROTABLE)) -#define ttislightfunction(o) (ttype_sig(o) == add_sig(LUA_TLIGHTFUNCTION)) -#endif // #ifndef LUA_PACK_VALUE + /* Macros to access values */ -#ifndef LUA_PACK_VALUE -#define ttype(o) ((o)->tt) -#else // #ifndef LUA_PACK_VALUE -#define ttype(o) ((o)->_t.sig == LUA_NOTNUMBER_SIG ? (o)->_t.tt : LUA_TNUMBER) -#define ttype_sig(o) ((o)->_ts.tt_sig) -#endif // #ifndef LUA_PACK_VALUE + +#define ttype(o) ((void) (o)->value, (o)->tt) #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) #define rvalue(o) check_exp(ttisrotable(o), (o)->value.p) @@ -182,24 +139,15 @@ typedef TValuefields TValue; /* ** for internal debug only */ -#ifndef LUA_PACK_VALUE + #define checkconsistency(obj) \ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) #define checkliveness(g,obj) \ lua_assert(!iscollectable(obj) || \ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) -#else // #ifndef LUA_PACK_VALUE -#define checkconsistency(obj) \ - lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch._t.tt)) - -#define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch._t.tt) && !isdead(g, (obj)->value.gc))) -#endif // #ifndef LUA_PACK_VALUE /* Macros to set values */ -#ifndef LUA_PACK_VALUE #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnvalue(obj,x) \ @@ -253,69 +201,10 @@ typedef TValuefields TValue; i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \ checkliveness(G(L),i_o); } - - - #define setobj(L,obj1,obj2) \ { const TValue *o2=(obj2); TValue *o1=(obj1); \ o1->value = o2->value; o1->tt=o2->tt; \ checkliveness(G(L),o1); } -#else // #ifndef LUA_PACK_VALUE -#define setnilvalue(obj) ( ttype_sig(obj) = add_sig(LUA_TNIL) ) - -#define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); } - -#define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTUSERDATA);} - -#define setrvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TROTABLE);} - -#define setfvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTFUNCTION);} - -#define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->_ts.tt_sig=add_sig(LUA_TBOOLEAN);} - -#define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TSTRING); \ - checkliveness(G(L),i_o); } - -#define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TUSERDATA); \ - checkliveness(G(L),i_o); } - -#define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTHREAD); \ - checkliveness(G(L),i_o); } - -#define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TFUNCTION); \ - checkliveness(G(L),i_o); } - -#define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTABLE); \ - checkliveness(G(L),i_o); } - -#define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TPROTO); \ - checkliveness(G(L),i_o); } - - - - -#define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; \ - checkliveness(G(L),o1); } -#endif // #ifndef LUA_PACK_VALUE /* ** different types of sets, according to destination @@ -336,18 +225,11 @@ typedef TValuefields TValue; #define setobj2n setobj #define setsvalue2n setsvalue -#ifndef LUA_PACK_VALUE -#define setttype(obj, tt) (ttype(obj) = (tt)) -#else // #ifndef LUA_PACK_VALUE -/* considering it used only in lgc to set LUA_TDEADKEY */ -/* we could define it this way */ -#define setttype(obj, _tt) ( ttype_sig(obj) = add_sig(_tt) ) -#endif // #ifndef LUA_PACK_VALUE +#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt)) #define iscollectable(o) (ttype(o) >= LUA_TSTRING) - typedef TValue *StkId; /* index to stack elements */ @@ -363,9 +245,16 @@ typedef union TString { } tsv; } TString; - -#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : cast(const char *, (ts) + 1)) -#define svalue(o) getstr(rawtsvalue(o)) +#ifdef LUA_CROSS_COMPILER +#define isreadonly(o) (0) +#else +#define isreadonly(o) ((o).marked & READONLYMASK) +#endif +#define ts_isreadonly(ts) isreadonly((ts)->tsv) +#define getstr(ts) (ts_isreadonly(ts) ? \ + cast(const char *, *(const char**)((ts) + 1)) : \ + cast(const char *, (ts) + 1)) +#define svalue(o) getstr(rawtsvalue(o)) @@ -414,6 +303,7 @@ typedef struct Proto { lu_byte is_vararg; lu_byte maxstacksize; } Proto; +#define proto_isreadonly(p) isreadonly(*(p)) /* masks for new-style vararg */ @@ -483,7 +373,6 @@ typedef union Closure { ** Tables */ -#ifndef LUA_PACK_VALUE typedef union TKey { struct { TValuefields; @@ -493,16 +382,6 @@ typedef union TKey { } TKey; #define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL} -#else // #ifndef LUA_PACK_VALUE -typedef struct TKey { - TValue tvk; - struct { - struct Node *next; /* for chaining */ - } nk; -} TKey; - -#define LUA_TKEY_NIL {LUA_TVALUE_NIL}, {NULL} -#endif // #ifndef LUA_PACK_VALUE typedef struct Node { TValue i_val; @@ -522,6 +401,7 @@ typedef struct Table { int sizearray; /* size of `array' array */ } Table; +typedef const struct luaR_entry ROTable; /* ** `module' operation for hashing (size is always a power of 2) diff --git a/components/lua/lparser.c b/components/lua/lparser.c index 7b14c3d25d..097d1a8441 100644 --- a/components/lua/lparser.c +++ b/components/lua/lparser.c @@ -10,7 +10,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lcode.h" #include "ldebug.h" @@ -916,12 +916,11 @@ static int block_follow (int token) { static void block (LexState *ls) { /* block -> chunk */ FuncState *fs = ls->fs; - BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt)); - enterblock(fs, pbl, 0); + BlockCnt bl; + enterblock(fs, &bl, 0); chunk(ls); - lua_assert(pbl->breaklist == NO_JUMP); + lua_assert(bl.breaklist == NO_JUMP); leaveblock(fs); - luaM_free(ls->L,pbl); } @@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) { static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { /* forbody -> DO block */ - BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt)); + 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, pbl, 0); /* scope for declared variables */ + enterblock(fs, &bl, 0); /* scope for declared variables */ adjustlocalvars(ls, nvars); luaK_reserveregs(fs, nvars); block(ls); @@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); - luaM_free(ls->L,pbl); } diff --git a/components/lua/lrodefs.h b/components/lua/lrodefs.h deleted file mode 100644 index e9bbe7feed..0000000000 --- a/components/lua/lrodefs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Read-only tables helper */ - -#ifndef lrodefs_h -#define lrodefs_h - -#include "lrotable.h" - -#undef LUA_REG_TYPE -#undef LSTRKEY -#undef LNILKEY -#undef LNUMKEY -#undef LFUNCVAL -#undef LNUMVAL -#undef LROVAL -#undef LNILVAL -#undef LREGISTER - -#if (MIN_OPT_LEVEL > 0) && (LUA_OPTIMIZE_MEMORY >= MIN_OPT_LEVEL) -#define LUA_REG_TYPE luaR_entry -#define LSTRKEY LRO_STRKEY -#define LNUMKEY LRO_NUMKEY -#define LNILKEY LRO_NILKEY -#define LFUNCVAL LRO_FUNCVAL -#define LUDATA LRO_LUDATA -#define LNUMVAL LRO_NUMVAL -#define LROVAL LRO_ROVAL -#define LNILVAL LRO_NILVAL -#define LREGISTER(L, name, table)\ - return 0 -#else -#define LUA_REG_TYPE luaL_reg -#define LSTRKEY(x) x -#define LNILKEY NULL -#define LFUNCVAL(x) x -#define LNILVAL NULL -#define LREGISTER(L, name, table)\ - luaL_register(L, name, table);\ - return 1 -#endif - -#endif /* lrodefs_h */ - diff --git a/components/lua/lrotable.c b/components/lua/lrotable.c index 250f14301f..d5f77942dc 100644 --- a/components/lua/lrotable.c +++ b/components/lua/lrotable.c @@ -2,135 +2,157 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lrotable.h" #include "lauxlib.h" #include "lstring.h" #include "lobject.h" #include "lapi.h" -/* Local defines */ -#define LUAR_FINDFUNCTION 0 -#define LUAR_FINDVALUE 1 +#ifdef _MSC_VER +#define ALIGNED_STRING (__declspec( align( 4 ) ) char*) +#else +#define ALIGNED_STRING (__attribute__((aligned(4))) char *) +#endif +#define LA_LINES 32 +#define LA_SLOTS 4 +//#define COLLECT_STATS -/* Externally defined read-only table array */ -extern const luaR_table lua_rotable[]; +/* + * All keyed ROtable access passes through luaR_findentry(). ROTables + * are simply a list of pairs. The existing algo + * did a linear scan of this vector of pairs looking for a match. + * + * A N×M lookaside cache has been added, with a simple hash on the key's + * TString addr and the ROTable addr to identify one of N lines. Each + * line has M slots which are scanned. This is all done in RAM and is + * perhaps 20x faster than the corresponding random Flash accesses which + * will cause flash faults. + * + * If a match is found and the table addresses match, then this entry is + * probed first. In practice the hit-rate here is over 99% so the code + * rarely fails back to doing the linear scan in ROM. + * + * Note that this hash does a couple of prime multiples and a modulus 2^X + * with is all evaluated in H/W, and adequately randomizes the lookup. + */ +#define HASH(a,b) ((((519*(size_t)(a)))>>4) + ((b) ? (b)->tsv.hash: 0)) -/* Find a global "read only table" in the constant lua_rotable array */ -void* luaR_findglobal(const char *name, unsigned len) { - unsigned i; +static struct { + unsigned hash; + unsigned addr:24; + unsigned ndx:8; +} cache[LA_LINES][LA_SLOTS]; - if (strlen(name) > LUA_MAX_ROTABLE_NAME) - return NULL; - for (i=0; lua_rotable[i].name; i ++) - if (*lua_rotable[i].name != '\0' && strlen(lua_rotable[i].name) == len && !strncmp(lua_rotable[i].name, name, len)) { - return (void*)(lua_rotable[i].pentries); - } - return NULL; -} +#ifdef COLLECT_STATS +unsigned cache_stats[3]; +#define COUNT(i) cache_stats[i]++ +#else +#define COUNT(i) +#endif + +static int lookup_cache(unsigned hash, ROTable *rotable) { + int i = (hash>>2) & (LA_LINES-1), j; -/* Find an entry in a rotable and return it */ -static const TValue* luaR_auxfind(const luaR_entry *pentry, const char *strkey, luaR_numkey numkey, unsigned *ppos) { - const TValue *res = NULL; - unsigned i = 0; - - if (pentry == NULL) - return NULL; - while(pentry->key.type != LUA_TNIL) { - if ((strkey && (pentry->key.type == LUA_TSTRING) && (!strcmp(pentry->key.id.strkey, strkey))) || - (!strkey && (pentry->key.type == LUA_TNUMBER) && ((luaR_numkey)pentry->key.id.numkey == numkey))) { - res = &pentry->value; - break; + for (j = 0; j>2 & (LA_LINES-1), j; + COUNT(2); + if (ndx>0xffu) + return; + for (j = LA_SLOTS-1; j>0; j--) + cache[i][j] = cache[i][j-1]; + cache[i][0].hash = hash; + cache[i][0].addr = (size_t) rotable; + cache[i][0].ndx = ndx; } +/* + * Find a string key entry in a rotable and return it. Note that this internally + * uses a null key to denote a metatable search. + */ +const TValue* luaR_findentry(ROTable *rotable, TString *key, unsigned *ppos) { + const luaR_entry *pentry = rotable; + const char *strkey = key ? getstr(key) : ALIGNED_STRING "__metatable" ; + unsigned hash = HASH(rotable, key); + + unsigned i = 0; + int j = lookup_cache(hash, rotable); + unsigned l = key ? key->tsv.len : sizeof("__metatable")-1; + + if (pentry) { + if (j >= 0 && !strcmp(pentry[j].key, strkey)) { + if (ppos) + *ppos = j; +//printf("%3d hit %p %s\n", (hash>>2) & (LA_LINES-1), rotable, strkey); + return &pentry[j].value; + } + /* + * The invariants for 1st word comparison are deferred to here since they + * aren't needed if there is a cache hit. Note that the termination null + * is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF. + */ + unsigned name4, mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8); + memcpy(&name4, strkey, sizeof(name4)); -/* Find an entry in a rotable and return its type - If "strkey" is not NULL, the function will look for a string key, - otherwise it will look for a number key */ -const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos) { - return luaR_auxfind((const luaR_entry*)data, strkey, numkey, ppos); + for(;pentry->key != NULL; i++, pentry++) { + if (((*(unsigned *)pentry->key ^ name4) & mask4) == 0 && + !strcmp(pentry->key, strkey)) { +//printf("%p %s hit after %d probes \n", rotable, strkey, (int)(pentry-rotable)); + if (ppos) + *ppos = i; + update_cache(hash, rotable, pentry - rotable); +//printf("%3d %3d %p %s\n", (hash>>2) & (LA_LINES-1), (int)(pentry-rotable), rotable, strkey); + return &pentry->value; + } + } + } +//printf("%p %s miss after %d probes \n", rotable, strkey, (int)(pentry-rotable)); + return luaO_nilobject; } /* Find the metatable of a given table */ -void* luaR_getmeta(void *data) { -#ifdef LUA_META_ROTABLES - const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL); +void* luaR_getmeta(ROTable *rotable) { + const TValue *res = luaR_findentry(rotable, NULL, NULL); return res && ttisrotable(res) ? rvalue(res) : NULL; -#else - return NULL; -#endif } -static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, TValue *key, TValue *val) { - setnilvalue(key); - setnilvalue(val); - if (pentries[pos].key.type != LUA_TNIL) { +static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos, + TValue *key, TValue *val) { + if (pentries[pos].key) { /* Found an entry */ - if (pentries[pos].key.type == LUA_TSTRING) - setsvalue(L, key, luaS_newro(L, pentries[pos].key.id.strkey)) - else - setnvalue(key, (lua_Number)pentries[pos].key.id.numkey) - setobj2s(L, val, &pentries[pos].value); + setsvalue(L, key, luaS_new(L, pentries[pos].key)); + setobj2s(L, val, &pentries[pos].value); + } else { + setnilvalue(key); + setnilvalue(val); } } + + /* next (used for iteration) */ -void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) { - const luaR_entry* pentries = (const luaR_entry*)data; - char strkey[LUA_MAX_ROTABLE_NAME + 1], *pstrkey = NULL; - luaR_numkey numkey = 0; +void luaR_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val) { unsigned keypos; - + /* Special case: if key is nil, return the first element of the rotable */ - if (ttisnil(key)) - luaR_next_helper(L, pentries, 0, key, val); - else if (ttisstring(key) || ttisnumber(key)) { - /* Find the previoud key again */ + if (ttisnil(key)) + luaR_next_helper(L, rotable, 0, key, val); + else if (ttisstring(key)) { + /* Find the previous key again */ if (ttisstring(key)) { - luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME); - pstrkey = strkey; - } else - numkey = (luaR_numkey)nvalue(key); - luaR_findentry(data, pstrkey, numkey, &keypos); + luaR_findentry(rotable, rawtsvalue(key), &keypos); + } /* Advance to next key */ - keypos ++; - luaR_next_helper(L, pentries, keypos, key, val); + keypos ++; + luaR_next_helper(L, rotable, keypos, key, val); } } - -/* Convert a Lua string to a C string */ -void luaR_getcstr(char *dest, const TString *src, size_t maxsize) { - if (src->tsv.len+1 > maxsize) - dest[0] = '\0'; - else { - memcpy(dest, getstr(src), src->tsv.len); - dest[src->tsv.len] = '\0'; - } -} - -/* Return 1 if the given pointer is a rotable */ -#ifdef LUA_META_ROTABLES - -#include "compiler.h" - -int luaR_isrotable(void *p) { - return RODATA_START_ADDRESS <= (char*)p && (char*)p <= RODATA_END_ADDRESS; -} -#endif diff --git a/components/lua/lrotable.h b/components/lua/lrotable.h index e8963e3b96..6bf7b91d25 100644 --- a/components/lua/lrotable.h +++ b/components/lua/lrotable.h @@ -4,35 +4,38 @@ #define lrotable_h #include "lua.h" -#include "llimits.h" -#include "lobject.h" #include "luaconf.h" +#include "lobject.h" +#include "llimits.h" /* Macros one can use to define rotable entries */ -#ifndef LUA_PACK_VALUE #define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION} #define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA} #define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL} -#else // #ifndef LUA_PACK_VALUE -#define LRO_NUMVAL(v) {.value.n = v} -#ifdef ELUA_ENDIAN_LITTLE -#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}} -#define LRO_LUDATA(v) {{(int)v, add_sig(LUA_TLIGHTUSERDATA)}} -#define LRO_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}} -#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}} -#else // #ifdef ELUA_ENDIAN_LITTLE -#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}} -#define LRO_LUDATA(v) {{add_sig(LUA_TLIGHTUSERDATA), (int)v}} -#define LRO_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}} -#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}} -#endif // #ifdef ELUA_ENDIAN_LITTLE -#endif // #ifndef LUA_PACK_VALUE - -#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}} -#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}} -#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}} + +#ifdef LUA_CROSS_COMPILER +#define LRO_STRKEY(k) k +#else +#define LRO_STRKEY(k) ((__attribute__((aligned(4))) char *) k) +#endif + +#define LROT_TABLE(t) static const LUA_REG_TYPE t ## _map[]; +#define LROT_PUBLIC_TABLE(t) const LUA_REG_TYPE t ## _map[]; +#define LROT_TABLEREF(t) ((void *) t ## _map) +#define LROT_BEGIN(t) static const LUA_REG_TYPE t ## _map [] = { +#define LROT_PUBLIC_BEGIN(t) const LUA_REG_TYPE t ## _map[] = { +#define LROT_EXTERN(t) extern const LUA_REG_TYPE t ## _map[] +#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t ## _map)}, +#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)}, +#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)}, +#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA((void *) x)}, +#define LROT_END(t,mt, f) {NULL, LRO_NILVAL} }; +#define LROT_BREAK(t) }; + +#define LUA_REG_TYPE luaR_entry +#define LREGISTER(L, name, table) return 0 /* Maximum length of a rotable name and of a string key*/ #define LUA_MAX_ROTABLE_NAME 32 @@ -40,41 +43,57 @@ /* Type of a numeric key in a rotable */ typedef int luaR_numkey; -/* The next structure defines the type of a key */ -typedef struct -{ - int type; - union - { - const char* strkey; - luaR_numkey numkey; - } id; -} luaR_key; - /* An entry in the read only table */ -typedef struct -{ - const luaR_key key; +typedef struct luaR_entry { + const char *key; const TValue value; } luaR_entry; -/* A rotable */ -typedef struct -{ - const char *name; - const luaR_entry *pentries; -} luaR_table; - -void* luaR_findglobal(const char *key, unsigned len); -int luaR_findfunction(lua_State *L, const luaR_entry *ptable); -const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos); -void luaR_getcstr(char *dest, const TString *src, size_t maxsize); -void luaR_next(lua_State *L, void *data, TValue *key, TValue *val); -void* luaR_getmeta(void *data); -#ifdef LUA_META_ROTABLES +/* + * The current ROTable implmentation is a vector of luaR_entry terminated by a + * nil record. The convention is to use ROtable * to refer to the entire vector + * as a logical ROTable. + */ +typedef const struct luaR_entry ROTable; + +const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos); +const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos); +void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val); +void* luaR_getmeta(ROTable *tab); int luaR_isrotable(void *p); + +/* + * Set inRO check depending on platform. Note that this implementation needs + * to work on both the host (luac.cross) and ESP targets. The luac.cross + * VM is used for the -e option, and is primarily used to be able to debug + * VM changes on the more developer-friendly hot gdb environment. + */ +#if defined(LUA_CROSS_COMPILER) + +#if defined(_MSC_VER) +//msvc build uses these dummy vars to locate the beginning and ending addresses of the RO data +extern const char _ro_start[], _ro_end[]; +#define IN_RODATA_AREA(p) (((const char*)(p)) >= _ro_start && ((const char *)(p)) <= _ro_end) +#else /* one of the POSIX variants */ +#if defined(__CYGWIN__) +#define _RODATA_END __end__ +#elif defined(__MINGW32__) +#define _RODATA_END end #else -#define luaR_isrotable(p) (0) +#define _RODATA_END _edata #endif +extern const char _RODATA_END[]; +#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END) +#endif /* defined(_MSC_VER) */ + +#else /* xtensa tool chain for ESP32 target */ + +#include "compiler.h" +#define IN_RODATA_AREA(p) (((const char *)p) >= RODATA_START_ADDRESS && ((const char *)p) <= RODATA_END_ADDRESS) + +#endif /* defined(LUA_CROSS_COMPILER) */ + +/* Return 1 if the given pointer is a rotable */ +#define luaR_isrotable(p) IN_RODATA_AREA(p) #endif diff --git a/components/lua/lstate.c b/components/lua/lstate.c index b428974210..cb6632461c 100644 --- a/components/lua/lstate.c +++ b/components/lua/lstate.c @@ -13,6 +13,7 @@ #include "ldebug.h" #include "ldo.h" +#include "lflash.h" #include "lfunc.h" #include "lgc.h" #include "llex.h" @@ -72,9 +73,12 @@ static void f_luaopen (lua_State *L, void *ud) { sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ +#ifndef LUA_CROSS_COMPILER + luaN_init(L); /* optionally map RO string table */ +#endif luaT_init(L); luaX_init(L); - luaS_fix(luaS_newliteral(L, MEMERRMSG)); + stringfix(luaS_newliteral(L, MEMERRMSG)); g->GCthreshold = 4*g->totalbytes; } @@ -191,6 +195,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->memlimit = EGC_INITIAL_MEMLIMIT; #else g->memlimit = 0; +#endif +#ifndef LUA_CROSS_COMPILER + g->ROstrt.size = 0; + g->ROstrt.nuse = 0; + g->ROstrt.hash = NULL; + g->ROpvmain = NULL; + g->LFSsize = 0; #endif for (i=0; imt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { diff --git a/components/lua/lstate.h b/components/lua/lstate.h index 1b3c363a84..88b7d57f5a 100644 --- a/components/lua/lstate.h +++ b/components/lua/lstate.h @@ -82,7 +82,7 @@ typedef struct global_State { Mbuffer buff; /* temporary buffer for string concatentation */ lu_mem GCthreshold; lu_mem totalbytes; /* number of bytes currently allocated */ - lu_mem memlimit; /* maximum number of bytes that can be allocated, 0 = no limit. */ + l_mem memlimit; /* maximum number of bytes that can be allocated, 0 = no limit. <0 used with EGC_ON_MEM_LIMIT when free heap falls below -memlimit */ lu_mem estimate; /* an estimate of number of bytes actually in use */ lu_mem gcdept; /* how much GC is `behind schedule' */ int gcpause; /* size of pause between successive GCs */ @@ -94,6 +94,11 @@ typedef struct global_State { UpVal uvhead; /* head of double-linked list of all open upvalues */ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ TString *tmname[TM_N]; /* array with tag-method names */ +#ifndef LUA_CROSS_COMPILER + stringtable ROstrt; /* Flash-based hash table for RO strings */ + Proto *ROpvmain; /* Flash-based Proto main */ + int LFSsize; /* Size of Lua Flash Store */ +#endif } global_State; diff --git a/components/lua/lstring.c b/components/lua/lstring.c index b7877eb289..5803b059dc 100644 --- a/components/lua/lstring.c +++ b/components/lua/lstring.c @@ -11,7 +11,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "lmem.h" #include "lobject.h" @@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, tb = &G(L)->strt; if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) luaS_resize(L, tb->size*2); /* too crowded */ - ts = cast(TString *, luaM_malloc(L, readonly ? sizeof(char**)+sizeof(TString) : (l+1)*sizeof(char)+sizeof(TString))); + ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (readonly ? sizeof(char**) : (l+1)*sizeof(char)))); ts->tsv.len = l; ts->tsv.hash = h; ts->tsv.marked = luaC_white(G(L)); @@ -71,7 +71,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, ((char *)(ts+1))[l] = '\0'; /* ending 0 */ } else { *(char **)(ts+1) = (char *)str; - luaS_readonly(ts); + l_setbit((ts)->tsv.marked, READONLYBIT); } h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ @@ -80,14 +80,28 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, return ts; } +static int lua_is_ptr_in_ro_area(const char *p) { +#ifdef LUA_CROSS_COMPILER + return 0; // TStrings are never in RO in luac.cross +#else + return IN_RODATA_AREA(p); +#endif +} + +/* + * The string algorithm has been modified to be LFS-friendly. The previous eLua + * algo used the address of the string was in flash and the string was >4 bytes + * This creates miminal savings and prevents the use of LFS based strings + */ -static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, int readonly) { +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { GCObject *o; unsigned int h = cast(unsigned int, l); /* seed */ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; for (l1=l; l1>=step; l1-=step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL; o = o->gch.next) { @@ -98,35 +112,27 @@ static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, in return ts; } } - return newlstr(L, str, l, h, readonly); /* not found */ -} - -static int lua_is_ptr_in_ro_area(const char *p) { -#ifdef LUA_CROSS_COMPILER - return 0; -#else - -#include "compiler.h" - - return p >= RODATA_START_ADDRESS && p <= RODATA_END_ADDRESS; +#ifndef LUA_CROSS_COMPILER + /* + * The RAM strt is searched first since RAM access is faster tham Flash access. + * If a miss, then search the RO string table. + */ + if (G(L)->ROstrt.hash) { + for (o = G(L)->ROstrt.hash[lmod(h, G(L)->ROstrt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + return ts; + } + } + } #endif -} - -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - // If the pointer is in a read-only memory and the string is at least 4 chars in length, - // create it as a read-only string instead - if(lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) && l == strlen(str)) - return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING); - else - return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING); -} - - -LUAI_FUNC TString *luaS_newrolstr (lua_State *L, const char *str, size_t l) { - if(l+1 > sizeof(char**) && l == strlen(str)) - return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING); - else // no point in creating a RO string, as it would actually be larger - return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING); + /* New additions to the RAM strt are tagged as readonly if the string address + * is in the CTEXT segment (target only, not luac.cross) */ + int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) && + l == strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING); + return newlstr(L, str, l, h, readonly); /* not found */ } diff --git a/components/lua/lstring.h b/components/lua/lstring.h index 442c9fc4bb..366f92b32e 100644 --- a/components/lua/lstring.h +++ b/components/lua/lstring.h @@ -13,22 +13,16 @@ #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+(luaS_isreadonly(s) ? sizeof(char **) : ((s)->len+1)*sizeof(char))) +#define sizestring(s) (sizeof(union TString)+(testbit(getmarked(s), READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char))) #define sizeudata(u) (sizeof(union Udata)+(u)->len) #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newro(L, s) (luaS_newrolstr(L, s, strlen(s))) #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) -#define luaS_readonly(s) l_setbit((s)->tsv.marked, READONLYBIT) -#define luaS_isreadonly(s) testbit((s)->marked, READONLYBIT) - 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_newrolstr (lua_State *L, const char *str, size_t l); #endif diff --git a/components/lua/lstrlib.c b/components/lua/lstrlib.c index 340a86fb3a..39e8604847 100644 --- a/components/lua/lstrlib.c +++ b/components/lua/lstrlib.c @@ -10,8 +10,8 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDIO -#include C_HEADER_STRING +#include +#include #include "lauxlib.h" #include "lualib.h" @@ -577,7 +577,7 @@ static int gmatch (lua_State *L) { return 1; } -#if LUA_OPTIMIZE_MEMORY == 0 || !defined(LUA_COMPAT_GFIND) +#ifndef LUA_COMPAT_GFIND static int gfind_nodef (lua_State *L) { return luaL_error(L, LUA_QL("string.gfind") " was renamed to " LUA_QL("string.gmatch")); @@ -825,67 +825,37 @@ static int str_format (lua_State *L) { return 1; } -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE strlib[] = { - {LSTRKEY("byte"), LFUNCVAL(str_byte)}, - {LSTRKEY("char"), LFUNCVAL(str_char)}, - {LSTRKEY("dump"), LFUNCVAL(str_dump)}, - {LSTRKEY("find"), LFUNCVAL(str_find)}, - {LSTRKEY("format"), LFUNCVAL(str_format)}, -#if LUA_OPTIMIZE_MEMORY > 0 && defined(LUA_COMPAT_GFIND) - {LSTRKEY("gfind"), LFUNCVAL(gmatch)}, +LROT_PUBLIC_BEGIN(strlib) + LROT_FUNCENTRY( byte, str_byte ) + LROT_FUNCENTRY( char, str_char ) + LROT_FUNCENTRY( dump, str_dump ) + LROT_FUNCENTRY( find, str_find ) + LROT_FUNCENTRY( format, str_format ) +#ifdef LUA_COMPAT_GFIND + LROT_FUNCENTRY( gfind, gmatch ) #else - {LSTRKEY("gfind"), LFUNCVAL(gfind_nodef)}, -#endif - {LSTRKEY("gmatch"), LFUNCVAL(gmatch)}, - {LSTRKEY("gsub"), LFUNCVAL(str_gsub)}, - {LSTRKEY("len"), LFUNCVAL(str_len)}, - {LSTRKEY("lower"), LFUNCVAL(str_lower)}, - {LSTRKEY("match"), LFUNCVAL(str_match)}, - {LSTRKEY("rep"), LFUNCVAL(str_rep)}, - {LSTRKEY("reverse"), LFUNCVAL(str_reverse)}, - {LSTRKEY("sub"), LFUNCVAL(str_sub)}, - {LSTRKEY("upper"), LFUNCVAL(str_upper)}, -#if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("__index"), LROVAL(strlib)}, -#endif - {LNILKEY, LNILVAL} -}; - - -#if LUA_OPTIMIZE_MEMORY != 2 -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* create metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); /* set string metatable */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* string library... */ - lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ - lua_pop(L, 1); /* pop metatable */ -} + LROT_FUNCENTRY( gfind, gfind_nodef ) #endif + LROT_FUNCENTRY( gmatch, gmatch ) + LROT_FUNCENTRY( gsub, str_gsub ) + LROT_FUNCENTRY( len, str_len ) + LROT_FUNCENTRY( lower, str_lower ) + LROT_FUNCENTRY( match, str_match ) + LROT_FUNCENTRY( rep, str_rep ) + LROT_FUNCENTRY( reverse, str_reverse ) + LROT_FUNCENTRY( sub, str_sub ) + LROT_FUNCENTRY( upper, str_upper ) + LROT_TABENTRY( __index, strlib ) +LROT_END(strlib, NULL, 0) // OR DO WE NEED LRTO_MASK_INDEX **TODO** /* ** Open string library */ LUALIB_API int luaopen_string (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY == 0 - luaL_register(L, LUA_STRLIBNAME, strlib); -#if defined(LUA_COMPAT_GFIND) - lua_getfield(L, -1, "gmatch"); - lua_setfield(L, -2, "gfind"); -#endif - createmetatable(L); - return 1; -#else lua_pushliteral(L,""); - lua_pushrotable(L, (void*)strlib); + lua_pushrotable(L, LROT_TABLEREF(strlib)); lua_setmetatable(L, -2); lua_pop(L,1); - return 0; -#endif + return 0; } diff --git a/components/lua/ltable.c b/components/lua/ltable.c index 6624888c5d..9463bed1a7 100644 --- a/components/lua/ltable.c +++ b/components/lua/ltable.c @@ -23,8 +23,8 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_MATH -#include C_HEADER_STRING +#include +#include #include "ldebug.h" #include "ldo.h" @@ -105,8 +105,9 @@ static Node *mainposition (const Table *t, const TValue *key) { return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: case LUA_TROTABLE: + return hashpointer(t, rvalue(key)); + case LUA_TLIGHTUSERDATA: case LUA_TLIGHTFUNCTION: return hashpointer(t, pvalue(key)); default: @@ -444,7 +445,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { int oldasize = t->sizearray; if (nasize > oldasize) /* array part must grow? */ setarrayvector(L, t, nasize); - resize_hashpart(L, t, nhsize); + if (t->node != dummynode || nhsize>0) + resize_hashpart(L, t, nhsize); if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ @@ -518,11 +520,11 @@ void luaH_free (lua_State *L, Table *t) { /* -** 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. +** 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. */ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { Node *mp = mainposition(t, key); @@ -578,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) { /* same thing for rotables */ const TValue *luaH_getnum_ro (void *t, int key) { - const TValue *res = luaR_findentry(t, NULL, key, NULL); + const TValue *res = NULL; // integer values not supported: luaR_findentryN(t, key, NULL); return res ? res : luaO_nilobject; } @@ -598,13 +600,9 @@ const TValue *luaH_getstr (Table *t, TString *key) { /* same thing for rotables */ const TValue *luaH_getstr_ro (void *t, TString *key) { - char keyname[LUA_MAX_ROTABLE_NAME + 1]; - const TValue *res; - if (!t) + if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME) return luaO_nilobject; - luaR_getcstr(keyname, key, LUA_MAX_ROTABLE_NAME); - res = luaR_findentry(t, keyname, 0, NULL); - return res ? res : luaO_nilobject; + return luaR_findentry(t, key, NULL); } @@ -741,19 +739,15 @@ int luaH_getn (Table *t) { /* same thing for rotables */ int luaH_getn_ro (void *t) { - int i = 1, len=0; - - while(luaR_findentry(t, NULL, i ++, NULL)) - len ++; - return len; + return 0; // Integer Keys are not currently supported for ROTables } -#if defined(LUA_DEBUG) +int luaH_isdummy (Node *n) { return n == dummynode; } +#if defined(LUA_DEBUG) Node *luaH_mainposition (const Table *t, const TValue *key) { return mainposition(t, key); } +#endif -int luaH_isdummy (Node *n) { return n == dummynode; } -#endif diff --git a/components/lua/ltable.h b/components/lua/ltable.h index 4835f2c3fb..d8c26d9af8 100644 --- a/components/lua/ltable.h +++ b/components/lua/ltable.h @@ -34,11 +34,9 @@ LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_next_ro (lua_State *L, void *t, StkId key); LUAI_FUNC int luaH_getn (Table *t); LUAI_FUNC int luaH_getn_ro (void *t); +LUAI_FUNC int luaH_isdummy (Node *n); #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/components/lua/ltablib.c b/components/lua/ltablib.c index 8b0a810b3b..39b6fb977b 100644 --- a/components/lua/ltablib.c +++ b/components/lua/ltablib.c @@ -266,22 +266,18 @@ static int sort (lua_State *L) { /* }====================================================== */ -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE tab_funcs[] = { - {LSTRKEY("concat"), LFUNCVAL(tconcat)}, - {LSTRKEY("foreach"), LFUNCVAL(foreach)}, - {LSTRKEY("foreachi"), LFUNCVAL(foreachi)}, - {LSTRKEY("getn"), LFUNCVAL(getn)}, - {LSTRKEY("maxn"), LFUNCVAL(maxn)}, - {LSTRKEY("insert"), LFUNCVAL(tinsert)}, - {LSTRKEY("remove"), LFUNCVAL(tremove)}, - {LSTRKEY("setn"), LFUNCVAL(setn)}, - {LSTRKEY("sort"), LFUNCVAL(sort)}, - {LNILKEY, LNILVAL} -}; +LROT_PUBLIC_BEGIN(tab_funcs) + LROT_FUNCENTRY( concat, tconcat ) + LROT_FUNCENTRY( foreach, foreach ) + LROT_FUNCENTRY( foreachi, foreachi ) + LROT_FUNCENTRY( getn, getn ) + LROT_FUNCENTRY( maxn, maxn ) + LROT_FUNCENTRY( insert, tinsert ) + LROT_FUNCENTRY( remove, tremove ) + LROT_FUNCENTRY( setn, setn ) + LROT_FUNCENTRY( sort, sort ) +LROT_END(tab_funcs, NULL, 0) LUALIB_API int luaopen_table (lua_State *L) { - LREGISTER(L, LUA_TABLIBNAME, tab_funcs); + return 1; } diff --git a/components/lua/ltm.c b/components/lua/ltm.c index bdbf4b94c7..6f5962db40 100644 --- a/components/lua/ltm.c +++ b/components/lua/ltm.c @@ -14,6 +14,7 @@ #include "lobject.h" #include "lstate.h" +#include "lgc.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" @@ -39,7 +40,7 @@ void luaT_init (lua_State *L) { int i; for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ + stringfix(G(L)->tmname[i]); /* never collect these names */ } } @@ -49,14 +50,22 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename); + const TValue *tm; lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - if (!luaR_isrotable(events)) + + if (luaR_isrotable(events)) { + tm = luaH_getstr_ro(events, ename); + if (ttisnil(tm)) { /* no tag method? */ + return NULL; + } + } else { + tm = luaH_getstr(events, ename); + if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + (!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -#define fasttm(l,et,e) gfasttm(G(l), et, e) +#define fasttm(l,et,e) gfasttm(G(l), et, e) LUAI_DATA const char *const luaT_typenames[]; diff --git a/components/lua/lua.c b/components/lua/lua.c index 55e6671f64..9cca08d97a 100644 --- a/components/lua/lua.c +++ b/components/lua/lua.c @@ -9,12 +9,10 @@ #include #include #include -#include "flash_fs.h" #include "user_version.h" #include "driver/console.h" #include "esp_system.h" #include "platform.h" -#include "c_stdlib.h" #define lua_c @@ -23,52 +21,13 @@ #include "lauxlib.h" #include "lualib.h" #include "legc.h" +#include "lflash.h" lua_State *globalL = NULL; lua_Load gLoad; - static const char *progname = LUA_PROGNAME; -#if 0 -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 (void) { -#if defined(LUA_USE_STDIO) - fprintf(stderr, -#else - luai_writestringerror( -#endif - "usage: %s [options] [script [args]].\n" - "Available options are:\n" - " -e stat execute string " LUA_QL("stat") "\n" - " -l name require library " LUA_QL("name") "\n" - " -m limit set memory limit. (units are in Kbytes)\n" - " -i enter interactive mode after executing " LUA_QL("script") "\n" - " -v show version information\n" - " -- stop handling options\n" - " - execute stdin and stop handling options\n" - , - progname); -#if defined(LUA_USE_STDIO) - fflush(stderr); -#endif -} -#endif - static void l_message (const char *pname, const char *msg) { #if defined(LUA_USE_STDIO) if (pname) fprintf(stderr, "%s: ", pname); @@ -128,14 +87,15 @@ static int docall (lua_State *L, int narg, int clear) { static void print_version (lua_State *L) { - lua_pushliteral (L, NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE); + lua_pushliteral (L, "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK "); + lua_pushstring (L, SDK_VERSION); + lua_concat (L, 2); const char *msg = lua_tostring (L, -1); l_message (NULL, msg); lua_pop (L, 1); } -#if 0 static int getargs (lua_State *L, char **argv, int n) { int narg; int i; @@ -153,16 +113,39 @@ static int getargs (lua_State *L, char **argv, int n) { return narg; } -static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name) || docall(L, 0, 1); - return report(L, status); -} -#else static int dofsfile (lua_State *L, const char *name) { int status = luaL_loadfsfile(L, name) || docall(L, 0, 1); return report(L, status); } -#endif + +static int dolfsfile (lua_State *L, const char *name) { + int status = 1; + const char *code_fmt = "if node.flashindex('%s') then node.flashindex('%s')() end"; + char *module_name = strdup(name); + unsigned name_len = strlen(name); + unsigned code_length = strlen(code_fmt) + name_len*2 + 1; + char *code_buf = malloc(code_length); + + if (code_buf && module_name) { + char *dot = strrchr(module_name, '.'); + if (dot) { + if (strstr(module_name, ".lua") == dot) + *dot = 0; + } + snprintf(code_buf, code_length, code_fmt, module_name, module_name); + status = luaL_dostring(L, code_buf); + if (status) + lua_pushfstring(L, "Failed to load %s from LFS", module_name); + } else { + lua_pushstring(L, "Failed to allocate memory"); + } + + if (module_name) + free(module_name); + if (code_buf) + free(code_buf); + 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) || docall(L, 0, 1); @@ -199,95 +182,9 @@ static int incomplete (lua_State *L, int status) { return 0; /* else... */ } -#if 0 -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); - if (lua_readline(L, b, prmt) == 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 */ - status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=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 == 0) status = docall(L, 0, 0); - report(L, status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) - l_message(progname, lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - -#if defined(LUA_USE_STDIO) - fputs("\n", stdout); - fflush(stdout); -#else - luai_writeline(); -#endif - - 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 == 0) - status = docall(L, narg, 0); - else - lua_pop(L, narg); - return report(L, status); -} -#endif /* check that argument has no extra characters at the end */ -#define notail(x) {if ((x)[2] != '\0') return -1;} +#define notail(x) {if ((x)[2] != '\0') return -1;} static int collectargs (char **argv, int *pi, int *pv, int *pe) { @@ -362,17 +259,21 @@ static int runargs (lua_State *L, char **argv, int n) { } +#ifndef LUA_INIT_STRING +#define LUA_INIT_STRING "@init.lua" +#endif + static int handle_luainit (lua_State *L) { - const char *init = c_getenv(LUA_INIT); - if (init == NULL) return 0; /* status OK */ - else if (init[0] == '@') -#if 0 - return dofile(L, init+1); -#else + const char *init = LUA_INIT_STRING; + if (init[0] == '@') { + #if CONFIG_LUA_EMBEDDED_FLASH_STORE > 0 + int status = dolfsfile(L, init+1); + if (status == 0) + return status; + #endif return dofsfile(L, init+1); -#endif - else - return dostring(L, init, "=" LUA_INIT); + } else + return dostring(L, init, LUA_INIT); } @@ -395,40 +296,18 @@ static int pmain (lua_State *L) { lua_gc(L, LUA_GCRESTART, 0); print_version(L); s->status = handle_luainit(L); -#if 0 - if (s->status != 0) return 0; -#endif script = collectargs(argv, &has_i, &has_v, &has_e); if (script < 0) { /* invalid args? */ -#if 0 - print_usage(); -#endif s->status = 1; return 0; } - // if (has_v) print_version(); s->status = runargs(L, argv, (script > 0) ? script : s->argc); if (s->status != 0) return 0; -#if 0 - if (script) - s->status = handle_script(L, argv, script); - if (s->status != 0) return 0; - if (has_i) - dotty(L); - else if (script == 0 && !has_e && !has_v) { - if (lua_stdin_is_tty()) { - print_version(); - dotty(L); - } - else dofile(L, NULL); /* executes stdin as a file */ - } -#endif return 0; } static void dojob(lua_Load *load); static bool readline(lua_Load *load); -char line_buffer[LUA_MAXINPUT]; #ifdef LUA_RPC int main (int argc, char **argv) { @@ -444,30 +323,47 @@ int lua_main (int argc, char **argv) { } s.argc = argc; s.argv = argv; + status = lua_cpcall(L, &pmain, &s); + report(L, status); gLoad.L = L; gLoad.firstline = 1; gLoad.done = 0; - gLoad.line = line_buffer; + gLoad.line = malloc(LUA_MAXINPUT); gLoad.len = LUA_MAXINPUT; gLoad.line_position = 0; gLoad.prmt = get_prompt(L, 1); dojob(&gLoad); - NODE_DBG("Heap size::%d.\n",system_get_free_heap_size()); + NODE_DBG("Heap size:%d.\n",system_get_free_heap_size()); legc_set_mode( L, EGC_ALWAYS, 4096 ); // legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 ); // lua_close(L); return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; } +int lua_put_line(const char *s, size_t l) { + if (s == NULL || ++l > LUA_MAXINPUT || gLoad.line_position > 0) + return 0; + memcpy(gLoad.line, s, l); + gLoad.line[l] = '\0'; + gLoad.line_position = l; + gLoad.done = 1; + NODE_DBG("Get command: %s\n", gLoad.line); + return 1; +} + void lua_handle_input (bool force) { - if (gLoad.L && (force || readline (&gLoad))) + while (gLoad.L && (force || readline (&gLoad))) { + NODE_DBG("Handle Input: first=%u, pos=%u, len=%u, actual=%u, line=%s\n", gLoad.firstline, + gLoad.line_position, gLoad.len, strlen(gLoad.line), gLoad.line); dojob (&gLoad); + force = false; + } } void donejob(lua_Load *load){ @@ -475,7 +371,7 @@ void donejob(lua_Load *load){ } static void dojob(lua_Load *load){ - size_t l; + size_t l, rs; int status; char *b = load->line; lua_State *L = load->L; diff --git a/components/lua/lua.h b/components/lua/lua.h index c7ab6a1fbd..25348c31c3 100644 --- a/components/lua/lua.h +++ b/components/lua/lua.h @@ -166,7 +166,6 @@ 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_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API void (lua_pushrolstring) (lua_State *L, const char *s, size_t l); LUA_API void (lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); diff --git a/components/lua/luac_cross/luac.c b/components/lua/luac_cross/luac.c deleted file mode 100644 index bdd3e01a4f..0000000000 --- a/components/lua/luac_cross/luac.c +++ /dev/null @@ -1,245 +0,0 @@ -/* -** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ -** Lua compiler (saves bytecodes to files; also list bytecodes) -** See Copyright Notice in lua.h -*/ - -#define LUAC_CROSS_FILE - -#include "luac_cross.h" -#include C_HEADER_ERRNO -#include C_HEADER_STDIO -#include C_HEADER_STDLIB -#include C_HEADER_STRING - -#define luac_c -#define LUA_CORE - -#include "lua.h" -#include "lauxlib.h" - -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstring.h" -#include "lundump.h" - -#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 DumpTargetInfo target; - -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" - " - process stdin\n" - " -l list\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" - " -cci bits cross-compile with given integer size\n" - " -ccn type bits cross-compile with given lua_Number type and size\n" - " -cce endian cross-compile with given endianness ('big' or 'little')\n" - " -- stop handling options\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))->l.p) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - int i,pc; - Proto* f=luaF_newproto(L); - setptvalue2s(L,L->top,f); incr_top(L); - f->source=luaS_newliteral(L,"=(" PROGNAME ")"); - f->maxstacksize=1; - pc=2*n+1; - f->code=luaM_newvector(L,pc,Instruction); - f->sizecode=pc; - f->p=luaM_newvector(L,n,Proto*); - f->sizep=n; - pc=0; - for (i=0; ip[i]=toproto(L,i-n-1); - f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); - f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); - } - f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,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); -} - -struct Smain { - int argc; - char** argv; -}; - -static int pmain(lua_State* L) -{ - struct Smain* s = (struct Smain*)lua_touserdata(L, 1); - int argc=s->argc; - char** argv=s->argv; - 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); - int result=luaU_dump_crosscompile(L,f,writer,D,stripping,target); - lua_unlock(L); - if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type"); - if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found"); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - struct Smain s; - - int test=1; - target.little_endian=*(char*)&test; - target.sizeof_int=sizeof(int); - target.sizeof_strsize_t=sizeof(strsize_t); - target.sizeof_lua_Number=sizeof(lua_Number); - target.lua_Number_integral=(((lua_Number)0.5)==0); - target.is_arm_fpa=0; - - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=lua_open(); - if (L==NULL) fatal("not enough memory for state"); - s.argc=argc; - s.argv=argv; - if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} diff --git a/components/lua/luaconf.h b/components/lua/luaconf.h index e5cdf041f9..075fc24e7d 100644 --- a/components/lua/luaconf.h +++ b/components/lua/luaconf.h @@ -10,6 +10,7 @@ #include #include +#include "sdkconfig.h" /* ** ================================================================== @@ -32,6 +33,11 @@ #define LUA_WIN #endif + +#if defined(LUA_CROSS_COMPILER) && !defined(_MSC_VER) && !defined(__MINGW32__) +#define LUA_USE_LINUX +#endif + #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ @@ -53,7 +59,7 @@ #if defined(LUA_USE_POSIX) #define LUA_USE_MKSTEMP #define LUA_USE_ISATTY -#define LUA_USE_POPEN +//#define LUA_USE_POPEN #define LUA_USE_ULONGJMP #endif @@ -161,7 +167,7 @@ #define LUA_INTEGER ptrdiff_t #else #if !defined LUA_INTEGRAL_LONGLONG - #define LUA_INTEGER long + #define LUA_INTEGER int #else #define LUA_INTEGER long long #endif // #if !defined LUA_INTEGRAL_LONGLONG @@ -251,11 +257,7 @@ #define lua_stdin_is_tty() isatty(0) #elif defined(LUA_WIN) #include -#ifdef LUA_CROSS_COMPILER -#include -else #include -#endif #define lua_stdin_is_tty() _isatty(_fileno(stdin)) #else @@ -481,7 +483,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length); /* 16-bit ints */ #define LUAI_UINT32 unsigned long #define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX +#define LUAI_MAXINT32 INT_MAX #define LUAI_UMEM unsigned long #define LUAI_MEM long #endif @@ -547,10 +549,10 @@ extern int readline4lua(const char *prompt, char *buffer, int length); @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. ** Attention: This value should probably not be set higher than 1K. ** The size has direct impact on the C stack size needed be auxlib functions. -** For example: If set to 4K a call to string.gsub will need more than +** For example: If set to 4K a call to string.gsub will need more than ** 5k C stack space. */ -#define LUAL_BUFFERSIZE 1024 +#define LUAL_BUFFERSIZE 256 /* }================================================================== */ @@ -568,10 +570,10 @@ extern int readline4lua(const char *prompt, char *buffer, int length); /* Define LUA_NUMBER_INTEGRAL to produce a system that uses no floating point operations by changing the type of Lua numbers from - double to long. It implements division and modulus so that + double to long. It implements division and modulus so that + + x == (x / y) * y + x % y. - x == (x / y) * y + x % y. - The exponentiation function returns zero for negative exponents. Defining LUA_NUMBER_INTEGRAL also removes the difftime function, and the math module should not be used. The string.format function @@ -601,8 +603,8 @@ extern int readline4lua(const char *prompt, char *buffer, int length); */ #if defined LUA_NUMBER_INTEGRAL #if !defined LUA_INTEGRAL_LONGLONG - #define LUA_NUMBER_SCAN "%ld" - #define LUA_NUMBER_FMT "%ld" + #define LUA_NUMBER_SCAN "%d" + #define LUA_NUMBER_FMT "%d" #else #define LUA_NUMBER_SCAN "%lld" #define LUA_NUMBER_FMT "%lld" @@ -745,18 +747,18 @@ union luai_Cast { double l_d; long l_l; }; { if ((c)->status == 0) (c)->status = -1; } #define luai_jmpbuf int /* dummy variable */ -#elif defined(LUA_USE_ULONGJMP) +#else +#if 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 - +#define LONGJMP(a,b) _longjmp(a,b) +#define SETJMP(a) _setjmp(a) #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 LONGJMP(a,b) longjmp(a,b) +#define SETJMP(a) setjmp(a) +#endif +#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 @@ -891,15 +893,8 @@ union luai_Cast { double l_d; long l_l; }; ** without modifying the main part of the file. */ -/* If you define the next macro you'll get the ability to set rotables as - metatables for tables/userdata/types (but the VM might run slower) -*/ -#if (LUA_OPTIMIZE_MEMORY == 2) && !defined(LUA_CROSS_COMPILER) -#define LUA_META_ROTABLES -#endif - -#if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN) -#error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)" +#if defined(LUA_USE_POPEN) +#error "Pipes not supported NodeMCU firmware" #endif #endif diff --git a/components/lua/lundump.c b/components/lua/lundump.c index 14ff1c3991..4ccb467719 100644 --- a/components/lua/lundump.c +++ b/components/lua/lundump.c @@ -9,7 +9,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "ldebug.h" #include "ldo.h" @@ -172,7 +172,7 @@ static TString* LoadString(LoadState* S) } else { s = (char*)luaZ_get_crt_address(S->Z); LoadBlock(S,NULL,size); - return luaS_newrolstr(S->L,s,size-1); + return luaS_newlstr(S->L,s,size-1); } } } @@ -280,7 +280,7 @@ static Proto* LoadFunction(LoadState* S, TString* p) Proto* f; if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); f=luaF_newproto(S->L); - if (luaZ_direct_mode(S->Z)) proto_readonly(f); + if (luaZ_direct_mode(S->Z)) l_setbit((f)->marked, READONLYBIT); setptvalue2s(S->L,S->L->top,f); incr_top(S->L); f->source=LoadString(S); if (f->source==NULL) f->source=p; f->linedefined=LoadInt(S); diff --git a/components/lua/lvm.c b/components/lua/lvm.c index c7e11de4e7..c3c971c685 100644 --- a/components/lua/lvm.c +++ b/components/lua/lvm.c @@ -10,9 +10,9 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STDIO -#include C_HEADER_STRING -#include C_HEADER_MATH +#include +#include +#include #include "ldebug.h" #include "ldo.h" @@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { TValue temp; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; - if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ - void *h = ttistable(t) ? hvalue(t) : rvalue(t); - const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */ + + 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 no nil? */ - (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); return; - } + } + /* else will try the tag method */ + } else if (ttisrotable(t)) { /* `t' is a table? */ + void *h = rvalue(t); + const TValue *res = luaH_get_ro(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, (Table*)luaR_getmeta(h), 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) || ttislightfunction(tm)) { callTMres(L, val, tm, t, key); return; @@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { L->top++; fixedstack(L); for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ - void *h = ttistable(t) ? hvalue(t) : rvalue(t); - TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */ - if ((oldval && !ttisnil(oldval)) || /* result is no nil? */ - (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */ - if(oldval) { - L->top--; - unfixedstack(L); - setobj2t(L, oldval, val); - ((Table *)h)->flags = 0; - luaC_barriert(L, (Table*)h, val); - } + const TValue *tm = NULL; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if ((!ttisnil(oldval)) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { + L->top--; + unfixedstack(L); + setobj2t(L, oldval, val); + ((Table *)h)->flags = 0; + luaC_barriert(L, (Table*)h, val); return; } /* else will try the tag method */ } + else if (ttisrotable(t)) { + luaG_runerror(L, "invalid write to ROM variable"); + } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); + if (ttisfunction(tm) || ttislightfunction(tm)) { L->top--; unfixedstack(L); @@ -292,8 +305,9 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { case LUA_TNIL: return 1; case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: case LUA_TROTABLE: + return rvalue(t1) == rvalue(t2); + case LUA_TLIGHTUSERDATA: case LUA_TLIGHTFUNCTION: return pvalue(t1) == pvalue(t2); case LUA_TUSERDATA: { @@ -320,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) { if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit; do { /* Any call which does a memory allocation may trim the stack, - invalidating top unless the stack is fixed duri ng the allocation */ + invalidating top unless the stack is fixed during the allocation */ StkId top = L->base + last + 1; fixedstack(L); int n = 2; /* number of elements handled in this pass (at least 2) */ diff --git a/components/lua/lzio.c b/components/lua/lzio.c index d4df1f1d41..16108489ee 100644 --- a/components/lua/lzio.c +++ b/components/lua/lzio.c @@ -10,7 +10,7 @@ #define LUAC_CROSS_FILE #include "lua.h" -#include C_HEADER_STRING +#include #include "llimits.h" #include "lmem.h" diff --git a/components/luac_cross/Makefile b/components/luac_cross/Makefile new file mode 100644 index 0000000000..54f9b96b4e --- /dev/null +++ b/components/luac_cross/Makefile @@ -0,0 +1,69 @@ +all: build + +ifeq ($V,) + Q:=@ +endif + +LUAC_CFLAGS:= -I$(COMPONENT_PATH)/../uzlib -I$(COMPONENT_PATH)/../lua -I$(BUILD_DIR_BASE)/include -I$(COMPONENT_PATH)/../base_nodemcu/include -O2 -g -Wall -Wextra +LUAC_LDFLAGS:= -ldl -lm + +LUAC_DEFINES += -DLUA_CROSS_COMPILER -DLUA_USE_STDIO +ifneq ($(CONFIG_LUA_OPTIMIZE_DEBUG),) +LUAC_DEFINES += -DLUA_OPTIMIZE_DEBUG=$(CONFIG_LUA_OPTIMIZE_DEBUG) +endif + +vpath %.c $(COMPONENT_PATH) $(COMPONENT_PATH)/../lua $(COMPONENT_PATH)/../uzlib $(COMPONENT_PATH)/../base_nodemcu + +LUAC_LUACSRC:= \ + luac.c lflashimg.c loslib.c print.c liolib.c + +LUAC_LUASRC:= $(addprefix $(COMPONENT_PATH)/../lua/, \ + lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c \ + ldo.c ldump.c lfunc.c lgc.c llex.c \ + lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c lparser.c \ + lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \ + ltm.c lundump.c lvm.c lzio.c \ +) + +LUAC_UZSRC:= $(addprefix $(COMPONENT_PATH)/../uzlib/, \ + uzlib_deflate.c crc32.c \ +) + +LUAC_NODEMCUSRC:= $(addprefix $(COMPONENT_PATH)/../base_nodemcu/, \ + linit.c \ +) + +LUAC_BUILD_DIR:=$(BUILD_DIR_BASE)/luac_cross + +LUAC_OBJS:=$(LUAC_LUACSRC:%.c=$(LUAC_BUILD_DIR)/%.o) +LUAC_OBJS+=$(LUAC_LUASRC:$(COMPONENT_PATH)/../lua/%.c=$(LUAC_BUILD_DIR)/%.o) +LUAC_OBJS+=$(LUAC_UZSRC:$(COMPONENT_PATH)/../uzlib/%.c=$(LUAC_BUILD_DIR)/%.o) +LUAC_OBJS+=$(LUAC_NODEMCUSRC:$(COMPONENT_PATH)/../base_nodemcu/%.c=$(LUAC_BUILD_DIR)/%.o) + + +LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d) + +LUAC_CROSS:=$(LUAC_BUILD_DIR)/luac.cross + +$(LUAC_BUILD_DIR): + @mkdir -p "$@" + +$(LUAC_BUILD_DIR)/%.o: | $(LUAC_BUILD_DIR) + @echo '[hostcc] $(notdir $@)' + $Q$(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) "$<" -c -o "$@" + +$(LUAC_BUILD_DIR)/%.d: SHELL=/bin/bash +$(LUAC_BUILD_DIR)/%.d: %.c | $(LUAC_BUILD_DIR) + @echo '[ dep] $<' + @rm -f "$@" + $Qset -eo pipefail; $(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) -M "$<" | sed 's,\($*\.o\)[ :]*,$(LUAC_BUILD_DIR)/\1 $@ : ,g' > "$@.tmp"; mv "$@.tmp" "$@" + +build: $(LUAC_DEPS) $(LUAC_CROSS) + +$(LUAC_CROSS): $(LUAC_OBJS) + @echo '[ link] $(notdir $@)' + $Q$(HOSTCC) $(LUAC_CFLAGS) $^ $(LUAC_LDFLAGS) -o "$@" + +ifneq ($(MAKECMDGOALS),clean) +-include $(LUAC_DEPS) +endif diff --git a/components/luac_cross/component.mk b/components/luac_cross/component.mk new file mode 100644 index 0000000000..b2ebcd7eb0 --- /dev/null +++ b/components/luac_cross/component.mk @@ -0,0 +1,6 @@ +COMPONENT_OWNBUILDTARGET:=build +COMPONENT_ADD_LDFLAGS:= + +build: + $(MAKE) -f $(COMPONENT_PATH)/Makefile HOSTCC=$(HOSTCC) BUILD_DIR_BASE=$(BUILD_DIR_BASE) V=$V COMPONENT_PATH=$(COMPONENT_PATH) CONFIG_LUA_OPTIMIZE_DEBUG=$(CONFIG_LUA_OPTIMIZE_DEBUG) + ar cr lib$(COMPONENT_NAME).a # work around IDF regression diff --git a/components/luac_cross/lflashimg.c b/components/luac_cross/lflashimg.c new file mode 100644 index 0000000000..4130b12bad --- /dev/null +++ b/components/luac_cross/lflashimg.c @@ -0,0 +1,447 @@ +/***-- +** lflashimg.c +** Dump a compiled Proto hiearchy to a RO (FLash) image file +** See Copyright Notice in lua.h +*/ + +#define LUAC_CROSS_FILE + +#include "luac_cross.h" +#include +#include +#include +#include + +#define lflashimg_c +#define LUA_CORE +#include "lobject.h" +#include "lstring.h" +#include "lflash.h" +#include "uzlib.h" + +//#define LOCAL_DEBUG + +#if INT_MAX != 2147483647 +# error "luac.cross requires C toolchain with 4 byte word size" +#endif +#define WORDSIZE ((int) sizeof(int)) +#define ALIGN(s) (((s)+(WORDSIZE-1)) & (-(signed) WORDSIZE)) +#define WORDSHIFT 2 +typedef unsigned int uint; +#define FLASH_WORDS(t) (sizeof(t)/sizeof(FlashAddr)) +/* + * + * This dumper is a variant of the standard ldump, in that instead of producing a + * binary loader format that lundump can load, it produces an image file that can be + * directly mapped or copied into addressable memory. The typical application is on + * small memory IoT devices which support programmable flash storage such as the + * ESP8266. A 64 Kb LFS image has 16Kb words and will enable all program-related + * storage to be accessed directly from flash, leaving the RAM for true R/W + * application data. + * + * The start address of the Lua Flash Store (LFS) is build-dependent, and the cross + * compiler '-a' option allows the developer to fix the LFS at a defined flash memory + * address. Alternatively and by default the cross compilation adopts a position + * independent image format, which permits the on-device image loader to load the LFS + * image at an appropriate base within the flash address space. As all objects in the + * LFS can be treated as multiples of 4-byte words, also all address fields are both + * word aligned, and any address references within the LFS are also word-aligned. + * + * This version adds gzip compression of the generated LFS image for more efficient + * over-the-air (OTA) transfer, so the method of tagging address words has been + * replaced by a scheme which achieves better compression: an additional bitmap + * has been added to the image, with each bit corresponding to a word in the image + * and set if the corresponding work is an address. The addresses are stored as + * signed relative word offsets. + * + * The unloader is documented in lflash.c Note that his relocation process is + * skipped for absolute addressed images (which are identified by the + * FLASH_SIG_ABSOLUTE bit setting in the flash signature). + * + * The flash image has a standard header detailed in lflash.h + * + * Note that luac.cross may be compiled on any little-endian machine with 32 or 64 bit + * word length so Flash addresses can't be handled as standard C pointers as size_t + * and int may not have the same size. Hence addresses with the must be declared as + * the FlashAddr type rather than typed C pointers and must be accessed through macros. + * + * Also note that image built with a given LUA_PACK_TVALUES / LUA_NUNBER_INTEGRAL + * combination must be loaded into a corresponding firmware build. Hence these + * configuration options are also included in the FLash Signature. + * + * The Flash image is assembled up by first building the RO stringtable containing + * all strings used in the compiled proto hierarchy. This is followed by the Protos. + * + * The storage is allocated bottom up using a serial allocator and the algortihm for + * building the image essentially does a bottom-uo serial enumeration so that any + * referenced storage has already been allocated in the image, and therefore (with the + * exception of the Flash Header) all pointer references are backwards. + * + * As addresses are 4 byte on the target and either 4 or (typically) 8 bytes on the + * host so any structures containing address fields (TStrings, TValues, Protos, other + * address vectors) need repacking. + */ + +typedef struct flashts { /* This is the fixed 32-bit equivalent of TString */ + FlashAddr next; + lu_byte tt; + lu_byte marked; + int hash; + int len; +} FlashTS; + +#ifndef LUA_MAX_FLASH_SIZE +#define LUA_MAX_FLASH_SIZE 0x10000 //in words +#endif + +static uint curOffset = 0; + +/* + * The flashAddrTag is a bit array, one bit per flashImage word denoting + * whether the corresponding word is a relative address. The defines + * are access methods for this bit array. + */ +static uint flashImage[LUA_MAX_FLASH_SIZE + LUA_MAX_FLASH_SIZE/32]; +static uint *flashAddrTag = flashImage + LUA_MAX_FLASH_SIZE; + +#define _TW(v) (v)>>5 +#define _TB(v) (1<<((v)&0x1F)) +#define setFlashAddrTag(v) flashAddrTag[_TW(v)] |= _TB(v) +#define getFlashAddrTag(v) ((flashAddrTag[_TW(v)]&_TB(v)) != 0) + +#ifdef _MSC_VER +extern void __declspec( noreturn ) fatal( const char* message ); +#else +extern void __attribute__((noreturn)) fatal(const char* message); +#endif + +#ifdef LOCAL_DEBUG +#define DBG_PRINT(...) printf(__VA_ARGS__) +#else +#define DBG_PRINT(...) ((void)0) +#endif + +/* + * Serial allocator. Throw a luac-style out of memory error is allocaiton fails. + */ +static void *flashAlloc(lua_State* L, size_t n) { + void *p = (void *)(flashImage + curOffset); + curOffset += ALIGN(n)>>WORDSHIFT; + if (curOffset > LUA_MAX_FLASH_SIZE) { + fatal("Out of Flash memory"); + } + return p; +} + +/* + * Convert an absolute address pointing inside the flash image to offset form. + * This macro form also takes the lvalue destination so that this can be tagged + * as a relocatable address. + */ +#define toFlashAddr(l, pd, s) _toFlashAddr(l, &(pd), s) +static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) { + uint doffset = cast(char *, a) - cast(char *,flashImage); + lua_assert(!(doffset & (WORDSIZE-1))); // check word aligned + doffset >>= WORDSHIFT; // and convert to a word offset + lua_assert(doffset <= curOffset); + if (p) { + uint poffset = cast(char *, p) - cast(char *,flashImage); + lua_assert(!(poffset & (WORDSIZE-1))); + poffset >>= WORDSHIFT; + lua_assert(poffset <= curOffset); + flashImage[doffset] = poffset; // Set the pointer to the offset + setFlashAddrTag(doffset); // And tag as an address + } /* else leave clear */ // Special case for NULL pointer +} + +/* + * Convert an image address in offset form back to (host) absolute form + */ +static void *fromFashAddr(FlashAddr a) { + return a ? cast(void *, flashImage + a) : NULL; +} + + +/* + * Add a TS found in the Proto Load to the table at the ToS + */ +static void addTS(lua_State *L, TString *ts) { + lua_assert(ts->tsv.tt==LUA_TSTRING); + lua_pushnil(L); + setsvalue(L, L->top-1, ts); + lua_pushinteger(L, 1); + lua_rawset(L, -3); + DBG_PRINT("Adding string: %s\n",getstr(ts)); +} + + +/* + * Enumerate all of the Protos in the Proto hiearchy and scan contents to collect + * all referenced strings in a Lua Array at ToS. + */ +static void scanProtoStrings(lua_State *L, const Proto* f) { + /* Table at L->Top[-1] is used to collect the strings */ + int i; + + if (f->source) + addTS(L, f->source); + +#ifdef LUA_OPTIMIZE_DEBUG + if (f->packedlineinfo) + addTS(L, luaS_new(L, cast(const char *, f->packedlineinfo))); +#endif + + for (i = 0; i < f->sizek; i++) { + if (ttisstring(f->k + i)) + addTS(L, rawtsvalue(f->k + i)); + } + for (i = 0; i < f->sizeupvalues; i++) addTS(L, f->upvalues[i]); + for (i = 0; i < f->sizelocvars; i++) addTS(L, f->locvars[i].varname); + for (i = 0; i < f->sizep; i++) scanProtoStrings(L, f->p[i]); +} + + +/* + * Use the collected strings table to build the new ROstrt in the Flash Image + * + * The input is an array of {"SomeString" = 1, ...} on the ToS. + * The output is an array of {"SomeString" = FlashOffset("SomeString"), ...} on ToS + */ +static void createROstrt(lua_State *L, FlashHeader *fh) { + + /* Table at L->Top[-1] on input is hash used to collect the strings */ + /* Count the number of strings. Can't use objlen as this is a hash */ + fh->nROuse = 0; + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + fh->nROuse++; + DBG_PRINT("Found: %s\n",getstr(rawtsvalue(L->top-2))); + lua_pop(L, 1); // dump the value + } + fh->nROsize = 2<nROuse); + FlashAddr *hashTab = flashAlloc(L, fh->nROsize * WORDSIZE); + toFlashAddr(L, fh->pROhash, hashTab); + + /* Now iterate over the strings to be added to the RO string table and build it */ + lua_newtable(L); // add output table + lua_pushnil(L); // First key + while (lua_next(L, -3) != 0) { // replaces key, pushes value + TString *ts = rawtsvalue(L->top - 2); // key.ts + const char *p = getstr(ts); // C string of key + uint hash = ts->tsv.hash; // hash of key + size_t len = ts->tsv.len; // and length + + DBG_PRINT("2nd pass: %s\n",p); + + FlashAddr *e = hashTab + lmod(hash, fh->nROsize); + FlashTS *last = cast(FlashTS *, fromFashAddr(*e)); + FlashTS *fts = cast(FlashTS *, flashAlloc(L, sizeof(FlashTS))); + toFlashAddr(L, *e, fts); // add reference to TS to lookup vector + toFlashAddr(L, fts->next, last); // and chain to previous entry if any + fts->tt = LUA_TSTRING; // Set as String + fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set + fts->hash = hash; // add hash + fts->len = len; // and length + memcpy(flashAlloc(L, len+1), p, len+1); // copy string + // include the trailing null char + lua_pop(L, 1); // Junk the value + lua_pushvalue(L, -1); // Dup the key as rawset dumps its copy + lua_pushinteger(L, cast(FlashAddr*,fts)-flashImage); // Value is new TS offset. + lua_rawset(L, -4); // Add to new table + } + /* At this point the old hash is done to derefence for GC */ + lua_remove(L, -2); +} + +/* + * Convert a TString reference in the host G(L)->strt entry into the corresponding + * TString address in the flashImage using the lookup table at ToS + */ +static void *resolveTString(lua_State* L, TString *s) { + if (!s) + return NULL; + lua_pushnil(L); + setsvalue(L, L->top-1, s); + lua_rawget(L, -2); + lua_assert(!lua_isnil(L, -1)); + void *ts = fromFashAddr(lua_tointeger(L, -1)); + lua_pop(L, 1); + return ts; +} + +/* + * In order to simplify repacking of structures from the host format to that target + * format, this simple copy routine is data-driven by a simple format specifier. + * n Number of consecutive records to be processed + * fmt A string of A, I, S, V specifiers spanning the record. + * src Source of record + * returns Address of destination record + */ +#if defined(LUA_PACK_TVALUES) +#define TARGET_TV_SIZE (sizeof(lua_Number)+sizeof(lu_int32)) +#else +#define TARGET_TV_SIZE (2*sizeof(lua_Number)) +#endif + +static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { + /* ToS is the string address mapping table */ + if (n == 0) + return NULL; + int i, recsize; + void *newts; + /* A bit of a botch because fmt is either "V" or a string of WORDSIZE specifiers */ + /* The size 8 / 12 / 16 bytes for integer builds, packed TV and default TVs resp */ + + if (fmt[0]=='V') { + lua_assert(fmt[1] == 0); /* V formats must be singetons */ + recsize = TARGET_TV_SIZE; + } else { + recsize = WORDSIZE * strlen(fmt); + } + + uint *d = cast(uint *, flashAlloc(L, n * recsize)); + uint *dest = d; + uint *s = cast(uint *, src); + + for (i = 0; i < n; i++) { + const char *p = fmt; + while (*p) { + /* All input address types (A,S,V) are aligned to size_t boundaries */ + if (*p != 'I' && ((size_t)s)&(sizeof(size_t)-1)) + s++; + + switch (*p++) { + case 'A': + toFlashAddr(L, *d, *cast(void**, s)); + s += FLASH_WORDS(size_t); + d++; + break; + case 'I': + *d++ = *s++; + break; + case 'H': + *d++ = (*s++) & 0; + break; + case 'S': + newts = resolveTString(L, *cast(TString **, s)); + toFlashAddr(L, *d, newts); + s += FLASH_WORDS(size_t); + d++; + break; + case 'V': + /* This code has to work for both Integer and Float build variants */ + memset(d, 0, TARGET_TV_SIZE); + TValue *sv = cast(TValue *, s); + /* The value is 0, 4 or 8 bytes depending on type */ + if (ttisstring(sv)) { + toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv))); + } else if (ttisnumber(sv)) { + *cast(lua_Number*,d) = *cast(lua_Number*,s); + } else if (!ttisnil(sv)){ + /* all other types are 4 byte */ + lua_assert(!iscollectable(sv)); + *cast(uint *,d) = *cast(uint *,s); + } + *cast(int *,cast(lua_Number*,d)+1) = ttype(sv); + s += FLASH_WORDS(TValue); + d += TARGET_TV_SIZE/WORDSIZE; + break; + default: + lua_assert (0); + } + } + } + return dest; +} + +/* The debug optimised version has a different Proto layout */ +#ifdef LUA_OPTIMIZE_DEBUG +#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIAI" +#else +#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIIAI" +#endif + +/* + * Do the actual prototype copy. + */ +static void *functionToFlash(lua_State* L, const Proto* orig) { + Proto f; + int i; + + memcpy (&f, orig, sizeof(Proto)); + f.gclist = NULL; + f.next = NULL; + l_setbit(f.marked, LFSBIT); /* OK to set the LFSBIT on a stack-cloned copy */ + + if (f.sizep) { /* clone included Protos */ + Proto **p = luaM_newvector(L, f.sizep, Proto *); + for (i=0; imainProto, functionToFlash(L, main)); + + fh->flash_sig = FLASH_SIG + (address ? FLASH_SIG_ABSOLUTE : 0); + fh->flash_size = curOffset*WORDSIZE; + if (fh->flash_size>maxSize) { + fatal ("The image is too large for specfied LFS size"); + } + if (address) { /* in absolute mode convert addresses to mapped address */ + for (i = 0 ; i < curOffset; i++) + if (getFlashAddrTag(i)) + flashImage[i] = 4*flashImage[i] + address; + lua_unlock(L); + status = w(L, flashImage, fh->flash_size, data); + } else { /* compressed PI mode */ + /* + * In image mode, shift the relocation bitmap down directly above + * the used flashimage. This consolidated array is then gzipped. + */ + uint oLen; + uint8_t *oBuf; + + int bmLen = sizeof(uint)*((curOffset+31)/32); /* 32 flags to a word */ + memmove(flashImage+curOffset, flashAddrTag, bmLen); + status = uzlib_compress (&oBuf, &oLen, + (const uint8_t *)flashImage, bmLen+fh->flash_size); + if (status != UZLIB_OK) { + fatal("Out of memory during image compression"); + } + lua_unlock(L); + #if 0 + status = w(L, flashImage, bmLen+fh->flash_size, data); + #else + status = w(L, oBuf, oLen, data); + free(oBuf); + #endif + + } + lua_lock(L); + return status; +} diff --git a/components/luac_cross/liolib.c b/components/luac_cross/liolib.c new file mode 100644 index 0000000000..3eda785682 --- /dev/null +++ b/components/luac_cross/liolib.c @@ -0,0 +1,492 @@ +/* +** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" +#include "lrotable.h" + +#define IO_INPUT 1 +#define IO_OUTPUT 2 +#define IO_STDERR 0 + +#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) +#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) + +/* "Pseudo-random" keys for the registry */ +static const size_t liolib_keys[] = { + (size_t)&luaL_callmeta, + (size_t)&luaL_typerror, + (size_t)&luaL_argerror + }; + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *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 FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +static int aux_close (lua_State *L) { + FILE **p = tofilep(L); + if(*p == stdin || *p == stdout || *p == stderr) + { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; + } + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, 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 idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + 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 = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + 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_objlen(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 - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +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); + 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); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(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) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* 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) - 1; + 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); + } + } + return pushresult(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) { + return g_write(L, tofile(L), 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); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(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 pushresult(L, res == 0, NULL); +} + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + +LROT_PUBLIC_BEGIN(iolib) + LROT_FUNCENTRY( close, io_close ) + LROT_FUNCENTRY( flush, io_flush ) + LROT_FUNCENTRY( input, io_input ) + LROT_FUNCENTRY( lines, io_lines ) + LROT_FUNCENTRY( open, io_open ) + LROT_FUNCENTRY( output, io_output ) + LROT_FUNCENTRY( read, io_read ) + LROT_FUNCENTRY( type, io_type ) + LROT_FUNCENTRY( write, io_write ) + LROT_TABENTRY( __index, iolib ) +LROT_END(iolib, NULL, 0) + +LROT_BEGIN(flib) + LROT_FUNCENTRY( close, io_close ) + LROT_FUNCENTRY( flush, f_flush ) + LROT_FUNCENTRY( lines, f_lines ) + LROT_FUNCENTRY( read, f_read ) + LROT_FUNCENTRY( seek, f_seek ) + LROT_FUNCENTRY( setvbuf, f_setvbuf ) + LROT_FUNCENTRY( write, f_write ) + LROT_FUNCENTRY( __gc, io_gc ) + LROT_FUNCENTRY( __tostring, io_tostring ) + LROT_TABENTRY( __index, flib ) +LROT_END(flib, NULL, LROT_MASK_GC_INDEX) + +static const luaL_Reg io_base[] = {{NULL, NULL}}; + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, (int)(liolib_keys[k])); + lua_setfield(L, -2, fname); +} + +LUALIB_API int luaopen_io(lua_State *L) { + luaL_rometatable(L, LUA_FILEHANDLE, LROT_TABLEREF(flib)); /* create metatable for file handles */ + luaL_register_light(L, LUA_IOLIBNAME, io_base); + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); + lua_pushliteral(L, "__index"); + lua_pushrotable(L, LROT_TABLEREF(iolib)); + lua_rawset(L, -3); + + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, IO_STDERR, "stderr"); + return 1; +} diff --git a/components/lua/luac_cross/loslib.c b/components/luac_cross/loslib.c similarity index 87% rename from components/lua/luac_cross/loslib.c rename to components/luac_cross/loslib.c index a35d2941b2..fb381ef77d 100644 --- a/components/lua/luac_cross/loslib.c +++ b/components/luac_cross/loslib.c @@ -7,11 +7,11 @@ #define LUAC_CROSS_FILE #include "luac_cross.h" -#include C_HEADER_ERRNO -#include C_HEADER_LOCALE -#include C_HEADER_STDLIB -#include C_HEADER_STRING -#include C_HEADER_TIME +#include +#include +#include +#include +#include #define loslib_c #define LUA_LIB @@ -218,33 +218,34 @@ static int os_setlocale (lua_State *L) { static int os_exit (lua_State *L) { - c_exit(luaL_optint(L, 1, EXIT_SUCCESS)); + exit(luaL_optint(L, 1, EXIT_SUCCESS)); } #undef MIN_OPT_LEVEL #define MIN_OPT_LEVEL 1 -#include "lrodefs.h" -const LUA_REG_TYPE syslib[] = { - {LSTRKEY("clock"), LFUNCVAL(os_clock)}, - {LSTRKEY("date"), LFUNCVAL(os_date)}, +#include "lrotable.h" +LROT_PUBLIC_BEGIN(oslib) + LROT_FUNCENTRY(clock, os_clock) + LROT_FUNCENTRY(date, os_date) #if !defined LUA_NUMBER_INTEGRAL - {LSTRKEY("difftime"), LFUNCVAL(os_difftime)}, + LROT_FUNCENTRY(difftime, os_difftime) #endif - {LSTRKEY("execute"), LFUNCVAL(os_execute)}, - {LSTRKEY("exit"), LFUNCVAL(os_exit)}, - {LSTRKEY("getenv"), LFUNCVAL(os_getenv)}, - {LSTRKEY("remove"), LFUNCVAL(os_remove)}, - {LSTRKEY("rename"), LFUNCVAL(os_rename)}, - {LSTRKEY("setlocale"), LFUNCVAL(os_setlocale)}, - {LSTRKEY("time"), LFUNCVAL(os_time)}, - {LSTRKEY("tmpname"), LFUNCVAL(os_tmpname)}, - {LNILKEY, LNILVAL} -}; + LROT_FUNCENTRY(execute, os_execute) + LROT_FUNCENTRY(exit, os_exit) + LROT_FUNCENTRY(getenv, os_getenv) + LROT_FUNCENTRY(remove, os_remove) + LROT_FUNCENTRY(rename, os_rename) + LROT_FUNCENTRY(setlocale, os_setlocale) + LROT_FUNCENTRY(time, os_time) + LROT_FUNCENTRY(tmpname, os_tmpname) +LROT_END(oslib, NULL, 0) + /* }====================================================== */ LUALIB_API int luaopen_os (lua_State *L) { - LREGISTER(L, LUA_OSLIBNAME, syslib); + //LREGISTER(L, LUA_OSLIBNAME, oslib); // <------------- ??? + return 0; } diff --git a/components/luac_cross/luac.c b/components/luac_cross/luac.c new file mode 100644 index 0000000000..729937bd24 --- /dev/null +++ b/components/luac_cross/luac.c @@ -0,0 +1,346 @@ +/* +** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#define LUAC_CROSS_FILE + +#include "luac_cross.h" +#include +#include +#include +#include + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#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 int flash=0; /* output flash image */ +static lu_int32 address=0; /* output flash image at absolute location */ +static lu_int32 maxSize=0x40000; /* maximuum uncompressed image size */ +static int lookup=0; /* output lookup-style master combination header */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* execute; /* executed a Lua file */ +static const char* progname=PROGNAME; /* actual program name */ +static DumpTargetInfo target; + +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" + " - process stdin\n" + " -l list\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -e name execute a lua source file\n" + " -f output a flash image file\n" + " -a addr generate an absolute, rather than position independent flash image file\n" + " -i generate lookup combination master (default with option -f)\n" + " -m size maximum LFS image in bytes\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\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))->l.p) + +static TString *corename(lua_State *L, const TString *filename) +{ + const char *fn = getstr(filename)+1; + const char *s = strrchr(fn, '/'); + if (!s) s = strrchr(fn, '\\'); + s = s ? s + 1 : fn; + while (*s == '.') s++; + const char *e = strchr(s, '.'); + int l = e ? e - s: strlen(s); + return l ? luaS_newlstr (L, s, l) : luaS_new(L, fn); +} +/* + * If the luac command line includes multiple files or has the -f option + * then luac generates a main function to reference all sub-main prototypes. + * This is one of two types: + * Type 0 The standard luac combination main + * Type 1 A lookup wrapper that facilitates indexing into the generated protos + */ +static const Proto* combine(lua_State* L, int n, int type) +{ + if (n==1 && type == 0) + return toproto(L,-1); + else + { + int i; + Instruction *pc; + Proto* f=luaF_newproto(L); + setptvalue2s(L,L->top,f); incr_top(L); + f->source=luaS_newliteral(L,"=(" PROGNAME ")"); + f->p=luaM_newvector(L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=toproto(L,i-n-1); + pc=0; + + if (type == 0) { + /* + * Type 0 is as per the standard luac, which is just a main routine which + * invokes all of the compiled functions sequentially. This is fine if + * they are self registering modules, but useless otherwise. + */ + f->numparams = 0; + f->maxstacksize = 1; + f->sizecode = 2*n + 1 ; + f->sizek = 0; + f->code = luaM_newvector(L, f->sizecode , Instruction); + f->k = luaM_newvector(L,f->sizek,TValue); + + for (i=0, pc = f->code; i LFIELDS_PER_FLUSH) { +#define NO_MOD_ERR_(n) ": Number of modules > " #n +#define NO_MOD_ERR(n) NO_MOD_ERR_(n) + usage(LUA_QL("-f") NO_MOD_ERR(LFIELDS_PER_FLUSH)); + } + f->numparams = 1; + f->maxstacksize = n + 3; + f->sizecode = 5*n + 5 ; + f->sizek = n + 1; + f->sizelocvars = 0; + f->code = luaM_newvector(L, f->sizecode , Instruction); + f->k = luaM_newvector(L,f->sizek,TValue); + for (i=0, pc = f->code; ik+i,corename(L, f->p[i]->source)); + *pc++ = CREATE_ABC(OP_EQ,0,0,RKASK(i)); + *pc++ = CREATE_ABx(OP_JMP,0,MAXARG_sBx+2); + *pc++ = CREATE_ABx(OP_CLOSURE,1,i); + *pc++ = CREATE_ABC(OP_RETURN,1,2,0); + } + + setnvalue(f->k+n, (lua_Number) time(NULL)); + + *pc++ = CREATE_ABx(OP_LOADK,1,n); + *pc++ = CREATE_ABC(OP_NEWTABLE,2,luaO_int2fb(i),0); + for (i=0; icode) == f->sizecode); + + 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); +} + +struct Smain { + int argc; + char** argv; +}; + +#if defined(_MSC_VER) || defined(__MINGW32__) +typedef unsigned int uint; +#endif +extern uint dumpToFlashImage (lua_State* L,const Proto *main, lua_Writer w, + void* data, int strip, + lu_int32 address, lu_int32 maxSize); + +static int pmain(lua_State* L) +{ + struct Smain* s = (struct Smain*)lua_touserdata(L, 1); + int argc=s->argc; + char** argv=s->argv; + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + if (execute) + { + if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1)); + luaL_openlibs(L); + lua_pushstring(L, execute); + if (lua_pcall(L, 1, 1, 0)) fatal(lua_tostring(L,-1)); + if (!lua_isfunction(L, -1)) + { + lua_pop(L,1); + if(argc == 0) return 0; + execute = NULL; + } + } + for (i=0; i1); + if (dumping) + { + int result; + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + if (flash) + { + result=dumpToFlashImage(L,f,writer, D, stripping, address, maxSize); + } else + { + result=luaU_dump_crosscompile(L,f,writer,D,stripping,target); + } + lua_unlock(L); + if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type"); + if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found"); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + struct Smain s; + + int test=1; + target.little_endian=*(char*)&test; + target.sizeof_int=sizeof(int); + target.sizeof_strsize_t=sizeof(strsize_t); + target.sizeof_lua_Number=sizeof(lua_Number); + target.lua_Number_integral=(((lua_Number)0.5)==0); + target.is_arm_fpa=0; + + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0 && execute==0) usage("no input files given"); + L=lua_open(); + if (L==NULL) fatal("not enough memory for state"); + s.argc=argc; + s.argv=argv; + if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} diff --git a/components/lua/luac_cross/print.c b/components/luac_cross/print.c similarity index 99% rename from components/lua/luac_cross/print.c rename to components/luac_cross/print.c index 1273d47e71..71b8352ac2 100644 --- a/components/lua/luac_cross/print.c +++ b/components/luac_cross/print.c @@ -7,8 +7,8 @@ #define LUAC_CROSS_FILE #include "luac_cross.h" -#include C_HEADER_CTYPE -#include C_HEADER_STDIO +#include +#include #define luac_c #define LUA_CORE diff --git a/components/modules/adc.c b/components/modules/adc.c index 94cabee79b..d0c60c4920 100644 --- a/components/modules/adc.c +++ b/components/modules/adc.c @@ -60,18 +60,16 @@ static int read_hall_sensor( lua_State *L ) } // Module function map -static const LUA_REG_TYPE adc_map[] = -{ - { LSTRKEY( "setwidth" ), LFUNCVAL( adc_set_width ) }, - { LSTRKEY( "setup" ), LFUNCVAL( adc_setup ) }, - { LSTRKEY( "read" ), LFUNCVAL( adc_read ) }, - { LSTRKEY( "read_hall_sensor" ), LFUNCVAL( read_hall_sensor ) }, - { LSTRKEY( "ATTEN_0db" ), LNUMVAL( PLATFORM_ADC_ATTEN_0db ) }, - { LSTRKEY( "ATTEN_2_5db" ), LNUMVAL( PLATFORM_ADC_ATTEN_2_5db ) }, - { LSTRKEY( "ATTEN_6db" ), LNUMVAL( PLATFORM_ADC_ATTEN_6db ) }, - { LSTRKEY( "ATTEN_11db" ), LNUMVAL( PLATFORM_ADC_ATTEN_11db ) }, - { LSTRKEY( "ADC1" ), LNUMVAL( 1 ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(adc) + LROT_FUNCENTRY( setwidth, adc_set_width ) + LROT_FUNCENTRY( setup, adc_setup ) + LROT_FUNCENTRY( read, adc_read ) + LROT_FUNCENTRY( read_hall_sensor, read_hall_sensor ) + LROT_NUMENTRY ( ATTEN_0db, PLATFORM_ADC_ATTEN_0db ) + LROT_NUMENTRY ( ATTEN_2_5db, PLATFORM_ADC_ATTEN_2_5db ) + LROT_NUMENTRY ( ATTEN_6db, PLATFORM_ADC_ATTEN_6db ) + LROT_NUMENTRY ( ATTEN_11db, PLATFORM_ADC_ATTEN_11db ) + LROT_NUMENTRY ( ADC1, 1 ) +LROT_END(adc, NULL, 0) -NODEMCU_MODULE(ADC, "adc", adc_map, NULL); +NODEMCU_MODULE(ADC, "adc", adc, NULL); diff --git a/components/modules/bit.c b/components/modules/bit.c index 67c0f2a3ac..b7b62cc048 100644 --- a/components/modules/bit.c +++ b/components/modules/bit.c @@ -119,20 +119,19 @@ static int bit_clear( lua_State* L ) return 1; } -static const LUA_REG_TYPE bit_map[] = { - { LSTRKEY( "bnot" ), LFUNCVAL( bit_bnot ) }, - { LSTRKEY( "band" ), LFUNCVAL( bit_band ) }, - { LSTRKEY( "bor" ), LFUNCVAL( bit_bor ) }, - { LSTRKEY( "bxor" ), LFUNCVAL( bit_bxor ) }, - { LSTRKEY( "lshift" ), LFUNCVAL( bit_lshift ) }, - { LSTRKEY( "rshift" ), LFUNCVAL( bit_rshift ) }, - { LSTRKEY( "arshift" ), LFUNCVAL( bit_arshift ) }, - { LSTRKEY( "bit" ), LFUNCVAL( bit_bit ) }, - { LSTRKEY( "set" ), LFUNCVAL( bit_set ) }, - { LSTRKEY( "clear" ), LFUNCVAL( bit_clear ) }, - { LSTRKEY( "isset" ), LFUNCVAL( bit_isset ) }, - { LSTRKEY( "isclear" ), LFUNCVAL( bit_isclear ) }, - { LNILKEY, LNILVAL} -}; - -NODEMCU_MODULE(BIT, "bit", bit_map, NULL); +LROT_BEGIN(bit) + LROT_FUNCENTRY( bnot, bit_bnot ) + LROT_FUNCENTRY( band, bit_band ) + LROT_FUNCENTRY( bor, bit_bor ) + LROT_FUNCENTRY( bxor, bit_bxor ) + LROT_FUNCENTRY( lshift, bit_lshift ) + LROT_FUNCENTRY( rshift, bit_rshift ) + LROT_FUNCENTRY( arshift, bit_arshift ) + LROT_FUNCENTRY( bit, bit_bit ) + LROT_FUNCENTRY( set, bit_set ) + LROT_FUNCENTRY( clear, bit_clear ) + LROT_FUNCENTRY( isset, bit_isset ) + LROT_FUNCENTRY( isclear, bit_isclear ) +LROT_END(bit, NULL, 0) + +NODEMCU_MODULE(BIT, "bit", bit, NULL); diff --git a/components/modules/bthci.c b/components/modules/bthci.c index 8fb79687e2..87006513cf 100644 --- a/components/modules/bthci.c +++ b/components/modules/bthci.c @@ -536,46 +536,38 @@ static int lbthci_rawhci (lua_State *L) } -static const LUA_REG_TYPE bthci_adv_map[] = -{ - { LSTRKEY( "enable" ), LFUNCVAL( lbthci_adv_enable ) }, - { LSTRKEY( "setdata" ), LFUNCVAL( lbthci_adv_setdata ) }, - { LSTRKEY( "setparams" ), LFUNCVAL( lbthci_adv_setparams ) }, +LROT_BEGIN(bthci_adv) + LROT_FUNCENTRY( enable, lbthci_adv_enable ) + LROT_FUNCENTRY( setdata, lbthci_adv_setdata ) + LROT_FUNCENTRY( setparams, lbthci_adv_setparams ) // Advertising types - { LSTRKEY( "CONN_UNDIR"), LNUMVAL( ADV_IND ) }, - { LSTRKEY( "CONN_DIR_HI"), LNUMVAL( ADV_DIRECT_IND_HI_DUTY ) }, - { LSTRKEY( "SCAN_UNDIR"), LNUMVAL( ADV_SCAN_IND ) }, - { LSTRKEY( "NONCONN_UNDIR"), LNUMVAL( ADV_NONCONN_IND ) }, - { LSTRKEY( "CONN_DIR_LO"), LNUMVAL( ADV_DIRECT_IND_LO_DUTY ) }, - - { LSTRKEY( "CHAN_37" ), LNUMVAL( ADV_CHAN_37 ) }, - { LSTRKEY( "CHAN_38" ), LNUMVAL( ADV_CHAN_38 ) }, - { LSTRKEY( "CHAN_39" ), LNUMVAL( ADV_CHAN_39 ) }, - { LSTRKEY( "CHAN_ALL" ), LNUMVAL( ADV_CHAN_ALL ) }, - - { LNILKEY, LNILVAL } -}; - - -static const LUA_REG_TYPE bthci_scan_map[] = -{ - { LSTRKEY( "enable" ), LFUNCVAL( lbthci_scan ) }, - { LSTRKEY( "setparams" ), LFUNCVAL( lbthci_scan_setparams ) }, - { LSTRKEY( "on" ), LFUNCVAL( lbthci_scan_on ) }, - { LNILKEY, LNILVAL } -}; - - -static const LUA_REG_TYPE bthci_map[] = -{ - { LSTRKEY( "rawhci" ), LFUNCVAL( lbthci_rawhci ) }, - { LSTRKEY( "reset" ), LFUNCVAL( lbthci_reset ) }, - { LSTRKEY( "adv" ), LROVAL( bthci_adv_map ) }, - { LSTRKEY( "scan" ), LROVAL( bthci_scan_map ) }, - - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(BTHCI, "bthci", bthci_map, lbthci_init); + LROT_NUMENTRY ( CONN_UNDIR, ADV_IND ) + LROT_NUMENTRY ( CONN_DIR_HI, ADV_DIRECT_IND_HI_DUTY ) + LROT_NUMENTRY ( SCAN_UNDIR, ADV_SCAN_IND ) + LROT_NUMENTRY ( NONCONN_UNDIR, ADV_NONCONN_IND ) + LROT_NUMENTRY ( CONN_DIR_LO, ADV_DIRECT_IND_LO_DUTY ) + + LROT_NUMENTRY ( CHAN_37, ADV_CHAN_37 ) + LROT_NUMENTRY ( CHAN_38, ADV_CHAN_38 ) + LROT_NUMENTRY ( CHAN_39, ADV_CHAN_39 ) + LROT_NUMENTRY ( CHAN_ALL, ADV_CHAN_ALL ) +LROT_END(bthci_adv, NULL, 0) + + +LROT_BEGIN(bthci_scan) + LROT_FUNCENTRY( enable, lbthci_scan ) + LROT_FUNCENTRY( setparams, lbthci_scan_setparams ) + LROT_FUNCENTRY( on, lbthci_scan_on ) +LROT_END(bthci_scan, NULL, 0) + + +LROT_BEGIN(bthci) + LROT_FUNCENTRY( rawhci, lbthci_rawhci ) + LROT_FUNCENTRY( reset, lbthci_reset ) + LROT_TABENTRY ( adv, bthci_adv ) + LROT_TABENTRY ( scan, bthci_scan ) +LROT_END(bthci, NULL, 0) + +NODEMCU_MODULE(BTHCI, "bthci", bthci, lbthci_init); #endif diff --git a/components/modules/can.c b/components/modules/can.c index 3768a59b0d..e9576a75bf 100644 --- a/components/modules/can.c +++ b/components/modules/can.c @@ -148,16 +148,14 @@ static int can_send( lua_State *L ) } // Module function map -static const LUA_REG_TYPE can_map[] = -{ - { LSTRKEY( "setup" ), LFUNCVAL( can_setup ) }, - { LSTRKEY( "start" ), LFUNCVAL( can_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( can_stop ) }, - { LSTRKEY( "send" ), LFUNCVAL( can_send ) }, - { LSTRKEY( "STANDARD_FRAME" ), LNUMVAL( 0 ) }, - { LSTRKEY( "EXTENDED_FRAME" ), LNUMVAL( 1 ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(can) + LROT_FUNCENTRY( setup, can_setup ) + LROT_FUNCENTRY( start, can_start ) + LROT_FUNCENTRY( stop, can_stop ) + LROT_FUNCENTRY( send, can_send ) + LROT_NUMENTRY ( STANDARD_FRAME, 0 ) + LROT_NUMENTRY ( EXTENDED_FRAME, 1 ) +LROT_END(can, NULL, 0) int luaopen_can( lua_State *L ) { can_data_task_id = task_get_id( can_data_task ); // reset CAN after sw reset @@ -165,4 +163,4 @@ int luaopen_can( lua_State *L ) { return 0; } -NODEMCU_MODULE(CAN, "can", can_map, luaopen_can); +NODEMCU_MODULE(CAN, "can", can, luaopen_can); diff --git a/components/modules/crypto.c b/components/modules/crypto.c index f1e1fbf472..42d96fa317 100644 --- a/components/modules/crypto.c +++ b/components/modules/crypto.c @@ -153,18 +153,18 @@ static int crypto_hash_gc(lua_State* L) { } // The following table defines methods of the hasher object -static const LUA_REG_TYPE crypto_hasher_map[] = { - {LSTRKEY("update"), LFUNCVAL(crypto_hash_update)}, - {LSTRKEY("finalize"), LFUNCVAL(crypto_hash_finalize)}, - {LSTRKEY("__gc"), LFUNCVAL(crypto_hash_gc)}, - {LSTRKEY("__index"), LROVAL(crypto_hasher_map)}, - {LNILKEY, LNILVAL}}; +LROT_BEGIN(crypto_hasher) + LROT_FUNCENTRY(update, crypto_hash_update) + LROT_FUNCENTRY(finalize, crypto_hash_finalize) + LROT_FUNCENTRY(__gc, crypto_hash_gc) + LROT_TABENTRY(__index, crypto_hasher) +LROT_END(crypto_hasher, NULL, 0) // This table defines the functions of the crypto module: -static const LUA_REG_TYPE crypto_map[] = { - {LSTRKEY("new_hash"), LFUNCVAL(crypto_new_hash)}, - {LSTRKEY("new_hmac"), LFUNCVAL(crypto_new_hmac)}, - {LNILKEY, LNILVAL}}; +LROT_BEGIN(crypto) + LROT_FUNCENTRY(new_hash, crypto_new_hash) + LROT_FUNCENTRY(new_hmac, crypto_new_hmac) +LROT_END(crypto, NULL, 0) // luaopen_crypto is the crypto module initialization function int luaopen_crypto(lua_State* L) { @@ -174,4 +174,4 @@ int luaopen_crypto(lua_State* L) { } // define the crypto NodeMCU module -NODEMCU_MODULE(CRYPTO, "crypto", crypto_map, luaopen_crypto); +NODEMCU_MODULE(CRYPTO, "crypto", crypto, luaopen_crypto); diff --git a/components/modules/dac.c b/components/modules/dac.c index f39c97e9ff..449a4d625c 100644 --- a/components/modules/dac.c +++ b/components/modules/dac.c @@ -52,16 +52,12 @@ static int ldac_write( lua_State *L ) // Module function map -static const LUA_REG_TYPE dac_map[] = -{ - { LSTRKEY( "enable" ), LFUNCVAL( ldac_enable ) }, - { LSTRKEY( "disable" ), LFUNCVAL( ldac_disable ) }, - { LSTRKEY( "write" ), LFUNCVAL( ldac_write ) }, - - { LSTRKEY( "CHANNEL_1" ), LNUMVAL( DAC_CHANNEL_1 ) }, - { LSTRKEY( "CHANNEL_2" ), LNUMVAL( DAC_CHANNEL_2 ) }, - - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(DAC, "dac", dac_map, NULL); +LROT_BEGIN(dac) + LROT_FUNCENTRY( enable, ldac_enable ) + LROT_FUNCENTRY( disable, ldac_disable ) + LROT_FUNCENTRY( write, ldac_write ) + LROT_NUMENTRY ( CHANNEL_1, DAC_CHANNEL_1 ) + LROT_NUMENTRY ( CHANNEL_2, DAC_CHANNEL_2 ) +LROT_END(dac, NULL, 0) + +NODEMCU_MODULE(DAC, "dac", dac, NULL); diff --git a/components/modules/dht.c b/components/modules/dht.c index 581f0973f1..c348ad0008 100644 --- a/components/modules/dht.c +++ b/components/modules/dht.c @@ -91,13 +91,12 @@ static int ldht_read2x( lua_State *L ) } -static const LUA_REG_TYPE dht_map[] = { - { LSTRKEY( "read11" ), LFUNCVAL( ldht_read11 ) }, - { LSTRKEY( "read2x" ), LFUNCVAL( ldht_read2x ) }, - { LSTRKEY( "OK" ), LNUMVAL( LDHT_OK ) }, - { LSTRKEY( "ERROR_CHECKSUM" ), LNUMVAL( LDHT_ERROR_CHECKSUM ) }, - { LSTRKEY( "ERROR_TIMEOUT" ), LNUMVAL( LDHT_ERROR_TIMEOUT ) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(DHT, "dht", dht_map, NULL); +LROT_BEGIN(dht) + LROT_FUNCENTRY( read11, ldht_read11 ) + LROT_FUNCENTRY( read2x, ldht_read2x ) + LROT_NUMENTRY ( OK, LDHT_OK ) + LROT_NUMENTRY ( ERROR_CHECKSUM, LDHT_ERROR_CHECKSUM ) + LROT_NUMENTRY ( ERROR_TIMEOUT, LDHT_ERROR_TIMEOUT ) +LROT_END(dht, NULL, 0) + +NODEMCU_MODULE(DHT, "dht", dht, NULL); diff --git a/components/modules/encoder.c b/components/modules/encoder.c index fcac50b425..53c2fae5ba 100644 --- a/components/modules/encoder.c +++ b/components/modules/encoder.c @@ -156,12 +156,11 @@ static int do_func (lua_State *L, uint8_t * (*conv_func)(lua_State *, const uint DECLARE_FUNCTION(toHex); // Module function map -static const LUA_REG_TYPE encoder_map[] = { - { LSTRKEY("fromBase64"), LFUNCVAL(encoder_fromBase64) }, - { LSTRKEY("toBase64"), LFUNCVAL(encoder_toBase64) }, - { LSTRKEY("fromHex"), LFUNCVAL(encoder_fromHex) }, - { LSTRKEY("toHex"), LFUNCVAL(encoder_toHex) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(ENCODER, "encoder", encoder_map, NULL); +LROT_BEGIN(encoder) + LROT_FUNCENTRY(fromBase64, encoder_fromBase64) + LROT_FUNCENTRY(toBase64, encoder_toBase64) + LROT_FUNCENTRY(fromHex, encoder_fromHex) + LROT_FUNCENTRY(toHex, encoder_toHex) +LROT_END(encoder, NULL, 0) + +NODEMCU_MODULE(ENCODER, "encoder", encoder, NULL); diff --git a/components/modules/eth.c b/components/modules/eth.c index bee21a6307..714efd1998 100644 --- a/components/modules/eth.c +++ b/components/modules/eth.c @@ -264,7 +264,6 @@ static int leth_init( lua_State *L ) default: // prevented by opt_checkint_range break; - }; config.phy_addr = phy_addr; @@ -287,30 +286,21 @@ static int leth_init( lua_State *L ) return 0; } +LROT_BEGIN(eth) + LROT_FUNCENTRY( init, leth_init ) + LROT_FUNCENTRY( on, leth_on ) + LROT_FUNCENTRY( get_speed, leth_get_speed ) + LROT_FUNCENTRY( get_mac, leth_get_mac ) + LROT_FUNCENTRY( set_mac, leth_set_mac ) -static const LUA_REG_TYPE eth_map[] = -{ - { LSTRKEY( "init" ), LFUNCVAL( leth_init ) }, - { LSTRKEY( "on" ), LFUNCVAL( leth_on ) }, - { LSTRKEY( "get_speed" ), LFUNCVAL( leth_get_speed ) }, - { LSTRKEY( "get_mac" ), LFUNCVAL( leth_get_mac ) }, - { LSTRKEY( "set_mac" ), LFUNCVAL( leth_set_mac ) }, - - { LSTRKEY( "PHY_LAN8720" ), LNUMVAL( ETH_PHY_LAN8720 ) }, - { LSTRKEY( "PHY_TLK110" ), LNUMVAL( ETH_PHY_TLK110 ) }, - { LSTRKEY( "PHY_IP101" ), LNUMVAL( ETH_PHY_IP101 ) }, - - { LSTRKEY( "CLOCK_GPIO0_IN" ), LNUMVAL( ETH_CLOCK_GPIO0_IN ) }, - { LSTRKEY( "CLOCK_GPIO0_OUT" ), LNUMVAL( ETH_CLOCK_GPIO0_OUT ) }, - { LSTRKEY( "CLOCK_GPIO16_OUT" ), LNUMVAL( ETH_CLOCK_GPIO16_OUT ) }, - { LSTRKEY( "CLOCK_GPIO17_OUT" ), LNUMVAL( ETH_CLOCK_GPIO17_OUT ) }, - - { LNILKEY, LNILVAL } -}; + LROT_NUMENTRY( PHY_LAN8720, ETH_PHY_LAN8720 ) + LROT_NUMENTRY( PHY_TLK110, ETH_PHY_TLK110 ) + LROT_NUMENTRY( PHY_IP101, ETH_PHY_IP101 ) -static int eth_init( lua_State *L ) -{ - return 1; -} + LROT_NUMENTRY( CLOCK_GPIO0_IN, ETH_CLOCK_GPIO0_IN ) + LROT_NUMENTRY( CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO0_OUT ) + LROT_NUMENTRY( CLOCK_GPIO16_OUT, ETH_CLOCK_GPIO16_OUT ) + LROT_NUMENTRY( CLOCK_GPIO17_OUT, ETH_CLOCK_GPIO17_OUT ) +LROT_END(eth, NULL, 0) -NODEMCU_MODULE(ETH, "eth", eth_map, eth_init); +NODEMCU_MODULE(ETH, "eth", eth, NULL); diff --git a/components/modules/file.c b/components/modules/file.c index e6d9a7a05f..0a257f5e81 100644 --- a/components/modules/file.c +++ b/components/modules/file.c @@ -550,50 +550,47 @@ static int file_chdir( lua_State *L ) } #endif -static const LUA_REG_TYPE file_obj_map[] = -{ - { LSTRKEY( "close" ), LFUNCVAL( file_close ) }, - { LSTRKEY( "read" ), LFUNCVAL( file_read ) }, - { LSTRKEY( "readline" ), LFUNCVAL( file_readline ) }, - { LSTRKEY( "write" ), LFUNCVAL( file_write ) }, - { LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) }, - { LSTRKEY( "seek" ), LFUNCVAL( file_seek ) }, - { LSTRKEY( "flush" ), LFUNCVAL( file_flush ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( file_obj_free ) }, - { LSTRKEY( "__index" ), LROVAL( file_obj_map ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(file_obj) + LROT_FUNCENTRY( close, file_close ) + LROT_FUNCENTRY( read, file_read ) + LROT_FUNCENTRY( readline, file_readline ) + LROT_FUNCENTRY( write, file_write ) + LROT_FUNCENTRY( writeline, file_writeline ) + LROT_FUNCENTRY( seek, file_seek ) + LROT_FUNCENTRY( flush, file_flush ) + LROT_FUNCENTRY( __gc, file_obj_free ) + LROT_TABENTRY ( __index, file_obj ) +LROT_END(file_obj, NULL, 0) // Module function map -static const LUA_REG_TYPE file_map[] = { - { LSTRKEY( "list" ), LFUNCVAL( file_list ) }, - { LSTRKEY( "open" ), LFUNCVAL( file_open ) }, - { LSTRKEY( "close" ), LFUNCVAL( file_close ) }, - { LSTRKEY( "write" ), LFUNCVAL( file_write ) }, - { LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) }, - { LSTRKEY( "read" ), LFUNCVAL( file_read ) }, - { LSTRKEY( "readline" ), LFUNCVAL( file_readline ) }, +LROT_BEGIN(file) + LROT_FUNCENTRY( list, file_list ) + LROT_FUNCENTRY( open, file_open ) + LROT_FUNCENTRY( close, file_close ) + LROT_FUNCENTRY( write, file_write ) + LROT_FUNCENTRY( writeline, file_writeline ) + LROT_FUNCENTRY( read, file_read ) + LROT_FUNCENTRY( readline, file_readline ) #ifdef CONFIG_BUILD_SPIFFS - { LSTRKEY( "format" ), LFUNCVAL( file_format ) }, - { LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) }, + LROT_FUNCENTRY( format, file_format ) + LROT_FUNCENTRY( fscfg, file_fscfg ) #endif - { LSTRKEY( "remove" ), LFUNCVAL( file_remove ) }, - { LSTRKEY( "seek" ), LFUNCVAL( file_seek ) }, - { LSTRKEY( "flush" ), LFUNCVAL( file_flush ) }, - { LSTRKEY( "rename" ), LFUNCVAL( file_rename ) }, - { LSTRKEY( "exists" ), LFUNCVAL( file_exists ) }, - { LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) }, - { LSTRKEY( "on" ), LFUNCVAL( file_on ) }, - { LSTRKEY( "stat" ), LFUNCVAL( file_stat ) }, + LROT_FUNCENTRY( remove, file_remove ) + LROT_FUNCENTRY( seek, file_seek ) + LROT_FUNCENTRY( flush, file_flush ) + LROT_FUNCENTRY( rename, file_rename ) + LROT_FUNCENTRY( exists, file_exists ) + LROT_FUNCENTRY( fsinfo, file_fsinfo ) + LROT_FUNCENTRY( on, file_on ) + LROT_FUNCENTRY( stat, file_stat ) #ifdef CONFIG_BUILD_FATFS - { LSTRKEY( "chdir" ), LFUNCVAL( file_chdir ) }, + LROT_FUNCENTRY( chdir, file_chdir ) #endif - { LNILKEY, LNILVAL } -}; +LROT_END(file, NULL, 0) int luaopen_file( lua_State *L ) { luaL_rometatable( L, "file.obj", (void *)file_obj_map ); return 0; } -NODEMCU_MODULE(FILE, "file", file_map, luaopen_file); +NODEMCU_MODULE(FILE, "file", file, luaopen_file); diff --git a/components/modules/gpio.c b/components/modules/gpio.c index 39a6bccf7e..e3ff68c27c 100644 --- a/components/modules/gpio.c +++ b/components/modules/gpio.c @@ -231,32 +231,29 @@ static int nodemcu_gpio_init (lua_State *L) } -static const LUA_REG_TYPE lgpio_map[] = -{ - { LSTRKEY( "config" ), LFUNCVAL( lgpio_config ) }, - { LSTRKEY( "read" ), LFUNCVAL( lgpio_read ) }, - { LSTRKEY( "trig" ), LFUNCVAL( lgpio_trig ) }, - { LSTRKEY( "wakeup" ), LFUNCVAL( lgpio_wakeup ) }, - { LSTRKEY( "write" ), LFUNCVAL( lgpio_write ) }, - - - { LSTRKEY( "OUT" ), LNUMVAL( GPIO_MODE_OUTPUT ) }, - { LSTRKEY( "IN" ), LNUMVAL( GPIO_MODE_INPUT ) }, - { LSTRKEY( "IN_OUT" ), LNUMVAL( GPIO_MODE_INPUT_OUTPUT ) }, - - { LSTRKEY( "FLOATING"), LNUMVAL( 0 ) }, - { LSTRKEY( "PULL_UP" ), LNUMVAL( PULL_UP ) }, - { LSTRKEY( "PULL_DOWN" ), LNUMVAL( PULL_DOWN ) }, - { LSTRKEY( "PULL_UP_DOWN"), LNUMVAL( PULL_UP | PULL_DOWN ) }, - - { LSTRKEY( "INTR_NONE" ), LNUMVAL( GPIO_INTR_DISABLE ) }, - { LSTRKEY( "INTR_UP" ), LNUMVAL( GPIO_INTR_POSEDGE ) }, - { LSTRKEY( "INTR_DOWN" ), LNUMVAL( GPIO_INTR_NEGEDGE ) }, - { LSTRKEY( "INTR_UP_DOWN" ), LNUMVAL( GPIO_INTR_ANYEDGE ) }, - { LSTRKEY( "INTR_LOW" ), LNUMVAL( GPIO_INTR_LOW_LEVEL ) }, - { LSTRKEY( "INTR_HIGH" ), LNUMVAL( GPIO_INTR_HIGH_LEVEL ) }, - - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(GPIO, "gpio", lgpio_map, nodemcu_gpio_init); +LROT_BEGIN(lgpio) + LROT_FUNCENTRY( config, lgpio_config ) + LROT_FUNCENTRY( read, lgpio_read ) + LROT_FUNCENTRY( trig, lgpio_trig ) + LROT_FUNCENTRY( wakeup, lgpio_wakeup ) + LROT_FUNCENTRY( write, lgpio_write ) + + + LROT_NUMENTRY ( OUT, GPIO_MODE_OUTPUT ) + LROT_NUMENTRY ( IN, GPIO_MODE_INPUT ) + LROT_NUMENTRY ( IN_OUT, GPIO_MODE_INPUT_OUTPUT ) + + LROT_NUMENTRY ( FLOATING, 0 ) + LROT_NUMENTRY ( PULL_UP, PULL_UP ) + LROT_NUMENTRY ( PULL_DOWN, PULL_DOWN ) + LROT_NUMENTRY ( PULL_UP_DOWN, PULL_UP | PULL_DOWN ) + + LROT_NUMENTRY ( INTR_NONE, GPIO_INTR_DISABLE ) + LROT_NUMENTRY ( INTR_UP, GPIO_INTR_POSEDGE ) + LROT_NUMENTRY ( INTR_DOWN, GPIO_INTR_NEGEDGE ) + LROT_NUMENTRY ( INTR_UP_DOWN, GPIO_INTR_ANYEDGE ) + LROT_NUMENTRY ( INTR_LOW, GPIO_INTR_LOW_LEVEL ) + LROT_NUMENTRY ( INTR_HIGH, GPIO_INTR_HIGH_LEVEL ) +LROT_END(lgpio, NULL, 0) + +NODEMCU_MODULE(GPIO, "gpio", lgpio, nodemcu_gpio_init); diff --git a/components/modules/http.c b/components/modules/http.c index d9ccad13b0..310d0dd465 100644 --- a/components/modules/http.c +++ b/components/modules/http.c @@ -778,32 +778,30 @@ static int http_lapi_post(lua_State *L) return make_oneshot_request(L, 4); // 4 = callback idx } -static const LUA_REG_TYPE http_map[] = { - { LSTRKEY("createConnection"), LFUNCVAL(http_lapi_createConnection) }, - { LSTRKEY("GET"), LNUMVAL(HTTP_METHOD_GET) }, - { LSTRKEY("POST"), LNUMVAL(HTTP_METHOD_POST) }, - { LSTRKEY("DELETE"), LNUMVAL(HTTP_METHOD_DELETE) }, - { LSTRKEY("HEAD"), LNUMVAL(HTTP_METHOD_HEAD) }, - { LSTRKEY("DELAYACK"), LNUMVAL(DELAY_ACK) }, - { LSTRKEY("ACKNOW"), LNUMVAL(0) }, // Doesn't really matter what this is - { LSTRKEY("get"), LFUNCVAL(http_lapi_get) }, - { LSTRKEY("post"), LFUNCVAL(http_lapi_post) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE http_context_map[] = { - { LSTRKEY("on"), LFUNCVAL(http_lapi_on) }, - { LSTRKEY("request"), LFUNCVAL(http_lapi_request) }, - { LSTRKEY("setmethod"), LFUNCVAL(http_lapi_setmethod) }, - { LSTRKEY("setheader"), LFUNCVAL(http_lapi_setheader) }, - { LSTRKEY("seturl"), LFUNCVAL(http_lapi_seturl) }, - { LSTRKEY("setpostdata"), LFUNCVAL(http_lapi_setpostdata) }, - { LSTRKEY("close"), LFUNCVAL(context_close) }, - { LSTRKEY("ack"), LFUNCVAL(http_lapi_ack) }, - { LSTRKEY("__gc"), LFUNCVAL(context_gc) }, - { LSTRKEY("__index"), LROVAL(http_context_map) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(http) + LROT_FUNCENTRY(createConnection, http_lapi_createConnection) + LROT_NUMENTRY (GET, HTTP_METHOD_GET) + LROT_NUMENTRY (POST, HTTP_METHOD_POST) + LROT_NUMENTRY (DELETE, HTTP_METHOD_DELETE) + LROT_NUMENTRY (HEAD, HTTP_METHOD_HEAD) + LROT_NUMENTRY (DELAYACK, DELAY_ACK) + LROT_NUMENTRY (ACKNOW, 0) // Doesn't really matter what this is + LROT_FUNCENTRY(get, http_lapi_get) + LROT_FUNCENTRY(post, http_lapi_post) +LROT_END(http, NULL, 0) + +LROT_BEGIN(http_context) + LROT_FUNCENTRY(on, http_lapi_on) + LROT_FUNCENTRY(request, http_lapi_request) + LROT_FUNCENTRY(setmethod, http_lapi_setmethod) + LROT_FUNCENTRY(setheader, http_lapi_setheader) + LROT_FUNCENTRY(seturl, http_lapi_seturl) + LROT_FUNCENTRY(setpostdata, http_lapi_setpostdata) + LROT_FUNCENTRY(close, context_close) + LROT_FUNCENTRY(ack, http_lapi_ack) + LROT_FUNCENTRY(__gc, context_gc) + LROT_TABENTRY (__index, http_context) +LROT_END(http_context, NULL, 0) static int luaopen_http(lua_State *L) { @@ -813,4 +811,4 @@ static int luaopen_http(lua_State *L) return 0; } -NODEMCU_MODULE(HTTP, "http", http_map, luaopen_http); +NODEMCU_MODULE(HTTP, "http", http, luaopen_http); diff --git a/components/modules/i2c.c b/components/modules/i2c.c index e457d4fc31..ed4ddd5600 100644 --- a/components/modules/i2c.c +++ b/components/modules/i2c.c @@ -202,25 +202,24 @@ static int i2c_read( lua_State *L ) } } -static const LUA_REG_TYPE i2c_map[] = { - { LSTRKEY( "setup" ), LFUNCVAL( i2c_setup ) }, - { LSTRKEY( "start" ), LFUNCVAL( i2c_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( i2c_stop ) }, - { LSTRKEY( "address" ), LFUNCVAL( i2c_address ) }, - { LSTRKEY( "write" ), LFUNCVAL( i2c_write ) }, - { LSTRKEY( "read" ), LFUNCVAL( i2c_read ) }, - { LSTRKEY( "transfer" ), LFUNCVAL( li2c_hw_master_transfer ) }, - { LSTRKEY( "slave"), LROVAL( li2c_slave_map ) }, - { LSTRKEY( "FASTPLUS" ), LNUMVAL( PLATFORM_I2C_SPEED_FASTPLUS ) }, - { LSTRKEY( "FAST" ), LNUMVAL( PLATFORM_I2C_SPEED_FAST ) }, - { LSTRKEY( "SLOW" ), LNUMVAL( PLATFORM_I2C_SPEED_SLOW ) }, - { LSTRKEY( "TRANSMITTER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_TRANSMITTER ) }, - { LSTRKEY( "RECEIVER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_RECEIVER ) }, - { LSTRKEY( "SW" ), LNUMVAL( I2C_ID_SW ) }, - { LSTRKEY( "HW0" ), LNUMVAL( I2C_ID_HW0 ) }, - { LSTRKEY( "HW1" ), LNUMVAL( I2C_ID_HW1 ) }, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(i2c) + LROT_FUNCENTRY( setup, i2c_setup ) + LROT_FUNCENTRY( start, i2c_start ) + LROT_FUNCENTRY( stop, i2c_stop ) + LROT_FUNCENTRY( address, i2c_address ) + LROT_FUNCENTRY( write, i2c_write ) + LROT_FUNCENTRY( read, i2c_read ) + LROT_FUNCENTRY( transfer, li2c_hw_master_transfer ) + LROT_TABENTRY ( slave, li2c_slave ) + LROT_NUMENTRY ( FASTPLUS, PLATFORM_I2C_SPEED_FASTPLUS ) + LROT_NUMENTRY ( FAST, PLATFORM_I2C_SPEED_FAST ) + LROT_NUMENTRY ( SLOW, PLATFORM_I2C_SPEED_SLOW ) + LROT_NUMENTRY ( TRANSMITTER, PLATFORM_I2C_DIRECTION_TRANSMITTER ) + LROT_NUMENTRY ( RECEIVER, PLATFORM_I2C_DIRECTION_RECEIVER ) + LROT_NUMENTRY ( SW, I2C_ID_SW ) + LROT_NUMENTRY ( HW0, I2C_ID_HW0 ) + LROT_NUMENTRY ( HW1, I2C_ID_HW1 ) +LROT_END(i2c, NULL, 0) int luaopen_i2c( lua_State *L ) { @@ -230,4 +229,4 @@ int luaopen_i2c( lua_State *L ) { } -NODEMCU_MODULE(I2C, "i2c", i2c_map, luaopen_i2c); +NODEMCU_MODULE(I2C, "i2c", i2c, luaopen_i2c); diff --git a/components/modules/i2c_common.h b/components/modules/i2c_common.h index 671bc27100..6098c798ff 100644 --- a/components/modules/i2c_common.h +++ b/components/modules/i2c_common.h @@ -29,7 +29,7 @@ int li2c_hw_master_transfer( lua_State *L ); // *************************************************************************** // Hardware slave prototypes // -extern const LUA_REG_TYPE li2c_slave_map[]; +LROT_EXTERN(li2c_slave); void li2c_hw_slave_init( lua_State *L ); diff --git a/components/modules/i2c_hw_slave.c b/components/modules/i2c_hw_slave.c index e53db11bdf..1564de9a88 100644 --- a/components/modules/i2c_hw_slave.c +++ b/components/modules/i2c_hw_slave.c @@ -318,12 +318,11 @@ static int li2c_slave_on( lua_State *L ) } -const LUA_REG_TYPE li2c_slave_map[] = { - { LSTRKEY( "on" ), LFUNCVAL( li2c_slave_on ) }, - { LSTRKEY( "setup" ), LFUNCVAL( li2c_slave_setup ) }, - { LSTRKEY( "send" ), LFUNCVAL( li2c_slave_send ) }, - { LNILKEY, LNILVAL } -}; +LROT_PUBLIC_BEGIN(li2c_slave) + LROT_FUNCENTRY( on, li2c_slave_on ) + LROT_FUNCENTRY( setup, li2c_slave_setup ) + LROT_FUNCENTRY( send, li2c_slave_send ) +LROT_END(li2c_slave, NULL, 0) void li2c_hw_slave_init( lua_State *L ) diff --git a/components/modules/i2s.c b/components/modules/i2s.c index 4ac48512e0..d0e95e044c 100644 --- a/components/modules/i2s.c +++ b/components/modules/i2s.c @@ -309,42 +309,39 @@ static int node_i2s_mute( lua_State *L ) // Module function map -static const LUA_REG_TYPE i2s_map[] = -{ - { LSTRKEY( "start" ), LFUNCVAL( node_i2s_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( node_i2s_stop ) }, - { LSTRKEY( "read" ), LFUNCVAL( node_i2s_read ) }, - { LSTRKEY( "write" ), LFUNCVAL( node_i2s_write ) }, - { LSTRKEY( "mute" ), LFUNCVAL( node_i2s_mute ) }, - - { LSTRKEY( "FORMAT_I2S" ), LNUMVAL( I2S_COMM_FORMAT_I2S ) }, - { LSTRKEY( "FORMAT_I2S_MSB" ), LNUMVAL( I2S_COMM_FORMAT_I2S_MSB ) }, - { LSTRKEY( "FORMAT_I2S_LSB" ), LNUMVAL( I2S_COMM_FORMAT_I2S_LSB ) }, - { LSTRKEY( "FORMAT_PCM" ), LNUMVAL( I2S_COMM_FORMAT_PCM ) }, - { LSTRKEY( "FORMAT_PCM_SHORT" ), LNUMVAL( I2S_COMM_FORMAT_PCM_SHORT ) }, - { LSTRKEY( "FORMAT_PCM_LONG" ), LNUMVAL( I2S_COMM_FORMAT_PCM_LONG ) }, - - { LSTRKEY( "CHANNEL_RIGHT_LEFT" ), LNUMVAL( I2S_CHANNEL_FMT_RIGHT_LEFT ) }, - { LSTRKEY( "CHANNEL_ALL_LEFT" ), LNUMVAL( I2S_CHANNEL_FMT_ALL_LEFT ) }, - { LSTRKEY( "CHANNEL_ONLY_LEFT" ), LNUMVAL( I2S_CHANNEL_FMT_ONLY_LEFT ) }, - { LSTRKEY( "CHANNEL_ALL_RIGHT" ), LNUMVAL( I2S_CHANNEL_FMT_ALL_RIGHT ) }, - { LSTRKEY( "CHANNEL_ONLY_RIGHT" ), LNUMVAL( I2S_CHANNEL_FMT_ONLY_RIGHT ) }, - - { LSTRKEY( "MODE_MASTER" ), LNUMVAL( I2S_MODE_MASTER ) }, - { LSTRKEY( "MODE_SLAVE" ), LNUMVAL( I2S_MODE_SLAVE ) }, - { LSTRKEY( "MODE_TX" ), LNUMVAL( I2S_MODE_TX ) }, - { LSTRKEY( "MODE_RX" ), LNUMVAL( I2S_MODE_RX ) }, - { LSTRKEY( "MODE_DAC_BUILT_IN" ), LNUMVAL( I2S_MODE_DAC_BUILT_IN ) }, - { LSTRKEY( "MODE_ADC_BUILT_IN" ), LNUMVAL( I2S_MODE_ADC_BUILT_IN ) }, - { LSTRKEY( "MODE_PDM" ), LNUMVAL( I2S_MODE_PDM ) }, - - { LSTRKEY( "DAC_CHANNEL_DISABLE" ), LNUMVAL( I2S_DAC_CHANNEL_DISABLE ) }, - { LSTRKEY( "DAC_CHANNEL_RIGHT" ), LNUMVAL( I2S_DAC_CHANNEL_RIGHT_EN ) }, - { LSTRKEY( "DAC_CHANNEL_LEFT" ), LNUMVAL( I2S_DAC_CHANNEL_LEFT_EN ) }, - { LSTRKEY( "DAC_CHANNEL_BOTH" ), LNUMVAL( I2S_DAC_CHANNEL_BOTH_EN ) }, - - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(i2s) + LROT_FUNCENTRY( start, node_i2s_start ) + LROT_FUNCENTRY( stop, node_i2s_stop ) + LROT_FUNCENTRY( read, node_i2s_read ) + LROT_FUNCENTRY( write, node_i2s_write ) + LROT_FUNCENTRY( mute, node_i2s_mute ) + + LROT_NUMENTRY( FORMAT_I2S, I2S_COMM_FORMAT_I2S ) + LROT_NUMENTRY( FORMAT_I2S_MSB, I2S_COMM_FORMAT_I2S_MSB ) + LROT_NUMENTRY( FORMAT_I2S_LSB, I2S_COMM_FORMAT_I2S_LSB ) + LROT_NUMENTRY( FORMAT_PCM, I2S_COMM_FORMAT_PCM ) + LROT_NUMENTRY( FORMAT_PCM_SHORT, I2S_COMM_FORMAT_PCM_SHORT ) + LROT_NUMENTRY( FORMAT_PCM_LONG, I2S_COMM_FORMAT_PCM_LONG ) + + LROT_NUMENTRY( CHANNEL_RIGHT_LEFT, I2S_CHANNEL_FMT_RIGHT_LEFT ) + LROT_NUMENTRY( CHANNEL_ALL_LEFT, I2S_CHANNEL_FMT_ALL_LEFT ) + LROT_NUMENTRY( CHANNEL_ONLY_LEFT, I2S_CHANNEL_FMT_ONLY_LEFT ) + LROT_NUMENTRY( CHANNEL_ALL_RIGHT, I2S_CHANNEL_FMT_ALL_RIGHT ) + LROT_NUMENTRY( CHANNEL_ONLY_RIGHT, I2S_CHANNEL_FMT_ONLY_RIGHT ) + + LROT_NUMENTRY( MODE_MASTER, I2S_MODE_MASTER ) + LROT_NUMENTRY( MODE_SLAVE, I2S_MODE_SLAVE ) + LROT_NUMENTRY( MODE_TX, I2S_MODE_TX ) + LROT_NUMENTRY( MODE_RX, I2S_MODE_RX ) + LROT_NUMENTRY( MODE_DAC_BUILT_IN, I2S_MODE_DAC_BUILT_IN ) + LROT_NUMENTRY( MODE_ADC_BUILT_IN, I2S_MODE_ADC_BUILT_IN ) + LROT_NUMENTRY( MODE_PDM, I2S_MODE_PDM ) + + LROT_NUMENTRY( DAC_CHANNEL_DISABLE, I2S_DAC_CHANNEL_DISABLE ) + LROT_NUMENTRY( DAC_CHANNEL_RIGHT, I2S_DAC_CHANNEL_RIGHT_EN ) + LROT_NUMENTRY( DAC_CHANNEL_LEFT, I2S_DAC_CHANNEL_LEFT_EN ) + LROT_NUMENTRY( DAC_CHANNEL_BOTH, I2S_DAC_CHANNEL_BOTH_EN ) +LROT_END(i2s, NULL, 0) int luaopen_i2s( lua_State *L ) { for(int i2s_id = 0; i2s_id < MAX_I2C_NUM; i2s_id++) { @@ -361,4 +358,4 @@ int luaopen_i2s( lua_State *L ) { return 0; } -NODEMCU_MODULE(I2S, "i2s", i2s_map, luaopen_i2s); +NODEMCU_MODULE(I2S, "i2s", i2s, luaopen_i2s); diff --git a/components/modules/ledc.c b/components/modules/ledc.c index 689287e995..ce491dead8 100644 --- a/components/modules/ledc.c +++ b/components/modules/ledc.c @@ -231,66 +231,61 @@ static int lledc_set_fade( lua_State *L ) { } // Module function map -static const LUA_REG_TYPE ledc_channel_map[] = -{ - { LSTRKEY( "getduty" ), LFUNCVAL( lledc_get_duty ) }, - { LSTRKEY( "setduty" ), LFUNCVAL( lledc_set_duty ) }, - { LSTRKEY( "getfreq" ), LFUNCVAL( lledc_get_freq ) }, - { LSTRKEY( "setfreq" ), LFUNCVAL( lledc_set_freq ) }, - - { LSTRKEY( "stop" ), LFUNCVAL( lledc_stop ) }, - { LSTRKEY( "reset" ), LFUNCVAL( lledc_timer_rst ) }, - { LSTRKEY( "pause" ), LFUNCVAL( lledc_timer_pause ) }, - { LSTRKEY( "resume" ), LFUNCVAL( lledc_timer_resume ) }, - - { LSTRKEY( "fadewithtime" ), LFUNCVAL( lledc_set_fade_with_time ) }, - { LSTRKEY( "fadewithstep" ), LFUNCVAL( lledc_set_fade_with_step ) }, - { LSTRKEY( "fade" ), LFUNCVAL( lledc_set_fade ) }, - - { LSTRKEY( "__index" ), LROVAL( ledc_channel_map )}, - - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE ledc_map[] = -{ - { LSTRKEY( "newChannel" ), LFUNCVAL( lledc_new_channel ) }, - - { LSTRKEY( "HIGH_SPEED"), LNUMVAL( LEDC_HIGH_SPEED_MODE ) }, - { LSTRKEY( "LOW_SPEED"), LNUMVAL( LEDC_LOW_SPEED_MODE ) }, - - { LSTRKEY( "TIMER_0"), LNUMVAL( LEDC_TIMER_0 ) }, - { LSTRKEY( "TIMER_1"), LNUMVAL( LEDC_TIMER_1 ) }, - { LSTRKEY( "TIMER_2"), LNUMVAL( LEDC_TIMER_2 ) }, - { LSTRKEY( "TIMER_10_BIT"), LNUMVAL( LEDC_TIMER_10_BIT ) }, - { LSTRKEY( "TIMER_11_BIT"), LNUMVAL( LEDC_TIMER_11_BIT ) }, - { LSTRKEY( "TIMER_12_BIT"), LNUMVAL( LEDC_TIMER_12_BIT ) }, - { LSTRKEY( "TIMER_13_BIT"), LNUMVAL( LEDC_TIMER_13_BIT ) }, - { LSTRKEY( "TIMER_14_BIT"), LNUMVAL( LEDC_TIMER_14_BIT ) }, - { LSTRKEY( "TIMER_15_BIT"), LNUMVAL( LEDC_TIMER_15_BIT ) }, - - { LSTRKEY( "CHANNEL_0"), LNUMVAL( LEDC_CHANNEL_0 ) }, - { LSTRKEY( "CHANNEL_1"), LNUMVAL( LEDC_CHANNEL_1 ) }, - { LSTRKEY( "CHANNEL_2"), LNUMVAL( LEDC_CHANNEL_2 ) }, - { LSTRKEY( "CHANNEL_3"), LNUMVAL( LEDC_CHANNEL_3 ) }, - { LSTRKEY( "CHANNEL_4"), LNUMVAL( LEDC_CHANNEL_4 ) }, - { LSTRKEY( "CHANNEL_5"), LNUMVAL( LEDC_CHANNEL_5 ) }, - { LSTRKEY( "CHANNEL_6"), LNUMVAL( LEDC_CHANNEL_6 ) }, - { LSTRKEY( "CHANNEL_7"), LNUMVAL( LEDC_CHANNEL_7 ) }, - - { LSTRKEY( "IDLE_LOW"), LNUMVAL( 0 ) }, - { LSTRKEY( "IDLE_HIGH"), LNUMVAL( 1 ) }, - - { LSTRKEY( "FADE_NO_WAIT"), LNUMVAL( LEDC_FADE_NO_WAIT ) }, - { LSTRKEY( "FADE_WAIT_DONE"), LNUMVAL( LEDC_FADE_WAIT_DONE ) }, - { LSTRKEY( "FADE_DECREASE"), LNUMVAL( LEDC_DUTY_DIR_DECREASE ) }, - { LSTRKEY( "FADE_INCREASE"), LNUMVAL( LEDC_DUTY_DIR_INCREASE ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(ledc_channel) + LROT_FUNCENTRY( getduty, lledc_get_duty ) + LROT_FUNCENTRY( setduty, lledc_set_duty ) + LROT_FUNCENTRY( getfreq, lledc_get_freq ) + LROT_FUNCENTRY( setfreq, lledc_set_freq ) + + LROT_FUNCENTRY( stop, lledc_stop ) + LROT_FUNCENTRY( reset, lledc_timer_rst ) + LROT_FUNCENTRY( pause, lledc_timer_pause ) + LROT_FUNCENTRY( resume, lledc_timer_resume ) + + LROT_FUNCENTRY( fadewithtime, lledc_set_fade_with_time ) + LROT_FUNCENTRY( fadewithstep, lledc_set_fade_with_step ) + LROT_FUNCENTRY( fade, lledc_set_fade ) + + LROT_TABENTRY ( __index, ledc_channel ) +LROT_END(ledc_channel, NULL, 0) + +LROT_BEGIN(ledc) + LROT_FUNCENTRY( newChannel, lledc_new_channel ) + + LROT_NUMENTRY ( HIGH_SPEED, LEDC_HIGH_SPEED_MODE ) + LROT_NUMENTRY ( LOW_SPEED, LEDC_LOW_SPEED_MODE ) + + LROT_NUMENTRY ( TIMER_0, LEDC_TIMER_0 ) + LROT_NUMENTRY ( TIMER_1, LEDC_TIMER_1 ) + LROT_NUMENTRY ( TIMER_2, LEDC_TIMER_2 ) + LROT_NUMENTRY ( TIMER_10_BIT, LEDC_TIMER_10_BIT ) + LROT_NUMENTRY ( TIMER_11_BIT, LEDC_TIMER_11_BIT ) + LROT_NUMENTRY ( TIMER_12_BIT, LEDC_TIMER_12_BIT ) + LROT_NUMENTRY ( TIMER_13_BIT, LEDC_TIMER_13_BIT ) + LROT_NUMENTRY ( TIMER_14_BIT, LEDC_TIMER_14_BIT ) + LROT_NUMENTRY ( TIMER_15_BIT, LEDC_TIMER_15_BIT ) + + LROT_NUMENTRY ( CHANNEL_0, LEDC_CHANNEL_0 ) + LROT_NUMENTRY ( CHANNEL_1, LEDC_CHANNEL_1 ) + LROT_NUMENTRY ( CHANNEL_2, LEDC_CHANNEL_2 ) + LROT_NUMENTRY ( CHANNEL_3, LEDC_CHANNEL_3 ) + LROT_NUMENTRY ( CHANNEL_4, LEDC_CHANNEL_4 ) + LROT_NUMENTRY ( CHANNEL_5, LEDC_CHANNEL_5 ) + LROT_NUMENTRY ( CHANNEL_6, LEDC_CHANNEL_6 ) + LROT_NUMENTRY ( CHANNEL_7, LEDC_CHANNEL_7 ) + + LROT_NUMENTRY ( IDLE_LOW, 0 ) + LROT_NUMENTRY ( IDLE_HIGH, 1 ) + + LROT_NUMENTRY ( FADE_NO_WAIT, LEDC_FADE_NO_WAIT ) + LROT_NUMENTRY ( FADE_WAIT_DONE, LEDC_FADE_WAIT_DONE ) + LROT_NUMENTRY ( FADE_DECREASE, LEDC_DUTY_DIR_DECREASE ) + LROT_NUMENTRY ( FADE_INCREASE, LEDC_DUTY_DIR_INCREASE ) +LROT_END(ledc, NULL, 0) int luaopen_ledc(lua_State *L) { luaL_rometatable(L, "ledc.channel", (void *)ledc_channel_map); // create metatable for ledc.channel return 0; } -NODEMCU_MODULE(LEDC, "ledc", ledc_map, luaopen_ledc); +NODEMCU_MODULE(LEDC, "ledc", ledc, luaopen_ledc); diff --git a/components/modules/mqtt.c b/components/modules/mqtt.c index 19cbad573a..43bb9d2330 100644 --- a/components/modules/mqtt.c +++ b/components/modules/mqtt.c @@ -635,27 +635,26 @@ static int mqtt_new(lua_State* L) { } // map client methods to functions: -static const LUA_REG_TYPE mqtt_metatable_map[] = - { - {LSTRKEY("connect"), LFUNCVAL(mqtt_connect)}, - {LSTRKEY("close"), LFUNCVAL(mqtt_close)}, - {LSTRKEY("lwt"), LFUNCVAL(mqtt_lwt)}, - {LSTRKEY("publish"), LFUNCVAL(mqtt_publish)}, - {LSTRKEY("subscribe"), LFUNCVAL(mqtt_subscribe)}, - {LSTRKEY("unsubscribe"), LFUNCVAL(mqtt_unsubscribe)}, - {LSTRKEY("on"), LFUNCVAL(mqtt_on)}, - {LSTRKEY("__gc"), LFUNCVAL(mqtt_delete)}, - {LSTRKEY("__index"), LROVAL(mqtt_metatable_map)}, - {LNILKEY, LNILVAL}}; +LROT_BEGIN(mqtt_metatable) + LROT_FUNCENTRY(connect, mqtt_connect) + LROT_FUNCENTRY(close, mqtt_close) + LROT_FUNCENTRY(lwt, mqtt_lwt) + LROT_FUNCENTRY(publish, mqtt_publish) + LROT_FUNCENTRY(subscribe, mqtt_subscribe) + LROT_FUNCENTRY(unsubscribe, mqtt_unsubscribe) + LROT_FUNCENTRY(on, mqtt_on) + LROT_FUNCENTRY(__gc, mqtt_delete) + LROT_TABENTRY(__index, mqtt_metatable) +LROT_END(mqtt_metatable, NULL, 0) // Module function map -static const LUA_REG_TYPE mqtt_map[] = { - {LSTRKEY("Client"), LFUNCVAL(mqtt_new)}, - {LNILKEY, LNILVAL}}; +LROT_BEGIN(mqtt) + LROT_FUNCENTRY(Client, mqtt_new) +LROT_END(mqtt, NULL, 0) int luaopen_mqtt(lua_State* L) { luaL_rometatable(L, MQTT_METATABLE, (void*)mqtt_metatable_map); // create metatable for mqtt return 0; } -NODEMCU_MODULE(MQTT, "mqtt", mqtt_map, luaopen_mqtt); +NODEMCU_MODULE(MQTT, "mqtt", mqtt, luaopen_mqtt); diff --git a/components/modules/net.c b/components/modules/net.c index 856cd98a62..1d8b314426 100644 --- a/components/modules/net.c +++ b/components/modules/net.c @@ -1155,62 +1155,56 @@ static void lerr_cb (lua_State *L, lnet_userdata *ud, err_t err) // --- Tables // Module function map -static const LUA_REG_TYPE net_tcpserver_map[] = { - { LSTRKEY( "listen" ), LFUNCVAL( net_listen ) }, - { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, - { LSTRKEY( "close" ), LFUNCVAL( net_close ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, - { LSTRKEY( "__index" ), LROVAL( net_tcpserver_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE net_tcpsocket_map[] = { - { LSTRKEY( "connect" ), LFUNCVAL( net_connect ) }, - { LSTRKEY( "close" ), LFUNCVAL( net_close ) }, - { LSTRKEY( "on" ), LFUNCVAL( net_on ) }, - { LSTRKEY( "send" ), LFUNCVAL( net_send ) }, - { LSTRKEY( "hold" ), LFUNCVAL( net_hold ) }, - { LSTRKEY( "unhold" ), LFUNCVAL( net_unhold ) }, - { LSTRKEY( "dns" ), LFUNCVAL( net_dns ) }, - { LSTRKEY( "getpeer" ), LFUNCVAL( net_getpeer ) }, - { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, - { LSTRKEY( "__index" ), LROVAL( net_tcpsocket_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE net_udpsocket_map[] = { - { LSTRKEY( "listen" ), LFUNCVAL( net_listen ) }, - { LSTRKEY( "close" ), LFUNCVAL( net_close ) }, - { LSTRKEY( "on" ), LFUNCVAL( net_on ) }, - { LSTRKEY( "send" ), LFUNCVAL( net_send ) }, - { LSTRKEY( "dns" ), LFUNCVAL( net_dns ) }, - { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, - { LSTRKEY( "__index" ), LROVAL( net_udpsocket_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE net_dns_map[] = { - { LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) }, - { LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) }, - { LSTRKEY( "resolve" ), LFUNCVAL( net_dns_static ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE net_map[] = { - { LSTRKEY( "createServer" ), LFUNCVAL( net_createServer ) }, - { LSTRKEY( "createConnection" ), LFUNCVAL( net_createConnection ) }, - { LSTRKEY( "createUDPSocket" ), LFUNCVAL( net_createUDPSocket ) }, - { LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) }, - { LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) }, - { LSTRKEY( "dns" ), LROVAL( net_dns_map ) }, - { LSTRKEY( "TCP" ), LNUMVAL( TYPE_TCP ) }, - { LSTRKEY( "UDP" ), LNUMVAL( TYPE_UDP ) }, - { LSTRKEY( "__metatable" ), LROVAL( net_map ) }, - { LNILKEY, LNILVAL } -}; - +LROT_BEGIN(net_tcpserver) + LROT_FUNCENTRY( listen, net_listen ) + LROT_FUNCENTRY( getaddr, net_getaddr ) + LROT_FUNCENTRY( close, net_close ) + LROT_FUNCENTRY( __gc, net_delete ) + LROT_TABENTRY ( __index, net_tcpserver ) +LROT_END(net_tcpserver, NULL, 0) + +LROT_BEGIN(net_tcpsocket) + LROT_FUNCENTRY( connect, net_connect ) + LROT_FUNCENTRY( close, net_close ) + LROT_FUNCENTRY( on, net_on ) + LROT_FUNCENTRY( send, net_send ) + LROT_FUNCENTRY( hold, net_hold ) + LROT_FUNCENTRY( unhold, net_unhold ) + LROT_FUNCENTRY( dns, net_dns ) + LROT_FUNCENTRY( getpeer, net_getpeer ) + LROT_FUNCENTRY( getaddr, net_getaddr ) + LROT_FUNCENTRY( __gc, net_delete ) + LROT_TABENTRY ( __index, net_tcpsocket ) +LROT_END(net_tcpsocket, NULL, 0) + +LROT_BEGIN(net_udpsocket) + LROT_FUNCENTRY( listen, net_listen ) + LROT_FUNCENTRY( close, net_close ) + LROT_FUNCENTRY( on, net_on ) + LROT_FUNCENTRY( send, net_send ) + LROT_FUNCENTRY( dns, net_dns ) + LROT_FUNCENTRY( getaddr, net_getaddr ) + LROT_FUNCENTRY( __gc, net_delete ) + LROT_TABENTRY ( __index, net_udpsocket ) +LROT_END(net_udpsocket, NULL, 0) + +LROT_BEGIN(net_dns) + LROT_FUNCENTRY( setdnsserver, net_setdnsserver ) + LROT_FUNCENTRY( getdnsserver, net_getdnsserver ) + LROT_FUNCENTRY( resolve, net_dns_static ) +LROT_END(net_dns, NULL, 0) + +LROT_BEGIN(net) + LROT_FUNCENTRY( createServer, net_createServer ) + LROT_FUNCENTRY( createConnection, net_createConnection ) + LROT_FUNCENTRY( createUDPSocket, net_createUDPSocket ) + LROT_FUNCENTRY( multicastJoin, net_multicastJoin ) + LROT_FUNCENTRY( multicastLeave, net_multicastLeave ) + LROT_TABENTRY ( dns, net_dns ) + LROT_NUMENTRY ( TCP, TYPE_TCP ) + LROT_NUMENTRY ( UDP, TYPE_UDP ) + LROT_TABENTRY ( __metatable, net ) +LROT_END(net, NULL, 0) int luaopen_net( lua_State *L ) { igmp_init(); @@ -1225,4 +1219,4 @@ int luaopen_net( lua_State *L ) { return 0; } -NODEMCU_MODULE(NET, "net", net_map, luaopen_net); +NODEMCU_MODULE(NET, "net", net, luaopen_net); diff --git a/components/modules/node.c b/components/modules/node.c index 5448a88f3e..5c4503e759 100644 --- a/components/modules/node.c +++ b/components/modules/node.c @@ -11,6 +11,7 @@ #include "ldebug.h" #include "esp_vfs.h" #include "lnodeaux.h" +#include "lflash.h" // Lua: node.chipid() static int node_chipid( lua_State *L ) @@ -371,40 +372,39 @@ static int node_uptime(lua_State *L) } -static const LUA_REG_TYPE node_egc_map[] = { - { LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) }, - { LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) }, - { LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) }, - { LSTRKEY( "ON_MEM_LIMIT" ), LNUMVAL( EGC_ON_MEM_LIMIT ) }, - { LSTRKEY( "ALWAYS" ), LNUMVAL( EGC_ALWAYS ) }, - { LNILKEY, LNILVAL } -}; - - -static const LUA_REG_TYPE node_task_map[] = { - { LSTRKEY( "post" ), LFUNCVAL( node_task_post ) }, - { LSTRKEY( "LOW_PRIORITY" ), LNUMVAL( TASK_PRIORITY_LOW ) }, - { LSTRKEY( "MEDIUM_PRIORITY" ), LNUMVAL( TASK_PRIORITY_MEDIUM ) }, - { LSTRKEY( "HIGH_PRIORITY" ), LNUMVAL( TASK_PRIORITY_HIGH ) }, - { LNILKEY, LNILVAL } -}; - - -static const LUA_REG_TYPE node_map[] = -{ - { LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) }, - { LSTRKEY( "compile" ), LFUNCVAL( node_compile ) }, - { LSTRKEY( "dsleep" ), LFUNCVAL( node_dsleep ) }, - { LSTRKEY( "egc" ), LROVAL( node_egc_map ) }, - { LSTRKEY( "heap" ), LFUNCVAL( node_heap ) }, - { LSTRKEY( "input" ), LFUNCVAL( node_input ) }, - { LSTRKEY( "output" ), LFUNCVAL( node_output ) }, - { LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) }, - { LSTRKEY( "restart" ), LFUNCVAL( node_restart ) }, - { LSTRKEY( "stripdebug"), LFUNCVAL( node_stripdebug ) }, - { LSTRKEY( "task" ), LROVAL( node_task_map ) }, - { LSTRKEY( "uptime" ), LFUNCVAL( node_uptime ) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(NODE, "node", node_map, NULL); +LROT_BEGIN(node_egc) + LROT_FUNCENTRY( setmode, node_egc_setmode ) + LROT_NUMENTRY ( NOT_ACTIVE, EGC_NOT_ACTIVE ) + LROT_NUMENTRY ( ON_ALLOC_FAILURE, EGC_ON_ALLOC_FAILURE ) + LROT_NUMENTRY ( ON_MEM_LIMIT, EGC_ON_MEM_LIMIT ) + LROT_NUMENTRY ( ALWAYS, EGC_ALWAYS ) +LROT_END(node_egc, NULL, 0) + + +LROT_BEGIN(node_task) + LROT_FUNCENTRY( post, node_task_post ) + LROT_NUMENTRY ( LOW_PRIORITY, TASK_PRIORITY_LOW ) + LROT_NUMENTRY ( MEDIUM_PRIORITY, TASK_PRIORITY_MEDIUM ) + LROT_NUMENTRY ( HIGH_PRIORITY, TASK_PRIORITY_HIGH ) +LROT_END(node_task, NULL, 0) + + +LROT_BEGIN(node) + LROT_FUNCENTRY( chipid, node_chipid ) + LROT_FUNCENTRY( compile, node_compile ) + LROT_FUNCENTRY( dsleep, node_dsleep ) + LROT_TABENTRY ( egc, node_egc ) + LROT_FUNCENTRY( flashreload,luaN_reload_reboot ) + LROT_FUNCENTRY( flashindex, luaN_index ) + LROT_FUNCENTRY( heap, node_heap ) + LROT_FUNCENTRY( input, node_input ) + LROT_FUNCENTRY( output, node_output ) + LROT_FUNCENTRY( osprint, node_osprint ) + LROT_FUNCENTRY( restart, node_restart ) + LROT_FUNCENTRY( stripdebug, node_stripdebug ) + LROT_TABENTRY ( task, node_task ) + LROT_FUNCENTRY( uptime, node_uptime ) +LROT_END(node, NULL, 0) + + +NODEMCU_MODULE(NODE, "node", node, NULL); diff --git a/components/modules/otaupgrade.c b/components/modules/otaupgrade.c index 92546b5479..4f41ccd178 100644 --- a/components/modules/otaupgrade.c +++ b/components/modules/otaupgrade.c @@ -239,15 +239,13 @@ static int lotaupgrade_info (lua_State *L) } -static const LUA_REG_TYPE otaupgrade_map[] = -{ - { LSTRKEY( "commence" ), LFUNCVAL( lotaupgrade_commence ) }, - { LSTRKEY( "write" ), LFUNCVAL( lotaupgrade_write) }, - { LSTRKEY( "complete" ), LFUNCVAL( lotaupgrade_complete) }, - { LSTRKEY( "accept" ), LFUNCVAL( lotaupgrade_accept) }, - { LSTRKEY( "rollback" ), LFUNCVAL( lotaupgrade_rollback) }, - { LSTRKEY( "info" ), LFUNCVAL( lotaupgrade_info) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(OTAUPGRADE, "otaupgrade", otaupgrade_map, NULL); +LROT_BEGIN(otaupgrade) + LROT_FUNCENTRY( commence, lotaupgrade_commence ) + LROT_FUNCENTRY( write, lotaupgrade_write ) + LROT_FUNCENTRY( complete, lotaupgrade_complete ) + LROT_FUNCENTRY( accept, lotaupgrade_accept ) + LROT_FUNCENTRY( rollback, lotaupgrade_rollback ) + LROT_FUNCENTRY( info, lotaupgrade_info ) +LROT_END(otaupgrade, 0, NULL) + +NODEMCU_MODULE(OTAUPGRADE, "otaupgrade", otaupgrade, NULL); diff --git a/components/modules/ow.c b/components/modules/ow.c index 303b3a0e26..40060905be 100644 --- a/components/modules/ow.c +++ b/components/modules/ow.c @@ -326,24 +326,23 @@ static int ow_crc16( lua_State *L ) return 1; } -static const LUA_REG_TYPE ow_map[] = { - { LSTRKEY( "setup" ), LFUNCVAL( ow_setup ) }, - { LSTRKEY( "reset" ), LFUNCVAL( ow_reset ) }, - { LSTRKEY( "skip" ), LFUNCVAL( ow_skip ) }, - { LSTRKEY( "select" ), LFUNCVAL( ow_select ) }, - { LSTRKEY( "write" ), LFUNCVAL( ow_write ) }, - { LSTRKEY( "write_bytes" ), LFUNCVAL( ow_write_bytes ) }, - { LSTRKEY( "read" ), LFUNCVAL( ow_read ) }, - { LSTRKEY( "read_bytes" ), LFUNCVAL( ow_read_bytes ) }, - { LSTRKEY( "depower" ), LFUNCVAL( ow_depower ) }, - { LSTRKEY( "reset_search" ), LFUNCVAL( ow_reset_search ) }, - { LSTRKEY( "target_search" ), LFUNCVAL( ow_target_search ) }, - { LSTRKEY( "search" ), LFUNCVAL( ow_search ) }, - { LSTRKEY( "crc8" ), LFUNCVAL( ow_crc8 ) }, - { LSTRKEY( "check_crc16" ), LFUNCVAL( ow_check_crc16 ) }, - { LSTRKEY( "crc16" ), LFUNCVAL( ow_crc16 ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(ow) + LROT_FUNCENTRY( setup, ow_setup ) + LROT_FUNCENTRY( reset, ow_reset ) + LROT_FUNCENTRY( skip, ow_skip ) + LROT_FUNCENTRY( select, ow_select ) + LROT_FUNCENTRY( write, ow_write ) + LROT_FUNCENTRY( write_bytes, ow_write_bytes ) + LROT_FUNCENTRY( read, ow_read ) + LROT_FUNCENTRY( read_bytes, ow_read_bytes ) + LROT_FUNCENTRY( depower, ow_depower ) + LROT_FUNCENTRY( reset_search, ow_reset_search ) + LROT_FUNCENTRY( target_search, ow_target_search ) + LROT_FUNCENTRY( search, ow_search ) + LROT_FUNCENTRY( crc8, ow_crc8 ) + LROT_FUNCENTRY( check_crc16, ow_check_crc16 ) + LROT_FUNCENTRY( crc16, ow_crc16 ) +LROT_END(ow, NULL, 0) int luaopen_ow( lua_State *L ) { @@ -354,4 +353,4 @@ int luaopen_ow( lua_State *L ) return 0; } -NODEMCU_MODULE(OW, "ow", ow_map, luaopen_ow); +NODEMCU_MODULE(OW, "ow", ow, luaopen_ow); diff --git a/components/modules/pulsecnt.c b/components/modules/pulsecnt.c index 99a0ef6e26..bcaf5f90a1 100644 --- a/components/modules/pulsecnt.c +++ b/components/modules/pulsecnt.c @@ -678,47 +678,42 @@ static int pulsecnt_unregister(lua_State* L){ return 0; } -static const LUA_REG_TYPE pulsecnt_dyn_map[] = -{ - { LSTRKEY( "getCnt" ), LFUNCVAL( pulsecnt_getCnt )}, - { LSTRKEY( "clear" ), LFUNCVAL( pulsecnt_clear )}, - { LSTRKEY( "testCb" ), LFUNCVAL( pulsecnt_testCb )}, - { LSTRKEY( "chan0Config" ), LFUNCVAL( pulsecnt_channel0_config )}, - { LSTRKEY( "chan1Config" ), LFUNCVAL( pulsecnt_channel1_config )}, - { LSTRKEY( "config" ), LFUNCVAL( pulsecnt_config )}, - - { LSTRKEY( "setThres" ), LFUNCVAL( pulsecnt_set_thres )}, - { LSTRKEY( "setFilter" ), LFUNCVAL( pulsecnt_set_filter )}, - { LSTRKEY( "rawSetEventVal" ), LFUNCVAL( pulsecnt_set_event_value )}, - { LSTRKEY( "rawGetEventVal" ), LFUNCVAL( pulsecnt_get_event_value )}, - - // { LSTRKEY( "__tostring" ), LFUNCVAL( pulsecnt_tostring )}, - { LSTRKEY( "__gc" ), LFUNCVAL( pulsecnt_unregister ) }, - { LSTRKEY( "__index" ), LROVAL( pulsecnt_dyn_map ) }, - - { LNILKEY, LNILVAL} -}; - -static const LUA_REG_TYPE pulsecnt_map[] = -{ - { LSTRKEY( "create" ), LFUNCVAL( pulsecnt_create )}, - { LSTRKEY( "PCNT_MODE_KEEP" ), LNUMVAL( 0 ) }, /*pcnt_ctrl_mode_t.PCNT_MODE_KEEP*/ - { LSTRKEY( "PCNT_MODE_REVERSE" ), LNUMVAL( 1 ) }, /*pcnt_ctrl_mode_t.PCNT_MODE_REVERSE*/ - { LSTRKEY( "PCNT_MODE_DISABLE" ), LNUMVAL( 2 ) }, /*pcnt_ctrl_mode_t.PCNT_MODE_DISABLE*/ - { LSTRKEY( "PCNT_COUNT_DIS" ), LNUMVAL( 0 ) }, /*pcnt_count_mode_t.PCNT_COUNT_DIS*/ - { LSTRKEY( "PCNT_COUNT_INC" ), LNUMVAL( 1 ) }, /*pcnt_count_mode_t.PCNT_COUNT_INC*/ - { LSTRKEY( "PCNT_COUNT_DEC" ), LNUMVAL( 2 ) }, /*pcnt_count_mode_t.PCNT_COUNT_DEC*/ - // { LSTRKEY( "PCNT_COUNT_MAX " ), LNUMVAL( pcnt_count_mode_t.PCNT_COUNT_MAX ) }, - { LSTRKEY( "PCNT_H_LIM_VAL" ), LNUMVAL( 32767 ) }, - { LSTRKEY( "PCNT_L_LIM_VAL" ), LNUMVAL( -32768 ) }, - { LSTRKEY( "PCNT_EVT_L_LIM" ), LNUMVAL( 0 ) }, - { LSTRKEY( "PCNT_EVT_H_LIM" ), LNUMVAL( 1 ) }, - { LSTRKEY( "PCNT_EVT_THRES_0" ), LNUMVAL( 2 ) }, - { LSTRKEY( "PCNT_EVT_THRES_1" ), LNUMVAL( 3 ) }, - { LSTRKEY( "PCNT_EVT_ZERO" ), LNUMVAL( 4 ) }, - { LSTRKEY( "PCNT_PIN_NOT_USED" ), LNUMVAL( -1 ) }, /*PCNT_PIN_NOT_USED*/ - { LNILKEY, LNILVAL} -}; +LROT_BEGIN(pulsecnt_dyn) + LROT_FUNCENTRY( getCnt, pulsecnt_getCnt ) + LROT_FUNCENTRY( clear, pulsecnt_clear ) + LROT_FUNCENTRY( testCb, pulsecnt_testCb ) + LROT_FUNCENTRY( chan0Config, pulsecnt_channel0_config ) + LROT_FUNCENTRY( chan1Config, pulsecnt_channel1_config ) + LROT_FUNCENTRY( config, pulsecnt_config ) + + LROT_FUNCENTRY( setThres, pulsecnt_set_thres ) + LROT_FUNCENTRY( setFilter, pulsecnt_set_filter ) + LROT_FUNCENTRY( rawSetEventVal, pulsecnt_set_event_value ) + LROT_FUNCENTRY( rawGetEventVal, pulsecnt_get_event_value ) + + // LROT_FUNCENTRY( __tostring, pulsecnt_tostring ) + LROT_FUNCENTRY( __gc, pulsecnt_unregister ) + LROT_TABENTRY ( __index, pulsecnt_dyn ) +LROT_END(pulsecnt_dyn, NULL, 0) + +LROT_BEGIN(pulsecnt) + LROT_FUNCENTRY( create, pulsecnt_create ) + LROT_NUMENTRY ( PCNT_MODE_KEEP, 0 ) /*pcnt_ctrl_mode_t.PCNT_MODE_KEEP*/ + LROT_NUMENTRY ( PCNT_MODE_REVERSE, 1 ) /*pcnt_ctrl_mode_t.PCNT_MODE_REVERSE*/ + LROT_NUMENTRY ( PCNT_MODE_DISABLE, 2 ) /*pcnt_ctrl_mode_t.PCNT_MODE_DISABLE*/ + LROT_NUMENTRY ( PCNT_COUNT_DIS, 0 ) /*pcnt_count_mode_t.PCNT_COUNT_DIS*/ + LROT_NUMENTRY ( PCNT_COUNT_INC, 1 ) /*pcnt_count_mode_t.PCNT_COUNT_INC*/ + LROT_NUMENTRY ( PCNT_COUNT_DEC, 2 ) /*pcnt_count_mode_t.PCNT_COUNT_DEC*/ + // LROT_NUMENTRY ( PCNT_COUNT_MAX , pcnt_count_mode_t.PCNT_COUNT_MAX ) + LROT_NUMENTRY ( PCNT_H_LIM_VAL, 32767 ) + LROT_NUMENTRY ( PCNT_L_LIM_VAL, -32768 ) + LROT_NUMENTRY ( PCNT_EVT_L_LIM, 0 ) + LROT_NUMENTRY ( PCNT_EVT_H_LIM, 1 ) + LROT_NUMENTRY ( PCNT_EVT_THRES_0, 2 ) + LROT_NUMENTRY ( PCNT_EVT_THRES_1, 3 ) + LROT_NUMENTRY ( PCNT_EVT_ZERO, 4 ) + LROT_NUMENTRY ( PCNT_PIN_NOT_USED, -1 ) /*PCNT_PIN_NOT_USED*/ +LROT_END(pulsecnt, NULL, 0) int luaopen_pulsecnt(lua_State *L) { @@ -729,4 +724,4 @@ int luaopen_pulsecnt(lua_State *L) { return 0; } -NODEMCU_MODULE(PULSECNT, "pulsecnt", pulsecnt_map, luaopen_pulsecnt); +NODEMCU_MODULE(PULSECNT, "pulsecnt", pulsecnt, luaopen_pulsecnt); diff --git a/components/modules/qrcodegen.c b/components/modules/qrcodegen.c index 8e9e5d93ce..0a3a1fa16d 100644 --- a/components/modules/qrcodegen.c +++ b/components/modules/qrcodegen.c @@ -56,16 +56,15 @@ static int getPixel(lua_State *L) return 1; } -static const LUA_REG_TYPE qrcodegen_map[] = { - { LSTRKEY("encodeText"), LFUNCVAL(encodeText) }, - { LSTRKEY("getSize"), LFUNCVAL(getSize) }, - { LSTRKEY("getPixel"), LFUNCVAL(getPixel) }, - { LSTRKEY("LOW"), LNUMVAL(qrcodegen_Ecc_LOW) }, - { LSTRKEY("MEDIUM"), LNUMVAL(qrcodegen_Ecc_MEDIUM) }, - { LSTRKEY("QUARTILE"), LNUMVAL(qrcodegen_Ecc_QUARTILE) }, - { LSTRKEY("HIGH"), LNUMVAL(qrcodegen_Ecc_HIGH) }, - { LSTRKEY("AUTO"), LNUMVAL(qrcodegen_Mask_AUTO) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(qrcodegen) + LROT_FUNCENTRY(encodeText, encodeText) + LROT_FUNCENTRY(getSize, getSize) + LROT_FUNCENTRY(getPixel, getPixel) + LROT_NUMENTRY(LOW, qrcodegen_Ecc_LOW) + LROT_NUMENTRY(MEDIUM, qrcodegen_Ecc_MEDIUM) + LROT_NUMENTRY(QUARTILE, qrcodegen_Ecc_QUARTILE) + LROT_NUMENTRY(HIGH, qrcodegen_Ecc_HIGH) + LROT_NUMENTRY(AUTO, qrcodegen_Mask_AUTO) +LROT_END(qrcodegen, NULL, 0) -NODEMCU_MODULE(QRCODEGEN, "qrcodegen", qrcodegen_map, NULL); +NODEMCU_MODULE(QRCODEGEN, "qrcodegen", qrcodegen, NULL); diff --git a/components/modules/sdmmc.c b/components/modules/sdmmc.c index 21aec0c7b2..94f8f83bac 100644 --- a/components/modules/sdmmc.c +++ b/components/modules/sdmmc.c @@ -327,30 +327,28 @@ static int lsdmmc_umount( lua_State *L ) return luaL_error( L, err_msg ); } -static const LUA_REG_TYPE sdmmc_card_map[] = { - { LSTRKEY( "read" ), LFUNCVAL( lsdmmc_read ) }, - { LSTRKEY( "write" ), LFUNCVAL( lsdmmc_write ) }, - { LSTRKEY( "get_info" ), LFUNCVAL( lsdmmc_get_info ) }, - { LSTRKEY( "mount" ), LFUNCVAL( lsdmmc_mount ) }, - { LSTRKEY( "umount" ), LFUNCVAL( lsdmmc_umount ) }, - { LSTRKEY( "__index" ), LROVAL( sdmmc_card_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE sdmmc_map[] = { - { LSTRKEY( "init" ), LFUNCVAL( lsdmmc_init ) }, - { LSTRKEY( "HS1" ), LNUMVAL( SDMMC_HOST_SLOT_0 ) }, - { LSTRKEY( "HS2" ), LNUMVAL( SDMMC_HOST_SLOT_1 ) }, - { LSTRKEY( "HSPI" ), LNUMVAL( LSDMMC_HOST_HSPI ) }, - { LSTRKEY( "VSPI" ), LNUMVAL( LSDMMC_HOST_VSPI ) }, - { LSTRKEY( "W1BIT" ), LNUMVAL( SDMMC_HOST_FLAG_1BIT ) }, - { LSTRKEY( "W4BIT" ), LNUMVAL( SDMMC_HOST_FLAG_1BIT | - SDMMC_HOST_FLAG_4BIT ) }, - { LSTRKEY( "W8BIT" ), LNUMVAL( SDMMC_HOST_FLAG_1BIT | - SDMMC_HOST_FLAG_4BIT | - SDMMC_HOST_FLAG_8BIT ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(sdmmc_card) + LROT_FUNCENTRY( read, lsdmmc_read ) + LROT_FUNCENTRY( write, lsdmmc_write ) + LROT_FUNCENTRY( get_info, lsdmmc_get_info ) + LROT_FUNCENTRY( mount, lsdmmc_mount ) + LROT_FUNCENTRY( umount, lsdmmc_umount ) + LROT_TABENTRY( __index, sdmmc_card ) +LROT_END(sdmmc_card, NULL, 0) + +LROT_BEGIN(sdmmc) + LROT_FUNCENTRY( init, lsdmmc_init ) + LROT_NUMENTRY( HS1, SDMMC_HOST_SLOT_0 ) + LROT_NUMENTRY( HS2, SDMMC_HOST_SLOT_1 ) + LROT_NUMENTRY( HSPI, LSDMMC_HOST_HSPI ) + LROT_NUMENTRY( VSPI, LSDMMC_HOST_VSPI ) + LROT_NUMENTRY( W1BIT, SDMMC_HOST_FLAG_1BIT ) + LROT_NUMENTRY( W4BIT, SDMMC_HOST_FLAG_1BIT | + SDMMC_HOST_FLAG_4BIT ) + LROT_NUMENTRY( W8BIT, SDMMC_HOST_FLAG_1BIT | + SDMMC_HOST_FLAG_4BIT | + SDMMC_HOST_FLAG_8BIT ) +LROT_END(sdmmc, NULL, 0) static int luaopen_sdmmc( lua_State *L ) { @@ -364,4 +362,4 @@ static int luaopen_sdmmc( lua_State *L ) return 0; } -NODEMCU_MODULE(SDMMC, "sdmmc", sdmmc_map, luaopen_sdmmc); +NODEMCU_MODULE(SDMMC, "sdmmc", sdmmc, luaopen_sdmmc); diff --git a/components/modules/sigma_delta.c b/components/modules/sigma_delta.c index 15a9a19075..551cda1028 100644 --- a/components/modules/sigma_delta.c +++ b/components/modules/sigma_delta.c @@ -77,14 +77,12 @@ static int sigma_delta_setduty( lua_State *L ) // Module function map -static const LUA_REG_TYPE sigma_delta_map[] = -{ - { LSTRKEY( "setup" ), LFUNCVAL( sigma_delta_setup ) }, - { LSTRKEY( "close" ), LFUNCVAL( sigma_delta_close ) }, - //{ LSTRKEY( "setpwmduty" ), LFUNCVAL( sigma_delta_setpwmduty ) }, - { LSTRKEY( "setprescale" ), LFUNCVAL( sigma_delta_setprescale ) }, - { LSTRKEY( "setduty" ), LFUNCVAL( sigma_delta_setduty ) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta_map, NULL); +LROT_BEGIN(sigma_delta) + LROT_FUNCENTRY( setup, sigma_delta_setup ) + LROT_FUNCENTRY( close, sigma_delta_close ) + //LROT_FUNCENTRY( setpwmduty, sigma_delta_setpwmduty ) + LROT_FUNCENTRY( setprescale, sigma_delta_setprescale ) + LROT_FUNCENTRY( setduty, sigma_delta_setduty ) +LROT_END(sigma_delta, NULL, 0) + +NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta, NULL); diff --git a/components/modules/sjson.c b/components/modules/sjson.c index e68947c416..567d4a0c1e 100644 --- a/components/modules/sjson.c +++ b/components/modules/sjson.c @@ -1014,29 +1014,26 @@ static const luaL_Reg sjsonlib[] = { {NULL, NULL} }; #else -static const LUA_REG_TYPE sjson_encoder_map[] = { - { LSTRKEY( "read" ), LFUNCVAL( sjson_encoder_read ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( sjson_encoder_destructor ) }, - { LSTRKEY( "__index" ), LROVAL( sjson_encoder_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE sjson_decoder_map[] = { - { LSTRKEY( "write" ), LFUNCVAL( sjson_decoder_write ) }, - { LSTRKEY( "result" ), LFUNCVAL( sjson_decoder_result ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( sjson_decoder_destructor ) }, - { LSTRKEY( "__index" ), LROVAL( sjson_decoder_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE sjson_map[] = { - { LSTRKEY( "encode" ), LFUNCVAL( sjson_encode ) }, - { LSTRKEY( "decode" ), LFUNCVAL( sjson_decode ) }, - { LSTRKEY( "encoder" ), LFUNCVAL( sjson_encoder ) }, - { LSTRKEY( "decoder" ), LFUNCVAL( sjson_decoder ) }, - { LSTRKEY( "NULL" ), LUDATA( 0 ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(sjson_encoder) + LROT_FUNCENTRY( read, sjson_encoder_read ) + LROT_FUNCENTRY( __gc, sjson_encoder_destructor ) + LROT_TABENTRY ( __index, sjson_encoder ) +LROT_END(sjson_encoder, NULL, 0) + +LROT_BEGIN(sjson_decoder) + LROT_FUNCENTRY( write, sjson_decoder_write ) + LROT_FUNCENTRY( result, sjson_decoder_result ) + LROT_FUNCENTRY( __gc, sjson_decoder_destructor ) + LROT_TABENTRY ( __index, sjson_decoder ) +LROT_END(sjson_decoder, NULL, 0) + +LROT_BEGIN(sjson) + LROT_FUNCENTRY( encode, sjson_encode ) + LROT_FUNCENTRY( decode, sjson_decode ) + LROT_FUNCENTRY( encoder, sjson_encoder ) + LROT_FUNCENTRY( decoder, sjson_decoder ) + LROT_LUDENTRY ( NULL, 0 ) +LROT_END(sjson, NULL, 0) #endif LUALIB_API int luaopen_sjson (lua_State *L) { @@ -1054,12 +1051,12 @@ LUALIB_API int luaopen_sjson (lua_State *L) { luaL_register(L, NULL, sjson_decoder_map); lua_setfield(L, -1, "__index"); #else - luaL_rometatable(L, "sjson.decoder", (void *)sjson_decoder_map); - luaL_rometatable(L, "sjson.encoder", (void *)sjson_encoder_map); + luaL_rometatable(L, "sjson.decoder", (void *)sjson_decoder_map); + luaL_rometatable(L, "sjson.encoder", (void *)sjson_encoder_map); #endif return 1; } #ifndef LOCAL_LUA -NODEMCU_MODULE(SJSON, "sjson", sjson_map, luaopen_sjson); -#endif \ No newline at end of file +NODEMCU_MODULE(SJSON, "sjson", sjson, luaopen_sjson); +#endif diff --git a/components/modules/sodium.c b/components/modules/sodium.c index cdba05e155..1431849af0 100644 --- a/components/modules/sodium.c +++ b/components/modules/sodium.c @@ -129,24 +129,21 @@ static int l_crypto_box_seal_open(lua_State *L) return 1; } -static const LUA_REG_TYPE random_map[] = { - { LSTRKEY("random"), LFUNCVAL(l_randombytes_random) }, - { LSTRKEY("uniform"), LFUNCVAL(l_randombytes_uniform) }, - { LSTRKEY("buf"), LFUNCVAL(l_randombytes_buf) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE crypto_box_map[] = { - { LSTRKEY("keypair"), LFUNCVAL(l_crypto_box_keypair) }, - { LSTRKEY("seal"), LFUNCVAL(l_crypto_box_seal) }, - { LSTRKEY("seal_open"), LFUNCVAL(l_crypto_box_seal_open) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE sodium_map[] = { - { LSTRKEY("random"), LROVAL(random_map) }, - { LSTRKEY("crypto_box"), LROVAL(crypto_box_map) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(SODIUM, "sodium", sodium_map, NULL); +LROT_BEGIN(random) + LROT_FUNCENTRY(random, l_randombytes_random) + LROT_FUNCENTRY(uniform, l_randombytes_uniform) + LROT_FUNCENTRY(buf, l_randombytes_buf) +LROT_END(random, NULL, 0) + +LROT_BEGIN(crypto_box) + LROT_FUNCENTRY(keypair, l_crypto_box_keypair) + LROT_FUNCENTRY(seal, l_crypto_box_seal) + LROT_FUNCENTRY(seal_open, l_crypto_box_seal_open) +LROT_END(crypto_box, NULL, 0) + +LROT_BEGIN(sodium) + LROT_TABENTRY(random, random) + LROT_TABENTRY(crypto_box, crypto_box) +LROT_END(sodium, NULL, 0) + +NODEMCU_MODULE(SODIUM, "sodium", sodium, NULL); diff --git a/components/modules/spi.c b/components/modules/spi.c index 58f2cc8898..e0fde70870 100644 --- a/components/modules/spi.c +++ b/components/modules/spi.c @@ -7,18 +7,17 @@ #include "driver/spi_common.h" -static const LUA_REG_TYPE lspi_map[] = { - { LSTRKEY( "master" ), LFUNCVAL( lspi_master ) }, -// { LSTRKEY( "slave" ), LFUNCVAL( lspi_slave ) }, - { LSTRKEY( "SPI" ), LNUMVAL( SPI_HOST ) }, - { LSTRKEY( "HSPI" ), LNUMVAL( HSPI_HOST ) }, - { LSTRKEY( "VSPI" ), LNUMVAL( VSPI_HOST ) }, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(lspi) + LROT_FUNCENTRY( master, lspi_master ) +// LROT_FUNCENTRY( slave, lspi_slave ) + LROT_NUMENTRY( SPI, SPI_HOST ) + LROT_NUMENTRY( HSPI, HSPI_HOST ) + LROT_NUMENTRY( VSPI, VSPI_HOST ) +LROT_END(lspi, NULL, 0) int luaopen_spi( lua_State *L ) { luaopen_spi_master( L ); return 0; } -NODEMCU_MODULE(SPI, "spi", lspi_map, luaopen_spi); +NODEMCU_MODULE(SPI, "spi", lspi, luaopen_spi); diff --git a/components/modules/spi_master.c b/components/modules/spi_master.c index 35cc8bd107..f212c9b79c 100644 --- a/components/modules/spi_master.c +++ b/components/modules/spi_master.c @@ -177,13 +177,12 @@ static int lspi_device_transfer( lua_State *L ) } -static const LUA_REG_TYPE lspi_device_map[] = { - { LSTRKEY( "transfer" ), LFUNCVAL( lspi_device_transfer ) }, - { LSTRKEY( "remove" ), LFUNCVAL( lspi_device_free ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( lspi_device_free ) }, - { LSTRKEY( "__index" ), LROVAL( lspi_device_map ) }, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(lspi_device) + LROT_FUNCENTRY( transfer, lspi_device_transfer ) + LROT_FUNCENTRY( remove, lspi_device_free ) + LROT_FUNCENTRY( __gc, lspi_device_free ) + LROT_TABENTRY( __index, lspi_device ) +LROT_END(lspi_device, NULL, 0) // **************************************************************************** @@ -321,13 +320,12 @@ static int lspi_host_device( lua_State *L ) } -static const LUA_REG_TYPE lspi_master_map[] = { - { LSTRKEY( "device" ), LFUNCVAL( lspi_host_device ) }, - { LSTRKEY( "close" ), LFUNCVAL( lspi_host_free ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( lspi_host_free ) }, - { LSTRKEY( "__index" ), LROVAL( lspi_master_map ) }, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(lspi_master) + LROT_FUNCENTRY( device, lspi_host_device ) + LROT_FUNCENTRY( close, lspi_host_free ) + LROT_FUNCENTRY( __gc, lspi_host_free ) + LROT_TABENTRY( __index, lspi_master ) +LROT_END(lspi_master, NULL, 0) // **************************************************************************** diff --git a/components/modules/struct.c b/components/modules/struct.c index cbe9da6946..ac6ccda51c 100644 --- a/components/modules/struct.c +++ b/components/modules/struct.c @@ -392,12 +392,11 @@ static int b_size (lua_State *L) { -static const LUA_REG_TYPE thislib[] = { - {LSTRKEY("pack"), LFUNCVAL(b_pack)}, - {LSTRKEY("unpack"), LFUNCVAL(b_unpack)}, - {LSTRKEY("size"), LFUNCVAL(b_size)}, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(thislib) + LROT_FUNCENTRY(pack, b_pack) + LROT_FUNCENTRY(unpack, b_unpack) + LROT_FUNCENTRY(size, b_size) +LROT_END(thislib, NULL, 0) NODEMCU_MODULE(STRUCT, "struct", thislib, NULL); diff --git a/components/modules/time.c b/components/modules/time.c index 1afc80b372..9559269f52 100644 --- a/components/modules/time.c +++ b/components/modules/time.c @@ -143,17 +143,16 @@ static int time_cal2epoc(lua_State *L) return 1; } -static const LUA_REG_TYPE time_map[] = { - { LSTRKEY("set"), LFUNCVAL(time_set) }, - { LSTRKEY("get"), LFUNCVAL(time_get) }, - { LSTRKEY("getlocal"), LFUNCVAL(time_getLocal) }, - { LSTRKEY("settimezone"), LFUNCVAL(time_setTimezone) }, - { LSTRKEY("initntp"), LFUNCVAL(time_initNTP) }, - { LSTRKEY("ntpenabled"), LFUNCVAL(time_ntpEnabled) }, - { LSTRKEY("ntpstop"), LFUNCVAL(time_ntpStop) }, - { LSTRKEY("epoch2cal"), LFUNCVAL(time_epoch2cal) }, - { LSTRKEY("cal2epoch"), LFUNCVAL(time_cal2epoc) }, - { LNILKEY, LNILVAL } -}; - -NODEMCU_MODULE(TIME, "time", time_map, NULL); +LROT_BEGIN(time) + LROT_FUNCENTRY(set, time_set) + LROT_FUNCENTRY(get, time_get) + LROT_FUNCENTRY(getlocal, time_getLocal) + LROT_FUNCENTRY(settimezone, time_setTimezone) + LROT_FUNCENTRY(initntp, time_initNTP) + LROT_FUNCENTRY(ntpenabled, time_ntpEnabled) + LROT_FUNCENTRY(ntpstop, time_ntpStop) + LROT_FUNCENTRY(epoch2cal, time_epoch2cal) + LROT_FUNCENTRY(cal2epoch, time_cal2epoc) +LROT_END(time, NULL, 0) + +NODEMCU_MODULE(TIME, "time", time, NULL); diff --git a/components/modules/tmr.c b/components/modules/tmr.c index 041ea4de8a..b45cea3803 100755 --- a/components/modules/tmr.c +++ b/components/modules/tmr.c @@ -235,26 +235,24 @@ static int tmr_create( lua_State *L ) { // Module function map -static const LUA_REG_TYPE tmr_dyn_map[] = { - { LSTRKEY( "register" ), LFUNCVAL( tmr_register ) }, - { LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) }, - { LSTRKEY( "start" ), LFUNCVAL( tmr_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) }, - { LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) }, - { LSTRKEY( "interval" ), LFUNCVAL( tmr_interval) }, - { LSTRKEY( "state" ), LFUNCVAL( tmr_state ) }, - { LSTRKEY( "__gc" ), LFUNCVAL( tmr_unregister ) }, - { LSTRKEY( "__index" ), LROVAL( tmr_dyn_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE tmr_map[] = { - { LSTRKEY( "create" ), LFUNCVAL( tmr_create ) }, - { LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) }, - { LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) }, - { LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) }, - { LNILKEY, LNILVAL } -}; +LROT_BEGIN(tmr_dyn) + LROT_FUNCENTRY( register, tmr_register ) + LROT_FUNCENTRY( alarm, tmr_alarm ) + LROT_FUNCENTRY( start, tmr_start ) + LROT_FUNCENTRY( stop, tmr_stop ) + LROT_FUNCENTRY( unregister, tmr_unregister ) + LROT_FUNCENTRY( interval, tmr_interval) + LROT_FUNCENTRY( state, tmr_state ) + LROT_FUNCENTRY( __gc, tmr_unregister ) + LROT_TABENTRY ( __index, tmr_dyn ) +LROT_END(tmr_dyn, NULL, 0) + +LROT_BEGIN(tmr) + LROT_FUNCENTRY( create, tmr_create ) + LROT_NUMENTRY ( ALARM_SINGLE, TIMER_MODE_SINGLE ) + LROT_NUMENTRY ( ALARM_SEMI, TIMER_MODE_SEMI ) + LROT_NUMENTRY ( ALARM_AUTO, TIMER_MODE_AUTO ) +LROT_END(tmr, NULL, 0) static int luaopen_tmr( lua_State *L ){ luaL_rometatable(L, "tmr.timer", (void *)tmr_dyn_map); @@ -264,4 +262,4 @@ static int luaopen_tmr( lua_State *L ){ return 0; } -NODEMCU_MODULE(TMR, "tmr", tmr_map, luaopen_tmr); +NODEMCU_MODULE(TMR, "tmr", tmr, luaopen_tmr); diff --git a/components/modules/u8g2.c b/components/modules/u8g2.c index dea6ad1241..fbc41e69e0 100644 --- a/components/modules/u8g2.c +++ b/components/modules/u8g2.c @@ -560,52 +560,51 @@ static int lu8g2_updateDisplayArea( lua_State *L ) } -static const LUA_REG_TYPE lu8g2_display_map[] = { - { LSTRKEY( "clearBuffer" ), LFUNCVAL( lu8g2_clearBuffer ) }, - { LSTRKEY( "drawBox" ), LFUNCVAL( lu8g2_drawBox ) }, - { LSTRKEY( "drawCircle" ), LFUNCVAL( lu8g2_drawCircle ) }, - { LSTRKEY( "drawDisc" ), LFUNCVAL( lu8g2_drawDisc ) }, - { LSTRKEY( "drawEllipse" ), LFUNCVAL( lu8g2_drawEllipse ) }, - { LSTRKEY( "drawFilledEllipse" ), LFUNCVAL( lu8g2_drawFilledEllipse ) }, - { LSTRKEY( "drawFrame" ), LFUNCVAL( lu8g2_drawFrame ) }, - { LSTRKEY( "drawGlyph" ), LFUNCVAL( lu8g2_drawGlyph ) }, - { LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g2_drawHLine ) }, - { LSTRKEY( "drawLine" ), LFUNCVAL( lu8g2_drawLine ) }, - { LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g2_drawPixel ) }, - { LSTRKEY( "drawRBox" ), LFUNCVAL( lu8g2_drawRBox ) }, - { LSTRKEY( "drawRFrame" ), LFUNCVAL( lu8g2_drawRFrame ) }, - { LSTRKEY( "drawStr" ), LFUNCVAL( lu8g2_drawStr ) }, - { LSTRKEY( "drawTriangle" ), LFUNCVAL( lu8g2_drawTriangle ) }, - { LSTRKEY( "drawUTF8" ), LFUNCVAL( lu8g2_drawUTF8 ) }, - { LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g2_drawVLine ) }, - { LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g2_drawXBM ) }, - { LSTRKEY( "getAscent" ), LFUNCVAL( lu8g2_getAscent ) }, - { LSTRKEY( "getDescent" ), LFUNCVAL( lu8g2_getDescent ) }, - { LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g2_getStrWidth ) }, - { LSTRKEY( "getUTF8Width" ), LFUNCVAL( lu8g2_getUTF8Width ) }, - { LSTRKEY( "sendBuffer" ), LFUNCVAL( lu8g2_sendBuffer ) }, - { LSTRKEY( "setBitmapMode" ), LFUNCVAL( lu8g2_setBitmapMode ) }, - { LSTRKEY( "setContrast" ), LFUNCVAL( lu8g2_setContrast ) }, - { LSTRKEY( "setDisplayRotation" ), LFUNCVAL( lu8g2_setDisplayRotation ) }, - { LSTRKEY( "setDrawColor" ), LFUNCVAL( lu8g2_setDrawColor ) }, - { LSTRKEY( "setFlipMode" ), LFUNCVAL( lu8g2_setFlipMode ) }, - { LSTRKEY( "setFont" ), LFUNCVAL( lu8g2_setFont ) }, - { LSTRKEY( "setFontDirection" ), LFUNCVAL( lu8g2_setFontDirection ) }, - { LSTRKEY( "setFontMode" ), LFUNCVAL( lu8g2_setFontMode ) }, - { LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lu8g2_setFontPosBaseline ) }, - { LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lu8g2_setFontPosBottom ) }, - { LSTRKEY( "setFontPosTop" ), LFUNCVAL( lu8g2_setFontPosTop ) }, - { LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lu8g2_setFontPosCenter ) }, - { LSTRKEY( "setFontRefHeightAll" ), LFUNCVAL( lu8g2_setFontRefHeightAll ) }, - { LSTRKEY( "setFontRefHeightExtendedText" ), LFUNCVAL( lu8g2_setFontRefHeightExtendedText ) }, - { LSTRKEY( "setFontRefHeightText" ), LFUNCVAL( lu8g2_setFontRefHeightText ) }, - { LSTRKEY( "setPowerSave" ), LFUNCVAL( lu8g2_setPowerSave ) }, - { LSTRKEY( "updateDispla" ), LFUNCVAL( lu8g2_updateDisplay ) }, - { LSTRKEY( "updateDisplayArea" ), LFUNCVAL( lu8g2_updateDisplayArea ) }, - //{ LSTRKEY( "__gc" ), LFUNCVAL( lu8g2_display_free ) }, - { LSTRKEY( "__index" ), LROVAL( lu8g2_display_map ) }, - {LNILKEY, LNILVAL} -}; +LROT_BEGIN(lu8g2_display) + LROT_FUNCENTRY( clearBuffer, lu8g2_clearBuffer ) + LROT_FUNCENTRY( drawBox, lu8g2_drawBox ) + LROT_FUNCENTRY( drawCircle, lu8g2_drawCircle ) + LROT_FUNCENTRY( drawDisc, lu8g2_drawDisc ) + LROT_FUNCENTRY( drawEllipse, lu8g2_drawEllipse ) + LROT_FUNCENTRY( drawFilledEllipse, lu8g2_drawFilledEllipse ) + LROT_FUNCENTRY( drawFrame, lu8g2_drawFrame ) + LROT_FUNCENTRY( drawGlyph, lu8g2_drawGlyph ) + LROT_FUNCENTRY( drawHLine, lu8g2_drawHLine ) + LROT_FUNCENTRY( drawLine, lu8g2_drawLine ) + LROT_FUNCENTRY( drawPixel, lu8g2_drawPixel ) + LROT_FUNCENTRY( drawRBox, lu8g2_drawRBox ) + LROT_FUNCENTRY( drawRFrame, lu8g2_drawRFrame ) + LROT_FUNCENTRY( drawStr, lu8g2_drawStr ) + LROT_FUNCENTRY( drawTriangle, lu8g2_drawTriangle ) + LROT_FUNCENTRY( drawUTF8, lu8g2_drawUTF8 ) + LROT_FUNCENTRY( drawVLine, lu8g2_drawVLine ) + LROT_FUNCENTRY( drawXBM, lu8g2_drawXBM ) + LROT_FUNCENTRY( getAscent, lu8g2_getAscent ) + LROT_FUNCENTRY( getDescent, lu8g2_getDescent ) + LROT_FUNCENTRY( getStrWidth, lu8g2_getStrWidth ) + LROT_FUNCENTRY( getUTF8Width, lu8g2_getUTF8Width ) + LROT_FUNCENTRY( sendBuffer, lu8g2_sendBuffer ) + LROT_FUNCENTRY( setBitmapMode, lu8g2_setBitmapMode ) + LROT_FUNCENTRY( setContrast, lu8g2_setContrast ) + LROT_FUNCENTRY( setDisplayRotation, lu8g2_setDisplayRotation ) + LROT_FUNCENTRY( setDrawColor, lu8g2_setDrawColor ) + LROT_FUNCENTRY( setFlipMode, lu8g2_setFlipMode ) + LROT_FUNCENTRY( setFont, lu8g2_setFont ) + LROT_FUNCENTRY( setFontDirection, lu8g2_setFontDirection ) + LROT_FUNCENTRY( setFontMode, lu8g2_setFontMode ) + LROT_FUNCENTRY( setFontPosBaseline, lu8g2_setFontPosBaseline ) + LROT_FUNCENTRY( setFontPosBottom, lu8g2_setFontPosBottom ) + LROT_FUNCENTRY( setFontPosTop, lu8g2_setFontPosTop ) + LROT_FUNCENTRY( setFontPosCenter, lu8g2_setFontPosCenter ) + LROT_FUNCENTRY( setFontRefHeightAll, lu8g2_setFontRefHeightAll ) + LROT_FUNCENTRY( setFontRefHeightExtendedText, lu8g2_setFontRefHeightExtendedText ) + LROT_FUNCENTRY( setFontRefHeightText, lu8g2_setFontRefHeightText ) + LROT_FUNCENTRY( setPowerSave, lu8g2_setPowerSave ) + LROT_FUNCENTRY( updateDispla, lu8g2_updateDisplay ) + LROT_FUNCENTRY( updateDisplayArea, lu8g2_updateDisplayArea ) + //LROT_FUNCENTRY( __gc, lu8g2_display_free ) + LROT_TABENTRY( __index, lu8g2_display ) +LROT_END(lu8g2_display, NULL, 0) uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); @@ -803,33 +802,32 @@ U8G2_DISPLAY_TABLE_SPI #undef U8G2_FONT_TABLE_ENTRY #undef U8G2_DISPLAY_TABLE_ENTRY #define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \ - { LSTRKEY( #binding ), LFUNCVAL( l ## binding ) }, + LROT_FUNCENTRY( #binding, l ## binding ) -static const LUA_REG_TYPE lu8g2_map[] = { +LROT_BEGIN(lu8g2) U8G2_DISPLAY_TABLE_I2C U8G2_DISPLAY_TABLE_SPI // // Register fonts #define U8G2_FONT_TABLE_ENTRY(font) \ - { LSTRKEY( #font ), LUDATA( (void *)(u8g2_ ## font) ) }, + LROT_LUDENTRY( #font, (void *)(u8g2_ ## font) ) U8G2_FONT_TABLE // - { LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( U8G2_DRAW_UPPER_RIGHT ) }, - { LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( U8G2_DRAW_UPPER_LEFT ) }, - { LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( U8G2_DRAW_LOWER_RIGHT ) }, - { LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( U8G2_DRAW_LOWER_LEFT ) }, - { LSTRKEY( "DRAW_ALL" ), LNUMVAL( U8G2_DRAW_ALL ) }, - { LSTRKEY( "R0" ), LUDATA( (void *)U8G2_R0 ) }, - { LSTRKEY( "R1" ), LUDATA( (void *)U8G2_R1 ) }, - { LSTRKEY( "R2" ), LUDATA( (void *)U8G2_R2 ) }, - { LSTRKEY( "R3" ), LUDATA( (void *)U8G2_R3 ) }, - { LSTRKEY( "MIRROR" ), LUDATA( (void *)U8G2_MIRROR ) }, - {LNILKEY, LNILVAL} -}; + LROT_NUMENTRY( DRAW_UPPER_RIGHT, U8G2_DRAW_UPPER_RIGHT ) + LROT_NUMENTRY( DRAW_UPPER_LEFT, U8G2_DRAW_UPPER_LEFT ) + LROT_NUMENTRY( DRAW_LOWER_RIGHT, U8G2_DRAW_LOWER_RIGHT ) + LROT_NUMENTRY( DRAW_LOWER_LEFT, U8G2_DRAW_LOWER_LEFT ) + LROT_NUMENTRY( DRAW_ALL, U8G2_DRAW_ALL ) + LROT_LUDENTRY( R0, (void *)U8G2_R0 ) + LROT_LUDENTRY( R1, (void *)U8G2_R1 ) + LROT_LUDENTRY( R2, (void *)U8G2_R2 ) + LROT_LUDENTRY( R3, (void *)U8G2_R3 ) + LROT_LUDENTRY( MIRROR, (void *)U8G2_MIRROR ) +LROT_END(lu8g2, NULL, 0) int luaopen_u8g2( lua_State *L ) { luaL_rometatable(L, "u8g2.display", (void *)lu8g2_display_map); return 0; } -NODEMCU_MODULE(U8G2, "u8g2", lu8g2_map, luaopen_u8g2); +NODEMCU_MODULE(U8G2, "u8g2", lu8g2, luaopen_u8g2); diff --git a/components/modules/ucg.c b/components/modules/ucg.c index 5794110e61..28d27e42af 100644 --- a/components/modules/ucg.c +++ b/components/modules/ucg.c @@ -684,82 +684,77 @@ UCG_DISPLAY_TABLE // Module function map -static const LUA_REG_TYPE lucg_display_map[] = -{ - { LSTRKEY( "begin" ), LFUNCVAL( lucg_begin ) }, - { LSTRKEY( "clearScreen" ), LFUNCVAL( lucg_clearScreen ) }, - { LSTRKEY( "draw90Line" ), LFUNCVAL( lucg_draw90Line ) }, - { LSTRKEY( "drawBox" ), LFUNCVAL( lucg_drawBox ) }, - { LSTRKEY( "drawCircle" ), LFUNCVAL( lucg_drawCircle ) }, - { LSTRKEY( "drawDisc" ), LFUNCVAL( lucg_drawDisc ) }, - { LSTRKEY( "drawFrame" ), LFUNCVAL( lucg_drawFrame ) }, - { LSTRKEY( "drawGlyph" ), LFUNCVAL( lucg_drawGlyph ) }, - { LSTRKEY( "drawGradientBox" ), LFUNCVAL( lucg_drawGradientBox ) }, - { LSTRKEY( "drawGradientLine" ), LFUNCVAL( lucg_drawGradientLine ) }, - { LSTRKEY( "drawHLine" ), LFUNCVAL( lucg_drawHLine ) }, - { LSTRKEY( "drawLine" ), LFUNCVAL( lucg_drawLine ) }, - { LSTRKEY( "drawPixel" ), LFUNCVAL( lucg_drawPixel ) }, - { LSTRKEY( "drawRBox" ), LFUNCVAL( lucg_drawRBox ) }, - { LSTRKEY( "drawRFrame" ), LFUNCVAL( lucg_drawRFrame ) }, - { LSTRKEY( "drawString" ), LFUNCVAL( lucg_drawString ) }, - { LSTRKEY( "drawTetragon" ), LFUNCVAL( lucg_drawTetragon ) }, - { LSTRKEY( "drawTriangle" ), LFUNCVAL( lucg_drawTriangle ) }, - { LSTRKEY( "drawVLine" ), LFUNCVAL( lucg_drawVLine ) }, - { LSTRKEY( "getFontAscent" ), LFUNCVAL( lucg_getFontAscent ) }, - { LSTRKEY( "getFontDescent" ), LFUNCVAL( lucg_getFontDescent ) }, - { LSTRKEY( "getHeight" ), LFUNCVAL( lucg_getHeight ) }, - { LSTRKEY( "getStrWidth" ), LFUNCVAL( lucg_getStrWidth ) }, - { LSTRKEY( "getWidth" ), LFUNCVAL( lucg_getWidth ) }, - { LSTRKEY( "print" ), LFUNCVAL( lucg_print ) }, - { LSTRKEY( "setClipRange" ), LFUNCVAL( lucg_setClipRange ) }, - { LSTRKEY( "setColor" ), LFUNCVAL( lucg_setColor ) }, - { LSTRKEY( "setFont" ), LFUNCVAL( lucg_setFont ) }, - { LSTRKEY( "setFontMode" ), LFUNCVAL( lucg_setFontMode ) }, - { LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lucg_setFontPosBaseline ) }, - { LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lucg_setFontPosBottom ) }, - { LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lucg_setFontPosCenter ) }, - { LSTRKEY( "setFontPosTop" ), LFUNCVAL( lucg_setFontPosTop ) }, - { LSTRKEY( "setMaxClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) }, - { LSTRKEY( "setPrintDir" ), LFUNCVAL( lucg_setPrintDir ) }, - { LSTRKEY( "setPrintPos" ), LFUNCVAL( lucg_setPrintPos ) }, - { LSTRKEY( "setRotate90" ), LFUNCVAL( lucg_setRotate90 ) }, - { LSTRKEY( "setRotate180" ), LFUNCVAL( lucg_setRotate180 ) }, - { LSTRKEY( "setRotate270" ), LFUNCVAL( lucg_setRotate270 ) }, - { LSTRKEY( "setScale2x2" ), LFUNCVAL( lucg_setScale2x2 ) }, - { LSTRKEY( "undoClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) }, - { LSTRKEY( "undoRotate" ), LFUNCVAL( lucg_undoRotate ) }, - { LSTRKEY( "undoScale" ), LFUNCVAL( lucg_undoScale ) }, - - { LSTRKEY( "__gc" ), LFUNCVAL( lucg_close_display ) }, - { LSTRKEY( "__index" ), LROVAL ( lucg_display_map ) }, - { LNILKEY, LNILVAL } -}; - -static const LUA_REG_TYPE lucg_map[] = -{ +LROT_BEGIN(lucg_display) + LROT_FUNCENTRY( begin, lucg_begin ) + LROT_FUNCENTRY( clearScreen, lucg_clearScreen ) + LROT_FUNCENTRY( draw90Line, lucg_draw90Line ) + LROT_FUNCENTRY( drawBox, lucg_drawBox ) + LROT_FUNCENTRY( drawCircle, lucg_drawCircle ) + LROT_FUNCENTRY( drawDisc, lucg_drawDisc ) + LROT_FUNCENTRY( drawFrame, lucg_drawFrame ) + LROT_FUNCENTRY( drawGlyph, lucg_drawGlyph ) + LROT_FUNCENTRY( drawGradientBox, lucg_drawGradientBox ) + LROT_FUNCENTRY( drawGradientLine, lucg_drawGradientLine ) + LROT_FUNCENTRY( drawHLine, lucg_drawHLine ) + LROT_FUNCENTRY( drawLine, lucg_drawLine ) + LROT_FUNCENTRY( drawPixel, lucg_drawPixel ) + LROT_FUNCENTRY( drawRBox, lucg_drawRBox ) + LROT_FUNCENTRY( drawRFrame, lucg_drawRFrame ) + LROT_FUNCENTRY( drawString, lucg_drawString ) + LROT_FUNCENTRY( drawTetragon, lucg_drawTetragon ) + LROT_FUNCENTRY( drawTriangle, lucg_drawTriangle ) + LROT_FUNCENTRY( drawVLine, lucg_drawVLine ) + LROT_FUNCENTRY( getFontAscent, lucg_getFontAscent ) + LROT_FUNCENTRY( getFontDescent, lucg_getFontDescent ) + LROT_FUNCENTRY( getHeight, lucg_getHeight ) + LROT_FUNCENTRY( getStrWidth, lucg_getStrWidth ) + LROT_FUNCENTRY( getWidth, lucg_getWidth ) + LROT_FUNCENTRY( print, lucg_print ) + LROT_FUNCENTRY( setClipRange, lucg_setClipRange ) + LROT_FUNCENTRY( setColor, lucg_setColor ) + LROT_FUNCENTRY( setFont, lucg_setFont ) + LROT_FUNCENTRY( setFontMode, lucg_setFontMode ) + LROT_FUNCENTRY( setFontPosBaseline, lucg_setFontPosBaseline ) + LROT_FUNCENTRY( setFontPosBottom, lucg_setFontPosBottom ) + LROT_FUNCENTRY( setFontPosCenter, lucg_setFontPosCenter ) + LROT_FUNCENTRY( setFontPosTop, lucg_setFontPosTop ) + LROT_FUNCENTRY( setMaxClipRange, lucg_setMaxClipRange ) + LROT_FUNCENTRY( setPrintDir, lucg_setPrintDir ) + LROT_FUNCENTRY( setPrintPos, lucg_setPrintPos ) + LROT_FUNCENTRY( setRotate90, lucg_setRotate90 ) + LROT_FUNCENTRY( setRotate180, lucg_setRotate180 ) + LROT_FUNCENTRY( setRotate270, lucg_setRotate270 ) + LROT_FUNCENTRY( setScale2x2, lucg_setScale2x2 ) + LROT_FUNCENTRY( undoClipRange, lucg_setMaxClipRange ) + LROT_FUNCENTRY( undoRotate, lucg_undoRotate ) + LROT_FUNCENTRY( undoScale, lucg_undoScale ) + LROT_FUNCENTRY( __gc, lucg_close_display ) + LROT_TABENTRY( __index, lucg_display ) +LROT_END(lucg_display, NULL, 0) + +LROT_BEGIN(lucg) #undef UCG_DISPLAY_TABLE_ENTRY -#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) { LSTRKEY( #binding ), LFUNCVAL ( l ## binding ) }, +#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) LROT_FUNCENTRY( #binding, l ## binding ) UCG_DISPLAY_TABLE // Register fonts #undef UCG_FONT_TABLE_ENTRY -#define UCG_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LUDATA( (void *)(ucg_ ## font) ) }, +#define UCG_FONT_TABLE_ENTRY(font) LROT_LUDENTRY( #font, (void *)(ucg_ ## font) ) UCG_FONT_TABLE // Font modes - { LSTRKEY( "FONT_MODE_TRANSPARENT" ), LNUMVAL( UCG_FONT_MODE_TRANSPARENT ) }, - { LSTRKEY( "FONT_MODE_SOLID" ), LNUMVAL( UCG_FONT_MODE_SOLID ) }, + LROT_NUMENTRY( FONT_MODE_TRANSPARENT, UCG_FONT_MODE_TRANSPARENT ) + LROT_NUMENTRY( FONT_MODE_SOLID, UCG_FONT_MODE_SOLID ) // Options for circle/ disc drawing - { LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( UCG_DRAW_UPPER_RIGHT ) }, - { LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( UCG_DRAW_UPPER_LEFT ) }, - { LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( UCG_DRAW_LOWER_RIGHT ) }, - { LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( UCG_DRAW_LOWER_LEFT ) }, - { LSTRKEY( "DRAW_ALL" ), LNUMVAL( UCG_DRAW_ALL ) }, + LROT_NUMENTRY( DRAW_UPPER_RIGHT, UCG_DRAW_UPPER_RIGHT ) + LROT_NUMENTRY( DRAW_UPPER_LEFT, UCG_DRAW_UPPER_LEFT ) + LROT_NUMENTRY( DRAW_LOWER_RIGHT, UCG_DRAW_LOWER_RIGHT ) + LROT_NUMENTRY( DRAW_LOWER_LEFT, UCG_DRAW_LOWER_LEFT ) + LROT_NUMENTRY( DRAW_ALL, UCG_DRAW_ALL ) - { LSTRKEY( "__metatable" ), LROVAL( lucg_map ) }, - { LNILKEY, LNILVAL } -}; + LROT_TABENTRY( __metatable, lucg ) +LROT_END(lucg, NULL, 0) int luaopen_ucg( lua_State *L ) { @@ -767,4 +762,4 @@ int luaopen_ucg( lua_State *L ) return 0; } -NODEMCU_MODULE(UCG, "ucg", lucg_map, luaopen_ucg); +NODEMCU_MODULE(UCG, "ucg", lucg, luaopen_ucg); diff --git a/components/modules/wifi.c b/components/modules/wifi.c index 38e8060682..0a6f45a081 100644 --- a/components/modules/wifi.c +++ b/components/modules/wifi.c @@ -108,37 +108,34 @@ static int wifi_init (lua_State *L) } -extern const LUA_REG_TYPE wifi_sta_map[]; -extern const LUA_REG_TYPE wifi_ap_map[]; +LROT_EXTERN(wifi_sta); +LROT_EXTERN(wifi_ap); -static const LUA_REG_TYPE wifi_map[] = -{ - { LSTRKEY( "getchannel"), LFUNCVAL( wifi_getchannel ) }, - { LSTRKEY( "getmode" ), LFUNCVAL( wifi_getmode ) }, - { LSTRKEY( "mode" ), LFUNCVAL( wifi_mode ) }, - { LSTRKEY( "start" ), LFUNCVAL( wifi_start ) }, - { LSTRKEY( "stop" ), LFUNCVAL( wifi_stop ) }, - - { LSTRKEY( "sta" ), LROVAL( wifi_sta_map ) }, - { LSTRKEY( "ap" ), LROVAL( wifi_ap_map ) }, +LROT_BEGIN(wifi) + LROT_FUNCENTRY( getchannel, wifi_getchannel ) + LROT_FUNCENTRY( getmode, wifi_getmode ) + LROT_FUNCENTRY( mode, wifi_mode ) + LROT_FUNCENTRY( start, wifi_start ) + LROT_FUNCENTRY( stop, wifi_stop ) + LROT_TABENTRY ( sta, wifi_sta ) + LROT_TABENTRY ( ap, wifi_ap ) - { LSTRKEY( "NULLMODE" ), LNUMVAL( WIFI_MODE_NULL ) }, - { LSTRKEY( "STATION" ), LNUMVAL( WIFI_MODE_STA ) }, - { LSTRKEY( "SOFTAP" ), LNUMVAL( WIFI_MODE_AP ) }, - { LSTRKEY( "STATIONAP" ), LNUMVAL( WIFI_MODE_APSTA ) }, - { LSTRKEY( "AUTH_OPEN" ), LNUMVAL( WIFI_AUTH_OPEN ) }, - { LSTRKEY( "AUTH_WEP" ), LNUMVAL( WIFI_AUTH_WEP ) }, - { LSTRKEY( "AUTH_WPA_PSK" ), LNUMVAL( WIFI_AUTH_WPA_PSK ) }, - { LSTRKEY( "AUTH_WPA2_PSK" ), LNUMVAL( WIFI_AUTH_WPA2_PSK ) }, - { LSTRKEY( "AUTH_WPA_WPA2_PSK" ), LNUMVAL( WIFI_AUTH_WPA_WPA2_PSK ) }, + LROT_NUMENTRY ( NULLMODE, WIFI_MODE_NULL ) + LROT_NUMENTRY ( STATION, WIFI_MODE_STA ) + LROT_NUMENTRY ( SOFTAP, WIFI_MODE_AP ) + LROT_NUMENTRY ( STATIONAP, WIFI_MODE_APSTA ) - { LSTRKEY( STR_WIFI_SECOND_CHAN_NONE ), LNUMVAL( WIFI_SECOND_CHAN_NONE ) }, - { LSTRKEY( STR_WIFI_SECOND_CHAN_ABOVE ), LNUMVAL( WIFI_SECOND_CHAN_ABOVE ) }, - { LSTRKEY( STR_WIFI_SECOND_CHAN_BELOW ), LNUMVAL( WIFI_SECOND_CHAN_BELOW ) }, + LROT_NUMENTRY ( AUTH_OPEN, WIFI_AUTH_OPEN ) + LROT_NUMENTRY ( AUTH_WEP, WIFI_AUTH_WEP ) + LROT_NUMENTRY ( AUTH_WPA_PSK, WIFI_AUTH_WPA_PSK ) + LROT_NUMENTRY ( AUTH_WPA2_PSK, WIFI_AUTH_WPA2_PSK ) + LROT_NUMENTRY ( AUTH_WPA_WPA2_PSK, WIFI_AUTH_WPA_WPA2_PSK ) - { LNILKEY, LNILVAL } -}; + LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_NONE, WIFI_SECOND_CHAN_NONE ) + LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_ABOVE, WIFI_SECOND_CHAN_ABOVE ) + LROT_NUMENTRY ( STR_WIFI_SECOND_CHAN_BELOW, WIFI_SECOND_CHAN_BELOW ) +LROT_END(wifi, NULL, 0) -NODEMCU_MODULE(WIFI, "wifi", wifi_map, wifi_init); +NODEMCU_MODULE(WIFI, "wifi", wifi, wifi_init); diff --git a/components/modules/wifi_ap.c b/components/modules/wifi_ap.c index a0ec454df1..1cec48ebf1 100644 --- a/components/modules/wifi_ap.c +++ b/components/modules/wifi_ap.c @@ -170,11 +170,9 @@ static int wifi_ap_setip(lua_State *L) str = luaL_optlstring(L, -1, "", &len); if(ipaddr_aton(str, &dns)) { - opt = 1; dhcps_dns_setserver(&dns); tcpip_adapter_dhcps_option(TCPIP_ADAPTER_OP_SET, DOMAIN_NAME_SERVER, &opt, sizeof(opt)); - } ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); @@ -237,7 +235,7 @@ static int wifi_ap_config (lua_State *L) lua_getfield (L, 1, "beacon"); cfg.ap.beacon_interval = luaL_optint (L, -1, DEFAULT_AP_BEACON); - + SET_SAVE_MODE(save); esp_err_t err = esp_wifi_set_config (WIFI_IF_AP, &cfg); return (err == ESP_OK) ? @@ -255,13 +253,10 @@ static int wifi_ap_on (lua_State *L) } -const LUA_REG_TYPE wifi_ap_map[] = -{ - { LSTRKEY( "setip" ), LFUNCVAL( wifi_ap_setip ) }, - { LSTRKEY( "sethostname" ), LFUNCVAL( wifi_ap_sethostname ) }, - { LSTRKEY( "config" ), LFUNCVAL( wifi_ap_config ) }, - { LSTRKEY( "on" ), LFUNCVAL( wifi_ap_on ) }, - { LSTRKEY( "getmac" ), LFUNCVAL( wifi_ap_getmac ) }, - - { LNILKEY, LNILVAL } -}; +LROT_PUBLIC_BEGIN(wifi_ap) + LROT_FUNCENTRY( setip, wifi_ap_setip ) + LROT_FUNCENTRY( sethostname, wifi_ap_sethostname ) + LROT_FUNCENTRY( config, wifi_ap_config ) + LROT_FUNCENTRY( on, wifi_ap_on ) + LROT_FUNCENTRY( getmac, wifi_ap_getmac ) +LROT_END(wifi_ap, NULL, 0) diff --git a/components/modules/wifi_sta.c b/components/modules/wifi_sta.c index 28ed1d6172..1e2c0713c4 100644 --- a/components/modules/wifi_sta.c +++ b/components/modules/wifi_sta.c @@ -169,14 +169,14 @@ static int wifi_sta_setip(lua_State *L) tcpip_adapter_dns_info_t dnsinfo; size_t len; const char *str; - + ip_addr_t ipAddr; ipAddr.type = IPADDR_TYPE_V4; luaL_checkanytable (L, 1); - + //memset(&ipInfo, 0, sizeof(tcpip_adapter_ip_info_t)); - + lua_getfield (L, 1, "ip"); str = luaL_checklstring (L, -1, &len); if(!ipaddr_aton(str, &ipAddr)) @@ -184,7 +184,7 @@ static int wifi_sta_setip(lua_State *L) return luaL_error(L, "Could not parse IP address, aborting"); } ipInfo.ip = ipAddr.u_addr.ip4; - + lua_getfield (L, 1, "netmask"); str = luaL_checklstring (L, -1, &len); if(!ipaddr_aton(str, &ipAddr)) @@ -192,7 +192,7 @@ static int wifi_sta_setip(lua_State *L) return luaL_error(L, "Could not parse Netmask, aborting"); } ipInfo.netmask = ipAddr.u_addr.ip4; - + lua_getfield (L, 1, "gateway"); str = luaL_checklstring (L, -1, &len); if(!ipaddr_aton(str, &ipAddr)) @@ -200,18 +200,18 @@ static int wifi_sta_setip(lua_State *L) return luaL_error(L, "Could not parse Gateway address, aborting"); } ipInfo.gw = ipAddr.u_addr.ip4; - + lua_getfield (L, 1, "dns"); str = luaL_optlstring(L, -1, str, &len); if(!ipaddr_aton(str, &dnsinfo.ip)) { return luaL_error(L, "Could not parse DNS address, aborting"); } - + ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)); tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo); tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &dnsinfo); - + return 0; } @@ -453,19 +453,17 @@ static int wifi_sta_scan (lua_State *L) } -const LUA_REG_TYPE wifi_sta_map[] = { - { LSTRKEY( "setip" ), LFUNCVAL( wifi_sta_setip ) }, - { LSTRKEY( "sethostname" ), LFUNCVAL( wifi_sta_sethostname )}, - { LSTRKEY( "config" ), LFUNCVAL( wifi_sta_config ) }, - { LSTRKEY( "connect" ), LFUNCVAL( wifi_sta_connect ) }, - { LSTRKEY( "disconnect" ), LFUNCVAL( wifi_sta_disconnect ) }, - { LSTRKEY( "getconfig" ), LFUNCVAL( wifi_sta_getconfig ) }, - { LSTRKEY( "getmac" ), LFUNCVAL( wifi_sta_getmac ) }, - { LSTRKEY( "on" ), LFUNCVAL( wifi_sta_on ) }, - { LSTRKEY( "scan" ), LFUNCVAL( wifi_sta_scan ) }, - - { LNILKEY, LNILVAL } -}; +LROT_PUBLIC_BEGIN(wifi_sta) + LROT_FUNCENTRY( setip, wifi_sta_setip ) + LROT_FUNCENTRY( sethostname, wifi_sta_sethostname ) + LROT_FUNCENTRY( config, wifi_sta_config ) + LROT_FUNCENTRY( connect, wifi_sta_connect ) + LROT_FUNCENTRY( disconnect, wifi_sta_disconnect ) + LROT_FUNCENTRY( getconfig, wifi_sta_getconfig ) + LROT_FUNCENTRY( getmac, wifi_sta_getmac ) + LROT_FUNCENTRY( on, wifi_sta_on ) + LROT_FUNCENTRY( scan, wifi_sta_scan ) +LROT_END(wifi_sta, NULL, 0) // Currently no auto-connect, so do that in response to events diff --git a/components/modules/ws2812.c b/components/modules/ws2812.c index 7369a399f2..681878c665 100644 --- a/components/modules/ws2812.c +++ b/components/modules/ws2812.c @@ -497,35 +497,31 @@ static int ws2812_buffer_tostring(lua_State* L) { return 1; } -static const LUA_REG_TYPE ws2812_buffer_map[] = -{ - { LSTRKEY( "dump" ), LFUNCVAL( ws2812_buffer_dump )}, - { LSTRKEY( "fade" ), LFUNCVAL( ws2812_buffer_fade )}, - { LSTRKEY( "fill" ), LFUNCVAL( ws2812_buffer_fill )}, - { LSTRKEY( "get" ), LFUNCVAL( ws2812_buffer_get )}, - { LSTRKEY( "replace" ), LFUNCVAL( ws2812_buffer_replace )}, - { LSTRKEY( "mix" ), LFUNCVAL( ws2812_buffer_mix )}, - { LSTRKEY( "power" ), LFUNCVAL( ws2812_buffer_power )}, - { LSTRKEY( "set" ), LFUNCVAL( ws2812_buffer_set )}, - { LSTRKEY( "shift" ), LFUNCVAL( ws2812_buffer_shift )}, - { LSTRKEY( "size" ), LFUNCVAL( ws2812_buffer_size )}, - { LSTRKEY( "sub" ), LFUNCVAL( ws2812_buffer_sub )}, - { LSTRKEY( "__concat" ),LFUNCVAL( ws2812_buffer_concat )}, - { LSTRKEY( "__index" ), LROVAL( ws2812_buffer_map )}, - { LSTRKEY( "__tostring" ), LFUNCVAL( ws2812_buffer_tostring )}, - { LNILKEY, LNILVAL} -}; - -static const LUA_REG_TYPE ws2812_map[] = -{ - { LSTRKEY( "newBuffer" ), LFUNCVAL( ws2812_new_buffer )}, - { LSTRKEY( "write" ), LFUNCVAL( ws2812_write )}, - { LSTRKEY( "FADE_IN" ), LNUMVAL( FADE_IN ) }, - { LSTRKEY( "FADE_OUT" ), LNUMVAL( FADE_OUT ) }, - { LSTRKEY( "SHIFT_LOGICAL" ), LNUMVAL( SHIFT_LOGICAL ) }, - { LSTRKEY( "SHIFT_CIRCULAR" ), LNUMVAL( SHIFT_CIRCULAR ) }, - { LNILKEY, LNILVAL} -}; +LROT_BEGIN(ws2812_buffer) + LROT_FUNCENTRY( dump, ws2812_buffer_dump ) + LROT_FUNCENTRY( fade, ws2812_buffer_fade ) + LROT_FUNCENTRY( fill, ws2812_buffer_fill ) + LROT_FUNCENTRY( get, ws2812_buffer_get ) + LROT_FUNCENTRY( replace, ws2812_buffer_replace ) + LROT_FUNCENTRY( mix, ws2812_buffer_mix ) + LROT_FUNCENTRY( power, ws2812_buffer_power ) + LROT_FUNCENTRY( set, ws2812_buffer_set ) + LROT_FUNCENTRY( shift, ws2812_buffer_shift ) + LROT_FUNCENTRY( size, ws2812_buffer_size ) + LROT_FUNCENTRY( sub, ws2812_buffer_sub ) + LROT_FUNCENTRY( __concat, ws2812_buffer_concat ) + LROT_TABENTRY ( __index, ws2812_buffer ) + LROT_FUNCENTRY( __tostring, ws2812_buffer_tostring ) +LROT_END(ws2812_buffer, NULL, 0) + +LROT_BEGIN(ws2812) + LROT_FUNCENTRY( newBuffer, ws2812_new_buffer ) + LROT_FUNCENTRY( write, ws2812_write ) + LROT_NUMENTRY ( FADE_IN, FADE_IN ) + LROT_NUMENTRY ( FADE_OUT, FADE_OUT ) + LROT_NUMENTRY ( SHIFT_LOGICAL, SHIFT_LOGICAL ) + LROT_NUMENTRY ( SHIFT_CIRCULAR, SHIFT_CIRCULAR ) +LROT_END(ws2812, NULL, 0) int luaopen_ws2812(lua_State *L) { // TODO: Make sure that the GPIO system is initialized @@ -533,4 +529,4 @@ int luaopen_ws2812(lua_State *L) { return 0; } -NODEMCU_MODULE(WS2812, "ws2812", ws2812_map, luaopen_ws2812); +NODEMCU_MODULE(WS2812, "ws2812", ws2812, luaopen_ws2812); diff --git a/components/platform/Kconfig b/components/platform/Kconfig index 88448cd1c6..8e554193a0 100644 --- a/components/platform/Kconfig +++ b/components/platform/Kconfig @@ -108,6 +108,32 @@ config BUILD_SPIFFS bool default "y" +config LUA_EMBED_LFS + bool "Embed LFS as part of the NodeMCU firmware" + default "n" + help + The LFS (Lua Flash Store) normally has its own partition entry, and can + can be replaced at will. Optionally, the LFS can instead be permanently + embedded into the NodeMCU firmware image itself. This can be useful for + scenarios where over-the-air firmware upgrades are needed to also + bundle Lua code. The major downside is that once embedded, the LFS can + no longer be changed, as doing so would break the firmware checksums + and signatures and leave the system unable to boot. + + The default option is to not embed the LFS, in which case LFS is + looked for in a partition of type 0xC2 and subtype 0x01. + + To embed LFS data into firmware, use: + ./tools/embed_lfs.sh /path/to/file1.lua /path/to/file2.lua ... + +config LUA_EMBEDDED_FLASH_STORE + hex "Embedded LUA Flash Store size" + default 0x0 + depends on LUA_EMBED_LFS + help + Embedded LUA Flash Store size. Set to zero to use an LFS partition instead + of embedding the LFS within the NodeMCU firmware itself. + config BUILD_FATFS bool "Support for FAT filesystems" default "n" diff --git a/components/platform/include/cpu_esp32.h b/components/platform/include/cpu_esp32.h index 8df54a07f7..2f5e42eb41 100644 --- a/components/platform/include/cpu_esp32.h +++ b/components/platform/include/cpu_esp32.h @@ -2,6 +2,7 @@ #define _CPU_ESP32_H_ #include "sdkconfig.h" +#include "esp_spi_flash.h" #define NUM_UART 3 diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index c540c8dbab..f75456b2f9 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -246,6 +246,7 @@ int platform_flash_erase_sector( uint32_t sector_id ); #define PLATFORM_PARTITION_SUBTYPE_DATA_WIFI 0x02 #define PLATFORM_PARTITION_SUBTYPE_NODEMCU_SPIFFS 0x00 +#define PLATFORM_PARTITION_SUBTYPE_NODEMCU_LFS 0x01 typedef struct { uint8_t label[16]; diff --git a/components/platform/partitions-2MB.csv b/components/platform/partitions-2MB.csv index 62b9b45f13..b6fdae2521 100644 --- a/components/platform/partitions-2MB.csv +++ b/components/platform/partitions-2MB.csv @@ -1,7 +1,8 @@ # Espressif ESP32 Partition Table for 2MB flash # Name, Type, SubType, Offset, Size -nvs, data, nvs, 0x9000, 0x6000 -phy_init, data, phy, 0xf000, 0x1000 -factory, app, factory, 0x10000, 0x180000 -# 0xC2 => NodeMCU, 0x0 => Spiffs -nodemcuspiffs, 0xC2, 0x0, , 0x70000 +nvs, data, nvs, 0x9000, 0x6000 +phy_init, data, phy, 0xf000, 0x1000 +factory, app, factory, 0x10000, 0x180000 +# Type 0xC2 => NodeMCU. SubTypes: 0x00 = SPIFFS, 0x01 = LFS +lfs, 0xC2, 0x01, , 0x10000 +nodemcuspiffs, 0xC2, 0x00, , 0x60000 diff --git a/components/platform/partitions.csv b/components/platform/partitions.csv index cead9a3b23..5f60b356d1 100644 --- a/components/platform/partitions.csv +++ b/components/platform/partitions.csv @@ -1,5 +1,7 @@ -# Espressif ESP32 Partition Table for 2MB flash # Name, Type, SubType, Offset, Size -nvs, data, nvs, 0x9000, 0x6000 -phy_init, data, phy, 0xf000, 0x1000 -factory, app, factory, 0x10000, 0x180000 +nvs, data, nvs, 0x9000, 0x6000 +phy_init, data, phy, 0xf000, 0x1000 +factory, app, factory, 0x10000, 0x180000 +# Type 0xC2 => NodeMCU. SubTypes: 0x00 = SPIFFS, 0x01 = LFS +lfs, 0xC2, 0x01, , 0x10000 +nodemcuspiffs, 0xC2, 0x00, , 0x70000 diff --git a/components/uzlib/Makefile.projbuild b/components/uzlib/Makefile.projbuild new file mode 100644 index 0000000000..f2c522d8d2 --- /dev/null +++ b/components/uzlib/Makefile.projbuild @@ -0,0 +1,2 @@ +-include $(PROJECT_PATH)/build/include/config/auto.conf + diff --git a/components/uzlib/README.md b/components/uzlib/README.md new file mode 100644 index 0000000000..10da2112d6 --- /dev/null +++ b/components/uzlib/README.md @@ -0,0 +1,35 @@ +uzlib - Deflate/Zlib-compatible LZ77 compression library +====================================================== + +This is a heavily modified and cut down version of Paul Sokolovsky's +uzlib library. This library has exported routines which + +- Can compress data to a Deflate-compatible bitstream, albeit with lower +compression ratio than the Zlib Deflate algorithm as a static Deflate Huffman +tree encoding is used for bitstream). Note that since this compression is +in RAM and requires ~4 bytes per byte of the input record, should only be +called for compressing small records on the ESP8266. + +- Can decompress any valid Deflate, Zlib, and Gzip (further called just +"Deflate") bitstream less than 16Kb, and any arbitrary length stream +compressed by the uzlib compressor. + +uzlib aims for minimal code size and runtime memory requirements, and thus +is suitable for embedded systems and IoT devices such as the ESP8266. + +uzlib is based on: + +- tinf library by Joergen Ibsen (Deflate decompression) +- Deflate Static Huffman tree routines by Simon Tatham +- LZ77 compressor by Paul Sokolovsky provided my initial inspiration, but +I ended up rewriting this following RFC 1951 to get improved compression +performance. + +The above 16Kb limitation arises from the RFC 1951 use of a 32Kb dictionary, +which is impractical on a chipset with only ~40 Kb RAM avialable to +applications. + +The relevant copyright statements are provided in the source files which +use this code. + +uzlib library is licensed under Zlib license. diff --git a/components/uzlib/component.mk b/components/uzlib/component.mk new file mode 100644 index 0000000000..f50bec1fa8 --- /dev/null +++ b/components/uzlib/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_INCLUDEDIRS:=. diff --git a/components/uzlib/crc32.c b/components/uzlib/crc32.c new file mode 100644 index 0000000000..04db3a487b --- /dev/null +++ b/components/uzlib/crc32.c @@ -0,0 +1,62 @@ +/* + * CRC32 checksum + * + * Copyright (c) 1998-2003 by Joergen Ibsen / Jibz + * All Rights Reserved + * + * http://www.ibsensoftware.com/ + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be + * held liable for any damages arising from the use of + * this software. + * + * Permission is granted to anyone to use this software + * for any purpose, including commercial applications, + * and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The origin of this software must not be + * misrepresented; you must not claim that you + * wrote the original software. If you use this + * software in a product, an acknowledgment in + * the product documentation would be appreciated + * but is not required. + * + * 2. Altered source versions must be plainly marked + * as such, and must not be misrepresented as + * being the original software. + * + * 3. This notice may not be removed or altered from + * any source distribution. + */ + +/* + * CRC32 algorithm taken from the zlib source, which is + * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + */ +#include + +static const unsigned int tinf_crc32tab[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, + 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, + 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, + 0xbdbdf21c +}; + +/* crc is previous value for incremental computation, 0xffffffff initially */ +uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc) +{ + const unsigned char *buf = (const unsigned char *)data; + unsigned int i; + + for (i = 0; i < length; ++i) + { + crc ^= buf[i]; + crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); + crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); + } + + // return value suitable for passing in next time, for final value invert it + return crc/* ^ 0xffffffff*/; +} diff --git a/components/uzlib/uzlib.h b/components/uzlib/uzlib.h new file mode 100644 index 0000000000..d046db1ec3 --- /dev/null +++ b/components/uzlib/uzlib.h @@ -0,0 +1,76 @@ +/* + * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) + * + * Copyright (c) 2003 by Joergen Ibsen / Jibz + * All Rights Reserved + * http://www.ibsensoftware.com/ + * + * Copyright (c) 2014-2016 by Paul Sokolovsky + */ + +#ifndef UZLIB_INFLATE_H +#define UZLIB_INFLATE_H + +#include + +#include +#include +#define uz_malloc malloc +#define uz_free free + +#if defined(__XTENSA__) + +#define UZLIB_THROW(v) longjmp(unwindAddr, (v)) +#define UZLIB_SETJMP setjmp + +#else /* Host */ + +extern int dbg_break(void); +#if defined(_MSC_VER) || defined(__MINGW32__) //msvc requires old name for longjmp +#define UZLIB_THROW(v) {dbg_break();longjmp(unwindAddr, (v));} +#define UZLIB_SETJMP(n) setjmp(n) +#else +#define UZLIB_THROW(v) {dbg_break();_longjmp(unwindAddr, (v));} +#define UZLIB_SETJMP(n) _setjmp(n) +#endif + +#endif /* defined(__XTENSA__) */ + +extern jmp_buf unwindAddr; + +/* ok status, more data produced */ +#define UZLIB_OK 0 +/* end of compressed stream reached */ +#define UZLIB_DONE 1 +#define UZLIB_DATA_ERROR (-3) +#define UZLIB_CHKSUM_ERROR (-4) +#define UZLIB_DICT_ERROR (-5) +#define UZLIB_MEMORY_ERROR (-6) + +/* checksum types */ +#define UZLIB_CHKSUM_NONE 0 +#define UZLIB_CHKSUM_ADLER 1 +#define UZLIB_CHKSUM_CRC 2 + +/* Gzip header codes */ +#define UZLIB_FTEXT 1 +#define UZLIB_FHCRC 2 +#define UZLIB_FEXTRA 4 +#define UZLIB_FNAME 8 +#define UZLIB_FCOMMENT 16 + +/* Compression API */ + +typedef struct uzlib_data UZLIB_DATA; + +int uzlib_inflate (uint8_t (*)(void), void (*)(uint8_t), + uint8_t (*)(uint32_t), uint32_t len, uint32_t *crc, void **state); + +int uzlib_compress (uint8_t **dest, uint32_t *destLen, + const uint8_t *src, uint32_t srcLen); + +/* Checksum API */ +/* crc is previous value for incremental computation, 0xffffffff initially */ +uint32_t uzlib_crc32(const void *data, uint32_t length, uint32_t crc); + +#endif /* UZLIB_INFLATE_H */ diff --git a/components/uzlib/uzlib_deflate.c b/components/uzlib/uzlib_deflate.c new file mode 100644 index 0000000000..e907d3e518 --- /dev/null +++ b/components/uzlib/uzlib_deflate.c @@ -0,0 +1,586 @@ +/* + * This implementation draws heavily on the work down by Paul Sokolovsky + * (https://github.com/pfalcon) and his uzlib library which in turn uses + * work done by Joergen Ibsen, Simon Tatham and others. All of this work + * is under an unrestricted right to use subject to copyright attribution. + * Two copyright wordings (variants A and B) are following. + * + * (c) statement A initTables, copy, literal + * + * The remainder of this code has been written by me, Terry Ellison 2018, + * under the standard NodeMCU MIT licence, but is available to the other + * contributors to this source under any permissive licence. + * + * My primary algorthmic reference is RFC 1951: "DEFLATE Compressed Data + * Format Specification version 1.3", dated May 1996. + * + * Also because the code in this module is drawn from different sources, + * the different coding practices can be confusing, I have standardised + * the source by: + * + * - Adopting the 2 indent rule as in the rest of the firmware + * + * - I have replaced the various mix of char, unsigned char and uchar + * by the single uchar type; ditto for ushort and uint. + * + * - All internal (non-exported) functions and data are static + * + * - Only exported functions and data have the module prefix. All + * internal (static) variables and fields are lowerCamalCase. + * + *********************************************************************** + * Copyright statement A for Zlib (RFC1950 / RFC1951) compression for PuTTY. + +PuTTY is copyright 1997-2014 Simon Tatham. + +Portions copyright Robert de Bath, Joris van Rantwijk, Delian +Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, +Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus +Kuhn, Colin Watson, and CORE SDI S.A. + +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 COP--YRIGHT 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. + +************************************************************************ +Copyright statement B for genlz77 functions: + * + * genlz77 - Generic LZ77 compressor + * + * Copyright (c) 2014 by Paul Sokolovsky + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be + * held liable for any damages arising from the use of + * this software. + * + * Permission is granted to anyone to use this software + * for any purpose, including commercial applications, + * and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The origin of this software must not be + * misrepresented; you must not claim that you + * wrote the original software. If you use this + * software in a product, an acknowledgment in + * the product documentation would be appreciated + * but is not required. + * + * 2. Altered source versions must be plainly marked + * as such, and must not be misrepresented as + * being the original software. + * + * 3. This notice may not be removed or altered from + * any source distribution. + */ +#include +#include +#include +#include +#include "uzlib.h" + +jmp_buf unwindAddr; + +/* Minimum and maximum length of matches to look for, inclusive */ +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* Max offset of the match to look for, inclusive */ +#define MAX_OFFSET 16384 // 32768 // +#define OFFSET16_MASK 0x7FFF +#define NULL_OFFSET 0xFFFF +#if MIN_MATCH < 3 +#error "Encoding requires a minium match of 3 bytes" +#endif + +#define SIZE(a) (sizeof(a)/sizeof(*a)) /* no of elements in array */ +#ifdef __XTENSA__ +#define RAM_COPY_BYTE_ARRAY(c,s,sl) uchar *c = alloca(sl); memcpy(c,s,(sl)) +#else +#define RAM_COPY_BYTE_ARRAY(c,s,sl) uchar *c = s; +#endif +#define FREE(v) if (v) uz_free(v) + +typedef uint8_t uchar; +typedef uint16_t ushort; +typedef uint32_t uint; + +#ifdef DEBUG_COUNTS +#define DBG_PRINT(...) printf(__VA_ARGS__) +#define DBG_COUNT(n) (debugCounts[n]++) +#define DBG_ADD_COUNT(n,m) (debugCounts[n]+=m) +int debugCounts[20]; +#else +#define DBG_PRINT(...) +#define DBG_COUNT(n) +#define DBG_ADD_COUNT(n,m) +#endif + +int dbg_break(void) {return 1;} + +typedef struct { + ushort code, extraBits, min, max; +} codeRecord; + +struct dynTables { + ushort *hashChain; + ushort *hashTable; + ushort hashMask; + ushort hashSlots; + ushort hashBits; + ushort dictLen; + const uchar bitrevNibble[16]; + const codeRecord lenCodes[285-257+1]; + const codeRecord distCodes[29-0+1]; +} *dynamicTables; + +struct outputBuf { + uchar *buffer; + uint len, size; + uint inLen, inNdx; + uint bits, nBits; + uint compDisabled; +} *oBuf; + + +/* + * Set up the constant tables used to drive the compression + * + * Constants are stored in flash memory on the ESP8266 NodeMCU firmware + * builds, but only word aligned data access are supported in hardare so + * short and byte accesses are handled by a S/W exception handler and are + * SLOW. RAM is also at premium, so these short routines are driven by + * byte vectors copied into RAM and then used to generate temporary RAM + * tables, which are the same as the above statically declared versions. + * + * This might seem a bit convolved but this runs faster and takes up less + * memory than the original version. This code also works fine on the + * x86-64s so we just use one code variant. + * + * Note that fixed Huffman trees as defined in RFC 1951 Sec 3.2.5 are + * always used. Whilst dynamic trees can give better compression for + * larger blocks, this comes at a performance hit of having to compute + * these trees. Fixed trees give better compression performance on short + * blocks and significantly reduce compression times. + * + * The following defines are used to initialise these tables. + */ +#define lenCodes_GEN \ + "\x03\x01\x01\x01\x01\x01\x01\x01\xff\x02\x02\x02\x02\xff\x04\x04\x04\x04" \ + "\xff\x08\x08\x08\x08\xff\x10\x10\x10\x10\xff\x20\x20\x20\x1f\xff\x01\x00" +#define lenCodes_LEN 29 +#define distCodes_GEN \ + "\x01\x01\x01\x01\xff\x02\x02\xff\x04\x04\xff\x08\x08\xff\x10\x10\xff" \ + "\x20\x20\xff\x40\x40\xff\x86\x86\xff\x87\x87\xff\x88\x88\xff" \ + "\x89\x89\xff\x8a\x8a\xff\x8b\x8b\xff\x8c\x8c" +#define distCodes_LEN 30 +#define BITREV16 "\x0\x8\x4\xc\x2\xa\x6\xe\x1\x9\x5\xd\x3\xb\x7\xf" + +static void genCodeRecs (const codeRecord *rec, ushort len, + char *init, int initLen, + ushort start, ushort m0) { + DBG_COUNT(0); + int i, b=0, m=0, last=m0; + RAM_COPY_BYTE_ARRAY(c, (uchar *)init,initLen); + codeRecord *p = (codeRecord *) rec; + + for (i = start; i < start+len; i++, c++) { + if (*c == 0xFF) + b++, c++; + m += (*c & 0x80) ? 2 << (*c & 0x1F) : *c; + *p++ = (codeRecord) {i, b, last + 1, (last = m)}; + } +} + +static void initTables (uint chainLen, uint hashSlots) { + DBG_COUNT(1); + uint dynamicSize = sizeof(struct dynTables) + + sizeof(struct outputBuf) + + chainLen * sizeof(ushort) + + hashSlots * sizeof(ushort); + struct dynTables *dt = uz_malloc(dynamicSize); + memset(dt, 0, dynamicSize); + dynamicTables = dt; + + /* Do a single malloc for dymanic tables and assign addresses */ + if(!dt ) + UZLIB_THROW(UZLIB_MEMORY_ERROR); + + memcpy((uchar*)dt->bitrevNibble, BITREV16, 16); + oBuf = (struct outputBuf *)(dt+1); + dt->hashTable = (ushort *)(oBuf+1); + dt->hashChain = dt->hashTable + hashSlots; + dt->hashSlots = hashSlots; + dt->hashMask = hashSlots - 1; + + /* As these are offset rather than pointer, 0 is a valid offset */ + /* (unlike NULL), so 0xFFFF is used to denote an unset value */ + memset(dt->hashTable, -1, sizeof(ushort)*hashSlots); + memset(dt->hashChain, -1, sizeof(ushort)*chainLen); + + /* Generate the code recors for the lenth and distance code tables */ + genCodeRecs(dt->lenCodes, SIZE(dt->lenCodes), + lenCodes_GEN, sizeof(lenCodes_GEN), + 257,2); + ((codeRecord *)(dynamicTables->lenCodes+285-257))->extraBits=0; /* odd ball entry */ + genCodeRecs(dt->distCodes, SIZE(dt->distCodes), + distCodes_GEN, sizeof(distCodes_GEN), + 0,0); +} + + +/* + * Routines to output bit streams and byte streams to the output buffer + */ +void resizeBuffer(void) { + uchar *nb; + DBG_COUNT(2); + /* The outbuf is given an initial size estimate but if we are running */ + /* out of space then extropolate size using current compression */ + double newEstimate = (((double) oBuf->len)*oBuf->inLen) / oBuf->inNdx; + oBuf->size = 128 + (uint) newEstimate; + if (!(nb = realloc(oBuf->buffer, oBuf->size))) + UZLIB_THROW(UZLIB_MEMORY_ERROR); + oBuf->buffer = nb; +} + +void outBits(ushort bits, int nBits) { + DBG_COUNT(3); + oBuf->bits |= bits << oBuf->nBits; + oBuf->nBits += nBits; + + if (oBuf->len >= oBuf->size - sizeof(bits)) + resizeBuffer(); + + while (oBuf->nBits >= 8) { + DBG_PRINT("%02x-", oBuf->bits & 0xFF); + oBuf->buffer[oBuf->len++] = oBuf->bits & 0xFF; + oBuf->bits >>= 8; + oBuf->nBits -= 8; + } +} + +void outBitsRev(uchar bits, int nBits) { + DBG_COUNT(4); + /* Note that bit reversal only operates on an 8-bit bits field */ + uchar bitsRev = (dynamicTables->bitrevNibble[bits & 0x0f]<<4) | + dynamicTables->bitrevNibble[bits>>4]; + outBits(bitsRev, nBits); +} + +void outBytes(void *bytes, int nBytes) { + DBG_COUNT(5); + int i; + if (oBuf->len >= oBuf->size - nBytes) + resizeBuffer(); + + /* Note that byte output dumps any bits data so the caller must */ + /* flush this first, if necessary */ + oBuf->nBits = oBuf->bits = 0; + for (i = 0; i < nBytes; i++) { + DBG_PRINT("%02x-", *((uchar*)bytes+i)); + oBuf->buffer[oBuf->len++] = *((uchar*)bytes+i); + } +} + +/* + * Output an literal byte as an 8 or 9 bit code + */ +void literal (uchar c) { + DBG_COUNT(6); + DBG_PRINT("sym: %02x %c\n", c, c); + if (oBuf->compDisabled) { + /* We're in an uncompressed block, so just output the byte. */ + outBits(c, 8); + } else if (c <= 143) { + /* 0 through 143 are 8 bits long starting at 00110000. */ + outBitsRev(0x30 + c, 8); + } else { + /* 144 through 255 are 9 bits long starting at 110010000. */ + outBits(1, 1); + outBitsRev(0x90 - 144 + c, 8); + } +} + +/* + * Output a dictionary (distance, length) pars as bitstream codes + */ +void copy (int distance, int len) { + DBG_COUNT(7); + const codeRecord *lenCodes = dynamicTables->lenCodes, *l; + const codeRecord *distCodes = dynamicTables->distCodes, *d; + int i, j, k; + + assert(!oBuf->compDisabled); + + while (len > 0) { + /* + * We can transmit matches of lengths 3 through 258 + * inclusive. So if len exceeds 258, we must transmit in + * several steps, with 258 or less in each step. + * + * Specifically: if len >= 261, we can transmit 258 and be + * sure of having at least 3 left for the next step. And if + * len <= 258, we can just transmit len. But if len == 259 + * or 260, we must transmit len-3. + */ + int thislen = (len > 260 ? 258 : len <= 258 ? len : len - 3); + len -= thislen; + /* + * Binary-search to find which length code we're + * transmitting. + */ + i = -1; + j = lenCodes_LEN; + while (1) { + assert(j - i >= 2); + k = (j + i) / 2; + if (thislen < lenCodes[k].min) + j = k; + else if (thislen > lenCodes[k].max) + i = k; + else { + l = &lenCodes[k]; + break; /* found it! */ + } + } + /* + * Transmit the length code. 256-279 are seven bits + * starting at 0000000; 280-287 are eight bits starting at + * 11000000. + */ + if (l->code <= 279) { + outBitsRev((l->code - 256) * 2, 7); + } else { + outBitsRev(0xc0 - 280 + l->code, 8); + } + /* + * Transmit the extra bits. + */ + if (l->extraBits) + outBits(thislen - l->min, l->extraBits); + /* + * Binary-search to find which distance code we're + * transmitting. + */ + i = -1; + j = distCodes_LEN; + while (1) { + assert(j - i >= 2); + k = (j + i) / 2; + if (distance < distCodes[k].min) + j = k; + else if (distance > distCodes[k].max) + i = k; + else { + d = &distCodes[k]; + break; /* found it! */ + } + } + + /* + * Transmit the distance code. Five bits starting at 00000. + */ + outBitsRev(d->code * 8, 5); + + /* + * Transmit the extra bits. + */ + if (d->extraBits) + outBits(distance - d->min, d->extraBits); + } +} + +/* + * Block compression uses a hashTable to index into a set of search + * chainList, where each chain links together the triples of chars within + * the dictionary (the last MAX_OFFSET bytes of the input buffer) with + * the same hash index. So for compressing a file of 200Kb, say, with a + * 16K dictionary (the largest that we can inflate within the memory + * constraints of the ESP8266), the chainList is 16K slots long, and the + * hashTable is 4K slots long, so a typical chain will have 4 links. + * + * These two tables use 16-bit ushort offsets rather than pointers to + * save memory (essential on the ESP8266). + * + * As per RFC 1951 sec 4, we also implement a "lazy match" procedure + */ + +void uzlibCompressBlock(const uchar *src, uint srcLen) { + int i, j, k, l; + uint hashMask = dynamicTables->hashMask; + ushort *hashChain = dynamicTables->hashChain; + ushort *hashTable = dynamicTables->hashTable; + uint hashShift = 24 - dynamicTables->hashBits; + uint lastOffset = 0, lastLen = 0; + oBuf->inLen = srcLen; /* used for output buffer resizing */ + DBG_COUNT(9); + + for (i = 0; i <= ((int)srcLen) - MIN_MATCH; i++) { + /* + * Calculate a hash on the next three chars using the liblzf hash + * function, then use this via the hashTable to index into the chain + * of triples within the dictionary window which have the same hash. + * + * Note that using 16-bit offsets requires a little manipulation to + * handle wrap-around and recover the correct offset, but all other + * working uses uint offsets simply because the compiler generates + * faster (and smaller in the case of the ESP8266) code. + * + * Also note that this code also works for any tail 2 literals; the + * hash will access beyond the array and will be incorrect, but + * these can't match and will flush the last cache. + */ + const uchar *this = src + i, *comp; + uint base = i & ~OFFSET16_MASK; + uint iOffset = i - base; + uint maxLen = srcLen - i; + uint matchLen = MIN_MATCH - 1; + uint matchOffset = 0; + uint v = (this[0] << 16) | (this[1] << 8) | this[2]; + uint hash = ((v >> hashShift) - v) & hashMask; + uint nextOffset = hashTable[hash]; + oBuf->inNdx = i; /* used for output buffer resizing */ + DBG_COUNT(10); + + if (maxLen>MAX_MATCH) + maxLen = MAX_MATCH; + + hashTable[hash] = iOffset; + hashChain[iOffset & (MAX_OFFSET-1)] = nextOffset; + + for (l = 0; nextOffset != NULL_OFFSET && l<60; l++) { + DBG_COUNT(11); + + /* handle the case where base has bumped */ + j = base + nextOffset - ((nextOffset < iOffset) ? 0 : (OFFSET16_MASK + 1)); + + if (i - j > MAX_OFFSET) + break; + + for (k = 0, comp = src + j; this[k] == comp[k] && k < maxLen; k++) + {} + DBG_ADD_COUNT(12, k); + + if (k > matchLen) { + matchOffset = i - j; + matchLen = k; + } + nextOffset = hashChain[nextOffset & (MAX_OFFSET-1)]; + } + + if (lastOffset) { + if (matchOffset == 0 || lastLen >= matchLen ) { + /* ignore this match (or not) and process last */ + DBG_COUNT(14); + copy(lastOffset, lastLen); + DBG_PRINT("dic: %6x %6x %6x\n", i-1, lastLen, lastOffset); + i += lastLen - 1 - 1; + lastOffset = lastLen = 0; + } else { + /* ignore last match and emit a symbol instead; cache this one */ + DBG_COUNT(15); + literal(this[-1]); + lastOffset = matchOffset; + lastLen = matchLen; + } + } else { /* no last match */ + if (matchOffset) { + DBG_COUNT(16); + /* cache this one */ + lastOffset = matchOffset; + lastLen = matchLen; + } else { + DBG_COUNT(17); + /* emit a symbol; last already clear */ + literal(this[0]); + } + } + } + + if (lastOffset) { /* flush cached match if any */ + copy(lastOffset, lastLen); + DBG_PRINT("dic: %6x %6x %6x\n", i, lastLen, lastOffset); + i += lastLen - 1; + } + while (i < srcLen) + literal(src[i++]); /* flush the last few bytes if needed */ +} + +/* + * This compress wrapper treats the input stream as a single block for + * compression using the default Static huffman block encoding + */ +int uzlib_compress (uchar **dest, uint *destLen, const uchar *src, uint srcLen) { + uint crc = ~uzlib_crc32(src, srcLen, ~0); + uint chainLen = srcLen < MAX_OFFSET ? srcLen : MAX_OFFSET; + uint hashSlots, i, j; + int status; + + uint FLG_MTIME[] = {0x00088b1f, 0}; + ushort XFL_OS = 0x0304; + + /* The hash table has 4K slots for a 16K chain and scaling down */ + /* accordingly, for an average chain length of 4 links or thereabouts */ + for (i = 256, j = 8 - 2; i < chainLen; i <<= 1) + j++; + hashSlots = i >> 2; + + if ((status = UZLIB_SETJMP(unwindAddr)) == 0) { + initTables(chainLen, hashSlots); + oBuf->size = srcLen/5; /* initial guess of a 5x compression ratio */ + oBuf->buffer = uz_malloc(oBuf->size); + dynamicTables->hashSlots = hashSlots; + dynamicTables->hashBits = j; + if(!oBuf->buffer ) { + status = UZLIB_MEMORY_ERROR; + } else { + /* Output gzip and block headers */ + outBytes(FLG_MTIME, sizeof(FLG_MTIME)); + outBytes(&XFL_OS, sizeof(XFL_OS)); + outBits(1, 1); /* Final block */ + outBits(1, 2); /* Static huffman block */ + + uzlibCompressBlock(src, srcLen); /* Do the compress */ + + /* Output block finish */ + outBits(0, 7); /* close block */ + outBits(0, 7); /* Make sure all bits are flushed */ + outBytes(&crc, sizeof(crc)); + outBytes(&srcLen, sizeof(srcLen)); + status = UZLIB_OK; + } + } else { + status = UZLIB_OK; + } + + for (i=0; i<20;i++) DBG_PRINT("count %u = %u\n",i,debugCounts[i]); + + if (status == UZLIB_OK) { + uchar *trimBuf = realloc(oBuf->buffer, oBuf->len); + *dest = trimBuf ? trimBuf : oBuf->buffer; + *destLen = oBuf->len; + } else { + *dest = NULL; + *destLen = 0; + FREE(oBuf->buffer); + } + + FREE(dynamicTables); + + return status; +} diff --git a/components/uzlib/uzlib_inflate.c b/components/uzlib/uzlib_inflate.c new file mode 100644 index 0000000000..a3eec362c0 --- /dev/null +++ b/components/uzlib/uzlib_inflate.c @@ -0,0 +1,599 @@ +/* + * tinfgzip.c - tiny gzip decompressor + * tinflate.c - tiny inflate + * + * The original source headers as below for licence compliance and in + * full acknowledgement of the originitor contributions. Modified by + * Terry Ellison 2018 to provide lightweight stream inflate for NodeMCU + * Lua. Modifications are under the standard NodeMCU MIT licence. + * + * Copyright (c) 2003 by Joergen Ibsen / Jibz + * All Rights Reserved + * http://www.ibsensoftware.com/ + * + * Copyright (c) 2014-2016 by Paul Sokolovsky + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be + * held liable for any damages arising from the use of + * this software. + * + * Permission is granted to anyone to use this software + * for any purpose, including commercial applications, + * and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The origin of this software must not be + * misrepresented; you must not claim that you + * wrote the original software. If you use this + * software in a product, an acknowledgment in + * the product documentation would be appreciated + * but is not required. + * + * 2. Altered source versions must be plainly marked + * as such, and must not be misrepresented as + * being the original software. + * + * 3. This notice may not be removed or altered from + * any source distribution. + */ + +#include +#include + +#include "uzlib.h" + +#ifdef DEBUG_COUNTS +#define DBG_PRINT(...) printf(__VA_ARGS__) +#define DBG_COUNT(n) (debugCounts[n]++) +#define DBG_ADD_COUNT(n,m) (debugCounts[n]+=m) +int debugCounts[20]; +#else +#define NDEBUG +#define DBG_PRINT(...) +#define DBG_COUNT(n) +#define DBG_ADD_COUNT(n,m) +#endif + + +#define SIZE(arr) (sizeof(arr) / sizeof(*(arr))) + +jmp_buf unwindAddr; +int dbg_break(void) {return 1;} + +typedef uint8_t uchar; +typedef uint16_t ushort; +typedef uint32_t uint; + +/* data structures */ + +typedef struct { + ushort table[16]; /* table of code length counts */ + ushort trans[288]; /* code -> symbol translation table */ +} UZLIB_TREE; + +struct uzlib_data { + /* + * extra bits and base tables for length and distance codes + */ + uchar lengthBits[30]; + ushort lengthBase[30]; + uchar distBits[30]; + ushort distBase[30]; + /* + * special ordering of code length codes + */ + uchar clcidx[19]; + /* + * dynamic length/symbol and distance trees + */ + UZLIB_TREE ltree; + UZLIB_TREE dtree; + /* + * methods encapsulate handling of the input and output streams + */ + uchar (*get_byte)(void); + void (*put_byte)(uchar b); + uchar (*recall_byte)(uint offset); + /* + * Other state values + */ + uint destSize; + uint tag; + uint bitcount; + uint lzOffs; + int bType; + int bFinal; + uint curLen; + uint checksum; +}; + +/* + * Note on changes to layout, naming, etc. This module combines extracts + * from 3 code files from two sources (Sokolovsky, Ibsen et al) with perhaps + * 30% from me Terry Ellison. These sources had inconsistent layout and + * naming conventions, plus extra condtional handling of platforms that + * cannot support NodeMCU. (This is intended to be run compiled and executed + * on GCC POSIX and XENTA newlib environments.) So I have (1) reformatted + * this file in line with NodeMCU rules; (2) demoted all private data and + * functions to static and removed the redundant name prefixes; (3) reordered + * functions into a more logic order; (4) added some ESP architecture + * optimisations, for example these IoT devices are very RAM limited, so + * statically allocating large RAM blocks is against programming guidelines. + */ + +static void skip_bytes(UZLIB_DATA *d, int num) { + if (num) /* Skip a fixed number of bytes */ + while (num--) (void) d->get_byte(); + else /* Skip to next nullchar */ + while (d->get_byte()) {} +} + +static uint16_t get_uint16(UZLIB_DATA *d) { + uint16_t v = d->get_byte(); + return v | (d->get_byte() << 8); +} + +static uint get_le_uint32 (UZLIB_DATA *d) { + uint v = get_uint16(d); + return v | ((uint) get_uint16(d) << 16); +} + +/* get one bit from source stream */ +static int getbit (UZLIB_DATA *d) { + uint bit; + + /* check if tag is empty */ + if (!d->bitcount--) { + /* load next tag */ + d->tag = d->get_byte(); + d->bitcount = 7; + } + + /* shift bit out of tag */ + bit = d->tag & 0x01; + d->tag >>= 1; + + return bit; +} + +/* read a num bit value from a stream and add base */ +static uint read_bits (UZLIB_DATA *d, int num, int base) { + /* This is an optimised version which doesn't call getbit num times */ + if (!num) + return base; + + uint i, n = (((uint)-1)<bitcount; i < num; i +=8) + d->tag |= ((uint)d->get_byte()) << i; + + n = d->tag & ~n; + d->tag >>= num; + d->bitcount = i - num; + return base + n; +} + +/* --------------------------------------------------- * + * -- uninitialized global data (static structures) -- * + * --------------------------------------------------- */ + +/* + * Constants are stored in flash memory on the ESP8266 NodeMCU firmware + * builds, but only word aligned data access are supported in hardare so + * short and byte accesses are handled by a S/W exception handler and + * are SLOW. RAM is also at premium, especially static initialised vars, + * so we malloc a single block on first call to hold all tables and call + * the dynamic generator to generate malloced RAM tables that have the + * same content as the above statically declared versions. + * + * This might seem a bit convolved but this runs faster and takes up + * less memory than the static version on the ESP8266. + */ + +#define CLCIDX_INIT \ +"\x10\x11\x12\x00\x08\x07\x09\x06\x0a\x05\x0b\x04\x0c\x03\x0d\x02\x0e\x01\x0f" + +/* ----------------------- * + * -- utility functions -- * + * ----------------------- */ + +/* build extra bits and base tables */ +static void build_bits_base (uchar *bits, ushort *base, + int delta, int first) { + int i, sum; + + /* build bits table */ + for (i = 0; i < delta; ++i) bits[i] = 0; + for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta; + + /* build base table */ + for (sum = first, i = 0; i < 30; ++i) { + base[i] = sum; + sum += 1 << bits[i]; + } +} + +/* build the fixed huffman trees */ +static void build_fixed_trees (UZLIB_TREE *lt, UZLIB_TREE *dt) { + int i; + + /* build fixed length tree */ + for (i = 0; i < 7; ++i) lt->table[i] = 0; + + lt->table[7] = 24; + lt->table[8] = 152; + lt->table[9] = 112; + + for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i; + for (i = 0; i < 144; ++i) lt->trans[24 + i] = i; + for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i; + for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i; + + /* build fixed distance tree */ + for (i = 0; i < 5; ++i) dt->table[i] = 0; + dt->table[5] = 32; + + for (i = 0; i < 32; ++i) dt->trans[i] = i; +} + +/* given an array of code lengths, build a tree */ +static void build_tree (UZLIB_TREE *t, const uchar *lengths, uint num) { + ushort offs[16]; + uint i, sum; + + /* clear code length count table */ + for (i = 0; i < 16; ++i) + t->table[i] = 0; + + /* scan symbol lengths, and sum code length counts */ + for (i = 0; i < num; ++i) + t->table[lengths[i]]++; + t->table[0] = 0; + + /* compute offset table for distribution sort */ + for (sum = 0, i = 0; i < 16; ++i) { + offs[i] = sum; + sum += t->table[i]; + } + + /* create code->symbol translation table (symbols sorted by code) */ + for (i = 0; i < num; ++i) { + if (lengths[i]) + t->trans[offs[lengths[i]]++] = i; + } +} + +/* ---------------------- * + * -- decode functions -- * + * ---------------------- */ + +/* given a data stream and a tree, decode a symbol */ +static int decode_symbol (UZLIB_DATA *d, UZLIB_TREE *t) { + int sum = 0, cur = 0, len = 0; + + /* get more bits while code value is above sum */ + do { + cur = 2*cur + getbit(d); + + if (++len == SIZE(t->table)) + return UZLIB_DATA_ERROR; + + sum += t->table[len]; + cur -= t->table[len]; + + } while (cur >= 0); + + sum += cur; + if (sum < 0 || sum >= SIZE(t->trans)) + return UZLIB_DATA_ERROR; + + return t->trans[sum]; +} + +/* given a data stream, decode dynamic trees from it */ +static int decode_trees (UZLIB_DATA *d, UZLIB_TREE *lt, UZLIB_TREE *dt) { + uchar lengths[288+32]; + uint hlit, hdist, hclen, hlimit; + uint i, num, length; + + /* get 5 bits HLIT (257-286) */ + hlit = read_bits(d, 5, 257); + + /* get 5 bits HDIST (1-32) */ + hdist = read_bits(d, 5, 1); + + /* get 4 bits HCLEN (4-19) */ + hclen = read_bits(d, 4, 4); + + for (i = 0; i < 19; ++i) lengths[i] = 0; + + /* read code lengths for code length alphabet */ + for (i = 0; i < hclen; ++i) { + /* get 3 bits code length (0-7) */ + uint clen = read_bits(d, 3, 0); + lengths[d->clcidx[i]] = clen; + } + + /* build code length tree, temporarily use length tree */ + build_tree(lt, lengths, 19); + + /* decode code lengths for the dynamic trees */ + hlimit = hlit + hdist; + for (num = 0; num < hlimit; ) { + int sym = decode_symbol(d, lt); + uchar fill_value = 0; + int lbits, lbase = 3; + + /* error decoding */ + if (sym < 0) + return sym; + + switch (sym) { + case 16: + /* copy previous code length 3-6 times (read 2 bits) */ + fill_value = lengths[num - 1]; + lbits = 2; + break; + case 17: + /* repeat code length 0 for 3-10 times (read 3 bits) */ + lbits = 3; + break; + case 18: + /* repeat code length 0 for 11-138 times (read 7 bits) */ + lbits = 7; + lbase = 11; + break; + default: + /* values 0-15 represent the actual code lengths */ + lengths[num++] = sym; + /* continue the for loop */ + continue; + } + + /* special code length 16-18 are handled here */ + length = read_bits(d, lbits, lbase); + if (num + length > hlimit) + return UZLIB_DATA_ERROR; + + for (; length; --length) + lengths[num++] = fill_value; + } + + /* build dynamic trees */ + build_tree(lt, lengths, hlit); + build_tree(dt, lengths + hlit, hdist); + + return UZLIB_OK; +} + +/* ----------------------------- * + * -- block inflate functions -- * + * ----------------------------- */ + +/* given a stream and two trees, inflate a block of data */ +static int inflate_block_data (UZLIB_DATA *d, UZLIB_TREE *lt, UZLIB_TREE *dt) { + if (d->curLen == 0) { + int dist; + int sym = decode_symbol(d, lt); + + /* literal byte */ + if (sym < 256) { + DBG_PRINT("huff sym: %02x %c\n", sym, sym); + d->put_byte(sym); + return UZLIB_OK; + } + + /* end of block */ + if (sym == 256) + return UZLIB_DONE; + + /* substring from sliding dictionary */ + sym -= 257; + /* possibly get more bits from length code */ + d->curLen = read_bits(d, d->lengthBits[sym], d->lengthBase[sym]); + dist = decode_symbol(d, dt); + /* possibly get more bits from distance code */ + d->lzOffs = read_bits(d, d->distBits[dist], d->distBase[dist]); + DBG_PRINT("huff dict: -%u for %u\n", d->lzOffs, d->curLen); + } + + /* copy next byte from dict substring */ + uchar b = d->recall_byte(d->lzOffs); + DBG_PRINT("huff dict byte(%u): -%u - %02x %c\n\n", + d->curLen, d->lzOffs, b, b); + d->put_byte(b); + d->curLen--; + return UZLIB_OK; +} + +/* inflate an uncompressed block of data */ +static int inflate_uncompressed_block (UZLIB_DATA *d) { + if (d->curLen == 0) { + uint length = get_uint16(d); + uint invlength = get_uint16(d); + + /* check length */ + if (length != (~invlength & 0x0000ffff)) + return UZLIB_DATA_ERROR; + + /* increment length to properly return UZLIB_DONE below, without + producing data at the same time */ + d->curLen = length + 1; + + /* make sure we start next block on a byte boundary */ + d->bitcount = 0; + } + + if (--d->curLen == 0) { + return UZLIB_DONE; + } + + d->put_byte(d->get_byte()); + return UZLIB_OK; +} + +/* -------------------------- * + * -- main parse functions -- * + * -------------------------- */ + +static int parse_gzip_header(UZLIB_DATA *d) { + + /* check id bytes */ + if (d->get_byte() != 0x1f || d->get_byte() != 0x8b) + return UZLIB_DATA_ERROR; + + if (d->get_byte() != 8) /* check method is deflate */ + return UZLIB_DATA_ERROR; + + uchar flg = d->get_byte();/* get flag byte */ + + if (flg & 0xe0)/* check that reserved bits are zero */ + return UZLIB_DATA_ERROR; + + skip_bytes(d, 6); /* skip rest of base header of 10 bytes */ + + if (flg & UZLIB_FEXTRA) /* skip extra data if present */ + skip_bytes(d, get_uint16(d)); + + if (flg & UZLIB_FNAME) /* skip file name if present */ + skip_bytes(d,0); + + if (flg & UZLIB_FCOMMENT) /* skip file comment if present */ + skip_bytes(d,0); + + if (flg & UZLIB_FHCRC) /* ignore header crc if present */ + skip_bytes(d,2); + + return UZLIB_OK; +} + + +/* inflate next byte of compressed stream */ +static int uncompress_stream (UZLIB_DATA *d) { + do { + int res; + + /* start a new block */ + if (d->bType == -1) { + next_blk: + /* read final block flag */ + d->bFinal = getbit(d); + /* read block type (2 bits) */ + d->bType = read_bits(d, 2, 0); + + DBG_PRINT("Started new block: type=%d final=%d\n", d->bType, d->bFinal); + + if (d->bType == 1) { + /* build fixed huffman trees */ + build_fixed_trees(&d->ltree, &d->dtree); + } else if (d->bType == 2) { + /* decode trees from stream */ + res = decode_trees(d, &d->ltree, &d->dtree); + if (res != UZLIB_OK) + return res; + } + } + + /* process current block */ + switch (d->bType) { + case 0: + /* decompress uncompressed block */ + res = inflate_uncompressed_block(d); + break; + case 1: + case 2: + /* decompress block with fixed or dynamic huffman trees. These */ + /* trees were decoded previously, so it's the same routine for both */ + res = inflate_block_data(d, &d->ltree, &d->dtree); + break; + default: + return UZLIB_DATA_ERROR; + } + + if (res == UZLIB_DONE && !d->bFinal) { + /* the block has ended (without producing more data), but we + can't return without data, so start procesing next block */ + goto next_blk; + } + + if (res != UZLIB_OK) + return res; + + } while (--d->destSize); + + return UZLIB_OK; +} + +/* + * This implementation has a different usecase to Paul Sokolovsky's + * uzlib implementation, in that it is designed to target IoT devices + * such as the ESP8266. Here clarity and compact code size is an + * advantage, but the ESP8266 only has 40-45Kb free heap, and has to + * process files with an unpacked size of up 256Kb, so a streaming + * implementation is essential. + * + * I have taken the architectural decision to hide the implementation + * detials from the uncompress routines and the caller must provide + * three support routines to handle the streaming: + * + * void get_byte(void) + * void put_byte(uchar b) + * uchar recall_byte(uint offset) + * + * This last must be able to recall an output byte with an offet up to + * the maximum dictionary size. + */ + +int uzlib_inflate ( + uchar (*get_byte)(void), + void (*put_byte)(uchar v), + uchar (*recall_byte)(uint offset), + uint len, uint *crc, void **state) { + int res; + + /* initialize decompression structure */ + UZLIB_DATA *d = (UZLIB_DATA *) uz_malloc(sizeof(*d)); + if (!d) + return UZLIB_MEMORY_ERROR; + *state = d; + + d->bitcount = 0; + d->bFinal = 0; + d->bType = -1; + d->curLen = 0; + d->destSize = len; + d->get_byte = get_byte; + d->put_byte = put_byte; + d->recall_byte = recall_byte; + + if ((res = UZLIB_SETJMP(unwindAddr)) != 0) { + if (crc) + *crc = d->checksum; + /* handle long jump */ + if (d) { + uz_free(d); + *state = NULL; + } + return res; + } + + /* create RAM copy of clcidx byte array */ + memcpy(d->clcidx, CLCIDX_INIT, sizeof(d->clcidx)); + + /* build extra bits and base tables */ + build_bits_base(d->lengthBits, d->lengthBase, 4, 3); + build_bits_base(d->distBits, d->distBase, 2, 1); + d->lengthBits[28] = 0; /* fix a special case */ + d->lengthBase[28] = 258; + + if ((res = parse_gzip_header(d))== UZLIB_OK) + while ((res = uncompress_stream(d)) == UZLIB_OK) + {} + + if (res == UZLIB_DONE) { + d->checksum = get_le_uint32(d); + (void) get_le_uint32(d); /* already got length so ignore */ + } + + UZLIB_THROW(res); +} diff --git a/docs/modules/eth.md b/docs/modules/eth.md index 6dce7b3e56..106487f2b1 100644 --- a/docs/modules/eth.md +++ b/docs/modules/eth.md @@ -1,4 +1,4 @@ -# WiFi Module +# Eth Module | Since | Origin / Contributor | Maintainer | Source | | :----- | :-------------------- | :---------- | :------ | | 2019-06-25 | [Arnim Laeuger](https://github.com/devsaurus) |[Arnim Laeuger](https://github.com/devsaurus) | [eth.c](../../components/modules/eth.c)| diff --git a/lua_examples/lfs/dummy_strings.lua b/lua_examples/lfs/dummy_strings.lua new file mode 100644 index 0000000000..cee2eaaf54 --- /dev/null +++ b/lua_examples/lfs/dummy_strings.lua @@ -0,0 +1,37 @@ +-- +-- File: LFS_dummy_strings.lua +--[[ + luac.cross -f generates a ROM string table which is part of the compiled LFS + image. This table includes all strings referenced in the loaded modules. + + If you want to preload other string constants, then one way to achieve this is + to include a dummy module in the LFS that references the strings that you want + to load. You never need to call this module; it's inclusion in the LFS image is + enough to add the strings to the ROM table. Your application can use any strings + in the ROM table without incuring any RAM or Lua Garbage Collector (LGC) + overhead. + + The local preload example is a useful starting point. However, if you call the + following code in your application during testing, then this will provide a + listing of the current RAM string table. + +do + local a=debug.getstrings'RAM' + for i =1, #a do a[i] = ('%q'):format(a[i]) end + print ('local preload='..table.concat(a,',')) +end + + This will exclude any strings already in the ROM table, so the output is the list + of putative strings that you should consider adding to LFS ROM table. + +---------------------------------------------------------------------------------]] + +local preload = "?.lc;?.lua", "/\n;\n?\n!\n-", "@init.lua", "_G", "_LOADED", +"_LOADLIB", "__add", "__call", "__concat", "__div", "__eq", "__gc", "__index", +"__le", "__len", "__lt", "__mod", "__mode", "__mul", "__newindex", "__pow", +"__sub", "__tostring", "__unm", "collectgarbage", "cpath", "debug", "file", +"file.obj", "file.vol", "flash", "getstrings", "index", "ipairs", "list", "loaded", +"loader", "loaders", "loadlib", "module", "net.tcpserver", "net.tcpsocket", +"net.udpsocket", "newproxy", "package", "pairs", "path", "preload", "reload", +"require", "seeall", "wdclr", "not enough memory", "sjson.decoder","sjson.encoder", +"tmr.timer" diff --git a/lua_examples/lfs/init.lua b/lua_examples/lfs/init.lua new file mode 100644 index 0000000000..f0c213d3a5 --- /dev/null +++ b/lua_examples/lfs/init.lua @@ -0,0 +1,98 @@ +-- +-- File: _init.lua +--[[ + + This is a template for the LFS equivalent of the SPIFFS init.lua. + + It is a good idea to such an _init.lua module to your LFS and do most of the LFS + module related initialisaion in this. This example uses standard Lua features to + simplify the LFS API. + + The first section adds a 'LFS' table to _G and uses the __index metamethod to + resolve functions in the LFS, so you can execute the main function of module + 'fred' by executing LFS.fred(params), etc. It also implements some standard + readonly properties: + + LFS._time The Unix Timestamp when the luac.cross was executed. This can be + used as a version identifier. + + LFS._config This returns a table of useful configuration parameters, hence + print (("0x%6x"):format(LFS._config.lfs_base)) + gives you the parameter to use in the luac.cross -a option. + + LFS._list This returns a table of the LFS modules, hence + print(table.concat(LFS._list,'\n')) + gives you a single column listing of all modules in the LFS. + +---------------------------------------------------------------------------------]] + +local index = node.flashindex + +local lfs_t = { + __index = function(_, name) + fn_ut, ba, ma, size, modules = index(name) + if not ba then + return fn_ut + elseif name == '_time' then + return fn_ut + elseif name == '_config' then + fs_ma, fs_size = file.fscfg() + return {lfs_base = ba, lfs_mapped = ma, lfs_size = size, + fs_mapped = fs_ma, fs_size = fs_size} + elseif name == '_list' then + return modules + else + return nil + end + end, + + __newindex = function(_, name, value) + error("LFS is readonly. Invalid write to LFS." .. name, 2) + end, + +} + +_G.LFS = setmetatable(lfs_t,lfs_t) + +--[[------------------------------------------------------------------------------- + The second section adds the LFS to the require searchlist, so that you can + require a Lua module 'jean' in the LFS by simply doing require "jean". However + note that this is at the search entry following the FS searcher, so if you also + have jean.lc or jean.lua in SPIFFS, then this SPIFFS version will get loaded into + RAM instead of using. (Useful, for development). + + See docs/en/lfs.md and the 'loaders' array in app/lua/loadlib.c for more details. + +---------------------------------------------------------------------------------]] + +package.loaders[3] = function(module) -- loader_flash + fn, ba = index(module) + return ba and "Module not in LFS" or fn +end + +--[[------------------------------------------------------------------------------- + You can add any other initialisation here, for example a couple of the globals + are never used, so setting them to nil saves a couple of global entries +---------------------------------------------------------------------------------]] + +_G.module = nil -- disable Lua 5.0 style modules to save RAM +package.seeall = nil + +--[[------------------------------------------------------------------------------- + These replaces the builtins loadfile & dofile with ones which preferentially + loads the corresponding module from LFS if present. Flipping the search order + is an exercise left to the reader.- +---------------------------------------------------------------------------------]] + +lf, df = loadfile, dofile +_G.loadfile = function(n) + mod, ext = n:match("(.*)%.(l[uc]a?)"); + fn, ba = index(mod) + if ba or (ext ~= 'lc' and ext ~= 'lua') then return lf(n) else return fn end +end + +_G.dofile = function(n) + mod, ext = n:match("(.*)%.(l[uc]a?)"); + fn, ba = index(mod) + if ba or (ext ~= 'lc' and ext ~= 'lua') then return df(n) else return fn() end +end diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 2f77ea27b2..11ea055b85 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -5,6 +5,9 @@ CONFIG_PARTITION_TABLE_SINGLE_APP=n CONFIG_PARTITION_TABLE_TWO_OTA=n CONFIG_PARTITION_TABLE_CUSTOM=y +# Default to 4MB for builds +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + # Don't warn about undefined variables CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=n diff --git a/tools/cross-lua.lua b/tools/cross-lua.lua deleted file mode 100644 index 69eaebe638..0000000000 --- a/tools/cross-lua.lua +++ /dev/null @@ -1,42 +0,0 @@ -local args = { ... } -local b = require "tools.build" -local builder = b.new_builder( ".build/cross-lua" ) -local utils = b.utils -local sf = string.format - -if not (_VERSION == "Lua 5.1" and pcall(require,"lfs")) then - print [[ - -cross_lua.lua must be run within Lua 5.1 and it requires the Lua Filesystem to be installed. -On most *nix distrubitions youwill find a packages lua-5.1 and lua-filesystem, or -alternalively you can install lua-rocks and use the Rocks package manager to install lfs. -]] - os.exit(1) -end -builder:init( args ) -builder:set_build_mode( builder.BUILD_DIR_LINEARIZED ) -local output = 'luac.cross' -local cdefs = '-DLUA_CROSS_COMPILER' - --- Lua source files and include path -local lua_files = [[ - lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ldo.c ldump.c - lfunc.c lgc.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c - lparser.c lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c - ltm.c lundump.c lvm.c lzio.c - luac_cross/luac.c luac_cross/loslib.c luac_cross/print.c - ../modules/linit.c - ../libc/c_stdlib.c - ]] -lua_files = lua_files:gsub( "\n" , "" ) -local lua_full_files = utils.prepend_path( lua_files, "app/lua" ) -local local_include = "-Iapp/include -Iinclude -Iapp/lua" - --- Compiler/linker options -builder:set_compile_cmd( sf( "gcc -O2 %s -Wall %s -c $(FIRST) -o $(TARGET)", local_include, cdefs ) ) -builder:set_link_cmd( "gcc -o $(TARGET) $(DEPENDS) -lm" ) - --- Build everything -builder:make_exe_target( output, lua_full_files ) -builder:build() - diff --git a/tools/embed_lfs.sh b/tools/embed_lfs.sh new file mode 100755 index 0000000000..deb3e01846 --- /dev/null +++ b/tools/embed_lfs.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +LUA_APP_SRC="$@" + +MAP_FILE=build/NodeMCU.map +LUAC_OUTPUT=build/luac.out +LUAC_CROSS=build/luac_cross/luac.cross + +if [ ! -f "${MAP_FILE}" ]; then + echo "Error: ${MAP_FILE} not found. Please run make first." + exit 1 +fi +if [ ! -f "${LUAC_CROSS}" ]; then + echo "Error: ${LUAC_CROSS} not found. Please run make first." + exit 1 +fi + +LFS_ADDR_SIZE=`grep -E "\.lfs\.reserved[ ]+0x[0-9a-f]+[ ]+0x[0-9a-z]+" ${MAP_FILE} | tr -s ' '` +if [ -z "${LFS_ADDR_SIZE}" ]; then + echo "Error: LFS segment not found. Use 'make clean; make' perhaps?" + exit 1 +fi + +LFS_ADDR=`echo "${LFS_ADDR_SIZE}" | cut -d ' ' -f 3` +if [ -z "${LFS_ADDR}" ]; then + echo "Error: LFS segment address not found" + exit 1 +fi +LFS_SIZE=`echo "${LFS_ADDR_SIZE}" | cut -d ' ' -f 4` +if [ -z "${LFS_SIZE}" ]; then + echo "Error: LFS segment size not found" + exit 1 +fi + +echo "LFS segment address ${LFS_ADDR}, length ${LFS_SIZE}" + +${LUAC_CROSS} -a ${LFS_ADDR} -m ${LFS_SIZE} -o ${LUAC_OUTPUT} ${LUA_APP_SRC} +if [ $? != 0 ]; then + echo "Error: luac.cross failed" + exit 1 +fi + +make diff --git a/tools/esptool.py b/tools/esptool.py deleted file mode 100755 index 944a59b728..0000000000 --- a/tools/esptool.py +++ /dev/null @@ -1,640 +0,0 @@ -#!/usr/bin/env python -# -# ESP8266 ROM Bootloader Utility -# https://github.com/themadinventor/esptool -# -# Copyright (C) 2014 Fredrik Ahlberg -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later version. -# -# 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. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin -# Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import sys -import struct -import serial -import math -import time -import argparse -import os -import subprocess - -class ESPROM: - - # These are the currently known commands supported by the ROM - ESP_FLASH_BEGIN = 0x02 - ESP_FLASH_DATA = 0x03 - ESP_FLASH_END = 0x04 - ESP_MEM_BEGIN = 0x05 - ESP_MEM_END = 0x06 - ESP_MEM_DATA = 0x07 - ESP_SYNC = 0x08 - ESP_WRITE_REG = 0x09 - ESP_READ_REG = 0x0a - - # Maximum block sized for RAM and Flash writes, respectively. - ESP_RAM_BLOCK = 0x1800 - ESP_FLASH_BLOCK = 0x400 - - # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. - ESP_ROM_BAUD = 115200 - - # First byte of the application image - ESP_IMAGE_MAGIC = 0xe9 - - # Initial state for the checksum routine - ESP_CHECKSUM_MAGIC = 0xef - - # OTP ROM addresses - ESP_OTP_MAC0 = 0x3ff00050 - ESP_OTP_MAC1 = 0x3ff00054 - - # Sflash stub: an assembly routine to read from spi flash and send to host - SFLASH_STUB = "\x80\x3c\x00\x40\x1c\x4b\x00\x40\x21\x11\x00\x40\x00\x80" \ - "\xfe\x3f\xc1\xfb\xff\xd1\xf8\xff\x2d\x0d\x31\xfd\xff\x41\xf7\xff\x4a" \ - "\xdd\x51\xf9\xff\xc0\x05\x00\x21\xf9\xff\x31\xf3\xff\x41\xf5\xff\xc0" \ - "\x04\x00\x0b\xcc\x56\xec\xfd\x06\xff\xff\x00\x00" - - def __init__(self, port = 0, baud = ESP_ROM_BAUD): - self._port = serial.Serial(port, baud) - - """ Read bytes from the serial port while performing SLIP unescaping """ - def read(self, length = 1): - b = '' - while len(b) < length: - c = self._port.read(1) - if c == '\xdb': - c = self._port.read(1) - if c == '\xdc': - b = b + '\xc0' - elif c == '\xdd': - b = b + '\xdb' - else: - raise Exception('Invalid SLIP escape') - else: - b = b + c - return b - - """ Write bytes to the serial port while performing SLIP escaping """ - def write(self, packet): - buf = '\xc0'+(packet.replace('\xdb','\xdb\xdd').replace('\xc0','\xdb\xdc'))+'\xc0' - self._port.write(buf) - - """ Calculate checksum of a blob, as it is defined by the ROM """ - @staticmethod - def checksum(data, state = ESP_CHECKSUM_MAGIC): - for b in data: - state ^= ord(b) - return state - - """ Send a request and read the response """ - def command(self, op = None, data = None, chk = 0): - if op: - # Construct and send request - pkt = struct.pack('> 16) & 0xff) == 0: - oui = (0x18, 0xfe, 0x34) - elif ((mac1 >> 16) & 0xff) == 1: - oui = (0xac, 0xd0, 0x74) - else: - raise Exception("Unknown OUI") - return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff) - - """ Read SPI flash manufacturer and device id """ - def flash_id(self): - self.flash_begin(0, 0) - self.write_reg(0x60000240, 0x0, 0xffffffff) - self.write_reg(0x60000200, 0x10000000, 0xffffffff) - flash_id = esp.read_reg(0x60000240) - self.flash_finish(False) - return flash_id - - """ Read SPI flash """ - def flash_read(self, offset, size, count = 1): - # Create a custom stub - stub = struct.pack(' 16: - raise Exception('Invalid firmware image') - - for i in xrange(segments): - (offset, size) = struct.unpack(' 0x40200000 or offset < 0x3ffe0000 or size > 65536: - raise Exception('Suspicious segment %x,%d' % (offset, size)) - self.segments.append((offset, size, f.read(size))) - - # Skip the padding. The checksum is stored in the last byte so that the - # file is a multiple of 16 bytes. - align = 15-(f.tell() % 16) - f.seek(align, 1) - - self.checksum = ord(f.read(1)) - - def add_segment(self, addr, data): - # Data should be aligned on word boundary - l = len(data) - if l % 4: - data += b"\x00" * (4 - l % 4) - self.segments.append((addr, len(data), data)) - - def save(self, filename): - f = file(filename, 'wb') - f.write(struct.pack(' 0: - esp.mem_block(data[0:esp.ESP_RAM_BLOCK], seq) - data = data[esp.ESP_RAM_BLOCK:] - seq += 1 - print 'done!' - - print 'All segments done, executing at %08x' % image.entrypoint - esp.mem_finish(image.entrypoint) - - elif args.operation == 'read_mem': - print '0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address)) - - elif args.operation == 'write_mem': - esp.write_reg(args.address, args.value, args.mask, 0) - print 'Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address) - - elif args.operation == 'dump_mem': - f = file(args.filename, 'wb') - for i in xrange(args.size/4): - d = esp.read_reg(args.address+(i*4)) - f.write(struct.pack(' 0: - print '\rWriting at 0x%08x... (%d %%)' % (address + seq*esp.ESP_FLASH_BLOCK, 100*(seq+1)/blocks), - sys.stdout.flush() - block = image[0:esp.ESP_FLASH_BLOCK] - # Fix sflash config data - if address == 0 and seq == 0 and block[0] == '\xe9': - block = block[0:2] + flash_info + block[4:] - # Pad the last block - block = block + '\xff' * (esp.ESP_FLASH_BLOCK-len(block)) - esp.flash_block(block, seq) - image = image[esp.ESP_FLASH_BLOCK:] - seq += 1 - print - print '\nLeaving...' - if args.flash_mode == 'dio': - esp.flash_unlock_dio() - else: - esp.flash_finish(False) - - elif args.operation == 'run': - esp.run() - - elif args.operation == 'image_info': - image = ESPFirmwareImage(args.filename) - print ('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set' - print '%d segments' % len(image.segments) - print - checksum = ESPROM.ESP_CHECKSUM_MAGIC - for (idx, (offset, size, data)) in enumerate(image.segments): - print 'Segment %d: %5d bytes at %08x' % (idx+1, size, offset) - checksum = ESPROM.checksum(data, checksum) - print - print 'Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!') - - elif args.operation == 'make_image': - image = ESPFirmwareImage() - if len(args.segfile) == 0: - raise Exception('No segments specified') - if len(args.segfile) != len(args.segaddr): - raise Exception('Number of specified files does not match number of specified addresses') - for (seg, addr) in zip(args.segfile, args.segaddr): - data = file(seg, 'rb').read() - image.add_segment(addr, data) - image.entrypoint = args.entrypoint - image.save(args.output) - - elif args.operation == 'elf2image': - if args.output is None: - args.output = args.input + '-' - e = ELFFile(args.input) - image = ESPFirmwareImage() - image.entrypoint = e.get_entry_point() - for section, start in ((".text", "_text_start"), (".data", "_data_start"), (".rodata", "_rodata_start")): - data = e.load_section(section) - image.add_segment(e.get_symbol_addr(start), data) - - image.flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode] - image.flash_size_freq = {'4m':0x00, '2m':0x10, '8m':0x20, '16m':0x30, '32m':0x40}[args.flash_size] - image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] - - image.save(args.output + "0x00000.bin") - data = e.load_section(".irom0.text") - off = e.get_symbol_addr("_irom0_text_start") - 0x40200000 - assert off >= 0 - f = open(args.output + "0x%05x.bin" % off, "wb") - f.write(data) - f.close() - - elif args.operation == 'read_mac': - mac = esp.read_mac() - print 'MAC: %s' % ':'.join(map(lambda x: '%02x'%x, mac)) - - elif args.operation == 'flash_id': - flash_id = esp.flash_id() - print 'Manufacturer: %02x' % (flash_id & 0xff) - print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff) - - elif args.operation == 'read_flash': - print 'Please wait...' - file(args.filename, 'wb').write(esp.flash_read(args.address, 1024, int(math.ceil(args.size / 1024.)))[:args.size]) - - elif args.operation == 'erase_flash': - esp.flash_erase()