diff --git a/.gdbinit b/.gdbinit index 4d31c1df..8e1afba5 100644 --- a/.gdbinit +++ b/.gdbinit @@ -5,6 +5,15 @@ # single hardware breakpoint which can be used as an hb or a wa. You have to # remember to delete the previous one, so the br macro does this for you. # +file app/.output/eagle/debug/image/eagle.app.v6.out +#set remotedebug 1 +set remotelogfile gdb_rsp_logfile.txt +set serial baud 115200 +set remote hardware-breakpoint-limit 1 +set remote hardware-watchpoint-limit 1 +#set debug xtensa 4 +target remote /dev/ttyUSB0 + set confirm off set print null-stop define br @@ -13,10 +22,30 @@ define br end set pagination off +define prTS + set $o = &(((TString *)($arg0))->tsv) + printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked + printf "String: hash = 0x%08x, len = %u : %s\n", $o->hash, $o->len, (char *)(&$o[1]) +end +define prTnodes + set $o = (Table *)($arg0) + set $n = 1<<($o->lsizenode) + set $i = 0 + while $i < $n + set $nd = ($o->node) + $i + if $nd->i_key.nk.tt && $nd->i_val.tt + if $nd->i_key.nk.tt == 6 + printf "%4u: %s %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt else + printf "%4u: %2i %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt + end + end + set $i = $i +1 + end +end define prTV if $arg0 - set $type = $arg0.tt - set $val = $arg0.value + set $type = ($arg0).tt + set $val = ($arg0).value if $type == 0 # NIL @@ -24,34 +53,33 @@ define prTV end if $type == 1 # Boolean - printf "Boolean: %u\n", $val->n + printf "Boolean: %u\n", $val.n end if $type == 2 # ROTable - printf "ROTable: %p\n", $val->p + printf "ROTable: %p\n", $val.p end if $type == 3 # Light Function - printf "Light Func: %p\n",p $arg $val->p + printf "Light Func: %p\n", $val.p end if $type == 4 # Light User Data - printf "Light Udata: %p\n", $val->pend + printf "Light Udata: %p\n", $val.p end if $type == 5 # Number - printf "Boolean: %u\n", $val->n + printf "Number: %u\n", $val.n end if $type == 6 - # TString - set $o = &($val.gc->ts.tsv) - printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked - printf "String: hash = 0x%08x, len = %u : %s\n", $o->hash, $o->len, (char *)($ts+1) + prTS $arg0 end if $type == 7 # Table - __printComHdr $arg0 - set $ts = (TString *)$val->p + set $o = &($val->gc.h) + printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked + printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->nodes + printf "Arry: %4i %p\n", $o->sizearray, $o->array end if $type == 8 # Function @@ -106,6 +134,25 @@ define dumpRAMstrt dumpstrt &(L->l_G->strt) end +define dumpROstrt + dumpstrt &(L->l_G->ROstrt) +end + +define graylist + set $n = $arg0 + while $n + printf "%p %2u %02X\n",$n, $n->gch.tt, $n->gch.marked + set $n=$n->gch.next + end +end + +define prPC + printf "Excuting instruction %i: %08x\n", (pc - cl->p->code)+1-1, i +end + +define prT + print *(Table*)($arg0) +end set history save on set history size 1000 diff --git a/Makefile b/Makefile index 840f7a3b..81d89252 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ ifdef DEBUG CCFLAGS += -ggdb -O0 LDFLAGS += -ggdb else - CCFLAGS += -Os + CCFLAGS += -O2 endif ############################################################# diff --git a/app/Makefile b/app/Makefile index c2250ead..a590f741 100644 --- a/app/Makefile +++ b/app/Makefile @@ -20,93 +20,64 @@ FLAVOR = debug ifndef PDIR # { GEN_IMAGES= eagle.app.v6.out GEN_BINS= eagle.app.v6.bin -SPECIAL_MKTARGETS=$(APP_MKTARGETS) +OPT_MKTARGETS := coap crypto dht http mqtt pcm sjson sqlite3 tsl2561 u8glib ucglib websocket +SEL_MKTARGETS := $(shell $(CC) -E -dM include/user_modules.h | sed -n '/^\#define LUA_USE_MODULES_/{s/.\{24\}\(.*\)/\L\1/; p}') +OPT_SEL_MKTARGETS := $(foreach tgt,$(OPT_MKTARGETS),$(findstring $(tgt), $(SEL_MKTARGETS))) +OPT_SEL_COMPONENTS := $(foreach tgt,$(OPT_SEL_MKTARGETS),$(tgt)/lib$(tgt).a) +SPECIAL_MKTARGETS :=$(APP_MKTARGETS) + SUBDIRS= \ user \ driver \ - pcm \ mbedtls \ platform \ libc \ lua \ lwip \ - coap \ - mqtt \ task \ - u8glib \ - ucglib \ smart \ modules \ spiffs \ - crypto \ - dhtlib \ - tsl2561 \ net \ - http \ fatfs \ esp-gdbstub \ - websocket \ swTimer \ misc \ pm \ - sjson \ - sqlite3 \ - + $(OPT_SEL_MKTARGETS) endif # } PDIR APPDIR = . LDDIR = ../ld -CCFLAGS += -Os - TARGET_LDFLAGS = \ -nostdlib \ -Wl,-EL \ --longcalls \ --text-section-literals -ifeq ($(FLAVOR),debug) - TARGET_LDFLAGS += -g -Os -endif - -ifeq ($(FLAVOR),release) - TARGET_LDFLAGS += -Os -endif - LD_FILE = $(LDDIR)/nodemcu.ld COMPONENTS_eagle.app.v6 = \ user/libuser.a \ driver/libdriver.a \ - pcm/pcm.a \ platform/libplatform.a \ task/libtask.a \ libc/liblibc.a \ lua/liblua.a \ lwip/liblwip.a \ - coap/coap.a \ - mqtt/mqtt.a \ - u8glib/u8glib.a \ - ucglib/ucglib.a \ smart/smart.a \ spiffs/spiffs.a \ fatfs/libfatfs.a \ - crypto/libcrypto.a \ - dhtlib/libdhtlib.a \ - tsl2561/tsl2561lib.a \ - http/libhttp.a \ pm/libpm.a \ - websocket/libwebsocket.a \ esp-gdbstub/libgdbstub.a \ net/libnodemcu_net.a \ mbedtls/libmbedtls.a \ modules/libmodules.a \ swTimer/libswtimer.a \ misc/libmisc.a \ - sjson/libsjson.a \ - sqlite3/libsqlite3.a \ - + $(OPT_SEL_COMPONENTS) # Inspect the modules library and work out which modules need to be linked. # For each enabled module, a symbol name of the form XYZ_module_selected is @@ -194,6 +165,5 @@ INCLUDES += -I ./ PDIR := ../$(PDIR) sinclude $(PDIR)Makefile - .PHONY: FORCE FORCE: diff --git a/app/coap/Makefile b/app/coap/Makefile index 3947069c..a0c55e0d 100644 --- a/app/coap/Makefile +++ b/app/coap/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = coap.a +GEN_LIBS = libcoap.a endif ############################################################# diff --git a/app/dhtlib/Makefile b/app/dht/Makefile similarity index 98% rename from app/dhtlib/Makefile rename to app/dht/Makefile index 9ef52484..9c302445 100644 --- a/app/dhtlib/Makefile +++ b/app/dht/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = libdhtlib.a +GEN_LIBS = libdht.a endif diff --git a/app/dhtlib/dht.c b/app/dht/dht.c similarity index 100% rename from app/dhtlib/dht.c rename to app/dht/dht.c diff --git a/app/dhtlib/dht.h b/app/dht/dht.h similarity index 100% rename from app/dhtlib/dht.h rename to app/dht/dht.h diff --git a/app/include/module.h b/app/include/module.h index 50b56cb3..b727fa9b 100644 --- a/app/include/module.h +++ b/app/include/module.h @@ -1,4 +1,4 @@ -#if !defined(__MODULE_H_) && !defined(LUA_CROSS_COMPILER) +#ifndef __MODULE_H__ #define __MODULE_H__ #include "user_modules.h" @@ -38,8 +38,11 @@ #define MODULE_PASTE_(x,y) x##y #define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(x,y) -#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(s))) - +#ifdef LUA_CROSS_COMPILER +#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".rodata1." #s))) +#else +#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s))) +#endif /* For the ROM table, we name the variable according to ( | denotes concat): * cfgname | _module_selected | LUA_USE_MODULES_##cfgname * where the LUA_USE_MODULES_XYZ macro is first expanded to yield either @@ -51,20 +54,20 @@ * to be linked in. */ #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 }; \ - const LOCK_IN_SECTION(".lua_rotable") \ + const LOCK_IN_SECTION(rotable) \ luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \ = { luaname, map } /* System module registration support, not using LUA_USE_MODULES_XYZ. */ #define BUILTIN_LIB_INIT(name, luaname, initfunc) \ - const LOCK_IN_SECTION(".lua_libs") \ + const LOCK_IN_SECTION(libs) \ luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc } #define BUILTIN_LIB(name, luaname, map) \ - const LOCK_IN_SECTION(".lua_rotable") \ + const LOCK_IN_SECTION(rotable) \ luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map } #if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2) diff --git a/app/include/user_config.h b/app/include/user_config.h index 4af87af5..60b846ea 100644 --- a/app/include/user_config.h +++ b/app/include/user_config.h @@ -12,8 +12,9 @@ // This adds the asserts in LUA. It also adds some useful extras to the // node module. This is all silent in normal operation and so can be enabled // without any harm (except for the code size increase and slight slowdown) -// Either here for a global change or in the DEFINES variable in the relevant -// Makefile for ony one subdirectory. If you want to use the remote GDB to +// You can either set these defines here to operate globally or you edit the +// relevant Makefile setting them in the DEFINES variable is you only want to +// enable extra debug for specific subdirs. If you want to use the remote GDB to // handle breaks and failed assetions then enable DEVELOPMENT_USE GDB //#define DEVELOPMENT_TOOLS //#define DEVELOPMENT_USE_GDB @@ -54,6 +55,8 @@ extern void luaL_dbgbreak(void); #define NODE_ERR #endif /* NODE_ERROR */ +#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback() + #define GPIO_INTERRUPT_ENABLE #define GPIO_INTERRUPT_HOOK_ENABLE // #define GPIO_SAFE_NO_INTR_ENABLE @@ -86,18 +89,22 @@ extern void luaL_dbgbreak(void); // maximum number of open files for SPIFFS #define SPIFFS_MAX_OPEN_FILES 4 -// Uncomment this next line for fastest startup -// It reduces the format time dramatically -// #define SPIFFS_MAX_FILESYSTEM_SIZE 32768 +// Uncomment this next line for fastest startup and set the FS only to what +// your application needs. This reduces the format time dramatically +//#define SPIFFS_MAX_FILESYSTEM_SIZE 0x10000 // // You can force the spiffs file system to be at a fixed location -// #define SPIFFS_FIXED_LOCATION 0x100000 +//#define SPIFFS_FIXED_LOCATION 0x100000 // // You can force the SPIFFS file system to end on the next !M boundary // (minus the 16k parameter space). THis is useful for certain OTA scenarios // #define SPIFFS_SIZE_1M_BOUNDARY -// #define LUA_NUMBER_INTEGRAL +//#define LUA_NUMBER_INTEGRAL + +// If you want to enable Lua Flash Store (LFS) then set the following define to +// the size of the store. This can be any multiple of 4kB up to a maximum 256Kb. +//#define LUA_FLASH_STORE 0x10000 #define READLINE_INTERVAL 80 #define LUA_TASK_PRIO USER_TASK_PRIO_0 diff --git a/app/include/user_modules.h b/app/include/user_modules.h index 1afdde13..2cd9b739 100644 --- a/app/include/user_modules.h +++ b/app/include/user_modules.h @@ -1,15 +1,7 @@ #ifndef __USER_MODULES_H__ #define __USER_MODULES_H__ -#define LUA_USE_BUILTIN_STRING // for string.xxx() -#define LUA_USE_BUILTIN_TABLE // for table.xxx() -#define LUA_USE_BUILTIN_COROUTINE // for coroutine.xxx() -#define LUA_USE_BUILTIN_MATH // for math.xxx(), partially work -// #define LUA_USE_BUILTIN_IO // for io.xxx(), partially work -// #define LUA_USE_BUILTIN_OS // for os.xxx(), not work -// #define LUA_USE_BUILTIN_DEBUG -#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback() #ifndef LUA_CROSS_COMPILER @@ -65,13 +57,13 @@ //#define LUA_USE_MODULES_SJSON //#define LUA_USE_MODULES_SNTP //#define LUA_USE_MODULES_SOMFY -#define LUA_USE_MODULES_SPI +//#define LUA_USE_MODULES_SPI //#define LUA_USE_MODULES_SQLITE3 //#define LUA_USE_MODULES_STRUCT //#define LUA_USE_MODULES_SWITEC -// #define LUA_USE_MODULES_TCS34725 +//#define LUA_USE_MODULES_TCS34725 //#define LUA_USE_MODULES_TM1829 -#define LUA_USE_MODULES_TLS +//#define LUA_USE_MODULES_TLS #define LUA_USE_MODULES_TMR //#define LUA_USE_MODULES_TSL2561 //#define LUA_USE_MODULES_U8G diff --git a/app/lua/Makefile b/app/lua/Makefile index 35860d66..a1f2e5ab 100644 --- a/app/lua/Makefile +++ b/app/lua/Makefile @@ -25,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit # makefile at its root level - these are then overridden # for a subtree within the makefile rooted therein # -#DEFINES += +#DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DNODE_DEBUG -DBREAK_ON_STARTUP_PIN=1 +#EXTRA_CCFLAGS += -ggdb -O0 ############################################################# # Recursion Magic - Don't touch this!! diff --git a/app/lua/lapi.c b/app/lua/lapi.c index 3f783cba..00c3746a 100644 --- a/app/lua/lapi.c +++ b/app/lua/lapi.c @@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { case LUA_TROTABLE: return rvalue(o); case LUA_TLIGHTFUNCTION: - return pvalue(o); + return fvalue(o); default: return NULL; } } @@ -459,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { } -LUA_API void lua_pushrolstring (lua_State *L, const char *s, size_t len) { - lua_lock(L); - luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newrolstr(L, s, len)); - api_incr_top(L); - lua_unlock(L); -} - - LUA_API void lua_pushstring (lua_State *L, const char *s) { if (s == NULL) lua_pushnil(L); diff --git a/app/lua/lauxlib.c b/app/lua/lauxlib.c index 8bac5923..c01eb4d5 100644 --- a/app/lua/lauxlib.c +++ b/app/lua/lauxlib.c @@ -46,6 +46,13 @@ //#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 @@ -56,31 +63,72 @@ ** ======================================================================= */ #define this_realloc debug_realloc -#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);} #define MARK 0x55 /* 01010101 (a nice pattern) */ -#define MARK4 0x55555555 -#define MARKSIZE 4 /* size of marks after each block */ -#define fillmem(mem,size) memset(mem, -MARK, size) +#define MARKSIZE 2*sizeof(size_t) /* size of marks after each block */ +#define fillmem(mem,size) memset(mem, ~MARK, size) -typedef struct Memcontrol { /* memory-allocator control variables */ - uint32_t numblocks; - uint32_t total; - uint32_t maxmem; - uint32_t memlimit; -} Memcontrol; -static Memcontrol mc = {0,0,0,32768}; - -typedef union MemHeader { +typedef union MemHeader MemHeader; +union MemHeader { L_Umaxalign a; /* ensures maximum alignment for Header */ struct { size_t size; - int mark; - } d; -} MemHeader; + 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) ? '>' : ' '; + c_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) { - size_t size = block->d.size; + 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 */ c_free(block); /* actually free block */ mc.numblocks--; /* update counts */ @@ -88,18 +136,17 @@ static void freeblock (MemHeader *block) { } } - void *debug_realloc (void *b, size_t oldsize, size_t size) { MemHeader *block = cast(MemHeader *, b); - int i; + ASSERT(checkBlocks()); + if (!marker[0]) memset(marker, MARK, MARKSIZE); if (block == NULL) { oldsize = 0; } else { block--; /* go to real header */ - ASSERT(block->d.mark == MARK4); - ASSERT(oldsize == block->d.size); - for (i = 0; i < MARKSIZE; i++) /* check marks after block */ - ASSERT (cast(char *, b)[oldsize + i] == MARK); + ASSERT(!memcmp(block->mark, marker, MARKSIZE)) + ASSERT(oldsize == block->size); + ASSERT(!memcmp(cast(char *, b)+oldsize, marker, MARKSIZE)); } if (size == 0) { freeblock(block); @@ -108,7 +155,6 @@ void *debug_realloc (void *b, size_t oldsize, size_t size) { return NULL; /* fake a memory allocation error */ else { MemHeader *newblock; - int i; size_t commonsize = (oldsize < size) ? oldsize : size; size_t realsize = sizeof(MemHeader) + size + MARKSIZE; newblock = cast(MemHeader *, c_malloc(realsize)); /* alloc a new block */ @@ -119,12 +165,14 @@ void *debug_realloc (void *b, size_t oldsize, size_t size) { freeblock(block); /* erase (and check) old copy */ } /* initialize new part of the block with something weird */ - fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize); + if (size > commonsize) + fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize); /* initialize marks after block */ - newblock->d.mark = MARK4; - newblock->d.size = size; - for (i = 0; i < MARKSIZE; i++) - cast(char *, newblock + 1)[size + i] = MARK; + 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; diff --git a/app/lua/lbaselib.c b/app/lua/lbaselib.c index 02dad463..a08f3eaa 100644 --- a/app/lua/lbaselib.c +++ b/app/lua/lbaselib.c @@ -712,10 +712,5 @@ static void base_open (lua_State *L) { LUALIB_API int luaopen_base (lua_State *L) { base_open(L); -#if LUA_OPTIMIZE_MEMORY == 0 - luaL_register(L, LUA_COLIBNAME, co_funcs); - return 2; -#else return 1; -#endif } diff --git a/app/lua/ldblib.c b/app/lua/ldblib.c index 10978970..e084e233 100644 --- a/app/lua/ldblib.c +++ b/app/lua/ldblib.c @@ -17,6 +17,8 @@ #include "lauxlib.h" #include "lualib.h" #include "lrotable.h" +#include "lstring.h" +#include "lflash.h" #include "user_modules.h" @@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) { return 1; } +static int db_getstrings (lua_State *L) { + size_t i,n; + stringtable *tb; + GCObject *o; +#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER) + const char *opt = lua_tolstring (L, 1, &n); + if (n==3 && memcmp(opt, "ROM", 4) == 0) { + if (G(L)->ROstrt.hash == NULL) + return 0; + tb = &G(L)->ROstrt; + } + else +#endif + tb = &G(L)->strt; + lua_settop(L, 0); + lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */ + for (i=0, n=1; isize; i++) { + for(o = tb->hash[i]; o; o=o->gch.next) { + TString *ts =cast(TString *, o); + lua_pushnil(L); + setsvalue2s(L, L->top-1, ts); + lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */ + } + } + lua_getfield(L, LUA_GLOBALSINDEX, "table"); + lua_getfield(L, -1, "sort"); /* look up table.sort function */ + lua_replace(L, -2); /* dump the table table */ + lua_pushvalue(L, -2); /* duplicate the strt_copy ref */ + lua_call(L, 1, 0); /* table.sort(strt_copy) */ + return 1; +} + + #ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL static int db_getmetatable (lua_State *L) { @@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = { {LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)}, #endif {LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)}, + {LSTRKEY("getstrings"), LFUNCVAL(db_getstrings)}, #ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL {LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)}, {LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)}, diff --git a/app/lua/lflash.c b/app/lua/lflash.c new file mode 100644 index 00000000..0c0636a8 --- /dev/null +++ b/app/lua/lflash.c @@ -0,0 +1,224 @@ +/* +** $Id: lflash.c +** See Copyright Notice in lua.h +*/ + +#define lflash_c +#define LUA_CORE +#define LUAC_CROSS_FILE +#include "lua.h" + +#ifdef LUA_FLASH_STORE +#include "lobject.h" +#include "lauxlib.h" +#include "lstate.h" +#include "lfunc.h" +#include "lflash.h" +#include "platform.h" +#include "vfs.h" + +#include "c_fcntl.h" +#include "c_stdio.h" +#include "c_stdlib.h" +#include "c_string.h" + +/* + * Flash memory is a fixed memory addressable block that is serially allocated by the + * luac build process and the out image can be downloaded into SPIFSS and loaded into + * flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build + * process. + */ + +static char *flashAddr; +static uint32_t flashAddrPhys; +static uint32_t flashSector; +static uint32_t curOffset; + +#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t)))) +#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1)) +#define ALL_SET cast(uint32_t, -1) +#define FLASH_SIZE LUA_FLASH_STORE +#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE +#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE) + +#define BREAK_ON_STARTUP_PIN 1 // GPIO 5 or setting to 0 will disable pin startup + +#ifdef NODE_DEBUG +extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void dumpStrt(stringtable *tb, const char *type) { + int i,j; + GCObject *o; + + NODE_DBG("\nDumping %s String table\n\n========================\n", type); + NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size); + for (i=0; isize; i++) + for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) { + TString *ts =cast(TString *, o); + NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n", + i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, + ts_isreadonly(ts) ? "R" : " ", getstr(ts)); + } +} + +LUA_API void dumpStrings(lua_State *L) { + dumpStrt(&G(L)->strt, "RAM"); + if (G(L)->ROstrt.hash) + dumpStrt(&G(L)->ROstrt, "ROM"); +} +#endif + +/* ===================================================================================== + * The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase + * wrap writing to flash. The last two are platform dependent. Also note that any + * writes are suppressed if the global writeToFlash is false. This is used in + * phase I where the pass is used to size the structures in flash. + */ +static char *flashPosition(void){ + return flashAddr + curOffset; +} + + +static char *flashSetPosition(uint32_t offset){ + NODE_DBG("flashSetPosition(%04x)\n", offset); + curOffset = offset; + return flashPosition(); +} + + +static char *flashBlock(const void* b, size_t size) { + void *cur = flashPosition(); + NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,b,size); + lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0); + platform_flash_write(b, flashAddrPhys+curOffset, size); + curOffset += size; + return cur; +} + +static void flashErase(uint32_t start, uint32_t end){ + int i; + if (start == -1) start = FLASH_PAGES - 1; + if (end == -1) end = FLASH_PAGES - 1; + NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end); + for (i = start; i<=end; i++) + platform_flash_erase_sector( flashSector + i ); +} + + +/* ===================================================================================== + * Hook in user_main.c to allocate flash memory for the lua flash store + */ +void luaN_user_init(void) { + curOffset = 0; + flashSector = platform_flash_reserve_section( FLASH_SIZE, &flashAddrPhys ); + flashAddr = cast(char *,platform_flash_phys2mapped(flashAddrPhys)); + NODE_DBG("Flash initialised: %x %08x\n", flashSector, flashAddr); +} + + +/* + * Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed + */ +LUAI_FUNC void luaN_init (lua_State *L) { + FlashHeader *fh = cast(FlashHeader *, flashAddr); + if (fh->flash_sig == FLASH_SIG && + fh->pROhash != ALL_SET && + fh->mainProto != ALL_SET) { + G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash); + G(L)->ROstrt.nuse = fh->nROuse ; + G(L)->ROstrt.size = fh->nROsize; + G(L)->ROpvmain = cast(Proto *,fh->mainProto); + } +} + +#define BYTE_OFFSET(t,f) cast(size_t, &(cast(t *, NULL)->f)) +/* + * Rehook address chain to correct Flash byte addressed within the mapped adress space + * Note that on input each 32-bit address field is split into 2×16-bit subfields + * - the lu_int16 offset of the target address being referenced + * - the lu_int16 offset of the next address pointer. + */ + +static int rebuild_core (int fd, uint32_t size, lu_int32 *buf) { + int bi; /* byte offset into memory mapped LFS of current buffer */ + int wNextOffset = BYTE_OFFSET(FlashHeader,mainProto)/sizeof(lu_int32); + int wj; /* word offset into current input buffer */ + for (bi = 0; bi < size; bi += FLASH_PAGE_SIZE) { + int wi = bi / sizeof(lu_int32); + int blen = ((bi + FLASH_PAGE_SIZE) < size) ? FLASH_PAGE_SIZE : size - bi; + int wlen = blen / sizeof(lu_int32); + if (vfs_read(fd, buf , blen) != blen) + return 0; + + for (wj = 0; wj < wlen; wj++) { + if ((wi + wj) == wNextOffset) { /* this word is the next linked address */ + int wTargetOffset = buf[wj]&0xFFFF; + wNextOffset = buf[wj]>>16; + lua_assert(!wNextOffset || (wNextOffset>(wi+wj) && wNextOffsetROpvmain) { + Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L))); + cl->l.p = G(L)->ROpvmain; + lua_settop(L, 1); + setclvalue(L, L->top-1, cl); + return 1; + } + return 0; +} + +#endif diff --git a/app/lua/lfunc.c b/app/lua/lfunc.c index 3d0dd133..fe502f6b 100644 --- a/app/lua/lfunc.c +++ b/app/lua/lfunc.c @@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->k, f->sizek, TValue); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); - if (!proto_is_readonly(f)) { + if (!proto_isreadonly(f)) { luaM_freearray(L, f->code, f->sizecode, Instruction); #ifdef LUA_OPTIMIZE_DEBUG if (f->packedlineinfo) { diff --git a/app/lua/lfunc.h b/app/lua/lfunc.h index 1450bb7d..2dc7266b 100644 --- a/app/lua/lfunc.h +++ b/app/lua/lfunc.h @@ -18,9 +18,6 @@ #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ cast(int, sizeof(TValue *)*((n)-1))) -#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT) -#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT) - LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); diff --git a/app/lua/lgc.c b/app/lua/lgc.c index e41a779d..2f860caf 100644 --- a/app/lua/lgc.c +++ b/app/lua/lgc.c @@ -28,6 +28,9 @@ #define GCSWEEPCOST 10 #define GCFINALIZECOST 100 +#if READONLYMASK != (1<gch.marked, WHITE0BIT, WHITE1BIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) +#define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);} #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) @@ -61,12 +64,17 @@ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) + if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n))) + lua_assert(!isLFSobject(&((gkey(n))->value.gc->gch))); setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ } static void reallymarkobject (global_State *g, GCObject *o) { + /* don't mark LFS Protos (or strings) */ + if (o->gch.tt == LUA_TPROTO && isLFSobject(&(o->gch))) + return; + lua_assert(iswhite(o) && !isdead(g, o)); white2gray(o); switch (o->gch.tt) { @@ -180,6 +188,8 @@ static int traversetable (global_State *g, Table *h) { while (i--) markvalue(g, &h->array[i]); } + if (luaH_isdummy (h->node)) + return weakkey || weakvalue; i = sizenode(h); while (i--) { Node *n = gnode(h, i); @@ -202,6 +212,8 @@ static int traversetable (global_State *g, Table *h) { */ static void traverseproto (global_State *g, Proto *f) { int i; + if (isLFSobject(f)) + return; /* don't traverse Protos in LFS */ if (f->source) stringmark(f->source); for (i=0; isizek; i++) /* mark literals */ markvalue(g, &f->k[i]); @@ -317,7 +329,7 @@ static l_mem propagatemark (global_State *g) { sizeof(TValue) * p->sizek + sizeof(LocVar) * p->sizelocvars + sizeof(TString *) * p->sizeupvalues + - (proto_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode + + (proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode + #ifdef LUA_OPTIMIZE_DEBUG (p->packedlineinfo ? c_strlen(cast(char *, p->packedlineinfo))+1 : @@ -388,7 +400,10 @@ static void cleartable (GCObject *l) { static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TPROTO: + lua_assert(!isLFSobject(&(o->gch))); + luaF_freeproto(L, gco2p(o)); + break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; @@ -398,6 +413,7 @@ static void freeobj (lua_State *L, GCObject *o) { break; } case LUA_TSTRING: { + lua_assert(!isLFSobject(&(o->gch))); G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; @@ -420,6 +436,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { + lua_assert(!isLFSobject(&(curr->gch)) || curr->gch.tt == LUA_TTHREAD); if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ sweepwholelist(L, &gco2th(curr)->openupval); if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ @@ -538,7 +555,7 @@ static void atomic (lua_State *L) { size_t udsize; /* total size of userdata to be finalized */ /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); - /* traverse objects cautch by write barrier and by 'remarkupvals' */ + /* traverse objects caucht by write barrier and by 'remarkupvals' */ propagateall(g); /* remark weak tables */ g->gray = g->weak; @@ -694,10 +711,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - lua_assert(ttype(&o->gch) != LUA_TTABLE); + lua_assert(o->gch.tt != LUA_TTABLE); /* must keep invariant? */ if (g->gcstate == GCSpropagate) - reallymarkobject(g, v); /* restore invariant */ + reallymarkobject(g, v); /* Restore invariant */ else /* don't mind */ makewhite(g, o); /* mark as white just to avoid other barriers */ } diff --git a/app/lua/lgc.h b/app/lua/lgc.h index 9c26932b..ed994d09 100644 --- a/app/lua/lgc.h +++ b/app/lua/lgc.h @@ -79,6 +79,7 @@ #define VALUEWEAKBIT 4 #define FIXEDBIT 5 #define SFIXEDBIT 6 +#define LFSBIT 6 #define READONLYBIT 7 #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) @@ -100,6 +101,13 @@ #define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT) #define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT) #define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT) +#ifdef LUA_FLASH_STORE +#define isLFSobject(x) testbit((x)->marked, LFSBIT) +#define stringfix(s) if (!test2bits((s)->tsv.marked, FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);} +#else +#define isLFSobject(x) (0) +#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);} +#endif #define luaC_checkGC(L) { \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ diff --git a/app/lua/linit.c b/app/lua/linit.c new file mode 100644 index 00000000..1a7c4b58 --- /dev/null +++ b/app/lua/linit.c @@ -0,0 +1,78 @@ +/* +** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ +** Initialization of libraries for lua.c +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB +#define LUAC_CROSS_FILE + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" +#include "luaconf.h" +#include "module.h" +#if defined(LUA_CROSS_COMPILER) +BUILTIN_LIB( start_list, NULL, NULL); +BUILTIN_LIB_INIT( start_list, NULL, NULL); +#endif +extern const luaR_entry strlib[], tab_funcs[], dblib[], + co_funcs[], math_map[], syslib[]; + +BUILTIN_LIB_INIT( BASE, "", luaopen_base); +BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package); + +BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib); +BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string); + +BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs); +BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table); + +BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib); +BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug); + +BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs); + +BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map); + +#if defined(LUA_CROSS_COMPILER) +extern const luaR_entry syslib[], iolib[]; +BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib); +BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io); +BUILTIN_LIB( end_list, NULL, NULL); +BUILTIN_LIB_INIT( end_list, NULL, NULL); +/* + * These base addresses are internal to this module for cross compile builds + * This also exploits feature of the GCC code generator that the variables are + * emitted in either normal OR reverse order within PSECT. + */ +#define isascending(n) ((&(n ## _end_list)-&(n ## _start_list))>0) +static const luaL_Reg *lua_libs; +const luaR_table *lua_rotable; +#else +/* These base addresses are Xtensa toolchain linker constants for Firmware builds */ +extern const luaL_Reg lua_libs_base[]; +extern const luaR_table lua_rotable_base[]; +static const luaL_Reg *lua_libs = lua_libs_base; +const luaR_table *lua_rotable = lua_rotable_base; +#endif + +void luaL_openlibs (lua_State *L) { +#if defined(LUA_CROSS_COMPILER) +lua_libs = (isascending(lua_lib) ? &lua_lib_start_list : &lua_lib_end_list) + 1; +lua_rotable = (isascending(lua_rotable) ? &lua_rotable_start_list : &lua_rotable_end_list) + 1; +#endif + const luaL_Reg *lib = lua_libs; + for (; lib->name; lib++) { + if (lib->func) + { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } + } +} + diff --git a/app/lua/lmathlib.c b/app/lua/lmathlib.c index e3fda445..8a3b9754 100644 --- a/app/lua/lmathlib.c +++ b/app/lua/lmathlib.c @@ -326,7 +326,7 @@ const LUA_REG_TYPE math_map[] = { {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)}, {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)}, #if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("huge"), LNUMVAL(LONG_MAX)}, + {LSTRKEY("huge"), LNUMVAL(INT_MAX)}, #endif #else {LSTRKEY("abs"), LFUNCVAL(math_abs)}, @@ -374,7 +374,7 @@ const LUA_REG_TYPE math_map[] = { */ #if defined LUA_NUMBER_INTEGRAL -# include "c_limits.h" /* for LONG_MAX */ +# include "c_limits.h" /* for INT_MAX */ #endif LUALIB_API int luaopen_math (lua_State *L) { @@ -383,7 +383,7 @@ LUALIB_API int luaopen_math (lua_State *L) { #else luaL_register(L, LUA_MATHLIBNAME, math_map); # if defined LUA_NUMBER_INTEGRAL - lua_pushnumber(L, LONG_MAX); + lua_pushnumber(L, INT_MAX); lua_setfield(L, -2, "huge"); # else lua_pushnumber(L, PI); diff --git a/app/lua/lobject.c b/app/lua/lobject.c index 6a684559..640378d0 100644 --- a/app/lua/lobject.c +++ b/app/lua/lobject.c @@ -53,7 +53,8 @@ int luaO_fb2int (int x) { int luaO_log2 (unsigned int x) { - static const lu_byte log_2[256] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = { +#ifdef LUA_CROSS_COMPILER + static const lu_byte log_2[256] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, @@ -65,10 +66,12 @@ int luaO_log2 (unsigned int x) { }; int l = -1; while (x >= 256) { l += 8; x >>= 8; } -#ifdef LUA_CROSS_COMPILER return l + log_2[x]; #else - return l + byte_of_aligned_array(log_2,x); + /* Use Normalization Shift Amount Unsigned: 0x1=>31 up to 0xffffffff =>0 + * See Xtensa Instruction Set Architecture (ISA) Refman P 462 */ + asm volatile ("nsau %0, %1;" :"=r"(x) : "r"(x)); + return 32 - x; #endif } @@ -103,7 +106,7 @@ int luaO_str2d (const char *s, lua_Number *result) { #if defined(LUA_CROSS_COMPILER) { long lres = strtoul(s, &endptr, 16); -#if LONG_MAX != 2147483647L +#if INT_MAX != 2147483647L if (lres & ~0xffffffffL) *result = cast_num(-1); else if (lres & 0x80000000L) diff --git a/app/lua/lobject.h b/app/lua/lobject.h index 5b020953..518ab507 100644 --- a/app/lua/lobject.h +++ b/app/lua/lobject.h @@ -23,10 +23,10 @@ #define NUM_TAGS (LAST_TAG+1) -/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */ -#define READONLYMASK 128 - - +#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */ +#ifdef LUA_FLASH_STORE +#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */ +#endif /* ** Extra tags for non-values */ @@ -55,86 +55,33 @@ typedef struct GCheader { CommonHeader; } GCheader; - +#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL) +# error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines" +#endif /* ** Union of all Lua values */ -#if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) -typedef union { - struct { - int _pad0; - GCObject *gc; - }; - struct { - int _pad1; - void *p; - }; - lua_Number n; - struct { - int _pad2; - int b; - }; -} Value; -#else // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) typedef union { GCObject *gc; void *p; lua_Number n; int b; } Value; -#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG ) /* ** Tagged Values */ -#ifndef LUA_PACK_VALUE #define TValuefields Value value; int tt #define LUA_TVALUE_NIL {NULL}, LUA_TNIL typedef struct lua_TValue { TValuefields; } TValue; -#else // #ifndef LUA_PACK_VALUE -#ifdef ELUA_ENDIAN_LITTLE -#define TValuefields union { \ - struct { \ - int _pad0; \ - int tt_sig; \ - } _ts; \ - struct { \ - int _pad; \ - short tt; \ - short sig; \ - } _t; \ - Value value; \ -} -#define LUA_TVALUE_NIL {0, add_sig(LUA_TNIL)} -#else // #ifdef ELUA_ENDIAN_LITTLE -#define TValuefields union { \ - struct { \ - int tt_sig; \ - int _pad0; \ - } _ts; \ - struct { \ - short sig; \ - short tt; \ - int _pad; \ - } _t; \ - Value value; \ -} -#define LUA_TVALUE_NIL {add_sig(LUA_TNIL), 0} -#endif // #ifdef ELUA_ENDIAN_LITTLE -#define LUA_NOTNUMBER_SIG (-1) -#define add_sig(tt) ( 0xffff0000 | (tt) ) - -typedef TValuefields TValue; -#endif // #ifndef LUA_PACK_VALUE /* Macros to test type */ -#ifndef LUA_PACK_VALUE #define ttisnil(o) (ttype(o) == LUA_TNIL) #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisstring(o) (ttype(o) == LUA_TSTRING) @@ -146,27 +93,11 @@ typedef TValuefields TValue; #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) #define ttisrotable(o) (ttype(o) == LUA_TROTABLE) #define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION) -#else // #ifndef LUA_PACK_VALUE -#define ttisnil(o) (ttype_sig(o) == add_sig(LUA_TNIL)) -#define ttisnumber(o) ((o)->_t.sig != LUA_NOTNUMBER_SIG) -#define ttisstring(o) (ttype_sig(o) == add_sig(LUA_TSTRING)) -#define ttistable(o) (ttype_sig(o) == add_sig(LUA_TTABLE)) -#define ttisfunction(o) (ttype_sig(o) == add_sig(LUA_TFUNCTION)) -#define ttisboolean(o) (ttype_sig(o) == add_sig(LUA_TBOOLEAN)) -#define ttisuserdata(o) (ttype_sig(o) == add_sig(LUA_TUSERDATA)) -#define ttisthread(o) (ttype_sig(o) == add_sig(LUA_TTHREAD)) -#define ttislightuserdata(o) (ttype_sig(o) == add_sig(LUA_TLIGHTUSERDATA)) -#define ttisrotable(o) (ttype_sig(o) == add_sig(LUA_TROTABLE)) -#define ttislightfunction(o) (ttype_sig(o) == add_sig(LUA_TLIGHTFUNCTION)) -#endif // #ifndef LUA_PACK_VALUE + /* Macros to access values */ -#ifndef LUA_PACK_VALUE -#define ttype(o) ((o)->tt) -#else // #ifndef LUA_PACK_VALUE -#define ttype(o) ((o)->_t.sig == LUA_NOTNUMBER_SIG ? (o)->_t.tt : LUA_TNUMBER) -#define ttype_sig(o) ((o)->_ts.tt_sig) -#endif // #ifndef LUA_PACK_VALUE + +#define ttype(o) ((void) (o)->value, (o)->tt) #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) #define rvalue(o) check_exp(ttisrotable(o), (o)->value.p) @@ -186,24 +117,15 @@ typedef TValuefields TValue; /* ** for internal debug only */ -#ifndef LUA_PACK_VALUE + #define checkconsistency(obj) \ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) #define checkliveness(g,obj) \ lua_assert(!iscollectable(obj) || \ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) -#else // #ifndef LUA_PACK_VALUE -#define checkconsistency(obj) \ - lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch._t.tt)) - -#define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch._t.tt) && !isdead(g, (obj)->value.gc))) -#endif // #ifndef LUA_PACK_VALUE /* Macros to set values */ -#ifndef LUA_PACK_VALUE #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnvalue(obj,x) \ @@ -257,69 +179,10 @@ typedef TValuefields TValue; i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \ checkliveness(G(L),i_o); } - - - #define setobj(L,obj1,obj2) \ { const TValue *o2=(obj2); TValue *o1=(obj1); \ o1->value = o2->value; o1->tt=o2->tt; \ checkliveness(G(L),o1); } -#else // #ifndef LUA_PACK_VALUE -#define setnilvalue(obj) ( ttype_sig(obj) = add_sig(LUA_TNIL) ) - -#define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); } - -#define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTUSERDATA);} - -#define setrvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TROTABLE);} - -#define setfvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTFUNCTION);} - -#define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->_ts.tt_sig=add_sig(LUA_TBOOLEAN);} - -#define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TSTRING); \ - checkliveness(G(L),i_o); } - -#define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TUSERDATA); \ - checkliveness(G(L),i_o); } - -#define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTHREAD); \ - checkliveness(G(L),i_o); } - -#define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TFUNCTION); \ - checkliveness(G(L),i_o); } - -#define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTABLE); \ - checkliveness(G(L),i_o); } - -#define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TPROTO); \ - checkliveness(G(L),i_o); } - - - - -#define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; \ - checkliveness(G(L),o1); } -#endif // #ifndef LUA_PACK_VALUE /* ** different types of sets, according to destination @@ -340,13 +203,7 @@ typedef TValuefields TValue; #define setobj2n setobj #define setsvalue2n setsvalue -#ifndef LUA_PACK_VALUE -#define setttype(obj, tt) (ttype(obj) = (tt)) -#else // #ifndef LUA_PACK_VALUE -/* considering it used only in lgc to set LUA_TDEADKEY */ -/* we could define it this way */ -#define setttype(obj, _tt) ( ttype_sig(obj) = add_sig(_tt) ) -#endif // #ifndef LUA_PACK_VALUE +#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt)) #define iscollectable(o) (ttype(o) >= LUA_TSTRING) @@ -367,9 +224,16 @@ typedef union TString { } tsv; } TString; - -#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : cast(const char *, (ts) + 1)) -#define svalue(o) getstr(rawtsvalue(o)) +#ifdef LUA_CROSS_COMPILER +#define isreadonly(o) (0) +#else +#define isreadonly(o) ((o).marked & READONLYMASK) +#endif +#define ts_isreadonly(ts) isreadonly((ts)->tsv) +#define getstr(ts) (ts_isreadonly(ts) ? \ + cast(const char *, *(const char**)((ts) + 1)) : \ + cast(const char *, (ts) + 1)) +#define svalue(o) getstr(rawtsvalue(o)) @@ -418,6 +282,7 @@ typedef struct Proto { lu_byte is_vararg; lu_byte maxstacksize; } Proto; +#define proto_isreadonly(p) isreadonly(*(p)) /* masks for new-style vararg */ @@ -487,7 +352,6 @@ typedef union Closure { ** Tables */ -#ifndef LUA_PACK_VALUE typedef union TKey { struct { TValuefields; @@ -497,16 +361,6 @@ typedef union TKey { } TKey; #define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL} -#else // #ifndef LUA_PACK_VALUE -typedef struct TKey { - TValue tvk; - struct { - struct Node *next; /* for chaining */ - } nk; -} TKey; - -#define LUA_TKEY_NIL {LUA_TVALUE_NIL}, {NULL} -#endif // #ifndef LUA_PACK_VALUE typedef struct Node { TValue i_val; diff --git a/app/lua/lrodefs.h b/app/lua/lrodefs.h index e9bbe7fe..451b3621 100644 --- a/app/lua/lrodefs.h +++ b/app/lua/lrodefs.h @@ -15,7 +15,7 @@ #undef LNILVAL #undef LREGISTER -#if (MIN_OPT_LEVEL > 0) && (LUA_OPTIMIZE_MEMORY >= MIN_OPT_LEVEL) +#if LUA_OPTIMIZE_MEMORY >=1 #define LUA_REG_TYPE luaR_entry #define LSTRKEY LRO_STRKEY #define LNUMKEY LRO_NUMKEY diff --git a/app/lua/lrotable.c b/app/lua/lrotable.c index 96e80bc9..a5cbb7ca 100644 --- a/app/lua/lrotable.c +++ b/app/lua/lrotable.c @@ -14,11 +14,10 @@ #define LUAR_FINDVALUE 1 /* Externally defined read-only table array */ -extern const luaR_table lua_rotable[]; +extern const luaR_table *lua_rotable; /* Find a global "read only table" in the constant lua_rotable array */ void* luaR_findglobal(const char *name, unsigned len) { -#ifndef LUA_CROSS_COMPILER unsigned i; if (c_strlen(name) > LUA_MAX_ROTABLE_NAME) @@ -27,7 +26,6 @@ void* luaR_findglobal(const char *name, unsigned len) { if (*lua_rotable[i].name != '\0' && c_strlen(lua_rotable[i].name) == len && !c_strncmp(lua_rotable[i].name, name, len)) { return (void*)(lua_rotable[i].pentries); } -#endif return NULL; } @@ -87,7 +85,7 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, if (pentries[pos].key.type != LUA_TNIL) { /* Found an entry */ if (pentries[pos].key.type == LUA_TSTRING) - setsvalue(L, key, luaS_newro(L, pentries[pos].key.id.strkey)) + setsvalue(L, key, luaS_new(L, pentries[pos].key.id.strkey)) else setnvalue(key, (lua_Number)pentries[pos].key.id.numkey) setobj2s(L, val, &pentries[pos].value); @@ -129,10 +127,15 @@ void luaR_getcstr(char *dest, const TString *src, size_t maxsize) { /* Return 1 if the given pointer is a rotable */ #ifdef LUA_META_ROTABLES - +#ifdef LUA_CROSS_COMPILER +extern char edata[]; +int luaR_isrotable(void *p) { + return (char*)p <= edata; +} +#else #include "compiler.h" - int luaR_isrotable(void *p) { return RODATA_START_ADDRESS <= (char*)p && (char*)p <= RODATA_END_ADDRESS; } #endif +#endif diff --git a/app/lua/lrotable.h b/app/lua/lrotable.h index e8963e3b..aba26352 100644 --- a/app/lua/lrotable.h +++ b/app/lua/lrotable.h @@ -4,32 +4,16 @@ #define lrotable_h #include "lua.h" -#include "llimits.h" -#include "lobject.h" #include "luaconf.h" +#include "lobject.h" +#include "llimits.h" /* Macros one can use to define rotable entries */ -#ifndef LUA_PACK_VALUE #define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION} #define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA} #define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL} -#else // #ifndef LUA_PACK_VALUE -#define LRO_NUMVAL(v) {.value.n = v} -#ifdef ELUA_ENDIAN_LITTLE -#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}} -#define LRO_LUDATA(v) {{(int)v, add_sig(LUA_TLIGHTUSERDATA)}} -#define LRO_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}} -#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}} -#else // #ifdef ELUA_ENDIAN_LITTLE -#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}} -#define LRO_LUDATA(v) {{add_sig(LUA_TLIGHTUSERDATA), (int)v}} -#define LRO_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}} -#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}} -#endif // #ifdef ELUA_ENDIAN_LITTLE -#endif // #ifndef LUA_PACK_VALUE - #define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}} #define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}} #define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}} diff --git a/app/lua/lstate.c b/app/lua/lstate.c index b4289742..a0cb60dc 100644 --- a/app/lua/lstate.c +++ b/app/lua/lstate.c @@ -13,6 +13,7 @@ #include "ldebug.h" #include "ldo.h" +#include "lflash.h" #include "lfunc.h" #include "lgc.h" #include "llex.h" @@ -72,9 +73,12 @@ static void f_luaopen (lua_State *L, void *ud) { sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ +#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER) + luaN_init(L); /* optionally map RO string table */ +#endif luaT_init(L); luaX_init(L); - luaS_fix(luaS_newliteral(L, MEMERRMSG)); + stringfix(luaS_newliteral(L, MEMERRMSG)); g->GCthreshold = 4*g->totalbytes; } @@ -191,6 +195,12 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->memlimit = EGC_INITIAL_MEMLIMIT; #else g->memlimit = 0; +#endif +#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER) + g->ROstrt.size = 0; + g->ROstrt.nuse = 0; + g->ROstrt.hash = NULL; + g->ROpvmain = NULL; #endif for (i=0; imt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { diff --git a/app/lua/lstate.h b/app/lua/lstate.h index 1b3c363a..75f88a12 100644 --- a/app/lua/lstate.h +++ b/app/lua/lstate.h @@ -94,6 +94,10 @@ typedef struct global_State { UpVal uvhead; /* head of double-linked list of all open upvalues */ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ TString *tmname[TM_N]; /* array with tag-method names */ +#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER) + stringtable ROstrt; /* Flash-based hash table for RO strings */ + Proto *ROpvmain; /* Flash-based Proto main */ +#endif } global_State; diff --git a/app/lua/lstring.c b/app/lua/lstring.c index 8f03e52a..2257c146 100644 --- a/app/lua/lstring.c +++ b/app/lua/lstring.c @@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, tb = &G(L)->strt; if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) luaS_resize(L, tb->size*2); /* too crowded */ - ts = cast(TString *, luaM_malloc(L, readonly ? sizeof(char**)+sizeof(TString) : (l+1)*sizeof(char)+sizeof(TString))); + ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (readonly ? sizeof(char**) : (l+1)*sizeof(char)))); ts->tsv.len = l; ts->tsv.hash = h; ts->tsv.marked = luaC_white(G(L)); @@ -71,7 +71,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, ((char *)(ts+1))[l] = '\0'; /* ending 0 */ } else { *(char **)(ts+1) = (char *)str; - luaS_readonly(ts); + l_setbit((ts)->tsv.marked, READONLYBIT); } h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ @@ -80,14 +80,29 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, return ts; } +#include "compiler.h" +static int lua_is_ptr_in_ro_area(const char *p) { +#ifdef LUA_CROSS_COMPILER + return 0; +#else + return p >= RODATA_START_ADDRESS && p <= RODATA_END_ADDRESS; +#endif +} -static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, int readonly) { +/* + * The string algorithm has been modified to be LFS-friendly. The previous eLua + * algo used the address of the string was in flash and the string was >4 bytes + * This creates miminal savings and prevents the use of LFS based strings + */ + +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { GCObject *o; unsigned int h = cast(unsigned int, l); /* seed */ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; for (l1=l; l1>=step; l1-=step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL; o = o->gch.next) { @@ -98,35 +113,27 @@ static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, in return ts; } } - return newlstr(L, str, l, h, readonly); /* not found */ -} - -static int lua_is_ptr_in_ro_area(const char *p) { -#ifdef LUA_CROSS_COMPILER - return 0; -#else - -#include "compiler.h" - - return p >= RODATA_START_ADDRESS && p <= RODATA_END_ADDRESS; +#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER) + /* + * The RAM strt is searched first since RAM access is faster tham Flash access. + * If a miss, then search the RO string table. + */ + if (G(L)->ROstrt.hash) { + for (o = G(L)->ROstrt.hash[lmod(h, G(L)->ROstrt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + return ts; + } + } + } #endif -} - -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - // If the pointer is in a read-only memory and the string is at least 4 chars in length, - // create it as a read-only string instead - if(lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) && l == c_strlen(str)) - return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING); - else - return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING); -} - - -LUAI_FUNC TString *luaS_newrolstr (lua_State *L, const char *str, size_t l) { - if(l+1 > sizeof(char**) && l == c_strlen(str)) - return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING); - else // no point in creating a RO string, as it would actually be larger - return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING); + /* New additions to the RAM strt are tagged as readonly if the string address + * is in the CTEXT segment (target only, not luac.cross) */ + int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) && + l == c_strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING); + return newlstr(L, str, l, h, readonly); /* not found */ } diff --git a/app/lua/lstring.h b/app/lua/lstring.h index b4cc3dda..6c5d8f66 100644 --- a/app/lua/lstring.h +++ b/app/lua/lstring.h @@ -13,22 +13,16 @@ #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+(luaS_isreadonly(s) ? sizeof(char **) : ((s)->len+1)*sizeof(char))) +#define sizestring(s) (sizeof(union TString)+(testbit((s)->marked, READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char))) #define sizeudata(u) (sizeof(union Udata)+(u)->len) #define luaS_new(L, s) (luaS_newlstr(L, s, c_strlen(s))) -#define luaS_newro(L, s) (luaS_newrolstr(L, s, c_strlen(s))) #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) -#define luaS_readonly(s) l_setbit((s)->tsv.marked, READONLYBIT) -#define luaS_isreadonly(s) testbit((s)->marked, READONLYBIT) - LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_newrolstr (lua_State *L, const char *str, size_t l); #endif diff --git a/app/lua/ltable.c b/app/lua/ltable.c index 2e486512..9a5f91bc 100644 --- a/app/lua/ltable.c +++ b/app/lua/ltable.c @@ -749,12 +749,12 @@ int luaH_getn_ro (void *t) { return len; } -#if defined(LUA_DEBUG) +int luaH_isdummy (Node *n) { return n == dummynode; } +#if defined(LUA_DEBUG) Node *luaH_mainposition (const Table *t, const TValue *key) { return mainposition(t, key); } - -int luaH_isdummy (Node *n) { return n == dummynode; } - #endif + + diff --git a/app/lua/ltable.h b/app/lua/ltable.h index 4835f2c3..d8c26d9a 100644 --- a/app/lua/ltable.h +++ b/app/lua/ltable.h @@ -34,11 +34,9 @@ LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_next_ro (lua_State *L, void *t, StkId key); LUAI_FUNC int luaH_getn (Table *t); LUAI_FUNC int luaH_getn_ro (void *t); +LUAI_FUNC int luaH_isdummy (Node *n); #if defined(LUA_DEBUG) LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (Node *n); #endif - - #endif diff --git a/app/lua/ltm.c b/app/lua/ltm.c index fccbbe67..6b27ccc0 100644 --- a/app/lua/ltm.c +++ b/app/lua/ltm.c @@ -14,6 +14,7 @@ #include "lobject.h" #include "lstate.h" +#include "lgc.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" @@ -39,7 +40,7 @@ void luaT_init (lua_State *L) { int i; for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ + stringfix(G(L)->tmname[i]); /* never collect these names */ } } diff --git a/app/lua/lua.c b/app/lua/lua.c index 3082bb28..f5c7461f 100644 --- a/app/lua/lua.c +++ b/app/lua/lua.c @@ -13,6 +13,7 @@ #include "user_version.h" #include "driver/readline.h" #include "driver/uart.h" +#include "platform.h" #define lua_c @@ -21,7 +22,9 @@ #include "lauxlib.h" #include "lualib.h" #include "legc.h" - +#ifdef LUA_FLASH_STORE +#include "lflash.h" +#endif #include "os_type.h" lua_State *globalL = NULL; @@ -30,44 +33,6 @@ lua_Load gLoad; static const char *progname = LUA_PROGNAME; -#if 0 -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); -} - - -static void laction (int i) { - // signal(i, SIG_DFL); - /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -static void print_usage (void) { -#if defined(LUA_USE_STDIO) - c_fprintf(c_stderr, -#else - luai_writestringerror( -#endif - "usage: %s [options] [script [args]].\n" - "Available options are:\n" - " -e stat execute string " LUA_QL("stat") "\n" - " -l name require library " LUA_QL("name") "\n" - " -m limit set memory limit. (units are in Kbytes)\n" - " -i enter interactive mode after executing " LUA_QL("script") "\n" - " -v show version information\n" - " -- stop handling options\n" - " - execute stdin and stop handling options\n" - , - progname); -#if defined(LUA_USE_STDIO) - c_fflush(c_stderr); -#endif -} -#endif static void l_message (const char *pname, const char *msg) { #if defined(LUA_USE_STDIO) @@ -154,17 +119,11 @@ static int getargs (lua_State *L, char **argv, int n) { return narg; } -#if 0 -static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name) || docall(L, 0, 1); - return report(L, status); -} -#else static int dofsfile (lua_State *L, const char *name) { int status = luaL_loadfsfile(L, name) || docall(L, 0, 1); return report(L, status); } -#endif + static int dostring (lua_State *L, const char *s, const char *name) { int status = luaL_loadbuffer(L, s, c_strlen(s), name) || docall(L, 0, 1); @@ -201,92 +160,6 @@ static int incomplete (lua_State *L, int status) { return 0; /* else... */ } -#if 0 -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - if (lua_readline(L, b, prmt) == 0) - return 0; /* no input */ - l = c_strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* first line starts with `=' ? */ - lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ - else - lua_pushstring(L, b); - lua_freeline(L, b); - return 1; -} - - -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_saveline(L, 1); - lua_remove(L, 1); /* remove line */ - return status; -} - - -static void dotty (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; - while ((status = loadline(L)) != -1) { - if (status == 0) status = docall(L, 0, 0); - report(L, status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) - l_message(progname, lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - -#if defined(LUA_USE_STDIO) - c_fputs("\n", c_stdout); - c_fflush(c_stdout); -#else - luai_writeline(); -#endif - - progname = oldprogname; -} - - -static int handle_script (lua_State *L, char **argv, int n) { - int status; - const char *fname; - int narg = getargs(L, argv, n); /* collect arguments */ - lua_setglobal(L, "arg"); - fname = argv[n]; - if (c_strcmp(fname, "-") == 0 && c_strcmp(argv[n-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - lua_insert(L, -(narg+1)); - if (status == 0) - status = docall(L, narg, 0); - else - lua_pop(L, narg); - return report(L, status); -} -#endif /* check that argument has no extra characters at the end */ #define notail(x) {if ((x)[2] != '\0') return -1;} @@ -368,11 +241,7 @@ static int handle_luainit (lua_State *L) { const char *init = c_getenv(LUA_INIT); if (init == NULL) return 0; /* status OK */ else if (init[0] == '@') -#if 0 - return dofile(L, init+1); -#else return dofsfile(L, init+1); -#endif else return dostring(L, init, "=" LUA_INIT); } @@ -397,34 +266,13 @@ static int pmain (lua_State *L) { lua_gc(L, LUA_GCRESTART, 0); print_version(L); s->status = handle_luainit(L); -#if 0 - if (s->status != 0) return 0; -#endif script = collectargs(argv, &has_i, &has_v, &has_e); if (script < 0) { /* invalid args? */ -#if 0 - print_usage(); -#endif s->status = 1; return 0; } - // if (has_v) print_version(); s->status = runargs(L, argv, (script > 0) ? script : s->argc); if (s->status != 0) return 0; -#if 0 - if (script) - s->status = handle_script(L, argv, script); - if (s->status != 0) return 0; - if (has_i) - dotty(L); - else if (script == 0 && !has_e && !has_v) { - if (lua_stdin_is_tty()) { - print_version(); - dotty(L); - } - else dofile(L, NULL); /* executes stdin as a file */ - } -#endif return 0; } @@ -439,6 +287,12 @@ int lua_main (int argc, char **argv) { #endif int status; struct Smain s; + +#if defined(NODE_DEBUG) && defined(DEVELOPMENT_USE_GDB) && BREAK_ON_STARTUP_PIN > 0 + platform_gpio_mode( BREAK_ON_STARTUP_PIN, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP ); + lua_assert(platform_gpio_read(BREAK_ON_STARTUP_PIN)); // Break if pin pulled low +#endif + lua_State *L = lua_open(); /* create state */ if (L == NULL) { l_message(argv[0], "cannot create state: not enough memory"); @@ -446,7 +300,9 @@ int lua_main (int argc, char **argv) { } s.argc = argc; s.argv = argv; + status = lua_cpcall(L, &pmain, &s); + report(L, status); gLoad.L = L; @@ -468,11 +324,8 @@ int lua_main (int argc, char **argv) { void lua_handle_input (bool force) { - while (gLoad.L && (force || readline (&gLoad))) - { + if (gLoad.L && (force || readline (&gLoad))) dojob (&gLoad); - force = false; - } } void donejob(lua_Load *load){ @@ -602,12 +455,11 @@ static bool readline(lua_Load *load){ { /* Get a empty line, then go to get a new line */ c_puts(load->prmt); - continue; } else { load->done = 1; need_dojob = true; - break; } + continue; } /* other control character or not an acsii character */ diff --git a/app/lua/lua.h b/app/lua/lua.h index 69fcc95b..b6f6c413 100644 --- a/app/lua/lua.h +++ b/app/lua/lua.h @@ -173,7 +173,6 @@ LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API void (lua_pushrolstring) (lua_State *L, const char *s, size_t l); LUA_API void (lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); diff --git a/app/lua/luac_cross.h b/app/lua/luac_cross.h index 8dba4620..f4a4da83 100644 --- a/app/lua/luac_cross.h +++ b/app/lua/luac_cross.h @@ -31,6 +31,7 @@ #define c_freopen freopen #define c_getc getc #define c_getenv getenv +#define c_malloc malloc #define c_memcmp memcmp #define c_memcpy memcpy #define c_printf printf diff --git a/app/lua/luac_cross/Makefile b/app/lua/luac_cross/Makefile index e58ec38e..25e97c4c 100644 --- a/app/lua/luac_cross/Makefile +++ b/app/lua/luac_cross/Makefile @@ -7,30 +7,29 @@ .NOTPARALLEL: CCFLAGS:= -I.. -I../../include -I../../../include -I ../../libc -LDFLAGS:= -L$(SDK_DIR)/lib -L$(SDK_DIR)/ld -lm +LDFLAGS:= -L$(SDK_DIR)/lib -L$(SDK_DIR)/ld -lm -Wl,-Map=mapfile CCFLAGS += -Wall -DEFINES += -DLUA_CROSS_COMPILER +DEFINES += -DLUA_CROSS_COMPILER -DLUA_OPTIMIZE_MEMORY=2 TARGET = host -ifeq ($(FLAVOR),release) +ifeq ($(FLAVOR),debug) + CCFLAGS += -O0 -g + TARGET_LDFLAGS += -O0 -g +else + FLAVOR = release CCFLAGS += -O2 TARGET_LDFLAGS += -O2 -else - FLAVOR = debug - CCFLAGS += -O2 -g - TARGET_LDFLAGS += -O2 -g endif -LUACSRC := luac.c lflashimg.c loslib.c print.c -LUASRC := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c \ - ldebug.c ldo.c ldump.c lfunc.c lgc.c \ - llex.c lmathlib.c lmem.c loadlib.c lobject.c \ - lopcodes.c lparser.c lrotable.c lstate.c lstring.c \ - lstrlib.c ltable.c ltablib.c ltm.c lundump.c \ - lvm.c lzio.c +LUACSRC := luac.c lflashimg.c liolib.c loslib.c print.c +LUASRC := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c \ + ldo.c ldump.c lfunc.c lgc.c linit.c llex.c \ + lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c lparser.c \ + lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \ + ltm.c lundump.c lvm.c lzio.c LIBCSRC := c_stdlib.c # @@ -83,6 +82,3 @@ $(ODIR)/%.d: %.c $(CC) -M $(CFLAGS) $< > $@.$$$$; \ sed 's,\($*\.o\)[ :]*,$(ODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ - -# echo 's,\($*\.o\)[ :]*,$(ODIR)/\1 $@ : ,g'; \ - diff --git a/app/lua/luac_cross/lflashimg.c b/app/lua/luac_cross/lflashimg.c index 94844f85..ee21f067 100644 --- a/app/lua/luac_cross/lflashimg.c +++ b/app/lua/luac_cross/lflashimg.c @@ -224,7 +224,7 @@ static void createROstrt(lua_State *L, FlashHeader *fh) { toFlashAddr(L, *e, fts); // add reference to TS to lookup vector toFlashAddr(L, fts->next, last); // and chain to previous entry if any fts->tt = LUA_TSTRING; // Set as String - fts->marked = bitmask(FIXEDBIT); // Fixed with no Whitebits set + fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set fts->hash = hash; // add hash fts->len = len; // and length memcpy(flashAlloc(L, ALIGN(len+1)), p, ALIGN(len+1)); // copy string @@ -262,14 +262,21 @@ static void *resolveTString(lua_State* L, TString *s) { * src Source of record * returns Address of destination record */ +#define TARGET_TV_SIZE (2*sizeof(lua_Number)) static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { /* ToS is the string address mapping table */ if (n == 0) return NULL; - int i; + int i, recsize; void *newts; - // A bit of a botch because fmt is either "V" or a string of WORDSIZE specifiers */ - int recsize = fmt[0]=='V' ? 16 : WORDSIZE * strlen(fmt); + /* A bit of a botch because fmt is either "V" or a string of WORDSIZE specifiers */ + /* The size 8 for integer builds and 16 for float ones on both architectures */ + if (fmt[0]=='V') { + lua_assert(fmt[1] == 0); /* V formats must be singetons */ + recsize = TARGET_TV_SIZE; + } else { + recsize = WORDSIZE * strlen(fmt); + } uint *d = cast(uint *, flashAlloc(L, n * recsize)); uint *dest = d; @@ -284,8 +291,8 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { switch (*p++) { case 'A': toFlashAddr(L, *d, *cast(void**, s)); - d++; s += FLASH_WORDS(size_t); + d++; break; case 'I': *d++ = *s++; @@ -293,22 +300,23 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { case 'S': newts = resolveTString(L, *cast(TString **, s)); toFlashAddr(L, *d, newts); - d++; s += FLASH_WORDS(size_t); + d++; break; case 'V': - memcpy(d, s, sizeof(TValue)); + /* This code has to work for both Integer and Float build variants */ + memset(d, 0, TARGET_TV_SIZE); TValue *sv = cast(TValue *, s); if (ttisstring(sv)) { - newts = resolveTString(L, rawtsvalue(sv)); - toFlashAddr(L, *d, newts); - d[1] = 0; - } else { + toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv))); + } else { /* non-collectable types all of size lua_Number */ lua_assert(!iscollectable(sv)); + *cast(lua_Number*,d) = *cast(lua_Number*,s); } - d += FLASH_WORDS(TValue); + *cast(int *,cast(lua_Number*,d)+1) = ttype(sv); s += FLASH_WORDS(TValue); - break; + d += TARGET_TV_SIZE/WORDSIZE; + break; default: lua_assert (0); } @@ -334,7 +342,7 @@ static void *functionToFlash(lua_State* L, const Proto* orig) { memcpy (&f, orig, sizeof(Proto)); f.gclist = NULL; f.next = NULL; - l_setbit(f.marked, FIXEDBIT); + l_setbit(f.marked, LFSBIT); /* OK to set the LFSBIT on a stack-cloned copy */ if (f.sizep) { /* clone included Protos */ Proto **p = luaM_newvector(L, f.sizep, Proto *); diff --git a/app/lua/liolib.c b/app/lua/luac_cross/liolib.c similarity index 52% rename from app/lua/liolib.c rename to app/lua/luac_cross/liolib.c index 4ac31fe4..e333a557 100644 --- a/app/lua/liolib.c +++ b/app/lua/luac_cross/liolib.c @@ -5,14 +5,14 @@ */ -// #include "c_errno.h" -#include "c_stdio.h" -#include "c_stdlib.h" -#include "c_string.h" -#include "vfs.h" +#include +#include +#include +#include #define liolib_c #define LUA_LIB +#define LUA_OPTIMIZE_MEMORY 2 #include "lua.h" @@ -20,26 +20,21 @@ #include "lualib.h" #include "lrotable.h" - #define IO_INPUT 1 #define IO_OUTPUT 2 #define IO_STDERR 0 -#if LUA_OPTIMIZE_MEMORY != 2 -#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_ENVIRONINDEX, f) -#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_ENVIRONINDEX, f) -#else -#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX, liolib_keys[f]) -#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[f]) +#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) +#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) /* "Pseudo-random" keys for the registry */ -static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int)&luaL_argerror}; -#endif +static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror}; static const char *const fnames[] = {"input", "output"}; + static int pushresult (lua_State *L, int i, const char *filename) { - int en = vfs_ferrno(0); /* calls to Lua API may change this value */ + int en = errno; /* calls to Lua API may change this value */ if (i) { lua_pushboolean(L, 1); return 1; @@ -47,9 +42,9 @@ static int pushresult (lua_State *L, int i, const char *filename) { else { lua_pushnil(L); if (filename) - lua_pushfstring(L, "%s: err(%d)", filename, en); + lua_pushfstring(L, "%s: %s", filename, strerror(en)); else - lua_pushfstring(L, "err(%d)", en); + lua_pushfstring(L, "%s", strerror(en)); lua_pushinteger(L, en); return 3; } @@ -57,12 +52,12 @@ static int pushresult (lua_State *L, int i, const char *filename) { static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: err(%d)", filename, vfs_ferrno(0)); + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); luaL_argerror(L, arg, lua_tostring(L, -1)); } -#define tofilep(L) ((int *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int io_type (lua_State *L) { @@ -72,7 +67,7 @@ static int io_type (lua_State *L) { lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) lua_pushnil(L); /* not a file */ - else if (*((int *)ud) < FS_OPEN_OK) + else if (*((FILE **)ud) == NULL) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); @@ -80,9 +75,9 @@ static int io_type (lua_State *L) { } -static int tofile (lua_State *L) { - int *f = tofilep(L); - if (*f < FS_OPEN_OK) +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) luaL_error(L, "attempt to use a closed file"); return *f; } @@ -94,91 +89,52 @@ static int tofile (lua_State *L) { ** before opening the actual file; so, if there is a memory error, the ** file is not left opened. */ -static int *newfile (lua_State *L) { - int *pf = (int *)lua_newuserdata(L, sizeof(int)); - *pf = FS_OPEN_OK - 1; /* file handle is currently `closed' */ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ luaL_getmetatable(L, LUA_FILEHANDLE); lua_setmetatable(L, -2); return pf; } -#if LUA_OPTIMIZE_MEMORY != 2 -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - -#if 0 -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - int *p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = FS_OPEN_OK - 1; - return pushresult(L, ok, NULL); -} -#endif - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - int *p = tofilep(L); - int ok = (vfs_close(*p) == 0); - *p = FS_OPEN_OK - 1; - return pushresult(L, ok, NULL); -} -#endif - static int aux_close (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY != 2 - lua_getfenv(L, 1); - lua_getfield(L, -1, "__close"); - return (lua_tocfunction(L, -1))(L); -#else - int *p = tofilep(L); - if(*p == c_stdin || *p == c_stdout || *p == c_stderr) + FILE **p = tofilep(L); + if(*p == stdin || *p == stdout || *p == stderr) { lua_pushnil(L); lua_pushliteral(L, "cannot close standard file"); - return 2; + return 2; } - int ok = (vfs_close(*p) == 0); - *p = FS_OPEN_OK - 1; + int ok = (fclose(*p) == 0); + *p = NULL; return pushresult(L, ok, NULL); -#endif } static int io_close (lua_State *L) { if (lua_isnone(L, 1)) - LUA_IO_GETFIELD(IO_OUTPUT); + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); tofile(L); /* make sure argument is a file */ return aux_close(L); } static int io_gc (lua_State *L) { - int f = *tofilep(L); + FILE *f = *tofilep(L); /* ignore closed files */ - if (f != FS_OPEN_OK - 1) + if (f != NULL) aux_close(L); return 0; } static int io_tostring (lua_State *L) { - int f = *tofilep(L); - if (f == FS_OPEN_OK - 1) + FILE *f = *tofilep(L); + if (f == NULL) lua_pushliteral(L, "file (closed)"); else - lua_pushfstring(L, "file (%i)", f); + lua_pushfstring(L, "file (%p)", f); return 1; } @@ -186,42 +142,19 @@ static int io_tostring (lua_State *L) { static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); - int *pf = newfile(L); - *pf = vfs_open(filename, mode); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -#if 0 -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - int *pf = newfile(L); - *pf = lua_popen(L, filename, fs_mode2flags(mode)); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - int *pf = newfile(L); - *pf = tmpfile(); - return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, NULL) : 1; -} -#endif - -static int getiofile (lua_State *L, int findex) { - int *pf; - LUA_IO_GETFIELD(findex); - pf = (int *)lua_touserdata(L, -1); - if (pf == NULL || *pf == FS_OPEN_OK - 1){ - luaL_error(L, "default %s file is closed", fnames[findex - 1]); - return FS_OPEN_OK - 1; - } - return *pf; +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; } @@ -229,19 +162,19 @@ static int g_iofile (lua_State *L, int f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); if (filename) { - int *pf = newfile(L); - *pf = vfs_open(filename, mode); - if (*pf == FS_OPEN_OK - 1) + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) fileerror(L, 1, filename); } else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } - LUA_IO_SETFIELD(f); + lua_rawseti(L, LUA_ENVIRONINDEX, f); } /* return current value */ - LUA_IO_GETFIELD(f); + lua_rawgeti(L, LUA_ENVIRONINDEX, f); return 1; } @@ -276,14 +209,14 @@ static int f_lines (lua_State *L) { static int io_lines (lua_State *L) { if (lua_isnoneornil(L, 1)) { /* no arguments? */ /* will iterate over default input */ - LUA_IO_GETFIELD(IO_INPUT); + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); return f_lines(L); } else { const char *filename = luaL_checkstring(L, 1); - int *pf = newfile(L); - *pf = vfs_open(filename, "r"); - if (*pf == FS_OPEN_OK - 1) + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) fileerror(L, 1, filename); aux_lines(L, lua_gettop(L), 1); return 1; @@ -297,10 +230,10 @@ static int io_lines (lua_State *L) { ** ======================================================= */ -#if 0 -static int read_number (lua_State *L, int f) { + +static int read_number (lua_State *L, FILE *f) { lua_Number d; - if (fs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) { + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { lua_pushnumber(L, d); return 1; } @@ -309,27 +242,27 @@ static int read_number (lua_State *L, int f) { return 0; /* read fails */ } } -#endif -static int test_eof (lua_State *L, int f) { - int c = vfs_getc(f); - vfs_ungetc(c, f); + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); lua_pushlstring(L, NULL, 0); return (c != EOF); } -#if 0 -static int read_line (lua_State *L, int f) { + +static int read_line (lua_State *L, FILE *f) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t l; char *p = luaL_prepbuffer(&b); - if (fs_gets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ luaL_pushresult(&b); /* close buffer */ return (lua_objlen(L, -1) > 0); /* check whether read something */ } - l = c_strlen(p); + l = strlen(p); if (l == 0 || p[l-1] != '\n') luaL_addsize(&b, l); else { @@ -339,27 +272,9 @@ static int read_line (lua_State *L, int f) { } } } -#else -static int read_line (lua_State *L, int f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - signed char c; - do { - c = (signed char)vfs_getc(f); - if (c==EOF) { - break; - } - if (c != '\n') { - luaL_addchar(&b, c); - } - } while (c != '\n'); - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ -} -#endif -static int read_chars (lua_State *L, int f, size_t n) { +static int read_chars (lua_State *L, FILE *f, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ luaL_Buffer b; @@ -368,7 +283,7 @@ static int read_chars (lua_State *L, int f, size_t n) { do { char *p = luaL_prepbuffer(&b); if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = vfs_read(f, p, rlen); + nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); n -= nr; /* still have to read `n' chars */ } while (n > 0 && nr == rlen); /* until end of count or eof */ @@ -377,11 +292,11 @@ static int read_chars (lua_State *L, int f, size_t n) { } -static int g_read (lua_State *L, int f, int first) { +static int g_read (lua_State *L, FILE *f, int first) { int nargs = lua_gettop(L) - 1; int success; int n; - //vfs_clearerr(f); + clearerr(f); if (nargs == 0) { /* no arguments? */ success = read_line(L, f); n = first+1; /* to return 1 result */ @@ -398,11 +313,9 @@ static int g_read (lua_State *L, int f, int first) { const char *p = lua_tostring(L, n); luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); switch (p[1]) { -#if 0 case 'n': /* number */ success = read_number(L, f); break; -#endif case 'l': /* line */ success = read_line(L, f); break; @@ -416,7 +329,7 @@ static int g_read (lua_State *L, int f, int first) { } } } - if (vfs_ferrno(f)) + if (ferror(f)) return pushresult(L, 0, NULL); if (!success) { lua_pop(L, 1); /* remove last result */ @@ -437,15 +350,13 @@ static int f_read (lua_State *L) { static int io_readline (lua_State *L) { - int *pf = (int *)lua_touserdata(L, lua_upvalueindex(1)); + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); int sucess; - if (pf == NULL || *pf == FS_OPEN_OK - 1){ /* file is already closed? */ + if (f == NULL) /* file is already closed? */ luaL_error(L, "file is already closed"); - return 0; - } - sucess = read_line(L, *pf); - if (vfs_ferrno(*pf)) - return luaL_error(L, "err(%d)", vfs_ferrno(*pf)); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); if (sucess) return 1; else { /* EOF */ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ @@ -460,22 +371,19 @@ static int io_readline (lua_State *L) { /* }====================================================== */ -static int g_write (lua_State *L, int f, int arg) { +static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; for (; nargs--; arg++) { -#if 0 if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ status = status && - fs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; } - else -#endif - { + else { size_t l; const char *s = luaL_checklstring(L, arg, &l); - status = status && (vfs_write(f, s, l) == l); + status = status && (fwrite(s, sizeof(char), l, f) == l); } } return pushresult(L, status, NULL); @@ -493,159 +401,103 @@ static int f_write (lua_State *L) { static int f_seek (lua_State *L) { - static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END}; + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; - int f = tofile(L); + FILE *f = tofile(L); int op = luaL_checkoption(L, 2, "cur", modenames); long offset = luaL_optlong(L, 3, 0); - op = vfs_lseek(f, offset, mode[op]); + op = fseek(f, offset, mode[op]); if (op) return pushresult(L, 0, NULL); /* error */ else { - lua_pushinteger(L, vfs_tell(f)); + lua_pushinteger(L, ftell(f)); return 1; } } -#if 0 + static int f_setvbuf (lua_State *L) { static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; static const char *const modenames[] = {"no", "full", "line", NULL}; - int f = tofile(L); + FILE *f = tofile(L); int op = luaL_checkoption(L, 2, NULL, modenames); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); int res = setvbuf(f, NULL, mode[op], sz); return pushresult(L, res == 0, NULL); } -#endif static int io_flush (lua_State *L) { - return pushresult(L, vfs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL); + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } static int f_flush (lua_State *L) { - return pushresult(L, vfs_flush(tofile(L)) == 0, NULL); + return pushresult(L, fflush(tofile(L)) == 0, NULL); } -#undef MIN_OPT_LEVEL #define MIN_OPT_LEVEL 2 #include "lrodefs.h" -#if LUA_OPTIMIZE_MEMORY == 2 const LUA_REG_TYPE iolib_funcs[] = { -#else -const LUA_REG_TYPE iolib[] = { -#endif - {LSTRKEY("close"), LFUNCVAL(io_close)}, - {LSTRKEY("flush"), LFUNCVAL(io_flush)}, - {LSTRKEY("input"), LFUNCVAL(io_input)}, - {LSTRKEY("lines"), LFUNCVAL(io_lines)}, - {LSTRKEY("open"), LFUNCVAL(io_open)}, - {LSTRKEY("output"), LFUNCVAL(io_output)}, - // {LSTRKEY("popen"), LFUNCVAL(io_popen)}, - {LSTRKEY("read"), LFUNCVAL(io_read)}, - // {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)}, - {LSTRKEY("type"), LFUNCVAL(io_type)}, - {LSTRKEY("write"), LFUNCVAL(io_write)}, + {LSTRKEY("close"), LFUNCVAL(io_close)}, + {LSTRKEY("flush"), LFUNCVAL(io_flush)}, + {LSTRKEY("input"), LFUNCVAL(io_input)}, + {LSTRKEY("lines"), LFUNCVAL(io_lines)}, + {LSTRKEY("open"), LFUNCVAL(io_open)}, + {LSTRKEY("output"), LFUNCVAL(io_output)}, + {LSTRKEY("read"), LFUNCVAL(io_read)}, + {LSTRKEY("type"), LFUNCVAL(io_type)}, + {LSTRKEY("write"), LFUNCVAL(io_write)}, + {LSTRKEY("__index"), LROVAL(iolib_funcs)}, {LNILKEY, LNILVAL} }; -#if LUA_OPTIMIZE_MEMORY == 2 -static int luaL_index(lua_State *L) +/* Note that IO objects use a RAM metatable created to allow extensibility */ + +static int io_index(lua_State *L) { return luaR_findfunction(L, iolib_funcs); } - + const luaL_Reg iolib[] = { - {"__index", luaL_index}, + {"__index", io_index}, {NULL, NULL} }; -#endif #undef MIN_OPT_LEVEL #define MIN_OPT_LEVEL 1 #include "lrodefs.h" const LUA_REG_TYPE flib[] = { - {LSTRKEY("close"), LFUNCVAL(io_close)}, - {LSTRKEY("flush"), LFUNCVAL(f_flush)}, - {LSTRKEY("lines"), LFUNCVAL(f_lines)}, - {LSTRKEY("read"), LFUNCVAL(f_read)}, - {LSTRKEY("seek"), LFUNCVAL(f_seek)}, - // {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)}, - {LSTRKEY("write"), LFUNCVAL(f_write)}, - {LSTRKEY("__gc"), LFUNCVAL(io_gc)}, + {LSTRKEY("close"), LFUNCVAL(io_close)}, + {LSTRKEY("flush"), LFUNCVAL(f_flush)}, + {LSTRKEY("lines"), LFUNCVAL(f_lines)}, + {LSTRKEY("read"), LFUNCVAL(f_read)}, + {LSTRKEY("seek"), LFUNCVAL(f_seek)}, + {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)}, + {LSTRKEY("write"), LFUNCVAL(f_write)}, + {LSTRKEY("__gc"), LFUNCVAL(io_gc)}, {LSTRKEY("__tostring"), LFUNCVAL(io_tostring)}, -#if LUA_OPTIMIZE_MEMORY > 0 - {LSTRKEY("__index"), LROVAL(flib)}, -#endif + {LSTRKEY("__index"), LROVAL(flib)}, {LNILKEY, LNILVAL} }; -static void createmeta (lua_State *L) { -#if LUA_OPTIMIZE_MEMORY == 0 - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_register(L, NULL, flib); /* file methods */ -#else - luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ -#endif -} - -static void createstdfile (lua_State *L, int f, int k, const char *fname) { +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { *newfile(L) = f; -#if LUA_OPTIMIZE_MEMORY != 2 - if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); - } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); -#else - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[k]); - lua_setfield(L, -2, fname); -#endif -} -#if LUA_OPTIMIZE_MEMORY != 2 -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, (int)(liolib_keys[k])); + lua_setfield(L, -2, fname); } -#endif LUALIB_API int luaopen_io (lua_State *L) { - createmeta(L); -#if LUA_OPTIMIZE_MEMORY != 2 - /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); - newfenv(L, io_noclose); /* close function for default files */ -#else + luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ luaL_register_light(L, LUA_IOLIBNAME, iolib); lua_pushvalue(L, -1); lua_setmetatable(L, -2); -#endif -#if 0 /* create (and set) default files */ - createstdfile(L, c_stdin, IO_INPUT, "stdin"); - createstdfile(L, c_stdout, IO_OUTPUT, "stdout"); - createstdfile(L, c_stderr, IO_STDERR, "stderr"); - -#if LUA_OPTIMIZE_MEMORY != 2 - lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ -#endif -#endif + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); return 1; } diff --git a/app/lua/luac_cross/luac.c b/app/lua/luac_cross/luac.c index 2dd909fc..a2fd1034 100644 --- a/app/lua/luac_cross/luac.c +++ b/app/lua/luac_cross/luac.c @@ -18,7 +18,7 @@ #include "lua.h" #include "lauxlib.h" - +#include "lualib.h" #include "ldo.h" #include "lfunc.h" #include "lmem.h" @@ -37,6 +37,7 @@ static int flash=0; /* output flash image */ static int lookup=0; /* output lookup-style master combination header */ static char Output[]={ OUTPUT }; /* default output file name */ static const char* output=Output; /* actual output file name */ +static const char* execute; /* executed a Lua file */ static const char* progname=PROGNAME; /* actual program name */ static DumpTargetInfo target; @@ -66,6 +67,7 @@ static void usage(const char* message) " - process stdin\n" " -l list\n" " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -e name execute a lua source file\n" " -f output a flash image file\n" " -i generate lookup combination master (default with option -f)\n" " -p parse only\n" @@ -93,8 +95,14 @@ static int doargs(int argc, char* argv[]) if (version) ++version; break; } - else if (IS("-")) /* end of options; use stdin */ + else if (IS("-")) /* end of options; use stdin */ break; + else if (IS("-e")) /* execute a lua source file file */ + { + execute=argv[++i]; + if (execute ==NULL || *execute==0 || *execute=='-' ) + usage(LUA_QL("-e") " needs argument"); + } else if (IS("-f")) /* Flash image file */ { flash=1; @@ -242,12 +250,25 @@ static int pmain(lua_State* L) const Proto* f; int i; if (!lua_checkstack(L,argc)) fatal("too many input files"); + if (execute) + { + if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1)); + luaL_openlibs(L); + lua_pushstring(L, execute); + if (lua_pcall(L, 1, 1, 0)) fatal(lua_tostring(L,-1)); + if (!lua_isfunction(L, -1)) + { + lua_pop(L,1); + if(argc == 0) return 0; + execute = NULL; + } + } for (i=0; i1); if (dumping) { @@ -286,7 +307,7 @@ int main(int argc, char* argv[]) int i=doargs(argc,argv); argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); + if (argc<=0 && execute==0) usage("no input files given"); L=lua_open(); if (L==NULL) fatal("not enough memory for state"); s.argc=argc; diff --git a/app/lua/luaconf.h b/app/lua/luaconf.h index d039b18f..aaeba816 100644 --- a/app/lua/luaconf.h +++ b/app/lua/luaconf.h @@ -167,7 +167,7 @@ #define LUA_INTEGER ptrdiff_t #else #if !defined LUA_INTEGRAL_LONGLONG - #define LUA_INTEGER long + #define LUA_INTEGER int #else #define LUA_INTEGER long long #endif // #if !defined LUA_INTEGRAL_LONGLONG @@ -487,7 +487,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length); /* 16-bit ints */ #define LUAI_UINT32 unsigned long #define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX +#define LUAI_MAXINT32 INT_MAX #define LUAI_UMEM unsigned long #define LUAI_MEM long #endif @@ -607,8 +607,8 @@ extern int readline4lua(const char *prompt, char *buffer, int length); */ #if defined LUA_NUMBER_INTEGRAL #if !defined LUA_INTEGRAL_LONGLONG - #define LUA_NUMBER_SCAN "%ld" - #define LUA_NUMBER_FMT "%ld" + #define LUA_NUMBER_SCAN "%d" + #define LUA_NUMBER_FMT "%d" #else #define LUA_NUMBER_SCAN "%lld" #define LUA_NUMBER_FMT "%lld" @@ -894,7 +894,7 @@ union luai_Cast { double l_d; long l_l; }; /* If you define the next macro you'll get the ability to set rotables as metatables for tables/userdata/types (but the VM might run slower) */ -#if (LUA_OPTIMIZE_MEMORY == 2) && !defined(LUA_CROSS_COMPILER) +#if (LUA_OPTIMIZE_MEMORY == 2) #define LUA_META_ROTABLES #endif diff --git a/app/lua/lundump.c b/app/lua/lundump.c index 76178c20..0baedf29 100644 --- a/app/lua/lundump.c +++ b/app/lua/lundump.c @@ -172,7 +172,7 @@ static TString* LoadString(LoadState* S) } else { s = (char*)luaZ_get_crt_address(S->Z); LoadBlock(S,NULL,size); - return luaS_newrolstr(S->L,s,size-1); + return luaS_newlstr(S->L,s,size-1); } } } @@ -280,7 +280,7 @@ static Proto* LoadFunction(LoadState* S, TString* p) Proto* f; if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); f=luaF_newproto(S->L); - if (luaZ_direct_mode(S->Z)) proto_readonly(f); + if (luaZ_direct_mode(S->Z)) l_setbit((f)->marked, READONLYBIT); setptvalue2s(S->L,S->L->top,f); incr_top(S->L); f->source=LoadString(S); if (f->source==NULL) f->source=p; f->linedefined=LoadInt(S); diff --git a/app/lua/lvm.c b/app/lua/lvm.c index 51cf9f21..0e256d8f 100644 --- a/app/lua/lvm.c +++ b/app/lua/lvm.c @@ -41,7 +41,7 @@ LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) { LUA_NUMBER c = 1; for (;;) { if (b & 1) - c *= a; + c *= a; b = b >> 1; if (b == 0) return c; diff --git a/app/modules/Makefile b/app/modules/Makefile index 316bd011..23d298b7 100644 --- a/app/modules/Makefile +++ b/app/modules/Makefile @@ -50,7 +50,7 @@ INCLUDES += -I ../pcm INCLUDES += -I ../platform INCLUDES += -I ../spiffs INCLUDES += -I ../smart -INCLUDES += -I ../dhtlib +INCLUDES += -I ../dht INCLUDES += -I ../fatfs INCLUDES += -I ../http INCLUDES += -I ../sjson diff --git a/app/modules/linit.c b/app/modules/linit.c deleted file mode 100644 index da14b73b..00000000 --- a/app/modules/linit.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ -** Initialization of libraries for lua.c -** See Copyright Notice in lua.h -*/ - - -#define linit_c -#define LUA_LIB -#define LUAC_CROSS_FILE - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" -#include "luaconf.h" -#include "module.h" - - -BUILTIN_LIB_INIT( BASE, "", luaopen_base); -BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package); - -#if defined(LUA_USE_BUILTIN_IO) -BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io); -#endif - -#if defined (LUA_USE_BUILTIN_STRING) -extern const luaR_entry strlib[]; -BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string); -BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib); -#endif - -#if defined(LUA_USE_BUILTIN_TABLE) -extern const luaR_entry tab_funcs[]; -BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table); -BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs); -#endif - -#if defined(LUA_USE_BUILTIN_DEBUG) || defined(LUA_USE_BUILTIN_DEBUG_MINIMAL) -extern const luaR_entry dblib[]; -BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug); -BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib); -#endif - -#if defined(LUA_USE_BUILTIN_OS) -extern const luaR_entry syslib[]; -BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib); -#endif - -#if defined(LUA_USE_BUILTIN_COROUTINE) -extern const luaR_entry co_funcs[]; -BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs); -#endif - -#if defined(LUA_USE_BUILTIN_MATH) -extern const luaR_entry math_map[]; -BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map); -#endif - -#ifdef LUA_CROSS_COMPILER -const luaL_Reg lua_libs[] = {{NULL, NULL}}; -const luaR_table lua_rotable[] = {{NULL, NULL}}; -#else -extern const luaL_Reg lua_libs[]; -#endif - -void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lua_libs; - for (; lib->name; lib++) { - if (lib->func) - { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } - } -} - diff --git a/app/modules/node.c b/app/modules/node.c index 8302ec8c..bfc5ae06 100644 --- a/app/modules/node.c +++ b/app/modules/node.c @@ -17,7 +17,9 @@ #include "platform.h" #include "lrodefs.h" - +#ifdef LUA_FLASH_STORE +#include "lflash.h" +#endif #include "c_types.h" #include "c_string.h" #include "driver/uart.h" @@ -134,7 +136,6 @@ static int node_chipid( lua_State* L ) // lua_pushinteger(L, vdd33); // return 1; // } - // Lua: flashid() static int node_flashid( lua_State* L ) { @@ -574,6 +575,13 @@ static const LUA_REG_TYPE node_task_map[] = { { LSTRKEY( "HIGH_PRIORITY" ), LNUMVAL( TASK_PRIORITY_HIGH ) }, { LNILKEY, LNILVAL } }; +#ifdef LUA_FLASH_STORE +static const LUA_REG_TYPE node_flash_map[] = { + { LSTRKEY( "reload" ), LFUNCVAL( luaN_reload_reboot ) }, + { LSTRKEY( "index" ), LFUNCVAL( luaN_index ) }, + { LNILKEY, LNILVAL } +}; +#endif static const LUA_REG_TYPE node_map[] = { @@ -601,6 +609,9 @@ static const LUA_REG_TYPE node_map[] = { LSTRKEY( "random" ), LFUNCVAL( node_random) }, #ifdef LUA_OPTIMIZE_DEBUG { LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) }, +#endif +#ifdef LUA_FLASH_STORE + { LSTRKEY( "flash") , LROVAL( node_flash_map ) }, #endif { LSTRKEY( "egc" ), LROVAL( node_egc_map ) }, { LSTRKEY( "task" ), LROVAL( node_task_map ) }, diff --git a/app/mqtt/Makefile b/app/mqtt/Makefile index 925cb5b7..efa5055c 100644 --- a/app/mqtt/Makefile +++ b/app/mqtt/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = mqtt.a +GEN_LIBS = libmqtt.a endif STD_CFLAGS=-std=gnu11 -Wimplicit diff --git a/app/pcm/Makefile b/app/pcm/Makefile index efa7e3bd..18ae9c44 100644 --- a/app/pcm/Makefile +++ b/app/pcm/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = pcm.a +GEN_LIBS = libpcm.a endif STD_CFLAGS=-std=gnu11 -Wimplicit diff --git a/app/platform/common.c b/app/platform/common.c index aa6fdba7..1140cf9a 100644 --- a/app/platform/common.c +++ b/app/platform/common.c @@ -67,22 +67,54 @@ uint32_t platform_flash_get_num_sectors(void) #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE } +static uint32_t allocated = 0; +static uint32_t phys_flash_used_end = 0; //Phyiscal address of last byte in last flash used sector + +uint32_t platform_flash_reserve_section( uint32_t regsize, uint32_t *start ) +{ + // Return Flash sector no (and optional flash mapped address of first allocated byte) + + if(phys_flash_used_end == 0) + flashh_find_sector(platform_flash_mapped2phys( (uint32_t)_flash_used_end - 1), NULL, &phys_flash_used_end ); + + /* find sector and last byte address of previous allocation */ + uint32_t end; + uint32_t sect = flashh_find_sector( phys_flash_used_end + allocated, NULL, &end ); + if(start) + *start = end + 1; + + /* allocated regions are always sector aligned */ + flashh_find_sector( phys_flash_used_end + allocated + regsize, NULL, &end ); + allocated = end - phys_flash_used_end; + + NODE_DBG("Flash base: %08x %08x %08x\n", regsize, allocated, phys_flash_used_end); + return sect + 1; +} + uint32_t platform_flash_get_first_free_block_address( uint32_t *psect ) { // Round the total used flash size to the closest flash block address uint32_t start, end, sect; NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end); +#if 0 if(_flash_used_end>0){ // find the used sector sect = flashh_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end ); - if( psect ) - *psect = sect + 1; - return end + 1; + sect++; + start = end + 1; }else{ sect = flashh_find_sector( 0, &start, NULL ); // find the first free sector - if( psect ) - *psect = sect; - return start; } + if(_flash_used_end>0){ // find the used sector + uint32_t sta1, sec1; + sec1 = platform_flash_reserve_section( 0, &sta1 ); + NODE_DBG("Flash base: %p %p %p %p\n", sect, start, sec1, sta1); + } +#endif + sect = _flash_used_end ? platform_flash_reserve_section( 0, &start ) : + flashh_find_sector( 0, &start, NULL ); + if( psect ) + *psect = sect; + return start; } uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size ) diff --git a/app/platform/platform.c b/app/platform/platform.c index 89d5070e..c296bb3c 100644 --- a/app/platform/platform.c +++ b/app/platform/platform.c @@ -879,7 +879,7 @@ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t siz if(SPI_FLASH_RESULT_OK == r) return size; else{ - NODE_ERR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr); + NODE_ERR( "ERROR in flash_write: r=%d at %p\n", ( int )r, ( unsigned )toaddr); return 0; } } @@ -917,7 +917,7 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size ) if(SPI_FLASH_RESULT_OK == r) return size; else{ - NODE_ERR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr); + NODE_ERR( "ERROR in flash_read: r=%d at %p\n", ( int )r, ( unsigned )fromaddr); return 0; } } @@ -928,15 +928,26 @@ int platform_flash_erase_sector( uint32_t sector_id ) return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR; } -uint32_t platform_flash_mapped2phys (uint32_t mapped_addr) +static uint32_t flash_map_meg_offset () { uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG); if (!(cache_ctrl & CACHE_FLASH_ACTIVE)) return -1; bool b0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 1 : 0; bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0; - uint32_t meg = (b1 << 1) | b0; - return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000; + return ((b1 << 1) | b0) * 0x100000; +} + +uint32_t platform_flash_mapped2phys (uint32_t mapped_addr) +{ + uint32_t meg = flash_map_meg_offset(); + return (meg&1) ? -1 : mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg ; +} + +uint32_t platform_flash_phys2mapped (uint32_t phys_addr) +{ + uint32_t meg = flash_map_meg_offset(); + return (meg&1) ? -1 : phys_addr + INTERNAL_FLASH_MAPPED_ADDRESS - meg; } void* platform_print_deprecation_note( const char *msg, const char *time_frame) diff --git a/app/platform/platform.h b/app/platform/platform.h index a1ab812b..aba89a05 100644 --- a/app/platform/platform.h +++ b/app/platform/platform.h @@ -268,8 +268,11 @@ uint32_t platform_eth_get_elapsed_time(void); // ***************************************************************************** // Internal flash erase/write functions +uint32_t platform_flash_reserve_section( uint32_t regsize, uint32_t *start ); uint32_t platform_flash_get_first_free_block_address( uint32_t *psect ); uint32_t platform_flash_get_sector_of_address( uint32_t addr ); +uint32_t platform_flash_mapped2phys (uint32_t mapped_addr); +uint32_t platform_flash_phys2mapped (uint32_t phys_addr); uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size ); uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size ); uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size ); diff --git a/app/tsl2561/Makefile b/app/tsl2561/Makefile index 7963bd5d..762105c0 100644 --- a/app/tsl2561/Makefile +++ b/app/tsl2561/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = tsl2561lib.a +GEN_LIBS = libtsl2561.a endif STD_CFLAGS=-std=gnu11 -Wimplicit diff --git a/app/u8glib/Makefile b/app/u8glib/Makefile index 7495a1d7..773f40bb 100644 --- a/app/u8glib/Makefile +++ b/app/u8glib/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = u8glib.a +GEN_LIBS = libu8glib.a endif STD_CFLAGS=-std=gnu11 -Wimplicit diff --git a/app/ucglib/Makefile b/app/ucglib/Makefile index 6a9c929b..ddd3d94f 100644 --- a/app/ucglib/Makefile +++ b/app/ucglib/Makefile @@ -12,7 +12,7 @@ # a generated lib/image xxx.a () # ifndef PDIR -GEN_LIBS = ucglib.a +GEN_LIBS = libucglib.a endif STD_CFLAGS=-std=gnu11 -Wimplicit diff --git a/app/user/user_main.c b/app/user/user_main.c index 97c18365..16b44f73 100644 --- a/app/user/user_main.c +++ b/app/user/user_main.c @@ -240,6 +240,7 @@ user_rf_cal_sector_set(void) return rf_cal_sec; } +extern void luaN_user_init(void); /****************************************************************************** * FunctionName : user_init * Description : entry of user application, init user function here @@ -261,5 +262,9 @@ void user_init(void) system_set_os_print(0); #endif +#ifdef LUA_FLASH_STORE + luaN_user_init(); +#endif + system_init_done_cb(nodemcu_init); } diff --git a/docs/en/modules/node.md b/docs/en/modules/node.md index e34c31f3..85a7ce35 100644 --- a/docs/en/modules/node.md +++ b/docs/en/modules/node.md @@ -173,7 +173,7 @@ system heap size left in bytes (number) ## node.info() -Returns NodeMCU version, chipid, flashid, flash size, flash mode, flash speed. +Returns NodeMCU version, chipid, flashid, flash size, flash mode, flash speed, and Lua File Store (LFS) usage statics. #### Syntax `node.info()` @@ -496,6 +496,37 @@ provides more detailed information on the EGC. `node.egc.setmode(node.egc.ALWAYS, 4096) -- This is the default setting at startup.` `node.egc.setmode(node.egc.ON_ALLOC_FAILURE) -- This is the fastest activeEGC mode.` +# node.flash module + +## node.flash.index() + +Returns the function reference for a function in the LFS (Lua Flash Store). + +#### Syntax +`node.flash.index()` + +#### Parameters +None + +#### Returns +- In the case where the LFS in not loaded, `node.flash.index` evaluates to `nil` +- If the LFS is loaded, this returns the index function within the LFS which indexes its contents. This index function can itself to called to interrogate or access the LFS contents: + - In that case where the function is called with the name of a valid module in the LFS, the function is returned in the same way the `load()` and the other Lua load functions do. + - Otherwise the function returns a list of module names in the LFS. Note that the first entry in the list is the Unix datetime of he build. + +## node.flash.reload() + +Reload the LFS (Lua Flash Store) with the flash image provided. Flash images are generated on the host machine using the `luac.cross`commnad. + +#### Syntax +`node.flash.rebuild(imageName)` + +#### Parameters +`imageName` The of name of a image file in the filesystem to be loaded into the LFS. + +#### Returns +_Not applicable_. The ESP will load the LFS image and immediately reboot. Control is not returned to the calling application. + # node.task module ## node.task.post() diff --git a/ld/nodemcu.ld b/ld/nodemcu.ld index 80a80058..2a66a906 100644 --- a/ld/nodemcu.ld +++ b/ld/nodemcu.ld @@ -234,11 +234,11 @@ SECTIONS /* Link-time arrays containing the defs for the included modules */ . = ALIGN(4); - lua_libs = ABSOLUTE(.); + lua_libs_base = ABSOLUTE(.); /* Allow either empty define or defined-to-1 to include the module */ KEEP(*(.lua_libs)) LONG(0) LONG(0) /* Null-terminate the array */ - lua_rotable = ABSOLUTE(.); + lua_rotable_base = ABSOLUTE(.); KEEP(*(.lua_rotable)) LONG(0) LONG(0) /* Null-terminate the array */ diff --git a/tools/Makefile b/tools/Makefile index b5c5b30e..608e9850 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -5,8 +5,8 @@ FSSOURCE ?= ../local/fs/ LUASOURCE ?= ../local/lua/ FLASHSIZE ?= 4mb 32mb 8mb +FLASH_SW = -S SUBDIRS = -HOSTCC ?= gcc OBJDUMP = $(or $(shell which objdump),xtensa-lx106-elf-objdump) @@ -20,16 +20,16 @@ SPIFFSFILES ?= $(patsubst $(FSSOURCE)%,%,$(shell find $(FSSOURCE) -name '*' '!' # Get the filesize of /bin/0x10000.bin and SPIFFS sizing # -FLASH_USED_END := $$((0x`$(OBJDUMP) -t ../app/.output/eagle/debug/image/eagle.app.v6.out |grep _flash_used_end |cut -f1 -d" "` - 0x40200000)) -FLASH_FS_SIZE := $(shell $(HOSTCC) -E -dM - <../app/include/user_config.h | grep SPIFFS_MAX_FILESYSTEM_SIZE| cut -d ' ' -f 3) -FLASH_FS_LOC := $(shell $(HOSTCC) -E -dM - <../app/include/user_config.h | grep SPIFFS_FIXED_LOCATION| cut -d ' ' -f 3) +FLASH_FS_SIZE := $(shell $(CC) -E -dM - <../app/include/user_config.h | grep SPIFFS_MAX_FILESYSTEM_SIZE| cut -d ' ' -f 3) -ifneq (FLASH_FS_SIZE,'') +ifneq ($(strip $(FLASH_FS_SIZE)),) FLASHSIZE = $(shell printf "0x%x" $(FLASH_FS_SIZE)) +FLASH_SW = -c endif -ifeq (FLASH_FS_LOC,'') -FLASH_FS_LOC := $(FLASH_USED_END) +FLASH_FS_LOC := $(shell $(CC) -E -dM - <../app/include/user_config.h | grep SPIFFS_FIXED_LOCATION| cut -d ' ' -f 3) +ifeq ($(strip $(FLASH_FS_LOC)),) +FLASH_FS_LOC := $(shell printf "0x%x" $$((0x$(shell $(OBJDUMP) -t ../app/.output/eagle/debug/image/eagle.app.v6.out |grep " _flash_used_end" |cut -f1 -d" ") - 0x40200000))) else FLASH_FS_LOC := $(shell printf "0x%x" $(FLASH_FS_LOC)) endif @@ -42,6 +42,16 @@ endif all: spiffsscript +.PHONY: TEST + +TEST: + @echo $(FLASHSIZE) + @echo $(FLASH_FS_SIZE) + @echo $(FLASH_FS_LOC) + @echo $(FLASH_USED_END) + +spiffsimg/spiffsimg: + .PHONY: spiffsimg .PHONY: spiffsimg/spiffsimg @@ -56,7 +66,7 @@ spiffsscript: remove-image LFSimage spiffsimg/spiffsimg rm -f ./spiffsimg/spiffs.lst @echo "" >> ./spiffsimg/spiffs.lst @$(foreach f, $(SPIFFSFILES), echo "import $(FSSOURCE)$(f) $(f)" >> ./spiffsimg/spiffs.lst ;) - $(foreach sz, $(FLASHSIZE), spiffsimg/spiffsimg -f ../bin/0x%x-$(sz).img -c $(sz) -U $(FLASH_FS_LOC) -r ./spiffsimg/spiffs.lst -d; ) + $(foreach sz, $(FLASHSIZE), spiffsimg/spiffsimg -f ../bin/0x%x-$(sz).img $(FLASH_SW) $(sz) -U $(FLASH_FS_LOC) -r ./spiffsimg/spiffs.lst -d; ) @$(foreach sz, $(FLASHSIZE), if [ -r ../bin/spiffs-$(sz).dat ]; then echo Built $$(cat ../bin/spiffs-$(sz).dat)-$(sz).bin; fi; ) LFSimage: $(LUASOURCE)*.lua