Unverified Commit eaac369d authored by Johny Mattsson's avatar Johny Mattsson Committed by GitHub
Browse files

LFS support for ESP32 NodeMCU (#2801)

* Port LFS from ESP8266 to ESP32
parent 7cb61a27
BASE_NODEMCU_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) BASE_NODEMCU_DIR:=$(dir $(lastword $(MAKEFILE_LIST)))
BASE_NODEMCU_BUILD_DIR:=$(BUILD_DIR_BASE)/base_nodemcu 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 $(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_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 $@ touch $@
#ifdef LUA_CROSS_COMPILER
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define true 1
#define false 0
#else
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
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
#ifndef _SDK_OVERRIDES_STDLIB_H_
#define _SDK_OVERRIDES_STDLIB_H_
extern const char *c_getenv (const char *);
#endif
#ifndef __MODULE_H__ #ifndef __MODULE_H__
#define __MODULE_H__ #define __MODULE_H__
#include "lrodefs.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "lrotable.h"
/* Registering a module within NodeMCU is really easy these days! /* Registering a module within NodeMCU is really easy these days!
* *
...@@ -36,37 +36,37 @@ ...@@ -36,37 +36,37 @@
#define MODULE_PASTE_(x,y) x##y #define MODULE_PASTE_(x,y) x##y
#define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(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): /* For the ROM table, we name the variable according to ( | denotes concat):
* cfgname | _module_selected | CONFIG_LUA_MODULE_##cfgname * cfgname | _module_selected | CONFIG_LUA_MODULE_##cfgname
* where the CONFIG_LUA_MODULE_XYZ macro is first expanded to yield either * 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 * 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 * 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, * 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 * letting the build system detect automatically (via nm) which modules need
* to be linked in. * to be linked in.
*/ */
#define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \ #define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \
const LOCK_IN_SECTION(".lua_libs") \ const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \ luaR_entry MODULE_PASTE_(lua_lib_,cfgname) = { luaname, LRO_FUNCVAL(initfunc) }; \
const LOCK_IN_SECTION(".lua_rotable") \ const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_LUA_MODULE_,cfgname))) \ luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_LUA_MODULE_,cfgname))) \
= { luaname, map } = {luaname, LRO_ROVAL(map ## _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
#endif #endif
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include "esp_event.h" #include "esp_event.h"
#include "module.h" #include "module.h"
#include <assert.h>
#include <stdalign.h>
/** /**
* Similarly to how a NodeMCU module is registered, a module can register * Similarly to how a NodeMCU module is registered, a module can register
...@@ -66,7 +68,10 @@ typedef struct { ...@@ -66,7 +68,10 @@ typedef struct {
extern nodemcu_esp_event_reg_t esp_event_cb_table; extern nodemcu_esp_event_reg_t esp_event_cb_table;
#define NODEMCU_ESP_EVENT(evcode, func) \ #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 }; 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 #endif
/* ----- Begin NodeMCU link-time arrays ------- */ /* ----- 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 */ /* Link-time arrays containing the defs for the included modules */
lua_libs = ABSOLUTE(.); lua_libs_map = ABSOLUTE(.);
KEEP(*(.lua_libs)) KEEP(*(.lua_libs))
LONG(0) LONG(0) /* Null-terminate the array */ /* Null-terminate the array, 24 bytes */
lua_rotable = ABSOLUTE(.); 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)) 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(.); esp_event_cb_table = ABSOLUTE(.);
KEEP(*(.esp_event_cb_table)) KEEP(*(.lua_esp_event_cb_table))
LONG(0) LONG(0) /* Null-terminate the array */ LONG(0) LONG(0) /* Null-terminate the array, 8 bytes */
/* ----- End NodeMCU link-time arrays ------- */ /* ----- End NodeMCU link-time arrays ------- */
/* ----- 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 ----- */
...@@ -15,64 +15,111 @@ ...@@ -15,64 +15,111 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "luaconf.h" #include "luaconf.h"
#include "module.h" #include "module.h"
#include "sdkconfig.h" #include "lstate.h"
#include <assert.h>
#include <stdalign.h>
BUILTIN_LIB_INIT( BASE, "", luaopen_base); LROT_EXTERN(strlib);
BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package); LROT_EXTERN(tab_funcs);
LROT_EXTERN(dblib);
#if defined(LUA_USE_BUILTIN_IO) LROT_EXTERN(co_funcs);
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io); LROT_EXTERN(math);
#endif #if defined(LUA_CROSS_COMPILER)
LROT_EXTERN(oslib);
#if defined (CONFIG_LUA_BUILTIN_STRING) //LROT_EXTERN(iolib);
extern const luaR_entry strlib[];
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string);
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib);
#endif #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) #ifdef _MSC_VER
extern const luaR_entry tab_funcs[]; //MSVC requires us to declare these sections before we refer to them
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table); #pragma section(__ROSECNAME(A), read)
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs); #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 #endif
#if defined(CONFIG_LUA_BUILTIN_DEBUG) LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(rotable) lua_rotables)
extern const luaR_entry dblib[]; LROT_TABENTRY( string, strlib )
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug); LROT_TABENTRY( table, tab_funcs )
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib); 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 #endif
#if defined(LUA_USE_BUILTIN_OS) LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(libs) lua_libs)
extern const luaR_entry syslib[]; LROT_FUNCENTRY( _, luaopen_base )
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib); 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 #endif
#if defined(CONFIG_LUA_BUILTIN_COROUTINE) #ifndef LUA_CROSS_COMPILER
extern const luaR_entry co_funcs[]; extern void luaL_dbgbreak(void);
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
#endif #endif
#if defined(CONFIG_LUA_BUILTIN_MATH) void luaL_openlibs (lua_State *L) {
extern const luaR_entry math_map[];
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#endif
#ifdef LUA_CROSS_COMPILER lua_pushrotable(L, LROT_TABLEREF(lua_libs));
const luaL_Reg lua_libs[] = {{NULL, NULL}}; lua_pushnil(L); /* first key */
const luaR_table lua_rotable[] = {{NULL, NULL}}; /* loop round and open libraries */
#else #ifndef LUA_CROSS_COMPILER
extern const luaL_Reg lua_libs[]; // luaL_dbgbreak(); // This is a test point for debugging library start ups
#endif #endif
while (lua_next(L, -2) != 0) {
void luaL_openlibs (lua_State *L) { if (lua_islightfunction(L,-1) &&
const luaL_Reg *lib = lua_libs; fvalue(L->top-1)) { // only process function entries
for (; lib->name; lib++) { lua_pushvalue(L, -2);
if (lib->func) lua_call(L, 1, 0); // call luaopen_XXX(libname)
{ } else {
lua_pushcfunction(L, lib->func); lua_pop(L, 1);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
} }
} }
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
...@@ -260,30 +260,29 @@ static int uart_getconfig(lua_State* L) { ...@@ -260,30 +260,29 @@ static int uart_getconfig(lua_State* L) {
} }
// Module function map // Module function map
static const LUA_REG_TYPE uart_map[] = { LROT_BEGIN(uart)
{ LSTRKEY( "setup" ), LFUNCVAL( uart_setup ) }, LROT_FUNCENTRY( setup, uart_setup )
{ LSTRKEY( "write" ), LFUNCVAL( uart_write ) }, LROT_FUNCENTRY( write, uart_write )
{ LSTRKEY( "start" ), LFUNCVAL( uart_start ) }, LROT_FUNCENTRY( start, uart_start )
{ LSTRKEY( "stop" ), LFUNCVAL( uart_stop ) }, LROT_FUNCENTRY( stop, uart_stop )
{ LSTRKEY( "on" ), LFUNCVAL( uart_on ) }, LROT_FUNCENTRY( on, uart_on )
{ LSTRKEY( "setmode" ), LFUNCVAL( uart_setmode ) }, LROT_FUNCENTRY( setmode, uart_setmode )
{ LSTRKEY( "getconfig" ), LFUNCVAL( uart_getconfig ) }, LROT_FUNCENTRY( getconfig, uart_getconfig )
{ LSTRKEY( "STOPBITS_1" ), LNUMVAL( PLATFORM_UART_STOPBITS_1 ) }, LROT_NUMENTRY( STOPBITS_1, PLATFORM_UART_STOPBITS_1 )
{ LSTRKEY( "STOPBITS_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) }, LROT_NUMENTRY( STOPBITS_1_5, PLATFORM_UART_STOPBITS_1_5 )
{ LSTRKEY( "STOPBITS_2" ), LNUMVAL( PLATFORM_UART_STOPBITS_2 ) }, LROT_NUMENTRY( STOPBITS_2, PLATFORM_UART_STOPBITS_2 )
{ LSTRKEY( "PARITY_NONE" ), LNUMVAL( PLATFORM_UART_PARITY_NONE ) }, LROT_NUMENTRY( PARITY_NONE, PLATFORM_UART_PARITY_NONE )
{ LSTRKEY( "PARITY_EVEN" ), LNUMVAL( PLATFORM_UART_PARITY_EVEN ) }, LROT_NUMENTRY( PARITY_EVEN, PLATFORM_UART_PARITY_EVEN )
{ LSTRKEY( "PARITY_ODD" ), LNUMVAL( PLATFORM_UART_PARITY_ODD ) }, LROT_NUMENTRY( PARITY_ODD, PLATFORM_UART_PARITY_ODD )
{ LSTRKEY( "FLOWCTRL_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) }, LROT_NUMENTRY( FLOWCTRL_NONE, PLATFORM_UART_FLOW_NONE )
{ LSTRKEY( "FLOWCTRL_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) }, LROT_NUMENTRY( FLOWCTRL_CTS, PLATFORM_UART_FLOW_CTS )
{ LSTRKEY( "FLOWCTRL_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) }, LROT_NUMENTRY( FLOWCTRL_RTS, PLATFORM_UART_FLOW_RTS )
{ LSTRKEY( "MODE_UART" ), LNUMVAL( PLATFORM_UART_MODE_UART ) }, LROT_NUMENTRY( MODE_UART, PLATFORM_UART_MODE_UART )
{ LSTRKEY( "MODE_RS485_COLLISION_DETECT" ), LNUMVAL( PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) }, LROT_NUMENTRY( MODE_RS485_COLLISION_DETECT, PLATFORM_UART_MODE_RS485_COLLISION_DETECT )
{ LSTRKEY( "MODE_RS485_APP_CONTROL" ), LNUMVAL( PLATFORM_UART_MODE_RS485_APP_CONTROL ) }, LROT_NUMENTRY( MODE_RS485_APP_CONTROL, PLATFORM_UART_MODE_RS485_APP_CONTROL )
{ LSTRKEY( "MODE_RS485_HALF_DUPLEX" ), LNUMVAL( PLATFORM_UART_MODE_HALF_DUPLEX ) }, LROT_NUMENTRY( MODE_RS485_HALF_DUPLEX, PLATFORM_UART_MODE_HALF_DUPLEX )
{ LSTRKEY( "MODE_IRDA" ), LNUMVAL( PLATFORM_UART_MODE_IRDA ) }, LROT_NUMENTRY( MODE_IRDA, PLATFORM_UART_MODE_IRDA )
{ LNILKEY, LNILVAL } LROT_END(uart, NULL, 0)
};
int luaopen_uart( lua_State *L ) { int luaopen_uart( lua_State *L ) {
uart_status_t *us; uart_status_t *us;
...@@ -297,4 +296,4 @@ int luaopen_uart( lua_State *L ) { ...@@ -297,4 +296,4 @@ int luaopen_uart( lua_State *L ) {
return 0; return 0;
} }
NODEMCU_MODULE(UART, "uart", uart_map, luaopen_uart); NODEMCU_MODULE(UART, "uart", uart, luaopen_uart);
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
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
#include "lua.h" #include "lua.h"
//#include C_HEADER_ASSERT //#include <assert.h>
#include C_HEADER_MATH #include <math.h>
#include C_HEADER_STRING #include <string.h>
#include "lapi.h" #include "lapi.h"
#include "ldebug.h" #include "ldebug.h"
#include "ldo.h" #include "ldo.h"
...@@ -213,7 +213,7 @@ LUA_API void lua_replace (lua_State *L, int idx) { ...@@ -213,7 +213,7 @@ LUA_API void lua_replace (lua_State *L, int idx) {
if (!func) if (!func)
luaG_runerror(L, "attempt to set environment on lightfunction"); luaG_runerror(L, "attempt to set environment on lightfunction");
else { else {
api_check(L, ttistable(L->top - 1)); api_check(L, ttistable(L->top - 1));
func->c.env = hvalue(L->top - 1); func->c.env = hvalue(L->top - 1);
luaC_barrier(L, func, 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) { ...@@ -411,9 +411,10 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TUSERDATA: case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
return lua_touserdata(L, idx); return lua_touserdata(L, idx);
case LUA_TROTABLE: case LUA_TROTABLE:
return rvalue(o);
case LUA_TLIGHTFUNCTION: case LUA_TLIGHTFUNCTION:
return pvalue(o); return fvalue(o);
default: return NULL; default: return NULL;
} }
} }
...@@ -458,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { ...@@ -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) { LUA_API void lua_pushstring (lua_State *L, const char *s) {
if (s == NULL) if (s == NULL)
lua_pushnil(L); lua_pushnil(L);
...@@ -593,7 +585,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) { ...@@ -593,7 +585,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) {
t = index2adr(L, idx); t = index2adr(L, idx);
api_check(L, ttistable(t) || ttisrotable(t)); 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); 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); lua_unlock(L);
} }
...@@ -633,7 +625,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { ...@@ -633,7 +625,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
break; break;
case LUA_TROTABLE: case LUA_TROTABLE:
mt = (Table*)luaR_getmeta(rvalue(obj)); mt = (Table*)luaR_getmeta(rvalue(obj));
break; break;
default: default:
mt = G(L)->mt[ttype(obj)]; mt = G(L)->mt[ttype(obj)];
break; break;
......
...@@ -7,12 +7,13 @@ ...@@ -7,12 +7,13 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_CTYPE #include <ctype.h>
#include C_HEADER_ERRNO #include <errno.h>
#include C_HEADER_STDIO #include <stdio.h>
#include C_HEADER_STDLIB #include <stdlib.h>
#include C_HEADER_STRING #include <string.h>
#ifndef LUA_CROSS_COMPILER #ifndef LUA_CROSS_COMPILER
#include "esp_system.h"
#include "vfs.h" #include "vfs.h"
#else #else
#endif #endif
...@@ -44,6 +45,149 @@ ...@@ -44,6 +45,149 @@
#define LUA_USECCLOSURES 0 #define LUA_USECCLOSURES 0
#define LUA_USELIGHTFUNCTIONS 1 #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 ** Error-report functions
...@@ -173,7 +317,7 @@ LUALIB_API void luaL_checkanyfunction (lua_State *L, int narg) { ...@@ -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) { 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", const char *msg = lua_pushfstring(L, "function or lightfunction expected, got %s",
luaL_typename(L, narg)); 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) { ...@@ -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) { 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", const char *msg = lua_pushfstring(L, "table or rotable expected, got %s",
luaL_typename(L, narg)); 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, ...@@ -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, LUALIB_API void (luaL_register_light) (lua_State *L, const char *libname,
const luaL_Reg *l) { const luaL_Reg *l) {
#if LUA_OPTIMIZE_MEMORY > 0
luaI_openlib(L, libname, l, 0, LUA_USELIGHTFUNCTIONS); 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) { static int libsize (const luaL_Reg *l) {
...@@ -411,14 +551,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx, ...@@ -411,14 +551,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
if (e == NULL) e = fname + strlen(fname); if (e == NULL) e = fname + strlen(fname);
lua_pushlstring(L, fname, e - fname); lua_pushlstring(L, fname, e - fname);
lua_rawget(L, -2); 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? */ if (lua_isnil(L, -1)) { /* no such field? */
lua_pop(L, 1); /* remove this nil */ lua_pop(L, 1); /* remove this nil */
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ 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) { ...@@ -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 */ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex); if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */ /* skip eventual `#!...' */
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
lf.extraline = 0;
lf.extraline = 0;
} }
ungetc(c, lf.f); ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1)); 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) { ...@@ -700,12 +834,12 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
lf.f = vfs_open(filename, "r"); lf.f = vfs_open(filename, "r");
if (!lf.f) return errfsfile(L, "open", fnameindex); 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"); // return luaL_error(L, "file is too big");
c = vfs_getc(lf.f); c = vfs_getc(lf.f);
if (c == '#') { /* Unix exec. file? */ if (c == '#') { /* Unix exec. file? */
lf.extraline = 1; 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 == '\n') c = vfs_getc(lf.f);
} }
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
...@@ -713,7 +847,7 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) { ...@@ -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 */ lf.f = vfs_open(filename, "r"); /* reopen in binary mode */
if (!lf.f) return errfsfile(L, "reopen", fnameindex); if (!lf.f) return errfsfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */ /* 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; lf.extraline = 0;
} }
vfs_ungetc(c, lf.f); vfs_ungetc(c, lf.f);
...@@ -786,11 +920,20 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ...@@ -786,11 +920,20 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
void *nptr; void *nptr;
if (nsize == 0) { if (nsize == 0) {
#ifdef DEBUG_ALLOCATOR
return (void *)this_realloc(ptr, osize, nsize);
#else
free(ptr); free(ptr);
return NULL; return NULL;
#endif
} }
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */ if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
luaC_fullgc(L); 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(nsize > osize && L != NULL) {
#if defined(LUA_STRESS_EMERGENCY_GC) #if defined(LUA_STRESS_EMERGENCY_GC)
luaC_fullgc(L); luaC_fullgc(L);
...@@ -798,16 +941,19 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ...@@ -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)) if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize))
return NULL; return NULL;
} }
nptr = (void *)realloc(ptr, nsize); nptr = (void *)this_realloc(ptr, osize, nsize);
if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) { if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) {
luaC_fullgc(L); /* emergency full collection. */ 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; return nptr;
} }
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) { 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) { static int panic (lua_State *L) {
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STDIO #include <stdio.h>
#include C_HEADER_STRING #include <string.h>
#include C_HEADER_STDLIB #include <stdlib.h>
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h" #include "lrotable.h"
...@@ -462,73 +462,59 @@ static int luaB_newproxy (lua_State *L) { ...@@ -462,73 +462,59 @@ static int luaB_newproxy (lua_State *L) {
return 1; return 1;
} }
#define LUA_BASELIB_FUNCLIST\ #include "lrotable.h"
{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
static int luaB_index(lua_State *L) { LROT_EXTERN(lua_rotable_base);
#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;
}
}
static const luaL_Reg base_funcs[] = { /*
#if LUA_OPTIMIZE_MEMORY != 2 * Separate ROTables are used for the base functions and library ROTables, with
#undef MIN_OPT_LEVEL * the base functions ROTable declared below. The library ROTable is chained
#define MIN_OPT_LEVEL 0 * from this using its __index meta-method.
#include "lrodefs.h" *
LUA_BASELIB_FUNCLIST, * ESP builds use specific linker directives to marshal all the ROTable entries
#endif * for the library modules into a single ROTable in the PSECT ".lua_rotable".
{"__index", luaB_index}, * This is not practical on Posix builds using a standard GNU link, so the
{NULL, NULL} * 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) { ...@@ -659,18 +645,14 @@ static int luaB_corunning (lua_State *L) {
return 1; return 1;
} }
#undef MIN_OPT_LEVEL LROT_PUBLIC_BEGIN(co_funcs)
#define MIN_OPT_LEVEL 1 LROT_FUNCENTRY( create, luaB_cocreate )
#include "lrodefs.h" LROT_FUNCENTRY( resume, luaB_coresume )
const LUA_REG_TYPE co_funcs[] = { LROT_FUNCENTRY( running, luaB_corunning )
{LSTRKEY("create"), LFUNCVAL(luaB_cocreate)}, LROT_FUNCENTRY( status, luaB_costatus )
{LSTRKEY("resume"), LFUNCVAL(luaB_coresume)}, LROT_FUNCENTRY( wrap, luaB_cowrap )
{LSTRKEY("running"), LFUNCVAL(luaB_corunning)}, LROT_FUNCENTRY( yield, luaB_yield )
{LSTRKEY("status"), LFUNCVAL(luaB_costatus)}, LROT_END (co_funcs, NULL, 0)
{LSTRKEY("wrap"), LFUNCVAL(luaB_cowrap)},
{LSTRKEY("yield"), LFUNCVAL(luaB_yield)},
{LNILKEY, LNILVAL}
};
/* }====================================================== */ /* }====================================================== */
...@@ -682,20 +664,18 @@ static void auxopen (lua_State *L, const char *name, ...@@ -682,20 +664,18 @@ static void auxopen (lua_State *L, const char *name,
lua_setfield(L, -2, name); lua_setfield(L, -2, name);
} }
static void base_open (lua_State *L) { static void base_open (lua_State *L) {
/* set global _G */ /* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setglobal(L, "_G"); lua_setglobal(L, "_G");
/* open lib into global table */ /* open lib into global table */
luaL_register_light(L, "_G", base_funcs); luaL_register_light(L, "_G", &((luaL_Reg) {0}));
#if LUA_OPTIMIZE_MEMORY > 0 lua_pushrotable(L, LROT_TABLEREF(G_meta));
lua_pushvalue(L, -1); lua_setmetatable(L, LUA_GLOBALSINDEX);
lua_setmetatable(L, -2);
#else
lua_pushliteral(L, LUA_VERSION); lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
#endif
/* `ipairs' and `pairs' need auxliliary functions as upvalues */ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next); auxopen(L, "pairs", luaB_pairs, luaB_next);
...@@ -712,10 +692,5 @@ static void base_open (lua_State *L) { ...@@ -712,10 +692,5 @@ static void base_open (lua_State *L) {
LUALIB_API int luaopen_base (lua_State *L) { LUALIB_API int luaopen_base (lua_State *L) {
base_open(L); base_open(L);
#if LUA_OPTIMIZE_MEMORY == 0
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
#else
return 1; return 1;
#endif
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STDLIB #include <stdlib.h>
#include "lcode.h" #include "lcode.h"
#include "ldebug.h" #include "ldebug.h"
......
...@@ -10,12 +10,14 @@ ...@@ -10,12 +10,14 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STDIO #include <stdio.h>
#include C_HEADER_STDLIB #include <stdlib.h>
#include C_HEADER_STRING #include <string.h>
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lstring.h"
#include "lflash.h"
#include "lrotable.h" #include "lrotable.h"
#include "sdkconfig.h" #include "sdkconfig.h"
...@@ -25,6 +27,39 @@ static int db_getregistry (lua_State *L) { ...@@ -25,6 +27,39 @@ static int db_getregistry (lua_State *L) {
return 1; 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; i<tb->size; 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 #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL
static int db_getmetatable (lua_State *L) { static int db_getmetatable (lua_State *L) {
...@@ -384,33 +419,30 @@ static int db_errorfb (lua_State *L) { ...@@ -384,33 +419,30 @@ static int db_errorfb (lua_State *L) {
return 1; return 1;
} }
#undef MIN_OPT_LEVEL LROT_PUBLIC_BEGIN(dblib)
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE dblib[] = {
#ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL
#if defined(LUA_CROSS_COMPILER) #if defined(LUA_CROSS_COMPILER)
{LSTRKEY("debug"), LFUNCVAL(db_debug)}, LROT_FUNCENTRY( debug, db_debug )
#endif // defined(LUA_CROSS_COMPILER) #endif
{LSTRKEY("getfenv"), LFUNCVAL(db_getfenv)}, LROT_FUNCENTRY( getfenv, db_getfenv )
{LSTRKEY("gethook"), LFUNCVAL(db_gethook)}, LROT_FUNCENTRY( gethook, db_gethook )
{LSTRKEY("getinfo"), LFUNCVAL(db_getinfo)}, LROT_FUNCENTRY( getinfo, db_getinfo )
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)}, LROT_FUNCENTRY( getlocal, db_getlocal )
#endif #endif
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)}, LROT_FUNCENTRY( getregistry, db_getregistry )
LROT_FUNCENTRY( getstrings, db_getstrings )
#ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL #ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)}, LROT_FUNCENTRY( getmetatable, db_getmetatable )
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)}, LROT_FUNCENTRY( getupvalue, db_getupvalue )
{LSTRKEY("setfenv"), LFUNCVAL(db_setfenv)}, LROT_FUNCENTRY( setfenv, db_setfenv )
{LSTRKEY("sethook"), LFUNCVAL(db_sethook)}, LROT_FUNCENTRY( sethook, db_sethook )
{LSTRKEY("setlocal"), LFUNCVAL(db_setlocal)}, LROT_FUNCENTRY( setlocal, db_setlocal )
{LSTRKEY("setmetatable"), LFUNCVAL(db_setmetatable)}, LROT_FUNCENTRY( setmetatable, db_setmetatable )
{LSTRKEY("setupvalue"), LFUNCVAL(db_setupvalue)}, LROT_FUNCENTRY( setupvalue, db_setupvalue )
#endif #endif
{LSTRKEY("traceback"), LFUNCVAL(db_errorfb)}, LROT_FUNCENTRY( traceback, db_errorfb )
{LNILKEY, LNILVAL} LROT_END(dblib, NULL, 0)
};
LUALIB_API int luaopen_debug (lua_State *L) { LUALIB_API int luaopen_debug (lua_State *L) {
LREGISTER(L, LUA_DBLIBNAME, dblib); return 0;
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STRING #include <string.h>
#include "lapi.h" #include "lapi.h"
#include "lcode.h" #include "lcode.h"
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STRING #include <string.h>
#include "ldebug.h" #include "ldebug.h"
#include "ldo.h" #include "ldo.h"
...@@ -106,7 +106,7 @@ void luaD_throw (lua_State *L, int errcode) { ...@@ -106,7 +106,7 @@ void luaD_throw (lua_State *L, int errcode) {
lua_unlock(L); lua_unlock(L);
G(L)->panic(L); G(L)->panic(L);
} }
// c_exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} }
} }
...@@ -144,8 +144,11 @@ static void correctstack (lua_State *L, TValue *oldstack) { ...@@ -144,8 +144,11 @@ static void correctstack (lua_State *L, TValue *oldstack) {
void luaD_reallocstack (lua_State *L, int newsize) { void luaD_reallocstack (lua_State *L, int newsize) {
TValue *oldstack = L->stack; TValue *oldstack = L->stack;
int realsize = newsize + 1 + EXTRA_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); 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); 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->stacksize = realsize;
L->stack_last = L->stack+newsize; L->stack_last = L->stack+newsize;
correctstack(L, oldstack); correctstack(L, oldstack);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#define LUAC_CROSS_FILE #define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include C_HEADER_STRING #include <string.h>
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
...@@ -47,7 +47,7 @@ static void DumpChar(int y, DumpState* D) ...@@ -47,7 +47,7 @@ static void DumpChar(int y, DumpState* D)
static void Align4(DumpState *D) static void Align4(DumpState *D)
{ {
while(D->wrote&3) while(D->wrote&3 && D->status==0)
DumpChar(0,D); DumpChar(0,D);
} }
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
#include "legc.h" #include "legc.h"
#include "lstate.h" #include "lstate.h"
void legc_set_mode(lua_State *L, int mode, unsigned limit) { void legc_set_mode(lua_State *L, int mode, int limit) {
global_State *g = G(L); global_State *g = G(L);
g->egcmode = mode; g->egcmode = mode;
g->memlimit = limit; g->memlimit = limit;
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit #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 #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 #endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment