Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
eaac369d
Unverified
Commit
eaac369d
authored
Jul 22, 2019
by
Johny Mattsson
Committed by
GitHub
Jul 22, 2019
Browse files
LFS support for ESP32 NodeMCU (#2801)
* Port LFS from ESP8266 to ESP32
parent
7cb61a27
Changes
116
Expand all
Hide whitespace changes
Inline
Side-by-side
components/lua/ltable.c
View file @
eaac369d
...
...
@@ -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_findentry
N
(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
components/lua/ltable.h
View file @
eaac369d
...
...
@@ -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
components/lua/ltablib.c
View file @
eaac369d
...
...
@@ -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
;
}
components/lua/ltm.c
View file @
eaac369d
...
...
@@ -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 */
string
fix
(
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
;
}
...
...
components/lua/ltm.h
View file @
eaac369d
...
...
@@ -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
[];
...
...
components/lua/lua.c
View file @
eaac369d
...
...
@@ -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
;
...
...
components/lua/lua.h
View file @
eaac369d
...
...
@@ -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
);
...
...
components/lua/luaconf.h
View file @
eaac369d
...
...
@@ -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 "%
l
d"
#define LUA_NUMBER_FMT "%
l
d"
#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
components/lua/lundump.c
View file @
eaac369d
...
...
@@ -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_new
ro
lstr
(
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
);
...
...
components/lua/lvm.c
View file @
eaac369d
...
...
@@ -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) */
...
...
components/lua/lzio.c
View file @
eaac369d
...
...
@@ -10,7 +10,7 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "llimits.h"
#include "lmem.h"
...
...
components/luac_cross/Makefile
0 → 100644
View file @
eaac369d
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
components/luac_cross/component.mk
0 → 100644
View file @
eaac369d
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
components/luac_cross/lflashimg.c
0 → 100644
View file @
eaac369d
/***--
** 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
;
}
components/lua/liolib.c
→
components/lua
c_cross
/liolib.c
View file @
eaac369d
This diff is collapsed.
Click to expand it.
components/
lua/
luac_cross/loslib.c
→
components/luac_cross/loslib.c
View file @
eaac369d
...
...
@@ -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 "lro
defs
.h"
const
LUA_REG_TYPE
syslib
[]
=
{
{
LSTRKE
Y
(
"
clock
"
)
,
LFUNCVAL
(
os_clock
)
},
{
LSTRKE
Y
(
"
date
"
)
,
LFUNCVAL
(
os_date
)
},
#include "lro
table
.h"
LROT_PUBLIC_BEGIN
(
oslib
)
LROT_FUNCENTR
Y
(
clock
,
os_clock
)
LROT_FUNCENTR
Y
(
date
,
os_date
)
#if !defined LUA_NUMBER_INTEGRAL
{
LSTRKE
Y
(
"
difftime
"
)
,
LFUNCVAL
(
os_difftime
)
},
LROT_FUNCENTR
Y
(
difftime
,
os_difftime
)
#endif
{
LSTRKE
Y
(
"
execute
"
)
,
LFUNCVAL
(
os_execute
)
},
{
LSTRKE
Y
(
"
exit
"
)
,
LFUNCVAL
(
os_exit
)
},
{
LSTRKE
Y
(
"
getenv
"
)
,
LFUNCVAL
(
os_getenv
)
},
{
LSTRKE
Y
(
"
remove
"
)
,
LFUNCVAL
(
os_remove
)
},
{
LSTRKE
Y
(
"
rename
"
)
,
LFUNCVAL
(
os_rename
)
},
{
LSTRKE
Y
(
"
setlocale
"
),
LFUNCVAL
(
os_setlocale
)
},
{
LSTRKE
Y
(
"
time
"
)
,
LFUNCVAL
(
os_time
)
},
{
LSTRKE
Y
(
"
tmpname
"
)
,
LFUNCVAL
(
os_tmpname
)
},
{
LNILKEY
,
LNILVAL
}
};
LROT_FUNCENTR
Y
(
execute
,
os_execute
)
LROT_FUNCENTR
Y
(
exit
,
os_exit
)
LROT_FUNCENTR
Y
(
getenv
,
os_getenv
)
LROT_FUNCENTR
Y
(
remove
,
os_remove
)
LROT_FUNCENTR
Y
(
rename
,
os_rename
)
LROT_FUNCENTR
Y
(
setlocale
,
os_setlocale
)
LROT_FUNCENTR
Y
(
time
,
os_time
)
LROT_FUNCENTR
Y
(
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
;
}
components/
lua/
luac_cross/luac.c
→
components/luac_cross/luac.c
View file @
eaac369d
This diff is collapsed.
Click to expand it.
components/
lua/
luac_cross/print.c
→
components/luac_cross/print.c
View file @
eaac369d
...
...
@@ -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
...
...
components/modules/adc.c
View file @
eaac369d
...
...
@@ -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
);
components/modules/bit.c
View file @
eaac369d
...
...
@@ -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
);
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment