diff --git a/app/include/module.h b/app/include/module.h index b727fa9b97..a892f21395 100644 --- a/app/include/module.h +++ b/app/include/module.h @@ -57,18 +57,8 @@ const LOCK_IN_SECTION(libs) \ luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \ 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(libs) \ - luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc } - -#define BUILTIN_LIB(name, luaname, map) \ - const LOCK_IN_SECTION(rotable) \ - luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map } + luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \ + = {LSTRKEY(luaname), LROVAL(map)} #if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2) # error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)" diff --git a/app/lua/lauxlib.c b/app/lua/lauxlib.c index c6d6f5ba07..22ef0b9be9 100644 --- a/app/lua/lauxlib.c +++ b/app/lua/lauxlib.c @@ -25,8 +25,6 @@ #define lauxlib_c #define LUA_LIB -#include "lrotable.h" - #include "lauxlib.h" #include "lgc.h" #include "ldo.h" @@ -555,14 +553,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx, if (e == NULL) e = fname + c_strlen(fname); lua_pushlstring(L, fname, e - fname); lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - /* If looking for a global variable, check the rotables too */ - void *ptable = luaR_findglobal(fname, e - fname); - if (ptable) { - lua_pop(L, 1); - lua_pushrotable(L, ptable); - } - } + if (lua_isnil(L, -1)) { /* no such field? */ lua_pop(L, 1); /* remove this nil */ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ diff --git a/app/lua/lbaselib.c b/app/lua/lbaselib.c index a08f3eaa3d..59aa33ddf1 100644 --- a/app/lua/lbaselib.c +++ b/app/lua/lbaselib.c @@ -16,7 +16,7 @@ #include C_HEADER_STDLIB #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" +#include "lrodefs.h" @@ -462,71 +462,62 @@ static int luaB_newproxy (lua_State *L) { return 1; } -#define LUA_BASELIB_FUNCLIST\ - {LSTRKEY("assert"), LFUNCVAL(luaB_assert)},\ - {LSTRKEY("collectgarbage"), LFUNCVAL(luaB_collectgarbage)},\ - {LSTRKEY("dofile"), LFUNCVAL(luaB_dofile)},\ - {LSTRKEY("error"), LFUNCVAL(luaB_error)},\ - {LSTRKEY("gcinfo"), LFUNCVAL(luaB_gcinfo)},\ - {LSTRKEY("getfenv"), LFUNCVAL(luaB_getfenv)},\ - {LSTRKEY("getmetatable"), LFUNCVAL(luaB_getmetatable)},\ - {LSTRKEY("loadfile"), LFUNCVAL(luaB_loadfile)},\ - {LSTRKEY("load"), LFUNCVAL(luaB_load)},\ - {LSTRKEY("loadstring"), LFUNCVAL(luaB_loadstring)},\ - {LSTRKEY("next"), LFUNCVAL(luaB_next)},\ - {LSTRKEY("pcall"), LFUNCVAL(luaB_pcall)},\ - {LSTRKEY("print"), LFUNCVAL(luaB_print)},\ - {LSTRKEY("rawequal"), LFUNCVAL(luaB_rawequal)},\ - {LSTRKEY("rawget"), LFUNCVAL(luaB_rawget)},\ - {LSTRKEY("rawset"), LFUNCVAL(luaB_rawset)},\ - {LSTRKEY("select"), LFUNCVAL(luaB_select)},\ - {LSTRKEY("setfenv"), LFUNCVAL(luaB_setfenv)},\ - {LSTRKEY("setmetatable"), LFUNCVAL(luaB_setmetatable)},\ - {LSTRKEY("tonumber"), LFUNCVAL(luaB_tonumber)},\ - {LSTRKEY("tostring"), LFUNCVAL(luaB_tostring)},\ - {LSTRKEY("type"), LFUNCVAL(luaB_type)},\ - {LSTRKEY("unpack"), LFUNCVAL(luaB_unpack)},\ - {LSTRKEY("xpcall"), LFUNCVAL(luaB_xpcall)} - -#if LUA_OPTIMIZE_MEMORY == 2 -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 2 #include "lrodefs.h" -const LUA_REG_TYPE base_funcs_list[] = { - LUA_BASELIB_FUNCLIST, - {LNILKEY, LNILVAL} -}; -#endif +extern const luaR_entry lua_rotable_base[]; -static int luaB_index(lua_State *L) { -#if LUA_OPTIMIZE_MEMORY == 2 - int fres; - if ((fres = luaR_findfunction(L, base_funcs_list)) != 0) - return fres; -#endif - const char *keyname = luaL_checkstring(L, 2); - if (!c_strcmp(keyname, "_VERSION")) { - lua_pushliteral(L, LUA_VERSION); - return 1; - } - void *res = luaR_findglobal(keyname, c_strlen(keyname)); - if (!res) - return 0; - else { - lua_pushrotable(L, res); - return 1; - } -} +/* + * ESP builds use specific linker directives to marshal all ROTable declarations + * into a single ROTable in the PSECT ".lua_rotable". + * + * This is not practical on Posix builds using a standard link so for cross + * compiler builds, separate ROTables are used for the base functions and library + * ROTables, with the latter chained from the former using its __index meta-method. + * In this case all library ROTables are defined in linit.c. + */ +#ifdef LUA_CROSS_COMPILER +#define BASE_ROTABLE base_func_map +#define LOCK_IN_ROTABLE +static const LUA_REG_TYPE base_func_meta[] = { + LROT_TABENTRY(__index, lua_rotable_base), + LROT_END}; +#else +#define BASE_ROTABLE lua_rotable_base +#define LOCK_IN_ROTABLE __attribute__((used,unused,section(".lua_rotable"))) +#endif -static const luaL_Reg base_funcs[] = { -#if LUA_OPTIMIZE_MEMORY != 2 -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 0 -#include "lrodefs.h" - LUA_BASELIB_FUNCLIST, +static const LUA_REG_TYPE LOCK_IN_ROTABLE base_func_map[] = { + LROT_FUNCENTRY(assert, luaB_assert), + LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage), + LROT_FUNCENTRY(dofile, luaB_dofile), + LROT_FUNCENTRY(error, luaB_error), + LROT_FUNCENTRY(gcinfo, luaB_gcinfo), + LROT_FUNCENTRY(getfenv, luaB_getfenv), + LROT_FUNCENTRY(getmetatable, luaB_getmetatable), + LROT_FUNCENTRY(loadfile, luaB_loadfile), + LROT_FUNCENTRY(load, luaB_load), + LROT_FUNCENTRY(loadstring, luaB_loadstring), + LROT_FUNCENTRY(next, luaB_next), + LROT_FUNCENTRY(pcall, luaB_pcall), + LROT_FUNCENTRY(print, luaB_print), + LROT_FUNCENTRY(rawequal, luaB_rawequal), + LROT_FUNCENTRY(rawget, luaB_rawget), + LROT_FUNCENTRY(rawset, luaB_rawset), + LROT_FUNCENTRY(select, luaB_select), + LROT_FUNCENTRY(setfenv, luaB_setfenv), + LROT_FUNCENTRY(setmetatable, luaB_setmetatable), + LROT_FUNCENTRY(tonumber, luaB_tonumber), + LROT_FUNCENTRY(tostring, luaB_tostring), + LROT_FUNCENTRY(type, luaB_type), + LROT_FUNCENTRY(unpack, luaB_unpack), + LROT_FUNCENTRY(xpcall, luaB_xpcall) +#ifdef LUA_CROSS_COMPILER + ,LROT_TABENTRY(__metatable, base_func_meta), + LROT_END #endif - {"__index", luaB_index}, +}; + +static const luaL_Reg base_funcs[] = { {NULL, NULL} }; @@ -661,7 +652,6 @@ static int luaB_corunning (lua_State *L) { #undef MIN_OPT_LEVEL #define MIN_OPT_LEVEL 1 -#include "lrodefs.h" const LUA_REG_TYPE co_funcs[] = { {LSTRKEY("create"), LFUNCVAL(luaB_cocreate)}, {LSTRKEY("resume"), LFUNCVAL(luaB_coresume)}, @@ -682,7 +672,6 @@ static void auxopen (lua_State *L, const char *name, lua_setfield(L, -2, name); } - static void base_open (lua_State *L) { /* set global _G */ lua_pushvalue(L, LUA_GLOBALSINDEX); @@ -691,11 +680,12 @@ static void base_open (lua_State *L) { luaL_register_light(L, "_G", base_funcs); #if LUA_OPTIMIZE_MEMORY > 0 lua_pushvalue(L, -1); - lua_setmetatable(L, -2); -#else + lua_setmetatable(L, -2); + lua_pushrotable(L, (void *)BASE_ROTABLE); + lua_setglobal(L, "__index"); +#endif lua_pushliteral(L, LUA_VERSION); lua_setglobal(L, "_VERSION"); /* set global _VERSION */ -#endif /* `ipairs' and `pairs' need auxliliary functions as upvalues */ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "pairs", luaB_pairs, luaB_next); diff --git a/app/lua/ldblib.c b/app/lua/ldblib.c index e084e23374..073ea9633f 100644 --- a/app/lua/ldblib.c +++ b/app/lua/ldblib.c @@ -16,7 +16,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" #include "lstring.h" #include "lflash.h" #include "user_modules.h" diff --git a/app/lua/lgc.c b/app/lua/lgc.c index 992d6fff03..d49421bde6 100644 --- a/app/lua/lgc.c +++ b/app/lua/lgc.c @@ -168,10 +168,14 @@ static int traversetable (global_State *g, Table *h) { int i; int weakkey = 0; int weakvalue = 0; - const TValue *mode; - if (h->metatable && !luaR_isrotable(h->metatable)) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); + const TValue *mode = luaO_nilobject; + + if (h->metatable) { + if (!luaR_isrotable(h->metatable)) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + } + if (mode && ttisstring(mode)) { /* is there a weak mode? */ weakkey = (c_strchr(svalue(mode), 'k') != NULL); weakvalue = (c_strchr(svalue(mode), 'v') != NULL); diff --git a/app/lua/linit.c b/app/lua/linit.c index 1a7c4b5813..b511d55383 100644 --- a/app/lua/linit.c +++ b/app/lua/linit.c @@ -15,60 +15,71 @@ #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); + +#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2) +# error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)" #endif + extern const luaR_entry strlib[], tab_funcs[], dblib[], co_funcs[], math_map[], syslib[]; +extern const luaR_entry syslib[], io_funcs[]; // Only used on cross-compile builds -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. + * The NodeMCU Lua initalisation has been adapted to use linker-based module + * registration. This uses a PSECT naming convention to allow the lib and rotab + * entries to be collected by the linker into consoliated tables. The linker + * defines lua_libs_base and lua_rotable_base. + * + * This is not practical on Posix builds which use a standard loader declaration + * so for cross compiler builds, separate ROTables are used for the base functions + * and library ROTables, with the latter chained from the former using its __index + * meta-method. In this case all library ROTables are defined here, avoiding the + * need for linker magic is avoided on host builds. */ -#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 */ + +#if defined(LUA_CROSS_COMPILER) +#define LUA_ROTABLES lua_rotable_base +#define LUA_LIBS lua_libs_base +#else /* declare Xtensa toolchain linker defined constants */ 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; +extern const luaR_entry lua_rotable_base[]; +#define LUA_ROTABLES lua_rotable_core +#define LUA_LIBS lua_libs_core #endif + +static const LOCK_IN_SECTION(libs) luaL_reg LUA_LIBS[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_DBLIBNAME, luaopen_debug} +#if defined(LUA_CROSS_COMPILER) + ,{LUA_IOLIBNAME, luaopen_io}, + {NULL, NULL} +#endif +}; -void luaL_openlibs (lua_State *L) { +#define ENTRY(n,t) {LSTRKEY(n), LRO_ROVAL(t)} + +const LOCK_IN_SECTION(rotable) ROTable LUA_ROTABLES[] = { + ENTRY("ROM", LUA_ROTABLES), + ENTRY(LUA_STRLIBNAME, strlib), + ENTRY(LUA_TABLIBNAME, tab_funcs), + ENTRY(LUA_DBLIBNAME, dblib), + ENTRY(LUA_COLIBNAME, co_funcs), + ENTRY(LUA_MATHLIBNAME, math_map) #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; + ,ENTRY(LUA_OSLIBNAME, syslib), + LROT_END #endif - const luaL_Reg *lib = lua_libs; + }; + +void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib = lua_libs_base; + + /* loop round and open libraries */ for (; lib->name; lib++) { - if (lib->func) - { + 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 8a3b975461..0670b41962 100644 --- a/app/lua/lmathlib.c +++ b/app/lua/lmathlib.c @@ -15,7 +15,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" #undef PI #define PI (3.14159265358979323846) diff --git a/app/lua/loadlib.c b/app/lua/loadlib.c index f884c3ca3a..ef1d33194d 100644 --- a/app/lua/loadlib.c +++ b/app/lua/loadlib.c @@ -24,7 +24,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" @@ -474,10 +473,11 @@ static int ll_require (lua_State *L) { return 1; /* package is already loaded */ } /* Is this a readonly table? */ - void *res = luaR_findglobal(name, c_strlen(name)); - if (res) { - lua_pushrotable(L, res); + lua_getfield(L, LUA_GLOBALSINDEX, name); + if(lua_isrotable(L,-1)) { return 1; + } else { + lua_pop(L, 1); } /* else must load it; iterate over available loaders */ lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); @@ -563,8 +563,13 @@ static void modinit (lua_State *L, const char *modname) { static int ll_module (lua_State *L) { const char *modname = luaL_checkstring(L, 1); - if (luaR_findglobal(modname, c_strlen(modname))) + /* Is this a readonly table? */ + lua_getfield(L, LUA_GLOBALSINDEX, modname); + if(lua_isrotable(L,-1)) { return 0; + } else { + lua_pop(L, 1); + } int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ diff --git a/app/lua/lobject.h b/app/lua/lobject.h index 49369c204e..b919d15b00 100644 --- a/app/lua/lobject.h +++ b/app/lua/lobject.h @@ -405,6 +405,7 @@ typedef struct Table { int sizearray; /* size of `array' array */ } Table; +typedef const struct luaR_entry ROTable; /* ** `module' operation for hashing (size is always a power of 2) diff --git a/app/lua/lrodefs.h b/app/lua/lrodefs.h index 451b36216e..064a673d72 100644 --- a/app/lua/lrodefs.h +++ b/app/lua/lrodefs.h @@ -38,5 +38,10 @@ return 1 #endif +#define LROT_TABENTRY(n,t) {LSTRKEY(#n), LRO_ROVAL(t)} +#define LROT_FUNCENTRY(n,f) {LSTRKEY(#n), LRO_FUNCVAL(f)} +#define LROT_NUMENTRY(n,x) {LSTRKEY(#n), LRO_NUMVAL(x)} +#define LROT_END {LNILKEY, LNILVAL} + #endif /* lrodefs_h */ diff --git a/app/lua/lrotable.c b/app/lua/lrotable.c index 5ece42ffd2..99d3e6ef41 100644 --- a/app/lua/lrotable.c +++ b/app/lua/lrotable.c @@ -9,77 +9,139 @@ #include "lobject.h" #include "lapi.h" -/* Local defines */ -#define LUAR_FINDFUNCTION 0 -#define LUAR_FINDVALUE 1 - -/* Externally defined read-only table array */ -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) { - unsigned i; - - if (c_strlen(name) > LUA_MAX_ROTABLE_NAME) - return NULL; - for (i=0; lua_rotable[i].name; i ++) - 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); +#define ALIGNED_STRING (__attribute__((aligned(4))) char *) +#define LA_LINES 16 +#define LA_SLOTS 4 +//#define COLLECT_STATS + +/* + * All keyed ROtable access passes through luaR_findentry(). ROTables + * are simply a list of pairs. The existing algo + * did a linear scan of this vector of pairs looking for a match. + * + * A N×M lookaside cache has been added, with a simple hash on the key's + * TString addr and the ROTable addr to identify one of N lines. Each + * line has M slots which are scanned. This is all done in RAM and is + * perhaps 20x faster than the corresponding random Flash accesses which + * will cause flash faults. + * + * If a match is found and the table addresses match, then this entry is + * probed first. In practice the hit-rate here is over 99% so the code + * rarely fails back to doing the linear scan in ROM. + * + * Note that this hash does a couple of prime multiples and a modulus 2^X + * with is all evaluated in H/W, and adequately randomizes the lookup. + */ +#define HASH(a,b) (519*((size_t)(a)>>4) + 17*((size_t)(b)>>4)) + +static struct { + unsigned hash; + unsigned addr:24; + unsigned ndx:8; +} cache[LA_LINES][LA_SLOTS]; + +#ifdef COLLECT_STATS +unsigned cache_stats[3]; +#define COUNT(i) cache_stats[i]++ +#else +#define COUNT(i) +#endif + +static int lookup_cache(unsigned hash, ROTable *rotable) { + int i = (hash>>2) & (LA_LINES-1), j; + + for (j = 0; jkey.type != LUA_TNIL) { - if ((strkey && (pentry->key.type == LUA_TSTRING) && (!c_strcmp(pentry->key.id.strkey, strkey))) || - (!strkey && (pentry->key.type == LUA_TNUMBER) && ((luaR_numkey)pentry->key.id.numkey == numkey))) { - res = &pentry->value; - break; +static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) { + int i = (hash)>>2 & (LA_LINES-1), j; + COUNT(2); + if (ndx>0xffu) + return; + for (j = LA_SLOTS-1; j>0; j--) + cache[i][j] = cache[i][j-1]; + cache[i][0].hash = hash; + cache[i][0].addr = (size_t) rotable; + cache[i][0].ndx = ndx; +} +/* + * Find a string key entry in a rotable and return it. Note that this internally + * uses a null key to denote a metatable search. + */ +const TValue* luaR_findentry(ROTable *rotable, TString *key, unsigned *ppos) { + const luaR_entry *pentry = rotable; + const char *strkey = key ? getstr(key) : ALIGNED_STRING "__metatable" ; + size_t hash = HASH(rotable, key); + unsigned i = 0; + int j = lookup_cache(hash, rotable); + + if (pentry) { + if (j >= 0){ + if ((pentry[j].key.type == LUA_TSTRING) && + !c_strcmp(pentry[j].key.id.strkey, strkey)) { + if (ppos) + *ppos = j; + return &pentry[j].value; + } + } + /* + * The invariants for 1st word comparison are deferred to here since they + * aren't needed if there is a cache hit. Note that the termination null + * is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF. + */ + unsigned name4 = *(unsigned *)strkey; + unsigned l = key ? key->tsv.len : sizeof("__metatable")-1; + unsigned mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8); + for(;pentry->key.type != LUA_TNIL; i++, pentry++) { + if ((pentry->key.type == LUA_TSTRING) && + ((*(unsigned *)pentry->key.id.strkey ^ name4) & mask4) == 0 && + !c_strcmp(pentry->key.id.strkey, strkey)) { + if (ppos) + *ppos = i; + if (j==-1) { + update_cache(hash, rotable, pentry - rotable); + } else if (j != (pentry - rotable)) { + j = 0; + } + return &pentry->value; + } } - i ++; pentry ++; } - if (res && ppos) - *ppos = i; - return res; + return luaO_nilobject; } -int luaR_findfunction(lua_State *L, const luaR_entry *ptable) { - const TValue *res = NULL; - const char *key = luaL_checkstring(L, 2); - - res = luaR_auxfind(ptable, key, 0, NULL); - if (res && ttislightfunction(res)) { - luaA_pushobject(L, res); - return 1; +const TValue* luaR_findentryN(ROTable *rotable, luaR_numkey numkey, unsigned *ppos) { + unsigned i = 0; + const luaR_entry *pentry = rotable; + if (pentry) { + for ( ;pentry->key.type != LUA_TNIL; i++, pentry++) { + if (pentry->key.type == LUA_TNUMBER && (luaR_numkey) pentry->key.id.numkey == numkey) { + if (ppos) + *ppos = i; + return &pentry->value; + } + } } - else - return 0; + return NULL; } -/* Find an entry in a rotable and return its type - If "strkey" is not NULL, the function will look for a string key, - otherwise it will look for a number key */ -const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos) { - return luaR_auxfind((const luaR_entry*)data, strkey, numkey, ppos); -} /* Find the metatable of a given table */ -void* luaR_getmeta(void *data) { -#ifdef LUA_META_ROTABLES - const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL); +void* luaR_getmeta(ROTable *rotable) { + const TValue *res = luaR_findentry(rotable, NULL, NULL); return res && ttisrotable(res) ? rvalue(res) : NULL; -#else - return NULL; -#endif } -static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, TValue *key, TValue *val) { +static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos, + TValue *key, TValue *val) { setnilvalue(key); setnilvalue(val); if (pentries[pos].key.type != LUA_TNIL) { @@ -91,56 +153,24 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, setobj2s(L, val, &pentries[pos].value); } } + + /* next (used for iteration) */ -void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) { - const luaR_entry* pentries = (const luaR_entry*)data; - char strkey[LUA_MAX_ROTABLE_NAME + 1], *pstrkey = NULL; - luaR_numkey numkey = 0; +void luaR_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val) { unsigned keypos; - + /* Special case: if key is nil, return the first element of the rotable */ - if (ttisnil(key)) - luaR_next_helper(L, pentries, 0, key, val); + if (ttisnil(key)) + luaR_next_helper(L, rotable, 0, key, val); else if (ttisstring(key) || ttisnumber(key)) { - /* Find the previoud key again */ + /* Find the previous key again */ if (ttisstring(key)) { - luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME); - pstrkey = strkey; - } else - numkey = (luaR_numkey)nvalue(key); - luaR_findentry(data, pstrkey, numkey, &keypos); + luaR_findentry(rotable, rawtsvalue(key), &keypos); + } else { + luaR_findentryN(rotable, (luaR_numkey)nvalue(key), &keypos); + } /* Advance to next key */ - keypos ++; - luaR_next_helper(L, pentries, keypos, key, val); + keypos ++; + luaR_next_helper(L, rotable, keypos, key, val); } } - -/* Convert a Lua string to a C string */ -void luaR_getcstr(char *dest, const TString *src, size_t maxsize) { - if (src->tsv.len+1 > maxsize) - dest[0] = '\0'; - else { - c_memcpy(dest, getstr(src), src->tsv.len); - dest[src->tsv.len] = '\0'; - } -} - -#ifdef LUA_META_ROTABLES -/* Set in RO check depending on platform */ -#if defined(LUA_CROSS_COMPILER) && defined(__CYGWIN__) -extern char __end__[]; -#define IN_RO_AREA(p) ((p) < __end__) -#elif defined(LUA_CROSS_COMPILER) -extern char _edata[]; -#define IN_RO_AREA(p) ((p) < _edata) -#else /* xtensa tool chain for ESP target */ -extern char _irom0_text_start[]; -extern char _irom0_text_end[]; -#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end) -#endif - -/* Return 1 if the given pointer is a rotable */ -int luaR_isrotable(void *p) { - return IN_RO_AREA((char *)p); -} -#endif diff --git a/app/lua/lrotable.h b/app/lua/lrotable.h index aba263527f..055590ac86 100644 --- a/app/lua/lrotable.h +++ b/app/lua/lrotable.h @@ -14,7 +14,11 @@ #define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL} +#ifdef LUA_CROSS_COMPILER #define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}} +#else +#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = (STORE_ATTR char *) k}} +#endif #define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}} #define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}} @@ -25,40 +29,58 @@ typedef int luaR_numkey; /* The next structure defines the type of a key */ -typedef struct -{ +typedef struct { int type; - union - { + union { const char* strkey; luaR_numkey numkey; } id; } luaR_key; /* An entry in the read only table */ -typedef struct -{ +typedef struct luaR_entry { const luaR_key key; const TValue value; } luaR_entry; -/* A rotable */ -typedef struct -{ - const char *name; - const luaR_entry *pentries; -} luaR_table; - -void* luaR_findglobal(const char *key, unsigned len); -int luaR_findfunction(lua_State *L, const luaR_entry *ptable); -const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos); -void luaR_getcstr(char *dest, const TString *src, size_t maxsize); -void luaR_next(lua_State *L, void *data, TValue *key, TValue *val); -void* luaR_getmeta(void *data); -#ifdef LUA_META_ROTABLES +/* + * The current ROTable implmentation is a vector of luaR_entry terminated by a + * nil record. The convention is to use ROtable * to refer to the entire vector + * as a logical ROTable. + */ +typedef const struct luaR_entry ROTable; + +const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos); +const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos); +void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val); +void* luaR_getmeta(ROTable *tab); int luaR_isrotable(void *p); + +/* + * Set inRO check depending on platform. Note that this implementation needs + * to work on both the host (luac.cross) and ESP targets. The luac.cross + * VM is used for the -e option, and is primarily used to be able to debug + * VM changes on the more developer-friendly hot gdb environment. + */ +#if defined(LUA_CROSS_COMPILER) + +#if defined(__CYGWIN__) +#define _RODATA_END __end__ #else -#define luaR_isrotable(p) (0) +#define _RODATA_END _edata +#endif +extern const char _RODATA_END[]; +#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END) + +#else /* xtensa tool chain for ESP target */ + +extern const char _irom0_text_start[]; +extern const char _irom0_text_end[]; +#define IN_RODATA_AREA(p) (((const char *)(p)) >= _irom0_text_start && ((const char *)(p)) <= _irom0_text_end) + #endif +/* Return 1 if the given pointer is a rotable */ +#define luaR_isrotable(p) IN_RODATA_AREA(p) + #endif diff --git a/app/lua/lstring.c b/app/lua/lstring.c index ee84e4d7ba..8fc0879651 100644 --- a/app/lua/lstring.c +++ b/app/lua/lstring.c @@ -80,16 +80,12 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, return ts; } -#ifdef LUA_CROSS_COMPILER -#define IN_RO_AREA(p) (0) -#else /* xtensa tool chain for ESP */ -extern char _irom0_text_start[]; -extern char _irom0_text_end[]; -#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end) +static int lua_is_ptr_in_ro_area(const char *p) { +#ifdef LUA_CROSS_COMPILER + return 0; // TStrings are never in RO in luac.cross +#else + return IN_RODATA_AREA(p); #endif - -int lua_is_ptr_in_ro_area(const char *p) { - return IN_RO_AREA(p); } /* diff --git a/app/lua/lstrlib.c b/app/lua/lstrlib.c index 4271c282b5..fb84243541 100644 --- a/app/lua/lstrlib.c +++ b/app/lua/lstrlib.c @@ -15,7 +15,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" /* macro to `unsign' a character */ #define uchar(c) ((unsigned char)(c)) diff --git a/app/lua/ltable.c b/app/lua/ltable.c index 73f64a0a4d..d773322a02 100644 --- a/app/lua/ltable.c +++ b/app/lua/ltable.c @@ -580,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) { /* same thing for rotables */ const TValue *luaH_getnum_ro (void *t, int key) { - const TValue *res = luaR_findentry(t, NULL, key, NULL); + const TValue *res = luaR_findentryN(t, key, NULL); return res ? res : luaO_nilobject; } @@ -599,14 +599,10 @@ const TValue *luaH_getstr (Table *t, TString *key) { } /* same thing for rotables */ -const TValue *luaH_getstr_ro (void *t, TString *key) { - char keyname[LUA_MAX_ROTABLE_NAME + 1]; - const TValue *res; - if (!t) +const TValue *luaH_getstr_ro (void *t, TString *key) { + if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME) return luaO_nilobject; - luaR_getcstr(keyname, key, LUA_MAX_ROTABLE_NAME); - res = luaR_findentry(t, keyname, 0, NULL); - return res ? res : luaO_nilobject; + return luaR_findentry(t, key, NULL); } @@ -745,7 +741,7 @@ int luaH_getn (Table *t) { int luaH_getn_ro (void *t) { int i = 1, len=0; - while(luaR_findentry(t, NULL, i ++, NULL)) + while(luaR_findentryN(t, i ++, NULL)) len ++; return len; } diff --git a/app/lua/ltablib.c b/app/lua/ltablib.c index 30eff7dfea..01422eeb7a 100644 --- a/app/lua/ltablib.c +++ b/app/lua/ltablib.c @@ -13,7 +13,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) diff --git a/app/lua/ltm.c b/app/lua/ltm.c index 6b27ccc0d1..145fa88895 100644 --- a/app/lua/ltm.c +++ b/app/lua/ltm.c @@ -50,14 +50,22 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename); + const TValue *tm; lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - if (!luaR_isrotable(events)) + + if (luaR_isrotable(events)) { + tm = luaH_getstr_ro(events, ename); + if (ttisnil(tm)) { /* no tag method? */ + return NULL; + } + } else { + tm = luaH_getstr(events, ename); + if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + (!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -#define fasttm(l,et,e) gfasttm(G(l), et, e) +#define fasttm(l,et,e) gfasttm(G(l), et, e) LUAI_DATA const char *const luaT_typenames[]; diff --git a/app/lua/luac_cross/Makefile b/app/lua/luac_cross/Makefile index 61433628af..49edd3b187 100644 --- a/app/lua/luac_cross/Makefile +++ b/app/lua/luac_cross/Makefile @@ -18,6 +18,7 @@ TARGET = host ifeq ($(FLAVOR),debug) CCFLAGS += -O0 -g TARGET_LDFLAGS += -O0 -g + DEFINES += -DLUA_DEBUG_BUILD else FLAVOR = release CCFLAGS += -O2 diff --git a/app/lua/luac_cross/liolib.c b/app/lua/luac_cross/liolib.c index e333a557a8..d83509ced9 100644 --- a/app/lua/luac_cross/liolib.c +++ b/app/lua/luac_cross/liolib.c @@ -18,7 +18,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" #define IO_INPUT 1 #define IO_OUTPUT 2 @@ -28,7 +27,11 @@ #define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) /* "Pseudo-random" keys for the registry */ -static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror}; +static const size_t liolib_keys[] = { + (size_t)&luaL_callmeta, + (size_t)&luaL_typerror, + (size_t)&luaL_argerror + }; static const char *const fnames[] = {"input", "output"}; @@ -452,20 +455,6 @@ const LUA_REG_TYPE iolib_funcs[] = { {LNILKEY, LNILVAL} }; -/* 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", io_index}, - {NULL, NULL} -}; - -#undef MIN_OPT_LEVEL -#define MIN_OPT_LEVEL 1 #include "lrodefs.h" const LUA_REG_TYPE flib[] = { {LSTRKEY("close"), LFUNCVAL(io_close)}, @@ -481,6 +470,7 @@ const LUA_REG_TYPE flib[] = { {LNILKEY, LNILVAL} }; +static const luaL_Reg io_base[] = {{NULL, NULL}}; static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { *newfile(L) = f; @@ -490,14 +480,18 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { lua_setfield(L, -2, fname); } -LUALIB_API int luaopen_io (lua_State *L) { - luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ - luaL_register_light(L, LUA_IOLIBNAME, iolib); +LUALIB_API int luaopen_io(lua_State *L) { + luaL_rometatable(L, LUA_FILEHANDLE, (void*) flib); /* create metatable for file handles */ + luaL_register_light(L, LUA_IOLIBNAME, io_base); lua_pushvalue(L, -1); lua_setmetatable(L, -2); + lua_pushliteral(L, "__index"); + lua_pushrotable(L, (void *)iolib_funcs); + lua_rawset(L, -3); + /* create (and set) default files */ createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, 0, "stderr"); + createstdfile(L, stderr, IO_STDERR, "stderr"); return 1; } diff --git a/app/lua/luac_cross/loslib.c b/app/lua/luac_cross/loslib.c index a35d2941b2..6792d48d73 100644 --- a/app/lua/luac_cross/loslib.c +++ b/app/lua/luac_cross/loslib.c @@ -20,8 +20,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lrotable.h" - static int os_pushresult (lua_State *L, int i, const char *filename) { int en = errno; /* calls to Lua API may change this value */ diff --git a/app/lua/luaconf.h b/app/lua/luaconf.h index d6c144cb6e..7ee4e41acd 100644 --- a/app/lua/luaconf.h +++ b/app/lua/luaconf.h @@ -896,13 +896,6 @@ union luai_Cast { double l_d; long l_l; }; ** without modifying the main part of the file. */ -/* If you define the next macro you'll get the ability to set rotables as - metatables for tables/userdata/types (but the VM might run slower) -*/ -#if (LUA_OPTIMIZE_MEMORY == 2) -#define LUA_META_ROTABLES -#endif - #if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN) #error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)" #endif diff --git a/app/lua/lvm.c b/app/lua/lvm.c index 0e256d8f62..a0243d6cd9 100644 --- a/app/lua/lvm.c +++ b/app/lua/lvm.c @@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { TValue temp; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; - if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ - void *h = ttistable(t) ? hvalue(t) : rvalue(t); - const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */ + + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ if (!ttisnil(res) || /* result is no nil? */ - (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); return; - } + } + /* else will try the tag method */ + } else if (ttisrotable(t)) { /* `t' is a table? */ + void *h = rvalue(t); + const TValue *res = luaH_get_ro(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } /* else will try the tag method */ } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); + if (ttisfunction(tm) || ttislightfunction(tm)) { callTMres(L, val, tm, t, key); return; @@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { L->top++; fixedstack(L); for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ - void *h = ttistable(t) ? hvalue(t) : rvalue(t); - TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */ - if ((oldval && !ttisnil(oldval)) || /* result is no nil? */ - (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */ - if(oldval) { - L->top--; - unfixedstack(L); - setobj2t(L, oldval, val); - ((Table *)h)->flags = 0; - luaC_barriert(L, (Table*)h, val); - } + const TValue *tm = NULL; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if ((!ttisnil(oldval)) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { + L->top--; + unfixedstack(L); + setobj2t(L, oldval, val); + ((Table *)h)->flags = 0; + luaC_barriert(L, (Table*)h, val); return; } /* else will try the tag method */ } + else if (ttisrotable(t)) { + luaG_runerror(L, "invalid write to ROM variable"); + } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); + if (ttisfunction(tm) || ttislightfunction(tm)) { L->top--; unfixedstack(L); @@ -294,7 +307,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TROTABLE: return rvalue(t1) == rvalue(t2); - case LUA_TLIGHTUSERDATA: + case LUA_TLIGHTUSERDATA: case LUA_TLIGHTFUNCTION: return pvalue(t1) == pvalue(t2); case LUA_TUSERDATA: { @@ -321,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) { if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit; do { /* Any call which does a memory allocation may trim the stack, - invalidating top unless the stack is fixed duri ng the allocation */ + invalidating top unless the stack is fixed during the allocation */ StkId top = L->base + last + 1; fixedstack(L); int n = 2; /* number of elements handled in this pass (at least 2) */ @@ -570,7 +583,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { case OP_LEN: { const TValue *rb = RB(i); switch (ttype(rb)) { - case LUA_TTABLE: + case LUA_TTABLE: case LUA_TROTABLE: { setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb)))); break; diff --git a/app/modules/wifi_monitor.c b/app/modules/wifi_monitor.c index a12585f735..ac991c80ed 100644 --- a/app/modules/wifi_monitor.c +++ b/app/modules/wifi_monitor.c @@ -570,9 +570,9 @@ static int packet_map_lookup(lua_State *L) { } // Now search the packet function map - const TValue *res = luaR_findentry((void *) packet_function_map, field, 0, NULL); - if (res) { - luaA_pushobject(L, res); + lua_pushrotable(L, (void *)packet_function_map); + lua_getfield(L, -1, field); + if (!lua_isnil(L, -1)) { return 1; } } diff --git a/app/uzlib/host/uz_unzip.c b/app/uzlib/host/uz_unzip.c index 177bebe202..26392aa3ac 100644 --- a/app/uzlib/host/uz_unzip.c +++ b/app/uzlib/host/uz_unzip.c @@ -131,20 +131,20 @@ int main(int argc, char *argv[]) { assert(sizeof(unsigned int) == 4); /* allocate and zero the in and out Blocks */ - assert(in = uz_malloc(sizeof(*in))); - assert(out = uz_malloc(sizeof(*out))); + assert((in = uz_malloc(sizeof(*in))) != NULL); + assert((out = uz_malloc(sizeof(*out))) != NULL); memset(in, 0, sizeof(*in)); memset(out, 0, sizeof(*out)); /* open input files and probe end to read the expanded length */ - assert((in->fin = fopen(inFile, "rb"))); + assert((in->fin = fopen(inFile, "rb")) != NULL); fseek(in->fin, -4, SEEK_END); assert(fread((uchar*)&(out->len), 1, 4, in->fin) == 4); in->len = ftell(in->fin); fseek(in->fin, 0, SEEK_SET); - assert((out->fout = fopen(outFile, "wb"))); + assert((out->fout = fopen(outFile, "wb")) != NULL); printf ("Inflating in=%s out=%s\n", inFile, outFile); @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) { n = (out->len > DICTIONARY_WINDOW) ? WRITE_BLOCKS : 1 + (out->len-1) / WRITE_BLOCKSIZE; for(i = WRITE_BLOCKS - n + 1; i <= WRITE_BLOCKS; i++) - assert(out->block[i % WRITE_BLOCKS] = uz_malloc(sizeof(outBlock))); + assert((out->block[i % WRITE_BLOCKS] = uz_malloc(sizeof(outBlock))) != NULL); out->breakNdx = (out->len < WRITE_BLOCKSIZE) ? out->len : WRITE_BLOCKSIZE; out->fullBlkCB = processOutRec;