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

LFS support for ESP32 NodeMCU (#2801)

* Port LFS from ESP8266 to ESP32
parent 7cb61a27
......@@ -23,8 +23,8 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_MATH
#include C_HEADER_STRING
#include <math.h>
#include <string.h>
#include "ldebug.h"
#include "ldo.h"
......@@ -105,8 +105,9 @@ static Node *mainposition (const Table *t, const TValue *key) {
return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
case LUA_TROTABLE:
return hashpointer(t, rvalue(key));
case LUA_TLIGHTUSERDATA:
case LUA_TLIGHTFUNCTION:
return hashpointer(t, pvalue(key));
default:
......@@ -444,7 +445,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
int oldasize = t->sizearray;
if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize);
resize_hashpart(L, t, nhsize);
if (t->node != dummynode || nhsize>0)
resize_hashpart(L, t, nhsize);
if (nasize < oldasize) { /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing slice */
......@@ -518,11 +520,11 @@ void luaH_free (lua_State *L, Table *t) {
/*
** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main
** position or not: if it is not, move colliding node to an empty place and
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main
** position or not: if it is not, move colliding node to an empty place and
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp = mainposition(t, key);
......@@ -578,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) {
/* same thing for rotables */
const TValue *luaH_getnum_ro (void *t, int key) {
const TValue *res = luaR_findentry(t, NULL, key, NULL);
const TValue *res = NULL; // integer values not supported: luaR_findentryN(t, key, NULL);
return res ? res : luaO_nilobject;
}
......@@ -598,13 +600,9 @@ const TValue *luaH_getstr (Table *t, TString *key) {
/* same thing for rotables */
const TValue *luaH_getstr_ro (void *t, TString *key) {
char keyname[LUA_MAX_ROTABLE_NAME + 1];
const TValue *res;
if (!t)
if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME)
return luaO_nilobject;
luaR_getcstr(keyname, key, LUA_MAX_ROTABLE_NAME);
res = luaR_findentry(t, keyname, 0, NULL);
return res ? res : luaO_nilobject;
return luaR_findentry(t, key, NULL);
}
......@@ -741,19 +739,15 @@ int luaH_getn (Table *t) {
/* same thing for rotables */
int luaH_getn_ro (void *t) {
int i = 1, len=0;
while(luaR_findentry(t, NULL, i ++, NULL))
len ++;
return len;
return 0; // Integer Keys are not currently supported for ROTables
}
#if defined(LUA_DEBUG)
int luaH_isdummy (Node *n) { return n == dummynode; }
#if defined(LUA_DEBUG)
Node *luaH_mainposition (const Table *t, const TValue *key) {
return mainposition(t, key);
}
#endif
int luaH_isdummy (Node *n) { return n == dummynode; }
#endif
......@@ -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
......@@ -266,22 +266,18 @@ static int sort (lua_State *L) {
/* }====================================================== */
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE tab_funcs[] = {
{LSTRKEY("concat"), LFUNCVAL(tconcat)},
{LSTRKEY("foreach"), LFUNCVAL(foreach)},
{LSTRKEY("foreachi"), LFUNCVAL(foreachi)},
{LSTRKEY("getn"), LFUNCVAL(getn)},
{LSTRKEY("maxn"), LFUNCVAL(maxn)},
{LSTRKEY("insert"), LFUNCVAL(tinsert)},
{LSTRKEY("remove"), LFUNCVAL(tremove)},
{LSTRKEY("setn"), LFUNCVAL(setn)},
{LSTRKEY("sort"), LFUNCVAL(sort)},
{LNILKEY, LNILVAL}
};
LROT_PUBLIC_BEGIN(tab_funcs)
LROT_FUNCENTRY( concat, tconcat )
LROT_FUNCENTRY( foreach, foreach )
LROT_FUNCENTRY( foreachi, foreachi )
LROT_FUNCENTRY( getn, getn )
LROT_FUNCENTRY( maxn, maxn )
LROT_FUNCENTRY( insert, tinsert )
LROT_FUNCENTRY( remove, tremove )
LROT_FUNCENTRY( setn, setn )
LROT_FUNCENTRY( sort, sort )
LROT_END(tab_funcs, NULL, 0)
LUALIB_API int luaopen_table (lua_State *L) {
LREGISTER(L, LUA_TABLIBNAME, tab_funcs);
return 1;
}
......@@ -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; i<TM_N; i++) {
G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
luaS_fix(G(L)->tmname[i]); /* never collect these names */
stringfix(G(L)->tmname[i]); /* never collect these names */
}
}
......@@ -49,14 +50,22 @@ void luaT_init (lua_State *L) {
** tag methods
*/
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename);
const TValue *tm;
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
if (!luaR_isrotable(events))
if (luaR_isrotable(events)) {
tm = luaH_getstr_ro(events, ename);
if (ttisnil(tm)) { /* no tag method? */
return NULL;
}
} else {
tm = luaH_getstr(events, ename);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL;
return NULL;
}
}
else return tm;
return tm;
}
......
......@@ -9,7 +9,7 @@
#include "lobject.h"
#include "lrotable.h"
/*
* WARNING: if you change the order of this enumeration,
......@@ -36,12 +36,10 @@ typedef enum {
TM_N /* number of elements in the enum */
} TMS;
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
!luaR_isrotable(et) && ((et)->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[];
......
......@@ -9,12 +9,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "flash_fs.h"
#include "user_version.h"
#include "driver/console.h"
#include "esp_system.h"
#include "platform.h"
#include "c_stdlib.h"
#define lua_c
......@@ -23,52 +21,13 @@
#include "lauxlib.h"
#include "lualib.h"
#include "legc.h"
#include "lflash.h"
lua_State *globalL = NULL;
lua_Load gLoad;
static const char *progname = LUA_PROGNAME;
#if 0
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
lua_sethook(L, NULL, 0, 0);
luaL_error(L, "interrupted!");
}
static void laction (int i) {
// signal(i, SIG_DFL);
/* if another SIGINT happens before lstop,
terminate process (default action) */
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
static void print_usage (void) {
#if defined(LUA_USE_STDIO)
fprintf(stderr,
#else
luai_writestringerror(
#endif
"usage: %s [options] [script [args]].\n"
"Available options are:\n"
" -e stat execute string " LUA_QL("stat") "\n"
" -l name require library " LUA_QL("name") "\n"
" -m limit set memory limit. (units are in Kbytes)\n"
" -i enter interactive mode after executing " LUA_QL("script") "\n"
" -v show version information\n"
" -- stop handling options\n"
" - execute stdin and stop handling options\n"
,
progname);
#if defined(LUA_USE_STDIO)
fflush(stderr);
#endif
}
#endif
static void l_message (const char *pname, const char *msg) {
#if defined(LUA_USE_STDIO)
if (pname) fprintf(stderr, "%s: ", pname);
......@@ -128,14 +87,15 @@ static int docall (lua_State *L, int narg, int clear) {
static void print_version (lua_State *L) {
lua_pushliteral (L, NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE);
lua_pushliteral (L, "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK ");
lua_pushstring (L, SDK_VERSION);
lua_concat (L, 2);
const char *msg = lua_tostring (L, -1);
l_message (NULL, msg);
lua_pop (L, 1);
}
#if 0
static int getargs (lua_State *L, char **argv, int n) {
int narg;
int i;
......@@ -153,16 +113,39 @@ static int getargs (lua_State *L, char **argv, int n) {
return narg;
}
static int dofile (lua_State *L, const char *name) {
int status = luaL_loadfile(L, name) || docall(L, 0, 1);
return report(L, status);
}
#else
static int dofsfile (lua_State *L, const char *name) {
int status = luaL_loadfsfile(L, name) || docall(L, 0, 1);
return report(L, status);
}
#endif
static int dolfsfile (lua_State *L, const char *name) {
int status = 1;
const char *code_fmt = "if node.flashindex('%s') then node.flashindex('%s')() end";
char *module_name = strdup(name);
unsigned name_len = strlen(name);
unsigned code_length = strlen(code_fmt) + name_len*2 + 1;
char *code_buf = malloc(code_length);
if (code_buf && module_name) {
char *dot = strrchr(module_name, '.');
if (dot) {
if (strstr(module_name, ".lua") == dot)
*dot = 0;
}
snprintf(code_buf, code_length, code_fmt, module_name, module_name);
status = luaL_dostring(L, code_buf);
if (status)
lua_pushfstring(L, "Failed to load %s from LFS", module_name);
} else {
lua_pushstring(L, "Failed to allocate memory");
}
if (module_name)
free(module_name);
if (code_buf)
free(code_buf);
return report(L, status);
}
static int dostring (lua_State *L, const char *s, const char *name) {
int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
......@@ -199,95 +182,9 @@ static int incomplete (lua_State *L, int status) {
return 0; /* else... */
}
#if 0
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
if (lua_readline(L, b, prmt) == 0)
return 0; /* no input */
l = strlen(b);
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
b[l-1] = '\0'; /* remove it */
if (firstline && b[0] == '=') /* first line starts with `=' ? */
lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
else
lua_pushstring(L, b);
lua_freeline(L, b);
return 1;
}
static int loadline (lua_State *L) {
int status;
lua_settop(L, 0);
if (!pushline(L, 1))
return -1; /* no input */
for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
if (!incomplete(L, status)) break; /* cannot try to add lines? */
if (!pushline(L, 0)) /* no more input? */
return -1;
lua_pushliteral(L, "\n"); /* add a new line... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
}
lua_saveline(L, 1);
lua_remove(L, 1); /* remove line */
return status;
}
static void dotty (lua_State *L) {
int status;
const char *oldprogname = progname;
progname = NULL;
while ((status = loadline(L)) != -1) {
if (status == 0) status = docall(L, 0, 0);
report(L, status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname, lua_pushfstring(L,
"error calling " LUA_QL("print") " (%s)",
lua_tostring(L, -1)));
}
}
lua_settop(L, 0); /* clear stack */
#if defined(LUA_USE_STDIO)
fputs("\n", stdout);
fflush(stdout);
#else
luai_writeline();
#endif
progname = oldprogname;
}
static int handle_script (lua_State *L, char **argv, int n) {
int status;
const char *fname;
int narg = getargs(L, argv, n); /* collect arguments */
lua_setglobal(L, "arg");
fname = argv[n];
if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
lua_insert(L, -(narg+1));
if (status == 0)
status = docall(L, narg, 0);
else
lua_pop(L, narg);
return report(L, status);
}
#endif
/* check that argument has no extra characters at the end */
#define notail(x) {if ((x)[2] != '\0') return -1;}
#define notail(x) {if ((x)[2] != '\0') return -1;}
static int collectargs (char **argv, int *pi, int *pv, int *pe) {
......@@ -362,17 +259,21 @@ static int runargs (lua_State *L, char **argv, int n) {
}
#ifndef LUA_INIT_STRING
#define LUA_INIT_STRING "@init.lua"
#endif
static int handle_luainit (lua_State *L) {
const char *init = c_getenv(LUA_INIT);
if (init == NULL) return 0; /* status OK */
else if (init[0] == '@')
#if 0
return dofile(L, init+1);
#else
const char *init = LUA_INIT_STRING;
if (init[0] == '@') {
#if CONFIG_LUA_EMBEDDED_FLASH_STORE > 0
int status = dolfsfile(L, init+1);
if (status == 0)
return status;
#endif
return dofsfile(L, init+1);
#endif
else
return dostring(L, init, "=" LUA_INIT);
} else
return dostring(L, init, LUA_INIT);
}
......@@ -395,40 +296,18 @@ static int pmain (lua_State *L) {
lua_gc(L, LUA_GCRESTART, 0);
print_version(L);
s->status = handle_luainit(L);
#if 0
if (s->status != 0) return 0;
#endif
script = collectargs(argv, &has_i, &has_v, &has_e);
if (script < 0) { /* invalid args? */
#if 0
print_usage();
#endif
s->status = 1;
return 0;
}
// if (has_v) print_version();
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
if (s->status != 0) return 0;
#if 0
if (script)
s->status = handle_script(L, argv, script);
if (s->status != 0) return 0;
if (has_i)
dotty(L);
else if (script == 0 && !has_e && !has_v) {
if (lua_stdin_is_tty()) {
print_version();
dotty(L);
}
else dofile(L, NULL); /* executes stdin as a file */
}
#endif
return 0;
}
static void dojob(lua_Load *load);
static bool readline(lua_Load *load);
char line_buffer[LUA_MAXINPUT];
#ifdef LUA_RPC
int main (int argc, char **argv) {
......@@ -444,30 +323,47 @@ int lua_main (int argc, char **argv) {
}
s.argc = argc;
s.argv = argv;
status = lua_cpcall(L, &pmain, &s);
report(L, status);
gLoad.L = L;
gLoad.firstline = 1;
gLoad.done = 0;
gLoad.line = line_buffer;
gLoad.line = malloc(LUA_MAXINPUT);
gLoad.len = LUA_MAXINPUT;
gLoad.line_position = 0;
gLoad.prmt = get_prompt(L, 1);
dojob(&gLoad);
NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
NODE_DBG("Heap size:%d.\n",system_get_free_heap_size());
legc_set_mode( L, EGC_ALWAYS, 4096 );
// legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
// lua_close(L);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
int lua_put_line(const char *s, size_t l) {
if (s == NULL || ++l > LUA_MAXINPUT || gLoad.line_position > 0)
return 0;
memcpy(gLoad.line, s, l);
gLoad.line[l] = '\0';
gLoad.line_position = l;
gLoad.done = 1;
NODE_DBG("Get command: %s\n", gLoad.line);
return 1;
}
void lua_handle_input (bool force)
{
if (gLoad.L && (force || readline (&gLoad)))
while (gLoad.L && (force || readline (&gLoad))) {
NODE_DBG("Handle Input: first=%u, pos=%u, len=%u, actual=%u, line=%s\n", gLoad.firstline,
gLoad.line_position, gLoad.len, strlen(gLoad.line), gLoad.line);
dojob (&gLoad);
force = false;
}
}
void donejob(lua_Load *load){
......@@ -475,7 +371,7 @@ void donejob(lua_Load *load){
}
static void dojob(lua_Load *load){
size_t l;
size_t l, rs;
int status;
char *b = load->line;
lua_State *L = load->L;
......
......@@ -166,7 +166,6 @@ LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushrolstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
......
......@@ -10,6 +10,7 @@
#include <limits.h>
#include <stddef.h>
#include "sdkconfig.h"
/*
** ==================================================================
......@@ -32,6 +33,11 @@
#define LUA_WIN
#endif
#if defined(LUA_CROSS_COMPILER) && !defined(_MSC_VER) && !defined(__MINGW32__)
#define LUA_USE_LINUX
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
......@@ -53,7 +59,7 @@
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
//#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif
......@@ -161,7 +167,7 @@
#define LUA_INTEGER ptrdiff_t
#else
#if !defined LUA_INTEGRAL_LONGLONG
#define LUA_INTEGER long
#define LUA_INTEGER int
#else
#define LUA_INTEGER long long
#endif // #if !defined LUA_INTEGRAL_LONGLONG
......@@ -251,11 +257,7 @@
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#ifdef LUA_CROSS_COMPILER
#include <stdio.h>
else
#include <stdio.h>
#endif
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
......@@ -481,7 +483,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
/* 16-bit ints */
#define LUAI_UINT32 unsigned long
#define LUAI_INT32 long
#define LUAI_MAXINT32 LONG_MAX
#define LUAI_MAXINT32 INT_MAX
#define LUAI_UMEM unsigned long
#define LUAI_MEM long
#endif
......@@ -547,10 +549,10 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
** Attention: This value should probably not be set higher than 1K.
** The size has direct impact on the C stack size needed be auxlib functions.
** For example: If set to 4K a call to string.gsub will need more than
** For example: If set to 4K a call to string.gsub will need more than
** 5k C stack space.
*/
#define LUAL_BUFFERSIZE 1024
#define LUAL_BUFFERSIZE 256
/* }================================================================== */
......@@ -568,10 +570,10 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
/* Define LUA_NUMBER_INTEGRAL to produce a system that uses no
floating point operations by changing the type of Lua numbers from
double to long. It implements division and modulus so that
double to long. It implements division and modulus so that
x == (x / y) * y + x % y.
x == (x / y) * y + x % y.
The exponentiation function returns zero for negative exponents.
Defining LUA_NUMBER_INTEGRAL also removes the difftime function,
and the math module should not be used. The string.format function
......@@ -601,8 +603,8 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
*/
#if defined LUA_NUMBER_INTEGRAL
#if !defined LUA_INTEGRAL_LONGLONG
#define LUA_NUMBER_SCAN "%ld"
#define LUA_NUMBER_FMT "%ld"
#define LUA_NUMBER_SCAN "%d"
#define LUA_NUMBER_FMT "%d"
#else
#define LUA_NUMBER_SCAN "%lld"
#define LUA_NUMBER_FMT "%lld"
......@@ -745,18 +747,18 @@ union luai_Cast { double l_d; long l_l; };
{ if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
#elif defined(LUA_USE_ULONGJMP)
#else
#if defined(LUA_USE_ULONGJMP)
/* in Unix, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#define LONGJMP(a,b) _longjmp(a,b)
#define SETJMP(a) _setjmp(a)
#else
/* default handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define LONGJMP(a,b) longjmp(a,b)
#define SETJMP(a) setjmp(a)
#endif
#define LUAI_THROW(L,c) LONGJMP((c)->b, 1)
#define LUAI_TRY(L,c,a) if (SETJMP((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#endif
......@@ -891,15 +893,8 @@ union luai_Cast { double l_d; long l_l; };
** without modifying the main part of the file.
*/
/* If you define the next macro you'll get the ability to set rotables as
metatables for tables/userdata/types (but the VM might run slower)
*/
#if (LUA_OPTIMIZE_MEMORY == 2) && !defined(LUA_CROSS_COMPILER)
#define LUA_META_ROTABLES
#endif
#if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN)
#error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)"
#if defined(LUA_USE_POPEN)
#error "Pipes not supported NodeMCU firmware"
#endif
#endif
......@@ -9,7 +9,7 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include <string.h>
#include "ldebug.h"
#include "ldo.h"
......@@ -172,7 +172,7 @@ static TString* LoadString(LoadState* S)
} else {
s = (char*)luaZ_get_crt_address(S->Z);
LoadBlock(S,NULL,size);
return luaS_newrolstr(S->L,s,size-1);
return luaS_newlstr(S->L,s,size-1);
}
}
}
......@@ -280,7 +280,7 @@ static Proto* LoadFunction(LoadState* S, TString* p)
Proto* f;
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
f=luaF_newproto(S->L);
if (luaZ_direct_mode(S->Z)) proto_readonly(f);
if (luaZ_direct_mode(S->Z)) l_setbit((f)->marked, READONLYBIT);
setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->linedefined=LoadInt(S);
......
......@@ -10,9 +10,9 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STDIO
#include C_HEADER_STRING
#include C_HEADER_MATH
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "ldebug.h"
#include "ldo.h"
......@@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
TValue temp;
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t);
const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is no nil? */
(tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res);
return;
}
}
/* else will try the tag method */
} else if (ttisrotable(t)) { /* `t' is a table? */
void *h = rvalue(t);
const TValue *res = luaH_get_ro(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is no nil? */
(tm = fasttm(L, (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res);
return;
}
/* else will try the tag method */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) {
callTMres(L, val, tm, t, key);
return;
......@@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
L->top++;
fixedstack(L);
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t);
TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */
if ((oldval && !ttisnil(oldval)) || /* result is no nil? */
(tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */
if(oldval) {
L->top--;
unfixedstack(L);
setobj2t(L, oldval, val);
((Table *)h)->flags = 0;
luaC_barriert(L, (Table*)h, val);
}
const TValue *tm = NULL;
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if ((!ttisnil(oldval)) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) {
L->top--;
unfixedstack(L);
setobj2t(L, oldval, val);
((Table *)h)->flags = 0;
luaC_barriert(L, (Table*)h, val);
return;
}
/* else will try the tag method */
}
else if (ttisrotable(t)) {
luaG_runerror(L, "invalid write to ROM variable");
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) {
L->top--;
unfixedstack(L);
......@@ -292,8 +305,9 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
case LUA_TNIL: return 1;
case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA:
case LUA_TROTABLE:
return rvalue(t1) == rvalue(t2);
case LUA_TLIGHTUSERDATA:
case LUA_TLIGHTFUNCTION:
return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA: {
......@@ -320,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) {
if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit;
do {
/* Any call which does a memory allocation may trim the stack,
invalidating top unless the stack is fixed duri ng the allocation */
invalidating top unless the stack is fixed during the allocation */
StkId top = L->base + last + 1;
fixedstack(L);
int n = 2; /* number of elements handled in this pass (at least 2) */
......
......@@ -10,7 +10,7 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include <string.h>
#include "llimits.h"
#include "lmem.h"
......
all: build
ifeq ($V,)
Q:=@
endif
LUAC_CFLAGS:= -I$(COMPONENT_PATH)/../uzlib -I$(COMPONENT_PATH)/../lua -I$(BUILD_DIR_BASE)/include -I$(COMPONENT_PATH)/../base_nodemcu/include -O2 -g -Wall -Wextra
LUAC_LDFLAGS:= -ldl -lm
LUAC_DEFINES += -DLUA_CROSS_COMPILER -DLUA_USE_STDIO
ifneq ($(CONFIG_LUA_OPTIMIZE_DEBUG),)
LUAC_DEFINES += -DLUA_OPTIMIZE_DEBUG=$(CONFIG_LUA_OPTIMIZE_DEBUG)
endif
vpath %.c $(COMPONENT_PATH) $(COMPONENT_PATH)/../lua $(COMPONENT_PATH)/../uzlib $(COMPONENT_PATH)/../base_nodemcu
LUAC_LUACSRC:= \
luac.c lflashimg.c loslib.c print.c liolib.c
LUAC_LUASRC:= $(addprefix $(COMPONENT_PATH)/../lua/, \
lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c \
ldo.c ldump.c lfunc.c lgc.c llex.c \
lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c lparser.c \
lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \
ltm.c lundump.c lvm.c lzio.c \
)
LUAC_UZSRC:= $(addprefix $(COMPONENT_PATH)/../uzlib/, \
uzlib_deflate.c crc32.c \
)
LUAC_NODEMCUSRC:= $(addprefix $(COMPONENT_PATH)/../base_nodemcu/, \
linit.c \
)
LUAC_BUILD_DIR:=$(BUILD_DIR_BASE)/luac_cross
LUAC_OBJS:=$(LUAC_LUACSRC:%.c=$(LUAC_BUILD_DIR)/%.o)
LUAC_OBJS+=$(LUAC_LUASRC:$(COMPONENT_PATH)/../lua/%.c=$(LUAC_BUILD_DIR)/%.o)
LUAC_OBJS+=$(LUAC_UZSRC:$(COMPONENT_PATH)/../uzlib/%.c=$(LUAC_BUILD_DIR)/%.o)
LUAC_OBJS+=$(LUAC_NODEMCUSRC:$(COMPONENT_PATH)/../base_nodemcu/%.c=$(LUAC_BUILD_DIR)/%.o)
LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d)
LUAC_CROSS:=$(LUAC_BUILD_DIR)/luac.cross
$(LUAC_BUILD_DIR):
@mkdir -p "$@"
$(LUAC_BUILD_DIR)/%.o: | $(LUAC_BUILD_DIR)
@echo '[hostcc] $(notdir $@)'
$Q$(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) "$<" -c -o "$@"
$(LUAC_BUILD_DIR)/%.d: SHELL=/bin/bash
$(LUAC_BUILD_DIR)/%.d: %.c | $(LUAC_BUILD_DIR)
@echo '[ dep] $<'
@rm -f "$@"
$Qset -eo pipefail; $(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) -M "$<" | sed 's,\($*\.o\)[ :]*,$(LUAC_BUILD_DIR)/\1 $@ : ,g' > "$@.tmp"; mv "$@.tmp" "$@"
build: $(LUAC_DEPS) $(LUAC_CROSS)
$(LUAC_CROSS): $(LUAC_OBJS)
@echo '[ link] $(notdir $@)'
$Q$(HOSTCC) $(LUAC_CFLAGS) $^ $(LUAC_LDFLAGS) -o "$@"
ifneq ($(MAKECMDGOALS),clean)
-include $(LUAC_DEPS)
endif
COMPONENT_OWNBUILDTARGET:=build
COMPONENT_ADD_LDFLAGS:=
build:
$(MAKE) -f $(COMPONENT_PATH)/Makefile HOSTCC=$(HOSTCC) BUILD_DIR_BASE=$(BUILD_DIR_BASE) V=$V COMPONENT_PATH=$(COMPONENT_PATH) CONFIG_LUA_OPTIMIZE_DEBUG=$(CONFIG_LUA_OPTIMIZE_DEBUG)
ar cr lib$(COMPONENT_NAME).a # work around IDF regression
/***--
** lflashimg.c
** Dump a compiled Proto hiearchy to a RO (FLash) image file
** See Copyright Notice in lua.h
*/
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lflashimg_c
#define LUA_CORE
#include "lobject.h"
#include "lstring.h"
#include "lflash.h"
#include "uzlib.h"
//#define LOCAL_DEBUG
#if INT_MAX != 2147483647
# error "luac.cross requires C toolchain with 4 byte word size"
#endif
#define WORDSIZE ((int) sizeof(int))
#define ALIGN(s) (((s)+(WORDSIZE-1)) & (-(signed) WORDSIZE))
#define WORDSHIFT 2
typedef unsigned int uint;
#define FLASH_WORDS(t) (sizeof(t)/sizeof(FlashAddr))
/*
*
* This dumper is a variant of the standard ldump, in that instead of producing a
* binary loader format that lundump can load, it produces an image file that can be
* directly mapped or copied into addressable memory. The typical application is on
* small memory IoT devices which support programmable flash storage such as the
* ESP8266. A 64 Kb LFS image has 16Kb words and will enable all program-related
* storage to be accessed directly from flash, leaving the RAM for true R/W
* application data.
*
* The start address of the Lua Flash Store (LFS) is build-dependent, and the cross
* compiler '-a' option allows the developer to fix the LFS at a defined flash memory
* address. Alternatively and by default the cross compilation adopts a position
* independent image format, which permits the on-device image loader to load the LFS
* image at an appropriate base within the flash address space. As all objects in the
* LFS can be treated as multiples of 4-byte words, also all address fields are both
* word aligned, and any address references within the LFS are also word-aligned.
*
* This version adds gzip compression of the generated LFS image for more efficient
* over-the-air (OTA) transfer, so the method of tagging address words has been
* replaced by a scheme which achieves better compression: an additional bitmap
* has been added to the image, with each bit corresponding to a word in the image
* and set if the corresponding work is an address. The addresses are stored as
* signed relative word offsets.
*
* The unloader is documented in lflash.c Note that his relocation process is
* skipped for absolute addressed images (which are identified by the
* FLASH_SIG_ABSOLUTE bit setting in the flash signature).
*
* The flash image has a standard header detailed in lflash.h
*
* Note that luac.cross may be compiled on any little-endian machine with 32 or 64 bit
* word length so Flash addresses can't be handled as standard C pointers as size_t
* and int may not have the same size. Hence addresses with the must be declared as
* the FlashAddr type rather than typed C pointers and must be accessed through macros.
*
* Also note that image built with a given LUA_PACK_TVALUES / LUA_NUNBER_INTEGRAL
* combination must be loaded into a corresponding firmware build. Hence these
* configuration options are also included in the FLash Signature.
*
* The Flash image is assembled up by first building the RO stringtable containing
* all strings used in the compiled proto hierarchy. This is followed by the Protos.
*
* The storage is allocated bottom up using a serial allocator and the algortihm for
* building the image essentially does a bottom-uo serial enumeration so that any
* referenced storage has already been allocated in the image, and therefore (with the
* exception of the Flash Header) all pointer references are backwards.
*
* As addresses are 4 byte on the target and either 4 or (typically) 8 bytes on the
* host so any structures containing address fields (TStrings, TValues, Protos, other
* address vectors) need repacking.
*/
typedef struct flashts { /* This is the fixed 32-bit equivalent of TString */
FlashAddr next;
lu_byte tt;
lu_byte marked;
int hash;
int len;
} FlashTS;
#ifndef LUA_MAX_FLASH_SIZE
#define LUA_MAX_FLASH_SIZE 0x10000 //in words
#endif
static uint curOffset = 0;
/*
* The flashAddrTag is a bit array, one bit per flashImage word denoting
* whether the corresponding word is a relative address. The defines
* are access methods for this bit array.
*/
static uint flashImage[LUA_MAX_FLASH_SIZE + LUA_MAX_FLASH_SIZE/32];
static uint *flashAddrTag = flashImage + LUA_MAX_FLASH_SIZE;
#define _TW(v) (v)>>5
#define _TB(v) (1<<((v)&0x1F))
#define setFlashAddrTag(v) flashAddrTag[_TW(v)] |= _TB(v)
#define getFlashAddrTag(v) ((flashAddrTag[_TW(v)]&_TB(v)) != 0)
#ifdef _MSC_VER
extern void __declspec( noreturn ) fatal( const char* message );
#else
extern void __attribute__((noreturn)) fatal(const char* message);
#endif
#ifdef LOCAL_DEBUG
#define DBG_PRINT(...) printf(__VA_ARGS__)
#else
#define DBG_PRINT(...) ((void)0)
#endif
/*
* Serial allocator. Throw a luac-style out of memory error is allocaiton fails.
*/
static void *flashAlloc(lua_State* L, size_t n) {
void *p = (void *)(flashImage + curOffset);
curOffset += ALIGN(n)>>WORDSHIFT;
if (curOffset > LUA_MAX_FLASH_SIZE) {
fatal("Out of Flash memory");
}
return p;
}
/*
* Convert an absolute address pointing inside the flash image to offset form.
* This macro form also takes the lvalue destination so that this can be tagged
* as a relocatable address.
*/
#define toFlashAddr(l, pd, s) _toFlashAddr(l, &(pd), s)
static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) {
uint doffset = cast(char *, a) - cast(char *,flashImage);
lua_assert(!(doffset & (WORDSIZE-1))); // check word aligned
doffset >>= WORDSHIFT; // and convert to a word offset
lua_assert(doffset <= curOffset);
if (p) {
uint poffset = cast(char *, p) - cast(char *,flashImage);
lua_assert(!(poffset & (WORDSIZE-1)));
poffset >>= WORDSHIFT;
lua_assert(poffset <= curOffset);
flashImage[doffset] = poffset; // Set the pointer to the offset
setFlashAddrTag(doffset); // And tag as an address
} /* else leave clear */ // Special case for NULL pointer
}
/*
* Convert an image address in offset form back to (host) absolute form
*/
static void *fromFashAddr(FlashAddr a) {
return a ? cast(void *, flashImage + a) : NULL;
}
/*
* Add a TS found in the Proto Load to the table at the ToS
*/
static void addTS(lua_State *L, TString *ts) {
lua_assert(ts->tsv.tt==LUA_TSTRING);
lua_pushnil(L);
setsvalue(L, L->top-1, ts);
lua_pushinteger(L, 1);
lua_rawset(L, -3);
DBG_PRINT("Adding string: %s\n",getstr(ts));
}
/*
* Enumerate all of the Protos in the Proto hiearchy and scan contents to collect
* all referenced strings in a Lua Array at ToS.
*/
static void scanProtoStrings(lua_State *L, const Proto* f) {
/* Table at L->Top[-1] is used to collect the strings */
int i;
if (f->source)
addTS(L, f->source);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo)
addTS(L, luaS_new(L, cast(const char *, f->packedlineinfo)));
#endif
for (i = 0; i < f->sizek; i++) {
if (ttisstring(f->k + i))
addTS(L, rawtsvalue(f->k + i));
}
for (i = 0; i < f->sizeupvalues; i++) addTS(L, f->upvalues[i]);
for (i = 0; i < f->sizelocvars; i++) addTS(L, f->locvars[i].varname);
for (i = 0; i < f->sizep; i++) scanProtoStrings(L, f->p[i]);
}
/*
* Use the collected strings table to build the new ROstrt in the Flash Image
*
* The input is an array of {"SomeString" = 1, ...} on the ToS.
* The output is an array of {"SomeString" = FlashOffset("SomeString"), ...} on ToS
*/
static void createROstrt(lua_State *L, FlashHeader *fh) {
/* Table at L->Top[-1] on input is hash used to collect the strings */
/* Count the number of strings. Can't use objlen as this is a hash */
fh->nROuse = 0;
lua_pushnil(L); /* first key */
while (lua_next(L, -2) != 0) {
fh->nROuse++;
DBG_PRINT("Found: %s\n",getstr(rawtsvalue(L->top-2)));
lua_pop(L, 1); // dump the value
}
fh->nROsize = 2<<luaO_log2(fh->nROuse);
FlashAddr *hashTab = flashAlloc(L, fh->nROsize * WORDSIZE);
toFlashAddr(L, fh->pROhash, hashTab);
/* Now iterate over the strings to be added to the RO string table and build it */
lua_newtable(L); // add output table
lua_pushnil(L); // First key
while (lua_next(L, -3) != 0) { // replaces key, pushes value
TString *ts = rawtsvalue(L->top - 2); // key.ts
const char *p = getstr(ts); // C string of key
uint hash = ts->tsv.hash; // hash of key
size_t len = ts->tsv.len; // and length
DBG_PRINT("2nd pass: %s\n",p);
FlashAddr *e = hashTab + lmod(hash, fh->nROsize);
FlashTS *last = cast(FlashTS *, fromFashAddr(*e));
FlashTS *fts = cast(FlashTS *, flashAlloc(L, sizeof(FlashTS)));
toFlashAddr(L, *e, fts); // add reference to TS to lookup vector
toFlashAddr(L, fts->next, last); // and chain to previous entry if any
fts->tt = LUA_TSTRING; // Set as String
fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set
fts->hash = hash; // add hash
fts->len = len; // and length
memcpy(flashAlloc(L, len+1), p, len+1); // copy string
// include the trailing null char
lua_pop(L, 1); // Junk the value
lua_pushvalue(L, -1); // Dup the key as rawset dumps its copy
lua_pushinteger(L, cast(FlashAddr*,fts)-flashImage); // Value is new TS offset.
lua_rawset(L, -4); // Add to new table
}
/* At this point the old hash is done to derefence for GC */
lua_remove(L, -2);
}
/*
* Convert a TString reference in the host G(L)->strt entry into the corresponding
* TString address in the flashImage using the lookup table at ToS
*/
static void *resolveTString(lua_State* L, TString *s) {
if (!s)
return NULL;
lua_pushnil(L);
setsvalue(L, L->top-1, s);
lua_rawget(L, -2);
lua_assert(!lua_isnil(L, -1));
void *ts = fromFashAddr(lua_tointeger(L, -1));
lua_pop(L, 1);
return ts;
}
/*
* In order to simplify repacking of structures from the host format to that target
* format, this simple copy routine is data-driven by a simple format specifier.
* n Number of consecutive records to be processed
* fmt A string of A, I, S, V specifiers spanning the record.
* src Source of record
* returns Address of destination record
*/
#if defined(LUA_PACK_TVALUES)
#define TARGET_TV_SIZE (sizeof(lua_Number)+sizeof(lu_int32))
#else
#define TARGET_TV_SIZE (2*sizeof(lua_Number))
#endif
static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
/* ToS is the string address mapping table */
if (n == 0)
return NULL;
int i, recsize;
void *newts;
/* A bit of a botch because fmt is either "V" or a string of WORDSIZE specifiers */
/* The size 8 / 12 / 16 bytes for integer builds, packed TV and default TVs resp */
if (fmt[0]=='V') {
lua_assert(fmt[1] == 0); /* V formats must be singetons */
recsize = TARGET_TV_SIZE;
} else {
recsize = WORDSIZE * strlen(fmt);
}
uint *d = cast(uint *, flashAlloc(L, n * recsize));
uint *dest = d;
uint *s = cast(uint *, src);
for (i = 0; i < n; i++) {
const char *p = fmt;
while (*p) {
/* All input address types (A,S,V) are aligned to size_t boundaries */
if (*p != 'I' && ((size_t)s)&(sizeof(size_t)-1))
s++;
switch (*p++) {
case 'A':
toFlashAddr(L, *d, *cast(void**, s));
s += FLASH_WORDS(size_t);
d++;
break;
case 'I':
*d++ = *s++;
break;
case 'H':
*d++ = (*s++) & 0;
break;
case 'S':
newts = resolveTString(L, *cast(TString **, s));
toFlashAddr(L, *d, newts);
s += FLASH_WORDS(size_t);
d++;
break;
case 'V':
/* This code has to work for both Integer and Float build variants */
memset(d, 0, TARGET_TV_SIZE);
TValue *sv = cast(TValue *, s);
/* The value is 0, 4 or 8 bytes depending on type */
if (ttisstring(sv)) {
toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv)));
} else if (ttisnumber(sv)) {
*cast(lua_Number*,d) = *cast(lua_Number*,s);
} else if (!ttisnil(sv)){
/* all other types are 4 byte */
lua_assert(!iscollectable(sv));
*cast(uint *,d) = *cast(uint *,s);
}
*cast(int *,cast(lua_Number*,d)+1) = ttype(sv);
s += FLASH_WORDS(TValue);
d += TARGET_TV_SIZE/WORDSIZE;
break;
default:
lua_assert (0);
}
}
}
return dest;
}
/* The debug optimised version has a different Proto layout */
#ifdef LUA_OPTIMIZE_DEBUG
#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIAI"
#else
#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIIAI"
#endif
/*
* Do the actual prototype copy.
*/
static void *functionToFlash(lua_State* L, const Proto* orig) {
Proto f;
int i;
memcpy (&f, orig, sizeof(Proto));
f.gclist = NULL;
f.next = NULL;
l_setbit(f.marked, LFSBIT); /* OK to set the LFSBIT on a stack-cloned copy */
if (f.sizep) { /* clone included Protos */
Proto **p = luaM_newvector(L, f.sizep, Proto *);
for (i=0; i<f.sizep; i++)
p[i] = cast(Proto *, functionToFlash(L, f.p[i]));
f.p = cast(Proto **, flashCopy(L, f.sizep, "A", p));
luaM_freearray(L, p, f.sizep, Proto *);
}
f.k = cast(TValue *, flashCopy(L, f.sizek, "V", f.k));
f.code = cast(Instruction *, flashCopy(L, f.sizecode, "I", f.code));
#ifdef LUA_OPTIMIZE_DEBUG
if (f.packedlineinfo) {
TString *ts=luaS_new(L, cast(const char *,f.packedlineinfo));
f.packedlineinfo = cast(unsigned char *, resolveTString(L, ts)) + sizeof (FlashTS);
}
#else
f.lineinfo = cast(int *, flashCopy(L, f.sizelineinfo, "I", f.lineinfo));
#endif
f.locvars = cast(struct LocVar *, flashCopy(L, f.sizelocvars, "SII", f.locvars));
f.upvalues = cast(TString **, flashCopy(L, f.sizeupvalues, "S", f.upvalues));
return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f));
}
uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
void* data, int strip,
lu_int32 address, lu_int32 maxSize) {
// parameter strip is ignored for now
FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader)));
int i, status;
lua_newtable(L);
scanProtoStrings(L, main);
createROstrt(L, fh);
toFlashAddr(L, fh->mainProto, functionToFlash(L, main));
fh->flash_sig = FLASH_SIG + (address ? FLASH_SIG_ABSOLUTE : 0);
fh->flash_size = curOffset*WORDSIZE;
if (fh->flash_size>maxSize) {
fatal ("The image is too large for specfied LFS size");
}
if (address) { /* in absolute mode convert addresses to mapped address */
for (i = 0 ; i < curOffset; i++)
if (getFlashAddrTag(i))
flashImage[i] = 4*flashImage[i] + address;
lua_unlock(L);
status = w(L, flashImage, fh->flash_size, data);
} else { /* compressed PI mode */
/*
* In image mode, shift the relocation bitmap down directly above
* the used flashimage. This consolidated array is then gzipped.
*/
uint oLen;
uint8_t *oBuf;
int bmLen = sizeof(uint)*((curOffset+31)/32); /* 32 flags to a word */
memmove(flashImage+curOffset, flashAddrTag, bmLen);
status = uzlib_compress (&oBuf, &oLen,
(const uint8_t *)flashImage, bmLen+fh->flash_size);
if (status != UZLIB_OK) {
fatal("Out of memory during image compression");
}
lua_unlock(L);
#if 0
status = w(L, flashImage, bmLen+fh->flash_size, data);
#else
status = w(L, oBuf, oLen, data);
free(oBuf);
#endif
}
lua_lock(L);
return status;
}
......@@ -5,11 +5,10 @@
*/
// #include <errno.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vfs.h"
#define liolib_c
#define LUA_LIB
......@@ -20,26 +19,25 @@
#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 +45,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 +55,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 +70,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 +78,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 +92,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 == fileno(stdin) || *p == fileno(stdout) || *p == fileno(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 +145,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, 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 +165,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 +212,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 +233,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 (vfs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) {
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
lua_pushnumber(L, d);
return 1;
}
......@@ -309,23 +245,23 @@ 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 (vfs_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 */
}
......@@ -339,36 +275,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);
char *p = luaL_prepbuffer(&b);
signed char c = EOF;
int i = 0;
do{
c = (signed char)vfs_getc(f);
if(c==EOF){
break;
}
p[i++] = c;
}while((c!=EOF) && (c!='\n') && (i<LUAL_BUFFERSIZE) );
if(i>0 && p[i-1] == '\n')
i--; /* do not include `eol' */
if(i==0){
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
luaL_addsize(&b, i);
luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */
}
#endif
static int read_chars (lua_State *L, int f, size_t n) {
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;
......@@ -377,7 +286,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 */
......@@ -386,11 +295,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 */
......@@ -407,11 +316,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;
......@@ -425,7 +332,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 */
......@@ -446,15 +353,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? */
......@@ -469,22 +374,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 &&
vfs_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);
......@@ -502,161 +404,89 @@ 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);
}
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
#if LUA_OPTIMIZE_MEMORY == 2
const LUA_REG_TYPE iolib_funcs[] = {
#else
const LUA_REG_TYPE iolib[] = {
#endif
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(io_flush)},
{LSTRKEY("input"), LFUNCVAL(io_input)},
{LSTRKEY("lines"), LFUNCVAL(io_lines)},
{LSTRKEY("open"), LFUNCVAL(io_open)},
{LSTRKEY("output"), LFUNCVAL(io_output)},
// {LSTRKEY("popen"), LFUNCVAL(io_popen)},
{LSTRKEY("read"), LFUNCVAL(io_read)},
// {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)},
{LSTRKEY("type"), LFUNCVAL(io_type)},
{LSTRKEY("write"), LFUNCVAL(io_write)},
{LNILKEY, LNILVAL}
};
#if LUA_OPTIMIZE_MEMORY == 2
static int luaL_index(lua_State *L)
{
return luaR_findfunction(L, iolib_funcs);
}
const luaL_Reg iolib[] = {
{"__index", luaL_index},
{NULL, NULL}
};
#endif
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE flib[] = {
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(f_flush)},
{LSTRKEY("lines"), LFUNCVAL(f_lines)},
{LSTRKEY("read"), LFUNCVAL(f_read)},
{LSTRKEY("seek"), LFUNCVAL(f_seek)},
// {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)},
{LSTRKEY("write"), LFUNCVAL(f_write)},
{LSTRKEY("__gc"), LFUNCVAL(io_gc)},
{LSTRKEY("__tostring"), LFUNCVAL(io_tostring)},
#if LUA_OPTIMIZE_MEMORY > 0
{LSTRKEY("__index"), LROVAL(flib)},
#endif
{LNILKEY, LNILVAL}
};
static void createmeta (lua_State *L) {
#if LUA_OPTIMIZE_MEMORY == 0
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, NULL, flib); /* file methods */
#else
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */
#endif
}
#if 0
static void createstdfile (lua_State *L, int f, int k, const char *fname) {
return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
LROT_PUBLIC_BEGIN(iolib)
LROT_FUNCENTRY( close, io_close )
LROT_FUNCENTRY( flush, io_flush )
LROT_FUNCENTRY( input, io_input )
LROT_FUNCENTRY( lines, io_lines )
LROT_FUNCENTRY( open, io_open )
LROT_FUNCENTRY( output, io_output )
LROT_FUNCENTRY( read, io_read )
LROT_FUNCENTRY( type, io_type )
LROT_FUNCENTRY( write, io_write )
LROT_TABENTRY( __index, iolib )
LROT_END(iolib, NULL, 0)
LROT_BEGIN(flib)
LROT_FUNCENTRY( close, io_close )
LROT_FUNCENTRY( flush, f_flush )
LROT_FUNCENTRY( lines, f_lines )
LROT_FUNCENTRY( read, f_read )
LROT_FUNCENTRY( seek, f_seek )
LROT_FUNCENTRY( setvbuf, f_setvbuf )
LROT_FUNCENTRY( write, f_write )
LROT_FUNCENTRY( __gc, io_gc )
LROT_FUNCENTRY( __tostring, io_tostring )
LROT_TABENTRY( __index, flib )
LROT_END(flib, NULL, LROT_MASK_GC_INDEX)
static const luaL_Reg io_base[] = {{NULL, NULL}};
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f;
#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_rawseti(L, LUA_REGISTRYINDEX, (int)(liolib_keys[k]));
lua_setfield(L, -2, fname);
#endif
}
#endif
#if LUA_OPTIMIZE_MEMORY != 2
static void newfenv (lua_State *L, lua_CFunction cls) {
lua_createtable(L, 0, 1);
lua_pushcfunction(L, cls);
lua_setfield(L, -2, "__close");
}
#endif
LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L);
#if LUA_OPTIMIZE_MEMORY != 2
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
newfenv(L, io_fclose);
lua_replace(L, LUA_ENVIRONINDEX);
/* open library */
luaL_register(L, LUA_IOLIBNAME, iolib);
newfenv(L, io_noclose); /* close function for default files */
#else
luaL_register_light(L, LUA_IOLIBNAME, iolib);
}
LUALIB_API int luaopen_io(lua_State *L) {
luaL_rometatable(L, LUA_FILEHANDLE, LROT_TABLEREF(flib)); /* create metatable for file handles */
luaL_register_light(L, LUA_IOLIBNAME, io_base);
lua_pushvalue(L, -1);
lua_setmetatable(L, -2);
#endif
#if 0
lua_pushliteral(L, "__index");
lua_pushrotable(L, LROT_TABLEREF(iolib));
lua_rawset(L, -3);
/* create (and set) default files */
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, IO_STDERR, "stderr");
#if LUA_OPTIMIZE_MEMORY != 2
lua_pop(L, 1); /* pop environment for default files */
lua_getfield(L, -1, "popen");
newfenv(L, io_pclose); /* create environment for 'popen' */
lua_setfenv(L, -2); /* set fenv for 'popen' */
lua_pop(L, 1); /* pop 'popen' */
#endif
#endif
return 1;
}
......@@ -7,11 +7,11 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_ERRNO
#include C_HEADER_LOCALE
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#include C_HEADER_TIME
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define loslib_c
#define LUA_LIB
......@@ -218,33 +218,34 @@ static int os_setlocale (lua_State *L) {
static int os_exit (lua_State *L) {
c_exit(luaL_optint(L, 1, EXIT_SUCCESS));
exit(luaL_optint(L, 1, EXIT_SUCCESS));
}
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE syslib[] = {
{LSTRKEY("clock"), LFUNCVAL(os_clock)},
{LSTRKEY("date"), LFUNCVAL(os_date)},
#include "lrotable.h"
LROT_PUBLIC_BEGIN(oslib)
LROT_FUNCENTRY(clock, os_clock)
LROT_FUNCENTRY(date, os_date)
#if !defined LUA_NUMBER_INTEGRAL
{LSTRKEY("difftime"), LFUNCVAL(os_difftime)},
LROT_FUNCENTRY(difftime, os_difftime)
#endif
{LSTRKEY("execute"), LFUNCVAL(os_execute)},
{LSTRKEY("exit"), LFUNCVAL(os_exit)},
{LSTRKEY("getenv"), LFUNCVAL(os_getenv)},
{LSTRKEY("remove"), LFUNCVAL(os_remove)},
{LSTRKEY("rename"), LFUNCVAL(os_rename)},
{LSTRKEY("setlocale"), LFUNCVAL(os_setlocale)},
{LSTRKEY("time"), LFUNCVAL(os_time)},
{LSTRKEY("tmpname"), LFUNCVAL(os_tmpname)},
{LNILKEY, LNILVAL}
};
LROT_FUNCENTRY(execute, os_execute)
LROT_FUNCENTRY(exit, os_exit)
LROT_FUNCENTRY(getenv, os_getenv)
LROT_FUNCENTRY(remove, os_remove)
LROT_FUNCENTRY(rename, os_rename)
LROT_FUNCENTRY(setlocale, os_setlocale)
LROT_FUNCENTRY(time, os_time)
LROT_FUNCENTRY(tmpname, os_tmpname)
LROT_END(oslib, NULL, 0)
/* }====================================================== */
LUALIB_API int luaopen_os (lua_State *L) {
LREGISTER(L, LUA_OSLIBNAME, syslib);
//LREGISTER(L, LUA_OSLIBNAME, oslib); // <------------- ???
return 0;
}
......@@ -7,17 +7,17 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_ERRNO
#include C_HEADER_STDIO
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define luac_c
#define LUA_CORE
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
......@@ -32,12 +32,17 @@
static int listing=0; /* list bytecodes? */
static int dumping=1; /* dump bytecodes? */
static int stripping=0; /* strip debug information? */
static int flash=0; /* output flash image */
static lu_int32 address=0; /* output flash image at absolute location */
static lu_int32 maxSize=0x40000; /* maximuum uncompressed image size */
static int lookup=0; /* output lookup-style master combination header */
static char Output[]={ OUTPUT }; /* default output file name */
static const char* output=Output; /* actual output file name */
static const char* execute; /* executed a Lua file */
static const char* progname=PROGNAME; /* actual program name */
static DumpTargetInfo target;
static void fatal(const char* message)
void fatal(const char* message)
{
fprintf(stderr,"%s: %s\n",progname,message);
exit(EXIT_FAILURE);
......@@ -61,12 +66,14 @@ 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"
" -a addr generate an absolute, rather than position independent flash image file\n"
" -i generate lookup combination master (default with option -f)\n"
" -m size maximum LFS image in bytes\n"
" -p parse only\n"
" -s strip debug information\n"
" -v show version information\n"
" -cci bits cross-compile with given integer size\n"
" -ccn type bits cross-compile with given lua_Number type and size\n"
" -cce endian cross-compile with given endianness ('big' or 'little')\n"
" -- stop handling options\n",
progname,Output);
exit(EXIT_FAILURE);
......@@ -91,8 +98,32 @@ static int doargs(int argc, char* argv[])
}
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=lookup=1;
}
else if (IS("-a")) /* Absolue flash image file */
{
flash=lookup=1;
address=strtol(argv[++i],NULL,0);
}
else if (IS("-i")) /* lookup */
lookup = 1;
else if (IS("-l")) /* list */
++listing;
else if (IS("-m")) /* specify a maximum image size */
{
flash=lookup=1;
maxSize=strtol(argv[++i],NULL,0);
if (maxSize & 0xFFF)
usage(LUA_QL("-e") " maximum size must be a multiple of 4,096");
}
else if (IS("-o")) /* output file */
{
output=argv[++i];
......@@ -105,33 +136,6 @@ static int doargs(int argc, char* argv[])
stripping=1;
else if (IS("-v")) /* show version */
++version;
else if (IS("-cci")) /* target integer size */
{
int s = target.sizeof_int = atoi(argv[++i])/8;
if (!(s==1 || s==2 || s==4)) fatal(LUA_QL("-cci") " must be 8, 16 or 32");
}
else if (IS("-ccn")) /* target lua_Number type and size */
{
const char *type=argv[++i];
if (strcmp(type,"int")==0) target.lua_Number_integral=1;
else if (strcmp(type,"float")==0) target.lua_Number_integral=0;
else if (strcmp(type,"float_arm")==0)
{
target.lua_Number_integral=0;
target.is_arm_fpa=1;
}
else fatal(LUA_QL("-ccn") " type must be " LUA_QL("int") " or " LUA_QL("float") " or " LUA_QL("float_arm"));
int s = target.sizeof_lua_Number = atoi(argv[++i])/8;
if (target.lua_Number_integral && !(s==1 || s==2 || s==4)) fatal(LUA_QL("-ccn") " size must be 8, 16, or 32 for int");
if (!target.lua_Number_integral && !(s==4 || s==8)) fatal(LUA_QL("-ccn") " size must be 32 or 64 for float");
}
else if (IS("-cce")) /* target endianness */
{
const char *val=argv[++i];
if (strcmp(val,"big")==0) target.little_endian=0;
else if (strcmp(val,"little")==0) target.little_endian=1;
else fatal(LUA_QL("-cce") " must be " LUA_QL("big") " or " LUA_QL("little"));
}
else /* unknown option */
usage(argv[i]);
}
......@@ -150,30 +154,100 @@ static int doargs(int argc, char* argv[])
#define toproto(L,i) (clvalue(L->top+(i))->l.p)
static const Proto* combine(lua_State* L, int n)
static TString *corename(lua_State *L, const TString *filename)
{
if (n==1)
const char *fn = getstr(filename)+1;
const char *s = strrchr(fn, '/');
if (!s) s = strrchr(fn, '\\');
s = s ? s + 1 : fn;
while (*s == '.') s++;
const char *e = strchr(s, '.');
int l = e ? e - s: strlen(s);
return l ? luaS_newlstr (L, s, l) : luaS_new(L, fn);
}
/*
* If the luac command line includes multiple files or has the -f option
* then luac generates a main function to reference all sub-main prototypes.
* This is one of two types:
* Type 0 The standard luac combination main
* Type 1 A lookup wrapper that facilitates indexing into the generated protos
*/
static const Proto* combine(lua_State* L, int n, int type)
{
if (n==1 && type == 0)
return toproto(L,-1);
else
{
int i,pc;
int i;
Instruction *pc;
Proto* f=luaF_newproto(L);
setptvalue2s(L,L->top,f); incr_top(L);
f->source=luaS_newliteral(L,"=(" PROGNAME ")");
f->maxstacksize=1;
pc=2*n+1;
f->code=luaM_newvector(L,pc,Instruction);
f->sizecode=pc;
f->p=luaM_newvector(L,n,Proto*);
f->sizep=n;
pc=0;
for (i=0; i<n; i++)
{
f->p[i]=toproto(L,i-n-1);
f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
f->p[i]=toproto(L,i-n-1);
pc=0;
if (type == 0) {
/*
* Type 0 is as per the standard luac, which is just a main routine which
* invokes all of the compiled functions sequentially. This is fine if
* they are self registering modules, but useless otherwise.
*/
f->numparams = 0;
f->maxstacksize = 1;
f->sizecode = 2*n + 1 ;
f->sizek = 0;
f->code = luaM_newvector(L, f->sizecode , Instruction);
f->k = luaM_newvector(L,f->sizek,TValue);
for (i=0, pc = f->code; i<n; i++) {
*pc++ = CREATE_ABx(OP_CLOSURE,0,i);
*pc++ = CREATE_ABC(OP_CALL,0,1,1);
}
*pc++ = CREATE_ABC(OP_RETURN,0,1,0);
} else {
/*
* The Type 1 main() is a lookup which takes a single argument, the name to
* be resolved. If this matches root name of one of the compiled files then
* a closure to this file main is returned. Otherwise the Unixtime of the
* compile and the list of root names is returned.
*/
if (n > LFIELDS_PER_FLUSH) {
#define NO_MOD_ERR_(n) ": Number of modules > " #n
#define NO_MOD_ERR(n) NO_MOD_ERR_(n)
usage(LUA_QL("-f") NO_MOD_ERR(LFIELDS_PER_FLUSH));
}
f->numparams = 1;
f->maxstacksize = n + 3;
f->sizecode = 5*n + 5 ;
f->sizek = n + 1;
f->sizelocvars = 0;
f->code = luaM_newvector(L, f->sizecode , Instruction);
f->k = luaM_newvector(L,f->sizek,TValue);
for (i=0, pc = f->code; i<n; i++)
{
/* if arg1 == FnameA then return function (...) -- funcA -- end end */
setsvalue2n(L,f->k+i,corename(L, f->p[i]->source));
*pc++ = CREATE_ABC(OP_EQ,0,0,RKASK(i));
*pc++ = CREATE_ABx(OP_JMP,0,MAXARG_sBx+2);
*pc++ = CREATE_ABx(OP_CLOSURE,1,i);
*pc++ = CREATE_ABC(OP_RETURN,1,2,0);
}
setnvalue(f->k+n, (lua_Number) time(NULL));
*pc++ = CREATE_ABx(OP_LOADK,1,n);
*pc++ = CREATE_ABC(OP_NEWTABLE,2,luaO_int2fb(i),0);
for (i=0; i<n; i++)
*pc++ = CREATE_ABx(OP_LOADK,i+3,i);
*pc++ = CREATE_ABC(OP_SETLIST,2,i,1);
*pc++ = CREATE_ABC(OP_RETURN,1,3,0);
*pc++ = CREATE_ABC(OP_RETURN,0,1,0);
}
f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
lua_assert((pc-f->code) == f->sizecode);
return f;
}
}
......@@ -189,6 +263,13 @@ struct Smain {
char** argv;
};
#if defined(_MSC_VER) || defined(__MINGW32__)
typedef unsigned int uint;
#endif
extern uint dumpToFlashImage (lua_State* L,const Proto *main, lua_Writer w,
void* data, int strip,
lu_int32 address, lu_int32 maxSize);
static int pmain(lua_State* L)
{
struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
......@@ -197,19 +278,39 @@ 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; i<argc; i++)
{
const char* filename=IS("-") ? NULL : argv[i];
if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
}
f=combine(L,argc);
f=combine(L,argc + (execute ? 1: 0), lookup);
if (listing) luaU_print(f,listing>1);
if (dumping)
{
int result;
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
if (D==NULL) cannot("open");
lua_lock(L);
int result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
if (flash)
{
result=dumpToFlashImage(L,f,writer, D, stripping, address, maxSize);
} else
{
result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
}
lua_unlock(L);
if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type");
if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found");
......@@ -223,7 +324,7 @@ int main(int argc, char* argv[])
{
lua_State* L;
struct Smain s;
int test=1;
target.little_endian=*(char*)&test;
target.sizeof_int=sizeof(int);
......@@ -234,7 +335,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;
......
......@@ -7,8 +7,8 @@
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_CTYPE
#include C_HEADER_STDIO
#include <ctype.h>
#include <stdio.h>
#define luac_c
#define LUA_CORE
......
......@@ -60,18 +60,16 @@ static int read_hall_sensor( lua_State *L )
}
// Module function map
static const LUA_REG_TYPE adc_map[] =
{
{ LSTRKEY( "setwidth" ), LFUNCVAL( adc_set_width ) },
{ LSTRKEY( "setup" ), LFUNCVAL( adc_setup ) },
{ LSTRKEY( "read" ), LFUNCVAL( adc_read ) },
{ LSTRKEY( "read_hall_sensor" ), LFUNCVAL( read_hall_sensor ) },
{ LSTRKEY( "ATTEN_0db" ), LNUMVAL( PLATFORM_ADC_ATTEN_0db ) },
{ LSTRKEY( "ATTEN_2_5db" ), LNUMVAL( PLATFORM_ADC_ATTEN_2_5db ) },
{ LSTRKEY( "ATTEN_6db" ), LNUMVAL( PLATFORM_ADC_ATTEN_6db ) },
{ LSTRKEY( "ATTEN_11db" ), LNUMVAL( PLATFORM_ADC_ATTEN_11db ) },
{ LSTRKEY( "ADC1" ), LNUMVAL( 1 ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(adc)
LROT_FUNCENTRY( setwidth, adc_set_width )
LROT_FUNCENTRY( setup, adc_setup )
LROT_FUNCENTRY( read, adc_read )
LROT_FUNCENTRY( read_hall_sensor, read_hall_sensor )
LROT_NUMENTRY ( ATTEN_0db, PLATFORM_ADC_ATTEN_0db )
LROT_NUMENTRY ( ATTEN_2_5db, PLATFORM_ADC_ATTEN_2_5db )
LROT_NUMENTRY ( ATTEN_6db, PLATFORM_ADC_ATTEN_6db )
LROT_NUMENTRY ( ATTEN_11db, PLATFORM_ADC_ATTEN_11db )
LROT_NUMENTRY ( ADC1, 1 )
LROT_END(adc, NULL, 0)
NODEMCU_MODULE(ADC, "adc", adc_map, NULL);
NODEMCU_MODULE(ADC, "adc", adc, NULL);
......@@ -119,20 +119,19 @@ static int bit_clear( lua_State* L )
return 1;
}
static const LUA_REG_TYPE bit_map[] = {
{ LSTRKEY( "bnot" ), LFUNCVAL( bit_bnot ) },
{ LSTRKEY( "band" ), LFUNCVAL( bit_band ) },
{ LSTRKEY( "bor" ), LFUNCVAL( bit_bor ) },
{ LSTRKEY( "bxor" ), LFUNCVAL( bit_bxor ) },
{ LSTRKEY( "lshift" ), LFUNCVAL( bit_lshift ) },
{ LSTRKEY( "rshift" ), LFUNCVAL( bit_rshift ) },
{ LSTRKEY( "arshift" ), LFUNCVAL( bit_arshift ) },
{ LSTRKEY( "bit" ), LFUNCVAL( bit_bit ) },
{ LSTRKEY( "set" ), LFUNCVAL( bit_set ) },
{ LSTRKEY( "clear" ), LFUNCVAL( bit_clear ) },
{ LSTRKEY( "isset" ), LFUNCVAL( bit_isset ) },
{ LSTRKEY( "isclear" ), LFUNCVAL( bit_isclear ) },
{ LNILKEY, LNILVAL}
};
NODEMCU_MODULE(BIT, "bit", bit_map, NULL);
LROT_BEGIN(bit)
LROT_FUNCENTRY( bnot, bit_bnot )
LROT_FUNCENTRY( band, bit_band )
LROT_FUNCENTRY( bor, bit_bor )
LROT_FUNCENTRY( bxor, bit_bxor )
LROT_FUNCENTRY( lshift, bit_lshift )
LROT_FUNCENTRY( rshift, bit_rshift )
LROT_FUNCENTRY( arshift, bit_arshift )
LROT_FUNCENTRY( bit, bit_bit )
LROT_FUNCENTRY( set, bit_set )
LROT_FUNCENTRY( clear, bit_clear )
LROT_FUNCENTRY( isset, bit_isset )
LROT_FUNCENTRY( isclear, bit_isclear )
LROT_END(bit, NULL, 0)
NODEMCU_MODULE(BIT, "bit", bit, NULL);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment