Commit dba57fa0 authored by Johny Mattsson's avatar Johny Mattsson
Browse files

Merge branch 'dev-esp32-idf4-lua53' into dev-esp32-idf4

parents 3a6961cc 8e5ce49d
......@@ -36,6 +36,7 @@
#define _NODEMCU_LNODEAUX_H_
#include "lua.h"
#include <stdbool.h>
// lua_ref_t represents a reference to a lua object in the registry
typedef int lua_ref_t;
......
#include "lpanic.h"
#include "lauxlib.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef LUA_CROSS_COMPILER
#include "esp_system.h"
/* defined in esp_system_internal.h */
void esp_reset_reason_set_hint(esp_reset_reason_t hint);
#endif
#ifndef LUA_CROSS_COMPILER
/*
* upper 28 bit have magic value 0xD1EC0DE0
* if paniclevel is valid (i.e. matches magic value)
* lower 4 bits have paniclevel:
* 0 = no panic occurred
* 1..15 = one..fifteen subsequent panic(s) occurred
*/
static __NOINIT_ATTR uint32_t l_rtc_panic_val;
void panic_clear_nvval() {
l_rtc_panic_val = 0xD1EC0DE0;
}
int panic_get_nvval() {
if ((l_rtc_panic_val & 0xfffffff0) == 0xD1EC0DE0) {
return (l_rtc_panic_val & 0xf);
}
panic_clear_nvval();
return 0;
}
#endif
int lpanic (lua_State *L) {
(void)L; /* to avoid warnings */
#ifndef LUA_CROSS_COMPILER
uint8_t paniclevel = panic_get_nvval();
if (paniclevel < 15) paniclevel++;
l_rtc_panic_val = 0xD1EC0DE0 | paniclevel;
#endif
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
lua_tostring(L, -1));
#ifndef LUA_CROSS_COMPILER
fflush(stdout);
/* call abort() directly - we don't want another reset cause to intervene */
esp_reset_reason_set_hint(ESP_RST_PANIC);
#endif
abort();
while (1) {}
return 0;
}
#ifndef _LUA_PANIC_H_
#define _LUA_PANIC_H_
#include "lua.h"
void panic_clear_nvval (void);
int panic_get_nvval (void);
int lpanic (lua_State *L);
#endif
// Lua EGC (Emergeny Garbage Collector) interface
#include "legc.h"
#include "lstate.h"
void legc_set_mode(lua_State *L, int mode, int limit) {
global_State *g = G(L);
g->egcmode = mode;
g->memlimit = limit;
}
// Lua EGC (Emergeny Garbage Collector) interface
#ifndef __LEGC_H__
#define __LEGC_H__
#include "lstate.h"
// EGC operations modes
#define EGC_NOT_ACTIVE 0 // EGC disabled
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
#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, int limit);
#endif
[sections:lua_libs]
entries:
.lua_libs
[sections:lua_libs_end_marker]
entries:
.lua_libs_end_marker
[sections:lua_rotable]
entries:
.lua_rotable
[sections:lua_rotable_end_marker]
entries:
.lua_rotable_end_marker
[scheme:lua_arrays]
entries:
lua_libs -> flash_rodata
lua_libs_end_marker -> flash_rodata
lua_rotable -> flash_rodata
lua_rotable_end_marker -> flash_rodata
# Important: don't change the alignments below without also updating the
# _Static_assert over in linit.c!
[mapping:lua]
archive: *
entries:
* (lua_arrays);
lua_libs -> flash_rodata KEEP() ALIGN(8) SURROUND(lua_libs_map),
lua_libs_end_marker -> flash_rodata KEEP(),
lua_rotable -> flash_rodata KEEP() ALIGN(8) SURROUND(lua_rotables_map),
lua_rotable_end_marker -> flash_rodata KEEP()
/* Read-only tables for Lua */
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
#include "lrotable.h"
#include "lauxlib.h"
#include "lstring.h"
#include "lobject.h"
#include "lapi.h"
#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
/*
* All keyed ROtable access passes through luaR_findentry(). ROTables
* are simply a list of <key><TValue value> 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))
static struct {
unsigned hash;
unsigned addr:24;
unsigned ndx:8;
} cache[LA_LINES][LA_SLOTS];
#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;
for (j = 0; j<LA_SLOTS; j++) {
if (cache[i][j].hash == hash &&
((size_t)rotable & 0xffffffu) == cache[i][j].addr) {
COUNT(0);
return cache[i][j].ndx;
}
}
COUNT(1);
return -1;
}
static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) {
int i = (hash)>>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;
static const ALIGNED_STRING metatablestr[] = "__metatable";
const char *strkey = key ? getstr(key) : metatablestr;
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));
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(ROTable *rotable) {
const TValue *res = luaR_findentry(rotable, NULL, NULL);
return res && ttisrotable(res) ? rvalue(res) : NULL;
}
static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos,
TValue *key, TValue *val) {
if (pentries[pos].key) {
/* Found an entry */
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, 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, rotable, 0, key, val);
else if (ttisstring(key)) {
/* Find the previous key again */
luaR_findentry(rotable, rawtsvalue(key), &keypos);
/* Advance to next key */
keypos ++;
luaR_next_helper(L, rotable, keypos, key, val);
}
}
/* Read-only tables for Lua */
#ifndef lrotable_h
#define lrotable_h
#include "lua.h"
#include "luaconf.h"
#include "lobject.h"
#include "llimits.h"
/* Macros one can use to define rotable entries */
#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}
#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
/* Type of a numeric key in a rotable */
typedef int luaR_numkey;
/* An entry in the read only table */
typedef struct luaR_entry {
const char *key;
const TValue value;
} luaR_entry;
/*
* 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 _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
......@@ -2,72 +2,54 @@ all: build
HOSTCC?=$(PYTHON) -m ziglang cc
# zig cc (0.8.0 at least) seems to get itself all confused with its cache
# when we're running a separate path for dependencies, so we skip them for
# now as for most people they're not needed anyway.
ifeq ($(findstring zig,$(HOSTCC)),zig)
WITHOUT_DEPS:=1
endif
ifeq ($V,)
Q:=@
endif
LUAC_CFLAGS:= -I$(COMPONENT_PATH)/../uzlib -I$(COMPONENT_PATH)/../lua -I$(BUILD_DIR_BASE)/config -I$(COMPONENT_PATH)/../base_nodemcu/include -O2 -g -Wall -Wextra
LUAC_LDFLAGS:= -ldl -lm
LUAC_OBJ_DIR:=$(LUAC_BUILD_DIR)/$(notdir $(LUA_PATH))
LUAC_DEFINES += -DLUA_CROSS_COMPILER -DLUA_USE_STDIO
ifneq ($(CONFIG_LUA_OPTIMIZE_DEBUG),)
LUAC_DEFINES += -DLUA_OPTIMIZE_DEBUG=$(CONFIG_LUA_OPTIMIZE_DEBUG)
endif
LUAC_CFLAGS:= \
-I$(LUAC_BUILD_DIR) \
-I$(LUA_PATH) \
-I$(LUA_PATH)/host \
-I$(LUA_PATH)/../common \
-I$(LUA_PATH)/../../uzlib \
-O2 -g -Wall -Wextra -Wno-sign-compare
vpath %.c $(COMPONENT_PATH) $(COMPONENT_PATH)/../lua $(COMPONENT_PATH)/../uzlib $(COMPONENT_PATH)/../base_nodemcu
LUAC_LDFLAGS:= -ldl -lm
LUAC_LUACSRC:= \
luac.c lflashimg.c loslib.c print.c liolib.c
LUAC_DEFINES += \
-DLUA_CROSS_COMPILER \
-DLUA_USE_HOST \
-DLUA_USE_STDIO \
LUAC_LUASRC:= $(addprefix $(COMPONENT_PATH)/../lua/, \
vpath %.c $(LUA_PATH)/host $(LUA_PATH) $(LUA_PATH)/../common $(LUA_PATH)/../../uzlib
LUA_SRCS:=\
luac.c lflashimg.c loslib.c print.c liolib.c \
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 \
lnodemcu.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/, \
linit.c lpanic.c \
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)
ifneq ($(WITHOUT_DEPS),1)
LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d)
endif
LUAC_OBJS:=$(LUA_SRCS:%.c=$(LUAC_OBJ_DIR)/%.o)
LUAC_CROSS:=$(LUAC_BUILD_DIR)/luac.cross
$(LUAC_BUILD_DIR):
$(LUAC_OBJ_DIR):
@mkdir -p "$@"
$(LUAC_BUILD_DIR)/%.o: %.c | $(LUAC_BUILD_DIR)
$(LUAC_OBJ_DIR)/%.o: %.c | $(LUAC_OBJ_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)
$(LUAC_OBJ_DIR)/%.d: SHELL=/bin/bash
$(LUAC_OBJ_DIR)/%.d: %.c | $(LUAC_OBJ_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" "$@"
$Qset -eo pipefail; $(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) -M "$<" | sed 's,\($*\.o\)[ :]*,$(LUAC_OBJ_DIR)/\1 $@ : ,g' > "$@.tmp"; mv "$@.tmp" "$@"
build: $(LUAC_DEPS) $(LUAC_CROSS)
......@@ -75,6 +57,12 @@ $(LUAC_CROSS): $(LUAC_OBJS)
@echo '[ link] $(notdir $@)'
$Q$(HOSTCC) $(LUAC_CFLAGS) $^ $(LUAC_LDFLAGS) -o "$@"
ifneq ($(MAKECMDGOALS),clean)
-include $(LUAC_DEPS)
# zig cc (0.8.0 at least) seems to get itself all confused with its cache
# when we're running a separate path for dependencies, so we skip them for
# now as for most people they're not needed anyway.
ifneq ($(findstring zig,$(HOSTCC)),zig)
LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d)
ifneq ($(MAKECMDGOALS),clean)
-include $(LUAC_DEPS)
endif
endif
......@@ -6,7 +6,6 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -109,10 +108,11 @@ static uint *flashAddrTag = flashImage + LUA_MAX_FLASH_SIZE;
#define setFlashAddrTag(v) flashAddrTag[_TW(v)] |= _TB(v)
#define getFlashAddrTag(v) ((flashAddrTag[_TW(v)]&_TB(v)) != 0)
#define fatal luac_fatal
#ifdef _MSC_VER
extern void __declspec( noreturn ) fatal( const char* message );
extern void __declspec( noreturn ) luac_fatal( const char* message );
#else
extern void __attribute__((noreturn)) fatal(const char* message);
extern void __attribute__((noreturn)) luac_fatal(const char* message);
#endif
#ifdef LOCAL_DEBUG
......@@ -188,10 +188,8 @@ static void scanProtoStrings(lua_State *L, const Proto* f) {
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))
......@@ -357,11 +355,7 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
}
/* 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.
......@@ -385,14 +379,10 @@ static void *functionToFlash(lua_State* L, const Proto* orig) {
f.k = cast(TValue *, flashCopy(L, f.sizek, "V", f.k));
f.code = cast(Instruction *, flashCopy(L, f.sizecode, "I", f.code));
#ifdef LUA_OPTIMIZE_DEBUG
if (f.packedlineinfo) {
TString *ts=luaS_new(L, cast(const char *,f.packedlineinfo));
f.packedlineinfo = cast(unsigned char *, resolveTString(L, ts)) + sizeof (FlashTS);
}
#else
f.lineinfo = cast(int *, flashCopy(L, f.sizelineinfo, "I", f.lineinfo));
#endif
f.locvars = cast(struct LocVar *, flashCopy(L, f.sizelocvars, "SII", f.locvars));
f.upvalues = cast(TString **, flashCopy(L, f.sizeupvalues, "S", f.upvalues));
return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f));
......@@ -401,10 +391,10 @@ static void *functionToFlash(lua_State* L, const Proto* orig) {
uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
void* data, int strip,
lu_int32 address, lu_int32 maxSize) {
(void)strip;
// parameter strip is ignored for now
(void)strip;
FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader)));
int status;
int i, status;
lua_newtable(L);
scanProtoStrings(L, main);
createROstrt(L, fh);
......@@ -416,7 +406,7 @@ uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
fatal ("The image is too large for specfied LFS size");
}
if (address) { /* in absolute mode convert addresses to mapped address */
for (uint i = 0 ; i < curOffset; i++)
for (i = 0 ; i < curOffset; i++)
if (getFlashAddrTag(i))
flashImage[i] = 4*flashImage[i] + address;
lua_unlock(L);
......@@ -434,7 +424,7 @@ uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
status = uzlib_compress (&oBuf, &oLen,
(const uint8_t *)flashImage, bmLen+fh->flash_size);
if (status != UZLIB_OK) {
fatal("Out of memory during image compression");
luac_fatal("Out of memory during image compression");
}
lua_unlock(L);
#if 0
......
......@@ -17,7 +17,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lnodemcu.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
......@@ -439,7 +439,10 @@ static int f_flush (lua_State *L) {
return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
LROT_PUBLIC_BEGIN(iolib)
LROT_TABLE(iolib);
LROT_BEGIN(iolib, NULL, LROT_MASK_GC_INDEX)
LROT_TABENTRY( __index, iolib )
LROT_FUNCENTRY( close, io_close )
LROT_FUNCENTRY( flush, io_flush )
LROT_FUNCENTRY( input, io_input )
......@@ -449,10 +452,14 @@ LROT_PUBLIC_BEGIN(iolib)
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_END(iolib, NULL, LROT_MASK_GC_INDEX)
LROT_BEGIN(flib)
LROT_TABLE(flib);
LROT_BEGIN(flib, NULL, LROT_MASK_GC_INDEX)
LROT_FUNCENTRY( __gc, io_gc )
LROT_TABENTRY( __index, flib )
LROT_FUNCENTRY( __tostring, io_tostring )
LROT_FUNCENTRY( close, io_close )
LROT_FUNCENTRY( flush, f_flush )
LROT_FUNCENTRY( lines, f_lines )
......@@ -460,9 +467,6 @@ LROT_BEGIN(flib)
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}};
......
......@@ -6,7 +6,6 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
......@@ -20,8 +19,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lnodemcu.h"
static int os_pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
......@@ -221,32 +219,26 @@ static int os_exit (lua_State *L) {
exit(luaL_optint(L, 1, EXIT_SUCCESS));
}
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrotable.h"
LROT_PUBLIC_BEGIN(oslib)
LROT_FUNCENTRY(clock, os_clock)
LROT_FUNCENTRY(date, os_date)
LROT_BEGIN(oslib, NULL, 0)
LROT_FUNCENTRY( clock, os_clock )
LROT_FUNCENTRY( date, os_date )
#if !defined LUA_NUMBER_INTEGRAL
LROT_FUNCENTRY(difftime, os_difftime)
LROT_FUNCENTRY( difftime, os_difftime )
#endif
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_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) {
(void)L;
//LREGISTER(L, LUA_OSLIBNAME, oslib); // <------------- ???
return 0;
return 1;
}
......@@ -5,15 +5,15 @@
*/
#define LUAC_CROSS_FILE
#define luac_c
#define LUA_CORE
#include "luac_cross.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define luac_c
#define LUA_CORE
#include "lua.h"
#include "lauxlib.h"
......@@ -42,11 +42,12 @@ static const char* execute; /* executed a Lua file */
static const char* progname=PROGNAME; /* actual program name */
static DumpTargetInfo target;
void fatal(const char* message)
void luac_fatal(const char* message)
{
fprintf(stderr,"%s: %s\n",progname,message);
exit(EXIT_FAILURE);
}
#define fatal(s) luac_fatal(s)
static void cannot(const char* what)
{
......@@ -280,8 +281,8 @@ static int pmain(lua_State* L)
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);
if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1));
lua_pushstring(L, execute);
if (lua_pcall(L, 1, 1, 0)) fatal(lua_tostring(L,-1));
if (!lua_isfunction(L, -1))
......
......@@ -6,7 +6,6 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include <ctype.h>
#include <stdio.h>
......
......@@ -6,11 +6,9 @@
#define lapi_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
//#include <assert.h>
#include <math.h>
#include <string.h>
#include "lapi.h"
......@@ -26,7 +24,6 @@
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
#include "lrotable.h"
#if 0
const char lua_ident[] =
......@@ -155,6 +152,16 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
*/
/*
** convert an acceptable stack index into an absolute index
*/
LUA_API int lua_absindex (lua_State *L, int idx) {
return (idx > 0 || idx <= LUA_REGISTRYINDEX)
? idx
: cast_int(L->top - L->base) - 1 + idx;
}
LUA_API int lua_gettop (lua_State *L) {
return cast_int(L->top - L->base);
}
......@@ -243,6 +250,12 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
return (o == luaO_nilobject) ? LUA_TNONE : ttnov(o);
}
LUA_API int lua_fulltype (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
}
......@@ -250,7 +263,7 @@ LUA_API int lua_type (lua_State *L, int idx) {
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
return (t == LUA_TNONE || t >= LUA_NUMTAGS) ? "no value" : luaT_typenames[t];
}
......@@ -287,32 +300,25 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
}
LUA_API int lua_equal (lua_State *L, int index1, int index2) {
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
StkId o1, o2;
int i;
int i = 0;
lua_lock(L); /* may call tag method */
o1 = index2adr(L, index1);
o2 = index2adr(L, index2);
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
lua_unlock(L);
return i;
}
LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
StkId o1, o2;
int i;
lua_lock(L); /* may call tag method */
o1 = index2adr(L, index1);
o2 = index2adr(L, index2);
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
: luaV_lessthan(L, o1, o2);
if (o1 != luaO_nilobject && o2 != luaO_nilobject) {
switch (op) {
case LUA_OPEQ: i = luaV_equalval(L, o1, o2); break;
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
default: api_check(L, 0);
}
}
lua_unlock(L);
return i;
}
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
TValue n;
const TValue *o = index2adr(L, idx);
......@@ -363,11 +369,10 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
LUA_API size_t lua_objlen (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
switch (ttype(o)) {
switch (ttnov(o)) {
case LUA_TSTRING: return tsvalue(o)->len;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
case LUA_TROTABLE: return luaH_getn_ro(rvalue(o));
case LUA_TNUMBER: {
size_t l;
lua_lock(L); /* `luaV_tostring' may create a new string */
......@@ -405,16 +410,14 @@ LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
LUA_API const void *lua_topointer (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
switch (ttype(o)) {
case LUA_TTABLE: return hvalue(o);
case LUA_TTABLE:
case LUA_TROTABLE:
return hvalue(o);
case LUA_TFUNCTION: return clvalue(o);
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
return lua_touserdata(L, idx);
case LUA_TROTABLE:
return rvalue(o);
case LUA_TLIGHTFUNCTION:
return fvalue(o);
case LUA_TUSERDATA: return lua_touserdata(L, idx);
case LUA_TLIGHTUSERDATA: return pvalue(o);
case LUA_TLIGHTFUNCTION: return fvalue(o);
default: return NULL;
}
}
......@@ -492,8 +495,12 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
Closure *cl;
lua_lock(L);
if (n == 0) {
setfvalue(L->top, fn);
api_incr_top(L);
} else {
Closure *cl;
luaC_checkGC(L);
api_checknelems(L, n);
cl = luaF_newCclosure(L, n, getcurrenv(L));
......@@ -504,6 +511,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
setclvalue(L, L->top, cl);
lua_assert(iswhite(obj2gco(cl)));
api_incr_top(L);
}
lua_unlock(L);
}
......@@ -523,16 +531,10 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
lua_unlock(L);
}
LUA_API void lua_pushrotable (lua_State *L, void *p) {
lua_lock(L);
setrvalue(L->top, p);
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushlightfunction(lua_State *L, void *p) {
LUA_API void lua_pushrotable (lua_State *L, const ROTable *t) {
lua_lock(L);
setfvalue(L->top, p);
sethvalue(L, L->top, cast(ROTable *,t));
api_incr_top(L);
lua_unlock(L);
}
......@@ -553,17 +555,17 @@ LUA_API int lua_pushthread (lua_State *L) {
*/
LUA_API void lua_gettable (lua_State *L, int idx) {
LUA_API int lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2adr(L, idx);
api_checkvalidindex(L, t);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
StkId t;
TValue key;
lua_lock(L);
......@@ -575,29 +577,58 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
luaV_gettable(L, t, &key, L->top);
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_geti (lua_State *L, int idx, int n) {
StkId t;
TValue key;
lua_lock(L);
t = index2adr(L, idx);
api_checkvalidindex(L, t);
fixedstack(L);
setnvalue(&key, n);
unfixedstack(L);
luaV_gettable(L, t, &key, L->top);
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API void lua_rawget (lua_State *L, int idx) {
LUA_API int lua_rawget (lua_State *L, int idx) {
StkId t;
const TValue *res;
lua_lock(L);
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);
api_check(L, ttistable(t));
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
LUA_API int lua_rawgeti (lua_State *L, int idx, int n) {
StkId o;
lua_lock(L);
o = index2adr(L, idx);
api_check(L, ttistable(o) || ttisrotable(o));
setobj2s(L, L->top, ttistable(o) ? luaH_getnum(hvalue(o), n) : luaH_getnum_ro(rvalue(o), n))
api_check(L, ttistable(o));
setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
StkId t;
TValue k;
lua_lock(L);
t = index2adr(L, idx);
api_check(L, ttistable(t));
setpvalue(&k, cast(void *, p));
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
......@@ -616,26 +647,20 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
int res;
lua_lock(L);
obj = index2adr(L, objindex);
switch (ttype(obj)) {
switch (ttnov(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj)->metatable;
break;
case LUA_TROTABLE:
mt = (Table*)luaR_getmeta(rvalue(obj));
break;
default:
mt = G(L)->mt[ttype(obj)];
mt = G(L)->mt[ttnov(obj)];
break;
}
if (mt == NULL)
res = 0;
else {
if(luaR_isrotable(mt))
setrvalue(L->top, mt)
else
sethvalue(L, L->top, mt)
api_incr_top(L);
res = 1;
......@@ -730,40 +755,54 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
}
LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
StkId o;
TValue k;
lua_lock(L);
api_checknelems(L, 1);
o = index2adr(L, idx);
api_check(L, ttistable(o));
fixedstack(L);
setpvalue(&k, cast(void *, p))
setobj2t(L, luaH_set(L, hvalue(o), &k), L->top-1);
unfixedstack(L);
luaC_barriert(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
TValue *obj;
Table *mt;
int isrometa = 0;
lua_lock(L);
api_checknelems(L, 1);
obj = index2adr(L, objindex);
api_checkvalidindex(L, obj);
if (ttisnil(L->top - 1))
if (ttisnil(L->top - 1)) {
mt = NULL;
else {
api_check(L, ttistable(L->top - 1) || ttisrotable(L->top - 1));
if (ttistable(L->top - 1))
} else {
api_check(L, ttistable(L->top - 1));
mt = hvalue(L->top - 1);
else {
mt = (Table*)rvalue(L->top - 1);
isrometa = 1;
}
}
switch (ttype(obj)) {
switch (ttype(obj)) { /* use basetype to retain subtypes*/
case LUA_TTABLE: {
hvalue(obj)->metatable = mt;
if (mt && !isrometa)
if (mt && !isrotable(mt))
luaC_objbarriert(L, hvalue(obj), mt);
break;
}
case LUA_TUSERDATA: {
uvalue(obj)->metatable = mt;
if (mt && !isrometa)
if (mt && !isrotable(mt))
luaC_objbarrier(L, rawuvalue(obj), mt);
break;
}
case LUA_TISROTABLE: { /* Ignore any changes to a ROTable MT */
break;
}
default: {
G(L)->mt[ttype(obj)] = mt;
G(L)->mt[ttnov(obj)] = mt;
break;
}
}
......@@ -914,14 +953,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
}
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int stripping) {
int status;
TValue *o;
lua_lock(L);
api_checknelems(L, 1);
o = L->top - 1;
if (isLfunction(o))
status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
status = luaU_dump(L, clvalue(o)->l.p, writer, data, stripping);
else
status = 1;
lua_unlock(L);
......@@ -929,6 +968,30 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
}
LUA_API int lua_stripdebug (lua_State *L, int stripping){
TValue *o = L->top - 1;
Proto *p = NULL;
int res = -1;
lua_lock(L);
api_checknelems(L, 1);
if (isLfunction(o)) {
p = clvalue(o)->l.p;
if (p && !isLFSobject(p) && (unsigned) stripping < 3 ) {
// found a valid proto to strip
res = luaG_stripdebug(L, p, stripping, 1);
}
} else if (ttisnil(L->top - 1)) {
// get or set the default strip level
if ((unsigned) stripping < 3)
G(L)->stripdefault = stripping;
res = G(L)->stripdefault;
}
L->top--;
lua_unlock(L);
return res;
}
LUA_API int lua_status (lua_State *L) {
return L->status;
}
......@@ -1039,8 +1102,8 @@ LUA_API int lua_next (lua_State *L, int idx) {
int more;
lua_lock(L);
t = index2adr(L, idx);
api_check(L, ttistable(t) || ttisrotable(t));
more = ttistable(t) ? luaH_next(L, hvalue(t), L->top - 1) : luaH_next_ro(L, rvalue(t), L->top - 1);
api_check(L, ttistable(t));
more = luaH_next(L, hvalue(t), L->top - 1);
if (more) {
api_incr_top(L);
}
......@@ -1149,3 +1212,15 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
return name;
}
LUA_API void lua_setegcmode ( lua_State *L, int mode, int limit) {
G(L)->egcmode = mode;
G(L)->memlimit = limit;
}
LUA_API void lua_getegcinfo (lua_State *L, int *totals) {
if (totals) {
totals[0] = G(L)->totalbytes;
totals[1] = G(L)->estimate;
}
}
......@@ -4,20 +4,16 @@
** See Copyright Notice in lua.h
*/
#define LUAC_CROSS_FILE
#include "lua.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#ifndef LUA_CROSS_COMPILER
#include "esp_system.h"
#include "vfs.h"
/* defined in esp_system_internal.h */
void esp_reset_reason_set_hint(esp_reset_reason_t hint);
#else
#endif
/* This file uses only the official API of Lua.
......@@ -27,14 +23,14 @@ void esp_reset_reason_set_hint(esp_reset_reason_t hint);
#define lauxlib_c
#define LUA_LIB
#include "lrotable.h"
#include "lnodemcu.h"
#include "lauxlib.h"
#include "lgc.h"
#include "ldo.h"
#include "lobject.h"
#include "lstate.h"
#include "legc.h"
#include "lpanic.h"
#define FREELIST_REF 0 /* free list of references */
......@@ -277,7 +273,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
return 1;
}
LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, void *p) {
LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, const ROTable *p) {
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
if (!lua_isnil(L, -1)) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
......@@ -288,21 +284,25 @@ LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, void *p) {
return 1;
}
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
void *p = lua_touserdata(L, ud);
if (p != NULL) { /* value is a userdata? */
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
if (!lua_rawequal(L, -1, -2)) /* not the same? */
p = NULL; /* value is a userdata with wrong metatable */
lua_pop(L, 2); /* remove both metatables */
return p;
}
}
}
luaL_typerror(L, ud, tname); /* else error */
return NULL; /* to avoid warnings */
return NULL; /* value is not a userdata with a metatable */
}
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
void *p = luaL_testudata(L, ud, tname);
if (p == NULL) luaL_typerror(L, ud, tname);
return p;
}
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
if (!lua_checkstack(L, space))
......@@ -315,22 +315,6 @@ LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
tag_error(L, narg, t);
}
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);
}
}
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);
}
}
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
if (lua_type(L, narg) == LUA_TNONE)
......@@ -449,7 +433,7 @@ LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
for (i=0; i<nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup);
if (ftype == LUA_USELIGHTFUNCTIONS)
lua_pushlightfunction(L, l->func);
lua_pushcfunction(L, l->func);
else
lua_pushcclosure(L, l->func, nup);
lua_setfield(L, -(nup+2), l->name);
......@@ -561,7 +545,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
lua_pushvalue(L, -2);
lua_settable(L, -4); /* set new table into field */
}
else if (!lua_istable(L, -1) && !lua_isrotable(L, -1)) { /* field has a non-table value? */
else if (!lua_istable(L, -1)) { /* field has a non-table value? */
lua_pop(L, 2); /* remove table and value */
return fname; /* return problematic part of the name */
}
......@@ -703,6 +687,26 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
}
LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref) {
int reft;
/*
* If the ref is positive and the entry in table t exists then
* overwrite the value otherwise fall through to luaL_ref()
*/
if (ref) {
if (*ref >= 0) {
t = abs_index(L, t);
lua_rawgeti(L, t, *ref);
reft = lua_type(L, -1);
lua_pop(L, 1);
if (reft != LUA_TNIL) {
lua_rawseti(L, t, *ref);
return;
}
}
*ref = luaL_ref(L, t);
}
}
/*
** {======================================================
......@@ -710,14 +714,33 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
** =======================================================
*/
#ifdef LUA_CROSS_COMPILER
typedef struct LoadF {
int extraline;
#ifdef LUA_CROSS_COMPILER
FILE *f;
#else
int f;
#endif
char buff[LUAL_BUFFERSIZE];
} LoadF;
#ifdef LUA_CROSS_COMPILER
# define freopen_bin(f,fn) freopen(f,"rb",fn)
# define read_buff(b,f) fread(b, 1, sizeof (b), f)
#else
# define strerror(n) ""
#undef feof
# define feof(f) vfs_eof(f)
#undef fopen
# define fopen(f, m) vfs_open(f, m)
# define freopen_bin(fn,f) ((void) vfs_close(f), vfs_open(fn, "r"))
#undef getc
# define getc(f) vfs_getc(f)
#undef ungetc
# define ungetc(c,f) vfs_ungetc(c, f)
# define read_buff(b,f) vfs_read(f, b, sizeof (b))
#endif
static const char *getF (lua_State *L, void *ud, size_t *size) {
LoadF *lf = (LoadF *)ud;
......@@ -728,7 +751,7 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
return "\n";
}
if (feof(lf->f)) return NULL;
*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
*size = read_buff(lf->buff, lf->f);
return (*size > 0) ? lf->buff : NULL;
}
......@@ -748,14 +771,19 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
lf.extraline = 0;
if (filename == NULL) {
#ifdef LUA_CROSS_COMPILER
lua_pushliteral(L, "=stdin");
lf.f = stdin;
#else
return luaL_error(L, "filename is NULL");
#endif
}
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
if (lf.f == NULL) return errfile(L, "open", fnameindex);
if (!lf.f) return errfile(L, "open", fnameindex);
}
c = getc(lf.f);
if (c == '#') { /* Unix exec. file? */
......@@ -764,8 +792,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
if (c == '\n') c = getc(lf.f);
}
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
lf.f = freopen_bin(filename, lf.f); /* reopen in binary mode */
if (!lf.f) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
......@@ -773,95 +801,21 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
}
ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
#ifdef LUA_CROSS_COMPILER
readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
return status;
}
#else
#include <fcntl.h>
typedef struct LoadFSF {
int extraline;
int f;
char buff[LUAL_BUFFERSIZE];
} LoadFSF;
static const char *getFSF (lua_State *L, void *ud, size_t *size) {
LoadFSF *lf = (LoadFSF *)ud;
(void)L;
if (L == NULL && size == NULL) // Direct mode check
return NULL;
if (lf->extraline) {
lf->extraline = 0;
*size = 1;
return "\n";
}
if (vfs_eof(lf->f)) return NULL;
*size = vfs_read(lf->f, lf->buff, sizeof(lf->buff));
return (*size > 0) ? lf->buff : NULL;
}
static int errfsfile (lua_State *L, const char *what, int fnameindex) {
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s", what, filename);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
LoadFSF lf;
int status;
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
lf.extraline = 0;
if (filename == NULL) {
return luaL_error(L, "filename is NULL");
}
else {
lua_pushfstring(L, "@%s", filename);
lf.f = vfs_open(filename, "r");
if (!lf.f) return errfsfile(L, "open", fnameindex);
}
// 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)) != VFS_EOF && c != '\n') ; /* skip first line */
if (c == '\n') c = vfs_getc(lf.f);
}
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
vfs_close(lf.f);
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)) != VFS_EOF && c != LUA_SIGNATURE[0])
;
lf.extraline = 0;
}
vfs_ungetc(c, lf.f);
status = lua_load(L, getFSF, &lf, lua_tostring(L, -1));
(void) readstatus;
if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
#endif
lua_remove(L, fnameindex);
return status;
}
#endif
typedef struct LoadS {
const char *s;
......@@ -959,56 +913,11 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
#endif
}
#ifndef LUA_CROSS_COMPILER
/*
* upper 28 bit have magic value 0xD1EC0DE0
* if paniclevel is valid (i.e. matches magic value)
* lower 4 bits have paniclevel:
* 0 = no panic occurred
* 1..15 = one..fifteen subsequent panic(s) occurred
*/
static __NOINIT_ATTR uint32_t l_rtc_panic_val;
int panic_get_nvval() {
if ((l_rtc_panic_val & 0xfffffff0) == 0xD1EC0DE0) {
return (l_rtc_panic_val & 0xf);
}
panic_clear_nvval();
return 0;
}
void panic_clear_nvval() {
l_rtc_panic_val = 0xD1EC0DE0;
}
#endif
static int panic (lua_State *L) {
(void)L; /* to avoid warnings */
#ifndef LUA_CROSS_COMPILER
uint8_t paniclevel = panic_get_nvval();
if (paniclevel < 15) paniclevel++;
l_rtc_panic_val = 0xD1EC0DE0 | paniclevel;
#endif
#if defined(LUA_USE_STDIO)
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
lua_tostring(L, -1));
#else
luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
lua_tostring(L, -1));
#endif
#ifndef LUA_CROSS_COMPILER
/* call abort() directly - we don't want another reset cause to intervene */
esp_reset_reason_set_hint(ESP_RST_PANIC);
abort();
#endif
while (1) {}
return 0;
}
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
lua_setallocf(L, l_alloc, L); /* allocator need lua_State. */
if (L) lua_atpanic(L, &panic);
if (L) lua_atpanic(L, lpanic);
return L;
}
......@@ -8,12 +8,13 @@
#ifndef lauxlib_h
#define lauxlib_h
#include "lua.h"
#ifdef LUA_LIB
#include "lnodemcu.h"
#endif
#include <stdio.h>
#if defined(LUA_COMPAT_GETN)
LUALIB_API int (luaL_getn) (lua_State *L, int t);
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
......@@ -62,11 +63,10 @@ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
LUALIB_API void (luaL_checkanyfunction) (lua_State *L, int narg);
LUALIB_API void (luaL_checkanytable) (lua_State *L, int narg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, void *p);
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, const ROTable *p);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
......@@ -77,12 +77,11 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
#define luaL_unref2(l,t,r) do {luaL_unref(L, (t), (r)); r = LUA_NOREF;} while (0)
LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref);
#ifdef LUA_CROSS_COMPILER
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
#else
LUALIB_API int (luaL_loadfsfile) (lua_State *L, const char *filename);
#endif
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
const char *name);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
......@@ -112,7 +111,12 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#define luaL_optunsigned(L,a,d) ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
#define luaL_checktable(L,n) luaL_checktype(L, (n), LUA_TTABLE);
#define luaL_checkfunction(L,n) luaL_checktype(L, (n), LUA_TFUNCTION);
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
......@@ -121,7 +125,7 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#else
#define luaL_dofile(L, fn) \
(luaL_loadfsfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#endif
#define luaL_dostring(L, s) \
......@@ -165,6 +169,18 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
/* }====================================================== */
LUALIB_API int (luaL_pushlfsmodules) (lua_State *L);
LUALIB_API int (luaL_pushlfsmodule) (lua_State *L);
LUALIB_API int (luaL_pushlfsdts) (lua_State *L);
LUALIB_API void (luaL_lfsreload) (lua_State *L);
LUALIB_API int (luaL_pcallx) (lua_State *L, int narg, int nres);
LUALIB_API int (luaL_posttask) ( lua_State* L, int prio );
#define LUA_TASK_LOW 0
#define LUA_TASK_MEDIUM 1
#define LUA_TASK_HIGH 2
/* }====================================================== */
/* compatibility with ref system */
......@@ -184,7 +200,3 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
#endif
#ifndef LUA_CROSS_COMPILER
int panic_get_nvval();
void panic_clear_nvval();
#endif
......@@ -8,17 +8,14 @@
#define lbaselib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
/*
......@@ -27,6 +24,10 @@
** model but changing `fputs' to put the strings at a proper place
** (a console window or a log file, for instance).
*/
#ifdef LUA_CROSS_COMPILER
#undef puts
#define puts(s) printf("%s",s)
#endif
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
......@@ -40,20 +41,11 @@ static int luaB_print (lua_State *L) {
if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print"));
#if defined(LUA_USE_STDIO)
if (i>1) fputs("\t", stdout);
fputs(s, stdout);
#else
if (i>1) luai_writestring("\t", 1);
luai_writestring(s, strlen(s));
#endif
if (i>1) puts("\t");
puts(s);
lua_pop(L, 1); /* pop result */
}
#if defined(LUA_USE_STDIO)
fputs("\n", stdout);
#else
luai_writeline();
#endif
puts("\n");
return 0;
}
......@@ -112,7 +104,7 @@ static int luaB_getmetatable (lua_State *L) {
static int luaB_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE || t == LUA_TROTABLE, 2,
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
if (luaL_getmetafield(L, 1, "__metatable"))
luaL_error(L, "cannot change a protected metatable");
......@@ -175,7 +167,7 @@ static int luaB_rawequal (lua_State *L) {
static int luaB_rawget (lua_State *L) {
luaL_checkanytable(L, 1);
luaL_checktable(L, 1);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_rawget(L, 1);
......@@ -183,7 +175,7 @@ static int luaB_rawget (lua_State *L) {
}
static int luaB_rawset (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktable(L, 1);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_settop(L, 3);
......@@ -233,7 +225,7 @@ static int luaB_type (lua_State *L) {
static int luaB_next (lua_State *L) {
luaL_checkanytable(L, 1);
luaL_checktable(L, 1);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
return 2;
......@@ -245,7 +237,7 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_checkanytable(L, 1);
luaL_checktable(L, 1);
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
......@@ -255,7 +247,7 @@ static int luaB_pairs (lua_State *L) {
static int ipairsaux (lua_State *L) {
int i = luaL_checkint(L, 2);
luaL_checkanytable(L, 1);
luaL_checktable(L, 1);
i++; /* next value */
lua_pushinteger(L, i);
lua_rawgeti(L, 1, i);
......@@ -264,7 +256,7 @@ static int ipairsaux (lua_State *L) {
static int luaB_ipairs (lua_State *L) {
luaL_checkanytable(L, 1);
luaL_checktable(L, 1);
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushinteger(L, 0); /* and initial value */
......@@ -296,7 +288,7 @@ static int luaB_loadfile (lua_State *L) {
#ifdef LUA_CROSS_COMPILER
return load_aux(L, luaL_loadfile(L, fname));
#else
return load_aux(L, luaL_loadfsfile(L, fname));
return load_aux(L, luaL_loadfile(L, fname));
#endif
}
......@@ -343,7 +335,7 @@ static int luaB_dofile (lua_State *L) {
#ifdef LUA_CROSS_COMPILER
if (luaL_loadfile(L, fname) != 0) lua_error(L);
#else
if (luaL_loadfsfile(L, fname) != 0) lua_error(L);
if (luaL_loadfile(L, fname) != 0) lua_error(L);
#endif
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L) - n;
......@@ -462,29 +454,24 @@ static int luaB_newproxy (lua_State *L) {
return 1;
}
#include "lrotable.h"
LROT_EXTERN(lua_rotable_base);
/*
* 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)
** ESP builds use specific linker directives to marshal all the ROTable entries
** for the library modules including the base library into an entry vector in
** the PSECT ".lua_rotable" including the base library entries; this is bound
** into a ROTable in linit.c which then hooked into the __index metaentry for
** _G so that base library and ROM tables are directly resolved through _G.
**
** The host-based luac.cross builds which must use a standard GNU link or
** MSVC so this linker-specfic assembly approach can't be used. In this case
** luaopen_base returns a base_func ROTable so a two cascade resolution. See
** description in init.c for further details.
*/
#ifdef LUA_CROSS_COMPILER
LROT_BEGIN(base_func, NULL, 0)
#else
LROT_ENTRIES_IN_SECTION(base_func, rotable)
#endif
LROT_FUNCENTRY(assert, luaB_assert)
LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage)
LROT_FUNCENTRY(dofile, luaB_dofile)
......@@ -509,13 +496,11 @@ LROT_PUBLIC_BEGIN(base_func)
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)
#ifdef LUA_CROSS_COMPILER
LROT_END(base_func, NULL, 0)
#else
LROT_BREAK(base_func)
#endif
/*
** {======================================================
......@@ -645,14 +630,14 @@ static int luaB_corunning (lua_State *L) {
return 1;
}
LROT_PUBLIC_BEGIN(co_funcs)
LROT_BEGIN(co_funcs, NULL, 0)
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)
LROT_END(co_funcs, NULL, 0)
/* }====================================================== */
......@@ -661,19 +646,13 @@ static void auxopen (lua_State *L, const char *name,
lua_CFunction f, lua_CFunction u) {
lua_pushcfunction(L, u);
lua_pushcclosure(L, f, 1);
lua_setfield(L, -2, name);
lua_setglobal(L, name);
}
static void base_open (lua_State *L) {
/* set global _G */
extern LROT_TABLE(rotables);
LUALIB_API int luaopen_base (lua_State *L) {
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setglobal(L, "_G");
/* open lib into global table */
luaL_register_light(L, "_G", &((luaL_Reg) {0}));
lua_pushrotable(L, LROT_TABLEREF(G_meta));
lua_setmetatable(L, LUA_GLOBALSINDEX);
lua_settable(L, LUA_GLOBALSINDEX); /* set global _G */
lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
......@@ -681,16 +660,15 @@ static void base_open (lua_State *L) {
auxopen(L, "pairs", luaB_pairs, luaB_next);
/* `newproxy' needs a weaktable as upvalue */
lua_createtable(L, 0, 1); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushcclosure(L, luaB_newproxy, 1); /* Upval is table w */
lua_setglobal(L, "newproxy"); /* set global `newproxy' */
}
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
return 1;
lua_pushrotable(L, LROT_TABLEREF(rotables));
lua_setglobal(L, "__index");
lua_pushvalue(L, LUA_GLOBALSINDEX); /* _G is its own metatable */
lua_setmetatable(L, LUA_GLOBALSINDEX);
return 0;
}
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