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
dba57fa0
Commit
dba57fa0
authored
Aug 24, 2021
by
Johny Mattsson
Browse files
Merge branch 'dev-esp32-idf4-lua53' into dev-esp32-idf4
parents
3a6961cc
8e5ce49d
Changes
224
Hide whitespace changes
Inline
Side-by-side
components/lua/lua.h
→
components/lua/lua
-5.1/lua
.h
View file @
dba57fa0
...
...
@@ -8,13 +8,11 @@
#ifndef lua_h
#define lua_h
#ifdef LUAC_CROSS_FILE
#include "luac_cross.h"
#endif
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <ctype.h>
#include <stdbool.h>
#include "luaconf.h"
...
...
@@ -41,7 +39,8 @@
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
/* thread status; 0 is OK */
/* thread status */
#define LUA_OK 0
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
...
...
@@ -72,18 +71,22 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TROTABLE 2
#define LUA_TLIGHTFUNCTION 3
#define LUA_TLIGHTUSERDATA 4
#define LUA_TNUMBER 5
#define LUA_TSTRING 6
#define LUA_TTABLE 7
#define LUA_TFUNCTION 8
#define LUA_TUSERDATA 9
#define LUA_TTHREAD 10
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_TISROTABLE (1<<4)
#define LUA_TISLIGHTFUNC (1<<5)
#define LUA_TMASK 15
#define LUA_TROTABLE (LUA_TTABLE + LUA_TISROTABLE)
#define LUA_TLIGHTFUNCTION (LUA_TFUNCTION + LUA_TISLIGHTFUNC)
/* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20
...
...
@@ -96,18 +99,14 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
#include LUA_USER_H
#endif
#if defined(LUA_OPTIMIZE_DEBUG) && LUA_OPTIMIZE_DEBUG == 0
#undef LUA_OPTIMIZE_DEBUG
#endif
/* type of numbers in Lua */
typedef
LUA_NUMBER
lua_Number
;
typedef
LUA_FLOAT
lua_Float
;
/* type for integer functions */
typedef
LUA_INTEGER
lua_Integer
;
typedef
LUAI_UINT32
lua_Unsigned
;
/*
** state manipulation
...
...
@@ -122,6 +121,7 @@ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
/*
** basic stack manipulation
*/
LUA_API
int
(
lua_absindex
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_gettop
)
(
lua_State
*
L
);
LUA_API
void
(
lua_settop
)
(
lua_State
*
L
,
int
idx
);
LUA_API
void
(
lua_pushvalue
)
(
lua_State
*
L
,
int
idx
);
...
...
@@ -142,11 +142,14 @@ LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API
int
(
lua_iscfunction
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_isuserdata
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_type
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_fulltype
)
(
lua_State
*
L
,
int
idx
);
LUA_API
const
char
*
(
lua_typename
)
(
lua_State
*
L
,
int
tp
);
LUA_API
int
(
lua_equal
)
(
lua_State
*
L
,
int
idx1
,
int
idx2
);
LUA_API
int
(
lua_rawequal
)
(
lua_State
*
L
,
int
idx1
,
int
idx2
);
LUA_API
int
(
lua_lessthan
)
(
lua_State
*
L
,
int
idx1
,
int
idx2
);
LUA_API
int
(
lua_rawequal
)
(
lua_State
*
L
,
int
idx1
,
int
idx2
);
#define LUA_OPEQ 0
#define LUA_OPLT 1
#define LUA_OPLE 2
LUA_API
int
(
lua_compare
)
(
lua_State
*
L
,
int
idx1
,
int
idx2
,
int
op
);
LUA_API
lua_Number
(
lua_tonumber
)
(
lua_State
*
L
,
int
idx
);
LUA_API
lua_Integer
(
lua_tointeger
)
(
lua_State
*
L
,
int
idx
);
...
...
@@ -173,18 +176,17 @@ LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API
void
(
lua_pushcclosure
)
(
lua_State
*
L
,
lua_CFunction
fn
,
int
n
);
LUA_API
void
(
lua_pushboolean
)
(
lua_State
*
L
,
int
b
);
LUA_API
void
(
lua_pushlightuserdata
)
(
lua_State
*
L
,
void
*
p
);
LUA_API
void
(
lua_pushlightfunction
)
(
lua_State
*
L
,
void
*
p
);
LUA_API
void
(
lua_pushrotable
)
(
lua_State
*
L
,
void
*
p
);
LUA_API
int
(
lua_pushthread
)
(
lua_State
*
L
);
/*
** get functions (Lua -> stack)
*/
LUA_API
void
(
lua_gettable
)
(
lua_State
*
L
,
int
idx
);
LUA_API
void
(
lua_getfield
)
(
lua_State
*
L
,
int
idx
,
const
char
*
k
);
LUA_API
void
(
lua_rawget
)
(
lua_State
*
L
,
int
idx
);
LUA_API
void
(
lua_rawgeti
)
(
lua_State
*
L
,
int
idx
,
int
n
);
LUA_API
int
(
lua_gettable
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_getfield
)
(
lua_State
*
L
,
int
idx
,
const
char
*
k
);
LUA_API
int
(
lua_rawget
)
(
lua_State
*
L
,
int
idx
);
LUA_API
int
(
lua_rawgeti
)
(
lua_State
*
L
,
int
idx
,
int
n
);
LUA_API
int
(
lua_rawgetp
)
(
lua_State
*
L
,
int
idx
,
const
void
*
p
);
LUA_API
void
(
lua_createtable
)
(
lua_State
*
L
,
int
narr
,
int
nrec
);
LUA_API
void
*
(
lua_newuserdata
)
(
lua_State
*
L
,
size_t
sz
);
LUA_API
int
(
lua_getmetatable
)
(
lua_State
*
L
,
int
objindex
);
...
...
@@ -198,6 +200,7 @@ LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API
void
(
lua_setfield
)
(
lua_State
*
L
,
int
idx
,
const
char
*
k
);
LUA_API
void
(
lua_rawset
)
(
lua_State
*
L
,
int
idx
);
LUA_API
void
(
lua_rawseti
)
(
lua_State
*
L
,
int
idx
,
int
n
);
LUA_API
void
(
lua_rawsetp
)
(
lua_State
*
L
,
int
idx
,
const
void
*
p
);
LUA_API
int
(
lua_setmetatable
)
(
lua_State
*
L
,
int
objindex
);
LUA_API
int
(
lua_setfenv
)
(
lua_State
*
L
,
int
idx
);
...
...
@@ -210,8 +213,8 @@ LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API
int
(
lua_cpcall
)
(
lua_State
*
L
,
lua_CFunction
func
,
void
*
ud
);
LUA_API
int
(
lua_load
)
(
lua_State
*
L
,
lua_Reader
reader
,
void
*
dt
,
const
char
*
chunkname
);
LUA_API
int
(
lua_
dump
)
(
lua_State
*
L
,
lua_Writer
writer
,
void
*
data
);
LUA_API
int
(
lua_dump
)
(
lua_State
*
L
,
lua_Writer
writer
,
void
*
data
,
int
stripping
);
LUA_API
int
(
lua_
stripdebug
)
(
lua_State
*
L
,
int
stripping
);
/*
...
...
@@ -271,10 +274,8 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
#define lua_strlen(L,i) lua_objlen(L, (i))
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_islightfunction(L,n) (lua_type(L, (n)) == LUA_TLIGHTFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_isrotable(L,n) (lua_type(L, (n)) == LUA_TROTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
...
...
@@ -289,14 +290,24 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define lua_tounsigned(L,i) ((lua_Unsigned)lua_tointeger(L,i))
/* error codes from cross-compiler returned by lua_dump */
/* target integer is too small to hold a value */
#define LUA_ERR_CC_INTOVERFLOW 101
/* target lua_Number is integral but a constant is non-integer */
#define LUA_ERR_CC_NOTINTEGER 102
/*
** compatibility macros and functions
*/
// BogdanM: modified for eLua interrupt support
//#define lua_open() luaL_newstate()
lua_State
*
lua_open
(
void
);
lua_State
*
lua_getstate
(
void
);
...
...
@@ -372,24 +383,62 @@ struct lua_Debug {
int
i_ci
;
/* active function */
};
int
lua_main
(
void
);
void
lua_input_string
(
const
char
*
line
,
int
len
);
/* }====================================================================== */
typedef
struct
__lua_load
{
lua_State
*
L
;
int
firstline
;
char
*
line
;
int
line_position
;
size_t
len
;
int
done
;
const
char
*
prmt
;
}
lua_Load
;
/* NodeMCU extensions to the standard API */
int
lua_main
(
int
argc
,
char
**
argv
);
typedef
struct
ROTable
ROTable
;
typedef
const
struct
ROTable_entry
ROTable_entry
;
#ifndef LUA_CROSS_COMPILER
void
lua_handle_input
(
bool
force
);
LUA_API
void
(
lua_pushrotable
)
(
lua_State
*
L
,
const
ROTable
*
p
);
LUA_API
void
(
lua_createrotable
)
(
lua_State
*
L
,
ROTable
*
t
,
ROTable_entry
*
e
,
ROTable
*
mt
);
LUA_API
int
(
lua_pushstringsarray
)
(
lua_State
*
L
,
int
opt
);
LUA_API
int
(
lua_freeheap
)
(
void
);
LUA_API
void
(
lua_getlfsconfig
)
(
lua_State
*
L
,
int
*
);
LUA_API
int
(
lua_pushlfsindex
)
(
lua_State
*
L
);
#define EGC_NOT_ACTIVE 0 // EGC disabled
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
#define EGC_ALWAYS 4 // always run EGC before an allocation
#ifdef LUA_USE_ESP
#define LUA_QUEUE_APP 0
#define LUA_QUEUE_UART 1
/**DEBUG**/
extern
void
dbg_printf
(
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
#define luaN_freearray(L,b,l) luaM_freearray(L,b,l,sizeof(*b))
LUA_API
void
(
lua_setegcmode
)
(
lua_State
*
L
,
int
mode
,
int
limit
);
LUA_API
void
(
lua_getegcinfo
)
(
lua_State
*
L
,
int
*
totals
);
#else
#define ICACHE_RODATA_ATTR
#define dbg_printf printf
#endif
#ifdef DEVELOPMENT_USE_GDB
LUALIB_API
void
(
lua_debugbreak
)(
void
);
#else
#define lua_debugbreak() (void)(0)
#endif
// EGC operations modes
#define EGC_NOT_ACTIVE 0 // EGC disabled
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
#define EGC_ALWAYS 4 // always run EGC before an allocation
void
legc_set_mode
(
lua_State
*
L
,
int
mode
,
int
limit
);
/******************************************************************************
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
*
...
...
components/lua/luaconf.h
→
components/lua/
lua-5.1/
luaconf.h
View file @
dba57fa0
...
...
@@ -155,6 +155,11 @@
#define LUA_EXECDIR "!"
#define LUA_IGMARK "-"
#ifdef CONFIG_LUA_NUMBER_INTEGRAL
# define LUA_NUMBER_INTEGRAL
#else
# define LUA_PACK_TVALUES
#endif
/*
@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
...
...
@@ -265,16 +270,6 @@
#endif
/*
@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
** CHANGE them if you want different prompts. (You can also change the
** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
*/
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
/*
@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
** CHANGE it if your stand-alone interpreter has a different name and
...
...
@@ -299,54 +294,34 @@
** CHANGE them if you want to improve this functionality (e.g., by using
** GNU readline and history facilities).
*/
#if defined(LUA_USE_STDIO)
#if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_strlen(L,idx) > 0)
/* non-empty line? */
\
add_history(lua_tostring(L, idx));
/* add it to history */
#define lua_freeline(L,b) ((void)L, free(b))
#else // #if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout),
/* show prompt */
\
fgets(b, LUA_MAXINPUT, stdin) != NULL)
/* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif // #if defined(LUA_USE_READLINE)
#else // #if defined(LUA_USE_STDIO)
#define lua_readline(L,b,p) (readline4lua(p, b, LUA_MAXINPUT))
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
extern
int
readline4lua
(
const
char
*
prompt
,
char
*
buffer
,
int
length
);
#endif // #if defined(LUA_USE_STDIO)
/*
@@ lua
i
_writestring/lua
i
_writeline define how 'print' prints its results.
@@ lua_writestring/lua_writeline define how 'print' prints its results.
** They are only used in libraries and the stand-alone program. (The #if
** avoids including 'stdio.h' everywhere.)
*/
#if !defined(LUA_USE_STDIO)
#define luai_writestring(s, l) fwrite(s, 1, l, stdout)
#define luai_writeline() puts("")
#endif // defined(LUA_USE_STDIO)
#ifdef LUA_USE_ESP
void
output_redirect
(
const
char
*
str
,
size_t
l
);
#define lua_writestring(s,l) output_redirect((s),(l))
#else
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#endif
#define luai_writeline() lua_writestring("\n",1)
/*
@@ lua
i
_writestringerror defines how to print error messages.
@@ lua_writestringerror defines how to print error messages.
** (A format string with one argument is enough for Lua...)
*/
#if !defined(LUA_USE_STDIO)
#define luai_writestringerror(s,p) printf((s), (p))
#endif // defined(LUA_USE_STDIO)
/* }================================================================== */
#ifdef LUA_USE_ESP
#define lua_writestringerror(s,p) dbg_printf((s), (p))
#else
#define lua_writestringerror(s,p) fprintf(stderr, (s), (p))
#endif
/*
...
...
@@ -586,6 +561,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double
#endif
#define LUA_FLOAT double
/*
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
...
...
@@ -897,4 +873,6 @@ union luai_Cast { double l_d; long l_l; };
#error "Pipes not supported NodeMCU firmware"
#endif
#define LUA_DEBUG_HOOK lua_debugbreak
#endif
components/lua/lualib.h
→
components/lua/
lua-5.1/
lualib.h
View file @
dba57fa0
...
...
@@ -41,7 +41,7 @@ LUALIB_API int (luaopen_package) (lua_State *L);
/* open all previous libraries */
LUALIB_API
void
(
luaL_openlibs
)
(
lua_State
*
L
);
LUALIB_API
void
(
luaL_openlibs
)
(
lua_State
*
L
);
...
...
components/lua/lundump.c
→
components/lua/
lua-5.1/
lundump.c
View file @
dba57fa0
...
...
@@ -6,7 +6,6 @@
#define lundump_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
...
...
@@ -164,16 +163,9 @@ static TString* LoadString(LoadState* S)
return
NULL
;
else
{
char
*
s
;
if
(
!
luaZ_direct_mode
(
S
->
Z
))
{
s
=
luaZ_openspace
(
S
->
L
,
S
->
b
,
size
);
LoadBlock
(
S
,
s
,
size
);
return
luaS_newlstr
(
S
->
L
,
s
,
size
-
1
);
/* remove trailing zero */
}
else
{
s
=
(
char
*
)
luaZ_get_crt_address
(
S
->
Z
);
LoadBlock
(
S
,
NULL
,
size
);
return
luaS_newlstr
(
S
->
L
,
s
,
size
-
1
);
}
char
*
s
=
luaZ_openspace
(
S
->
L
,
S
->
b
,
size
);
LoadBlock
(
S
,
s
,
size
);
return
luaS_newlstr
(
S
->
L
,
s
,
size
-
1
);
/* remove trailing zero */
}
}
...
...
@@ -181,13 +173,8 @@ static void LoadCode(LoadState* S, Proto* f)
{
int
n
=
LoadInt
(
S
);
Align4
(
S
);
if
(
!
luaZ_direct_mode
(
S
->
Z
))
{
f
->
code
=
luaM_newvector
(
S
->
L
,
n
,
Instruction
);
LoadVector
(
S
,
f
->
code
,
n
,
sizeof
(
Instruction
));
}
else
{
f
->
code
=
(
Instruction
*
)
luaZ_get_crt_address
(
S
->
Z
);
LoadVector
(
S
,
NULL
,
n
,
sizeof
(
Instruction
));
}
f
->
code
=
luaM_newvector
(
S
->
L
,
n
,
Instruction
);
LoadVector
(
S
,
f
->
code
,
n
,
sizeof
(
Instruction
));
f
->
sizecode
=
n
;
}
...
...
@@ -236,28 +223,12 @@ static void LoadDebug(LoadState* S, Proto* f)
n
=
LoadInt
(
S
);
Align4
(
S
);
#ifdef LUA_OPTIMIZE_DEBUG
if
(
n
)
{
if
(
!
luaZ_direct_mode
(
S
->
Z
))
{
f
->
packedlineinfo
=
luaM_newvector
(
S
->
L
,
n
,
unsigned
char
);
LoadBlock
(
S
,
f
->
packedlineinfo
,
n
);
}
else
{
f
->
packedlineinfo
=
(
unsigned
char
*
)
luaZ_get_crt_address
(
S
->
Z
);
LoadBlock
(
S
,
NULL
,
n
);
}
f
->
packedlineinfo
=
luaM_newvector
(
S
->
L
,
n
,
unsigned
char
);
LoadBlock
(
S
,
f
->
packedlineinfo
,
n
);
}
else
{
f
->
packedlineinfo
=
NULL
;
}
#else
if
(
!
luaZ_direct_mode
(
S
->
Z
))
{
f
->
lineinfo
=
luaM_newvector
(
S
->
L
,
n
,
int
);
LoadVector
(
S
,
f
->
lineinfo
,
n
,
sizeof
(
int
));
}
else
{
f
->
lineinfo
=
(
int
*
)
luaZ_get_crt_address
(
S
->
Z
);
LoadVector
(
S
,
NULL
,
n
,
sizeof
(
int
));
}
f
->
sizelineinfo
=
n
;
#endif
n
=
LoadInt
(
S
);
f
->
locvars
=
luaM_newvector
(
S
->
L
,
n
,
LocVar
);
f
->
sizelocvars
=
n
;
...
...
@@ -280,7 +251,6 @@ 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
))
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/lundump.h
→
components/lua/
lua-5.1/
lundump.h
View file @
dba57fa0
...
...
@@ -50,11 +50,4 @@ LUAI_FUNC void luaU_print (const Proto* f, int full);
/* size of header of binary files */
#define LUAC_HEADERSIZE 12
/* error codes from cross-compiler */
/* target integer is too small to hold a value */
#define LUA_ERR_CC_INTOVERFLOW 101
/* target lua_Number is integral but a constant is non-integer */
#define LUA_ERR_CC_NOTINTEGER 102
#endif
components/lua/lvm.c
→
components/lua/
lua-5.1/
lvm.c
View file @
dba57fa0
...
...
@@ -7,7 +7,6 @@
#define lvm_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdio.h>
...
...
@@ -25,7 +24,6 @@
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
#include "lrotable.h"
/* limit for table tag-method chains (to avoid loops) */
...
...
@@ -41,7 +39,7 @@ LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) {
LUA_NUMBER
c
=
1
;
for
(;;)
{
if
(
b
&
1
)
c
*=
a
;
c
*=
a
;
b
=
b
>>
1
;
if
(
b
==
0
)
return
c
;
...
...
@@ -134,26 +132,17 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
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? */
if
(
!
ttisnil
(
res
)
||
/* result is no nil? */
(
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
)
)
{
if
(
ttisfunction
(
tm
))
{
callTMres
(
L
,
val
,
tm
,
t
,
key
);
return
;
}
...
...
@@ -193,7 +182,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
else
if
(
ttisnil
(
tm
=
luaT_gettmbyobj
(
L
,
t
,
TM_NEWINDEX
)))
luaG_typeerror
(
L
,
t
,
"index"
);
if
(
ttisfunction
(
tm
)
||
ttislightfunction
(
tm
)
)
{
if
(
ttisfunction
(
tm
))
{
L
->
top
--
;
unfixedstack
(
L
);
callTM
(
L
,
tm
,
t
,
key
,
val
);
...
...
@@ -282,7 +271,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
}
static
int
lessequal
(
lua_State
*
L
,
const
TValue
*
l
,
const
TValue
*
r
)
{
int
luaV_
lessequal
(
lua_State
*
L
,
const
TValue
*
l
,
const
TValue
*
r
)
{
int
res
;
if
(
ttype
(
l
)
!=
ttype
(
r
))
return
luaG_ordererror
(
L
,
l
,
r
);
...
...
@@ -305,8 +294,6 @@ 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_TROTABLE
:
return
rvalue
(
t1
)
==
rvalue
(
t2
);
case
LUA_TLIGHTUSERDATA
:
case
LUA_TLIGHTFUNCTION
:
return
pvalue
(
t1
)
==
pvalue
(
t2
);
...
...
@@ -316,6 +303,8 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
TM_EQ
);
break
;
/* will try TM */
}
case
LUA_TROTABLE
:
return
hvalue
(
t1
)
==
hvalue
(
t2
);
case
LUA_TTABLE
:
{
if
(
hvalue
(
t1
)
==
hvalue
(
t2
))
return
1
;
tm
=
get_compTM
(
L
,
hvalue
(
t1
)
->
metatable
,
hvalue
(
t2
)
->
metatable
,
TM_EQ
);
...
...
@@ -440,7 +429,6 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
}
void
luaV_execute
(
lua_State
*
L
,
int
nexeccalls
)
{
LClosure
*
cl
;
StkId
base
;
...
...
@@ -582,10 +570,9 @@ void luaV_execute (lua_State *L, int nexeccalls) {
}
case
OP_LEN
:
{
const
TValue
*
rb
=
RB
(
i
);
switch
(
ttype
(
rb
))
{
case
LUA_TTABLE
:
case
LUA_TROTABLE
:
{
setnvalue
(
ra
,
ttistable
(
rb
)
?
cast_num
(
luaH_getn
(
hvalue
(
rb
)))
:
cast_num
(
luaH_getn_ro
(
rvalue
(
rb
))));
switch
(
ttnov
(
rb
))
{
case
LUA_TTABLE
:
{
setnvalue
(
ra
,
cast_num
(
luaH_getn
(
hvalue
(
rb
))));
break
;
}
case
LUA_TSTRING
:
{
...
...
@@ -633,7 +620,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
}
case
OP_LE
:
{
Protect
(
if
(
lessequal
(
L
,
RKB
(
i
),
RKC
(
i
))
==
GETARG_A
(
i
))
if
(
luaV_
lessequal
(
L
,
RKB
(
i
),
RKC
(
i
))
==
GETARG_A
(
i
))
dojump
(
L
,
pc
,
GETARG_sBx
(
*
pc
));
)
pc
++
;
...
...
@@ -785,7 +772,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
setobj2t
(
L
,
luaH_setnum
(
L
,
h
,
last
--
),
val
);
luaC_barriert
(
L
,
h
,
val
);
}
L
->
top
=
L
->
ci
->
top
;
L
->
top
=
L
->
ci
->
top
;
unfixedstack
(
L
);
continue
;
}
...
...
components/lua/lvm.h
→
components/lua/
lua-5.1/
lvm.h
View file @
dba57fa0
...
...
@@ -23,6 +23,7 @@
LUAI_FUNC
int
luaV_lessthan
(
lua_State
*
L
,
const
TValue
*
l
,
const
TValue
*
r
);
LUAI_FUNC
int
luaV_lessequal
(
lua_State
*
L
,
const
TValue
*
l
,
const
TValue
*
r
);
LUAI_FUNC
int
luaV_equalval
(
lua_State
*
L
,
const
TValue
*
t1
,
const
TValue
*
t2
);
LUAI_FUNC
const
TValue
*
luaV_tonumber
(
const
TValue
*
obj
,
TValue
*
n
);
LUAI_FUNC
int
luaV_tostring
(
lua_State
*
L
,
StkId
obj
);
...
...
components/lua/lzio.c
→
components/lua/
lua-5.1/
lzio.c
View file @
dba57fa0
...
...
@@ -7,7 +7,6 @@
#define lzio_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
...
...
@@ -49,7 +48,7 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
z
->
L
=
L
;
z
->
reader
=
reader
;
z
->
data
=
data
;
z
->
n
=
z
->
i
=
0
;
z
->
n
=
0
;
z
->
p
=
NULL
;
}
...
...
@@ -64,7 +63,6 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
if
(
b
)
memcpy
(
b
,
z
->
p
,
m
);
z
->
n
-=
m
;
z
->
i
+=
m
;
z
->
p
+=
m
;
if
(
b
)
b
=
(
char
*
)
b
+
m
;
...
...
components/lua/lzio.h
→
components/lua/
lua-5.1/
lzio.h
View file @
dba57fa0
...
...
@@ -43,9 +43,6 @@ typedef struct Mbuffer {
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
#define luaZ_get_base_address(zio) ((const char *)((zio)->reader(NULL, (zio)->data, NULL)))
#define luaZ_direct_mode(zio) (luaZ_get_base_address(zio) != NULL)
#define luaZ_get_crt_address(zio) (luaZ_get_base_address(zio) + (zio)->i)
LUAI_FUNC
char
*
luaZ_openspace
(
lua_State
*
L
,
Mbuffer
*
buff
,
size_t
n
);
LUAI_FUNC
void
luaZ_init
(
lua_State
*
L
,
ZIO
*
z
,
lua_Reader
reader
,
...
...
@@ -59,7 +56,6 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z);
struct
Zio
{
size_t
n
;
/* bytes still unread */
size_t
i
;
/* buffer offset */
const
char
*
p
;
/* current position in buffer */
lua_Reader
reader
;
void
*
data
;
/* additional data */
...
...
components/lua/lua-5.3/Makefile
0 → 100644
View file @
dba57fa0
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef
PDIR
SUBDIRS
=
host
GEN_LIBS
=
liblua.a
endif
STD_CFLAGS
=
-std
=
gnu11
-Wimplicit
-Wall
# Validate LUA setting
ifeq
("$(LUA)","53")
# ok
else
ifeq
("$(LUA)","51")
$(error
Your
variable
LUA
=
"
$(LUA)
"
looks like you probably want
\
app/lua/Makefile instead
)
else
$(error
Expected
environment
variable
"LUA"
to
be
"53"
,
not
"$(LUA)"
)
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
#
#DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DDEVELOPMENT_BREAK_ON_STARTUP_PIN=1
#EXTRA_CCFLAGS += -ggdb -O0
#############################################################
# Recursion Magic - Don't touch this!!
#
INCLUDES
:=
$(INCLUDES)
-I
$(PDIR)
include
INCLUDES
+=
-I
./
INCLUDES
+=
-I
../spiffs
INCLUDES
+=
-I
../libc
INCLUDES
+=
-I
../modules
INCLUDES
+=
-I
../platform
INCLUDES
+=
-I
../uzlib
PDIR
:=
../
$(PDIR)
sinclude
$(PDIR)Makefile
components/lua/lua-5.3/host/idf.mk
0 → 100644
View file @
dba57fa0
all
:
build
HOSTCC
?=
$(PYTHON)
-m
ziglang cc
ifeq
($V,)
Q
:=
@
endif
LUAC_OBJ_DIR
:=
$(LUAC_BUILD_DIR)
/
$(
notdir
$(LUA_PATH)
)
LUAC_CFLAGS
:=
\
-I
$(LUAC_BUILD_DIR)
\
-I
$(LUA_PATH)
\
-I
$(LUA_PATH)
/host
\
-I
$(LUA_PATH)
/../common
\
-I
$(LUA_PATH)
/../../uzlib
\
-O2
-g
-Wall
-Wextra
-Wno-sign-compare
-Wno-string-plus-int
LUAC_LDFLAGS
:=
-ldl
-lm
LUAC_DEFINES
+=
\
-DLUA_CROSS_COMPILER
\
-DLUA_USE_HOST
\
-DLUA_USE_STDIO
\
vpath
%.c
$(LUA_PATH)/host
$(LUA_PATH)
$(LUA_PATH)/../common
$(LUA_PATH)/../../uzlib
LUA_SRCS
:=
\
luac.c loslib.c liolib.c
\
lapi.c lauxlib.c lbaselib.c lbitlib.c lcode.c lcorolib.c
\
lctype.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c
\
lgc.c llex.c lmathlib.c lmem.c lnodemcu.c loadlib.c
\
lobject.c lopcodes.c lparser.c lstate.c lstring.c lstrlib.c
\
ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c
\
lzio.c
\
linit.c lpanic.c
\
uzlib_deflate.c crc32.c
\
LUAC_OBJS
:=
$
(
LUA_SRCS:%.c
=
$(LUAC_OBJ_DIR)
/%.o
)
LUAC_CROSS
:=
$(LUAC_BUILD_DIR)
/luac.cross
$(LUAC_OBJ_DIR)
:
@
mkdir
-p
"
$@
"
$(LUAC_OBJ_DIR)/%.o
:
%.c | $(LUAC_OBJ_DIR)
@
echo
'[hostcc]
$(
notdir
$@
)
'
$Q$(HOSTCC)
$(LUAC_DEFINES)
$(LUAC_CFLAGS)
"
$<
"
-c
-o
"
$@
"
$(LUAC_OBJ_DIR)/%.d
:
SHELL=/bin/bash
$(LUAC_OBJ_DIR)/%.d
:
%.c | $(LUAC_OBJ_DIR)
@
echo
'[ dep] $<'
@
rm
-f
"
$@
"
$Qset
-eo
pipefail
;
$(HOSTCC)
$(LUAC_DEFINES)
$(LUAC_CFLAGS)
-M
"
$<
"
|
sed
's,\($*\.o\)[ :]*,
$(LUAC_OBJ_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
"
$@
"
# zig cc (0.8.0 at least) seems to get itself all confused with its cache
# when we're running a separate path for dependencies, so we skip them for
# now as for most people they're not needed anyway.
ifneq
($(findstring zig,$(HOSTCC)),zig)
LUAC_DEPS
:=
$(LUAC_OBJS:%.o=%.d)
ifneq
($(MAKECMDGOALS),clean)
-include
$(LUAC_DEPS)
endif
endif
components/lua/lua-5.3/host/liolib.c
0 → 100644
View file @
dba57fa0
/*
** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#define liolib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** Change this macro to accept other modes for 'fopen' besides
** the standard ones.
*/
#if !defined(l_checkmode)
/* accepted extensions to 'mode' in 'fopen' */
#if !defined(L_MODEEXT)
#define L_MODEEXT "b"
#endif
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
static
int
l_checkmode
(
const
char
*
mode
)
{
return
(
*
mode
!=
'\0'
&&
strchr
(
"rwa"
,
*
(
mode
++
))
!=
NULL
&&
(
*
mode
!=
'+'
||
(
++
mode
,
1
))
&&
/* skip if char is '+' */
(
strspn
(
mode
,
L_MODEEXT
)
==
strlen
(
mode
)));
/* check extensions */
}
#endif
/*
** {======================================================
** l_popen spawns a new process connected to the current
** one through the file streams.
** =======================================================
*/
#if !defined(l_popen)
/* { */
#if defined(LUA_USE_POSIX)
/* { */
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
#define l_pclose(L,file) (pclose(file))
#elif defined(LUA_USE_WINDOWS)
/* }{ */
#define l_popen(L,c,m) (_popen(c,m))
#define l_pclose(L,file) (_pclose(file))
#else
/* }{ */
/* ISO C definitions */
#define l_popen(L,c,m) \
((void)((void)c, m), \
luaL_error(L, "'popen' not supported"), \
(FILE*)0)
#define l_pclose(L,file) ((void)L, (void)file, -1)
#endif
/* } */
#endif
/* } */
/* }====================================================== */
#if !defined(l_getc)
/* { */
#if defined(LUA_USE_POSIX)
#define l_getc(f) getc_unlocked(f)
#define l_lockfile(f) flockfile(f)
#define l_unlockfile(f) funlockfile(f)
#else
#define l_getc(f) getc(f)
#define l_lockfile(f) ((void)0)
#define l_unlockfile(f) ((void)0)
#endif
#endif
/* } */
/*
** {======================================================
** l_fseek: configuration for longer offsets
** =======================================================
*/
#if !defined(l_fseek)
/* { */
#if defined(LUA_USE_POSIX)
/* { */
#include <sys/types.h>
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
&& defined(_MSC_VER) && (_MSC_VER >= 1400)
/* }{ */
/* Windows (but not DDK) and Visual C++ 2005 or higher */
#define l_fseek(f,o,w) _fseeki64(f,o,w)
#define l_ftell(f) _ftelli64(f)
#define l_seeknum __int64
#else
/* }{ */
/* ISO C definitions */
#define l_fseek(f,o,w) fseek(f,o,w)
#define l_ftell(f) ftell(f)
#define l_seeknum long
#endif
/* } */
#endif
/* } */
/* }====================================================== */
#define IO_PREFIX "_IO_"
#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
#define IO_INPUT (IO_PREFIX "input")
#define IO_OUTPUT (IO_PREFIX "output")
typedef
luaL_Stream
LStream
;
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#define isclosed(p) ((p)->closef == NULL)
static
int
io_type
(
lua_State
*
L
)
{
LStream
*
p
;
luaL_checkany
(
L
,
1
);
p
=
(
LStream
*
)
luaL_testudata
(
L
,
1
,
LUA_FILEHANDLE
);
if
(
p
==
NULL
)
lua_pushnil
(
L
);
/* not a file */
else
if
(
isclosed
(
p
))
lua_pushliteral
(
L
,
"closed file"
);
else
lua_pushliteral
(
L
,
"file"
);
return
1
;
}
static
int
f_tostring
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
if
(
isclosed
(
p
))
lua_pushliteral
(
L
,
"file (closed)"
);
else
lua_pushfstring
(
L
,
"file (%p)"
,
p
->
f
);
return
1
;
}
static
FILE
*
tofile
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
if
(
isclosed
(
p
))
luaL_error
(
L
,
"attempt to use a closed file"
);
lua_assert
(
p
->
f
);
return
p
->
f
;
}
/*
** When creating file handles, always creates a 'closed' file handle
** before opening the actual file; so, if there is a memory error, the
** handle is in a consistent state.
*/
static
LStream
*
newprefile
(
lua_State
*
L
)
{
LStream
*
p
=
(
LStream
*
)
lua_newuserdata
(
L
,
sizeof
(
LStream
));
p
->
closef
=
NULL
;
/* mark file handle as 'closed' */
luaL_setmetatable
(
L
,
LUA_FILEHANDLE
);
return
p
;
}
/*
** Calls the 'close' function from a file handle. The 'volatile' avoids
** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
** 32 bits).
*/
static
int
aux_close
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
volatile
lua_CFunction
cf
=
p
->
closef
;
p
->
closef
=
NULL
;
/* mark stream as closed */
return
(
*
cf
)(
L
);
/* close it */
}
static
int
f_close
(
lua_State
*
L
)
{
tofile
(
L
);
/* make sure argument is an open stream */
return
aux_close
(
L
);
}
static
int
io_close
(
lua_State
*
L
)
{
if
(
lua_isnone
(
L
,
1
))
/* no argument? */
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
IO_OUTPUT
);
/* use standard output */
return
f_close
(
L
);
}
static
int
f_gc
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
if
(
!
isclosed
(
p
)
&&
p
->
f
!=
NULL
)
aux_close
(
L
);
/* ignore closed and incompletely open files */
return
0
;
}
/*
** function to close regular files
*/
static
int
io_fclose
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
int
res
=
fclose
(
p
->
f
);
return
luaL_fileresult
(
L
,
(
res
==
0
),
NULL
);
}
static
LStream
*
newfile
(
lua_State
*
L
)
{
LStream
*
p
=
newprefile
(
L
);
p
->
f
=
NULL
;
p
->
closef
=
&
io_fclose
;
return
p
;
}
static
void
opencheck
(
lua_State
*
L
,
const
char
*
fname
,
const
char
*
mode
)
{
LStream
*
p
=
newfile
(
L
);
p
->
f
=
fopen
(
fname
,
mode
);
if
(
p
->
f
==
NULL
)
luaL_error
(
L
,
"cannot open file '%s' (%s)"
,
fname
,
strerror
(
errno
));
}
static
int
io_open
(
lua_State
*
L
)
{
const
char
*
filename
=
luaL_checkstring
(
L
,
1
);
const
char
*
mode
=
luaL_optstring
(
L
,
2
,
"r"
);
LStream
*
p
=
newfile
(
L
);
const
char
*
md
=
mode
;
/* to traverse/check mode */
luaL_argcheck
(
L
,
l_checkmode
(
md
),
2
,
"invalid mode"
);
p
->
f
=
fopen
(
filename
,
mode
);
return
(
p
->
f
==
NULL
)
?
luaL_fileresult
(
L
,
0
,
filename
)
:
1
;
}
/*
** function to close 'popen' files
*/
static
int
io_pclose
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
return
luaL_execresult
(
L
,
l_pclose
(
L
,
p
->
f
));
}
static
int
io_popen
(
lua_State
*
L
)
{
const
char
*
filename
=
luaL_checkstring
(
L
,
1
);
const
char
*
mode
=
luaL_optstring
(
L
,
2
,
"r"
);
LStream
*
p
=
newprefile
(
L
);
p
->
f
=
l_popen
(
L
,
filename
,
mode
);
p
->
closef
=
&
io_pclose
;
return
(
p
->
f
==
NULL
)
?
luaL_fileresult
(
L
,
0
,
filename
)
:
1
;
}
static
int
io_tmpfile
(
lua_State
*
L
)
{
LStream
*
p
=
newfile
(
L
);
p
->
f
=
tmpfile
();
return
(
p
->
f
==
NULL
)
?
luaL_fileresult
(
L
,
0
,
NULL
)
:
1
;
}
static
FILE
*
getiofile
(
lua_State
*
L
,
const
char
*
findex
)
{
LStream
*
p
;
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
findex
);
p
=
(
LStream
*
)
lua_touserdata
(
L
,
-
1
);
if
(
isclosed
(
p
))
luaL_error
(
L
,
"standard %s file is closed"
,
findex
+
IOPREF_LEN
);
return
p
->
f
;
}
static
int
g_iofile
(
lua_State
*
L
,
const
char
*
f
,
const
char
*
mode
)
{
if
(
!
lua_isnoneornil
(
L
,
1
))
{
const
char
*
filename
=
lua_tostring
(
L
,
1
);
if
(
filename
)
opencheck
(
L
,
filename
,
mode
);
else
{
tofile
(
L
);
/* check that it's a valid file handle */
lua_pushvalue
(
L
,
1
);
}
lua_setfield
(
L
,
LUA_REGISTRYINDEX
,
f
);
}
/* return current value */
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
f
);
return
1
;
}
static
int
io_input
(
lua_State
*
L
)
{
return
g_iofile
(
L
,
IO_INPUT
,
"r"
);
}
static
int
io_output
(
lua_State
*
L
)
{
return
g_iofile
(
L
,
IO_OUTPUT
,
"w"
);
}
static
int
io_readline
(
lua_State
*
L
);
/*
** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
** in the limit for upvalues of a closure)
*/
#define MAXARGLINE 250
static
void
aux_lines
(
lua_State
*
L
,
int
toclose
)
{
int
n
=
lua_gettop
(
L
)
-
1
;
/* number of arguments to read */
luaL_argcheck
(
L
,
n
<=
MAXARGLINE
,
MAXARGLINE
+
2
,
"too many arguments"
);
lua_pushinteger
(
L
,
n
);
/* number of arguments to read */
lua_pushboolean
(
L
,
toclose
);
/* close/not close file when finished */
lua_rotate
(
L
,
2
,
2
);
/* move 'n' and 'toclose' to their positions */
lua_pushcclosure
(
L
,
io_readline
,
3
+
n
);
}
static
int
f_lines
(
lua_State
*
L
)
{
tofile
(
L
);
/* check that it's a valid file handle */
aux_lines
(
L
,
0
);
return
1
;
}
static
int
io_lines
(
lua_State
*
L
)
{
int
toclose
;
if
(
lua_isnone
(
L
,
1
))
lua_pushnil
(
L
);
/* at least one argument */
if
(
lua_isnil
(
L
,
1
))
{
/* no file name? */
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
IO_INPUT
);
/* get default input */
lua_replace
(
L
,
1
);
/* put it at index 1 */
tofile
(
L
);
/* check that it's a valid file handle */
toclose
=
0
;
/* do not close it after iteration */
}
else
{
/* open a new file */
const
char
*
filename
=
luaL_checkstring
(
L
,
1
);
opencheck
(
L
,
filename
,
"r"
);
lua_replace
(
L
,
1
);
/* put file at index 1 */
toclose
=
1
;
/* close it after iteration */
}
aux_lines
(
L
,
toclose
);
return
1
;
}
/*
** {======================================================
** READ
** =======================================================
*/
/* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
/* auxiliary structure used by 'read_number' */
typedef
struct
{
FILE
*
f
;
/* file being read */
int
c
;
/* current character (look ahead) */
int
n
;
/* number of elements in buffer 'buff' */
char
buff
[
L_MAXLENNUM
+
1
];
/* +1 for ending '\0' */
}
RN
;
/*
** Add current char to buffer (if not out of space) and read next one
*/
static
int
nextc
(
RN
*
rn
)
{
if
(
rn
->
n
>=
L_MAXLENNUM
)
{
/* buffer overflow? */
rn
->
buff
[
0
]
=
'\0'
;
/* invalidate result */
return
0
;
/* fail */
}
else
{
rn
->
buff
[
rn
->
n
++
]
=
rn
->
c
;
/* save current char */
rn
->
c
=
l_getc
(
rn
->
f
);
/* read next one */
return
1
;
}
}
/*
** Accept current char if it is in 'set' (of size 2)
*/
static
int
test2
(
RN
*
rn
,
const
char
*
set
)
{
if
(
rn
->
c
==
set
[
0
]
||
rn
->
c
==
set
[
1
])
return
nextc
(
rn
);
else
return
0
;
}
/*
** Read a sequence of (hex)digits
*/
static
int
readdigits
(
RN
*
rn
,
int
hex
)
{
int
count
=
0
;
while
((
hex
?
isxdigit
(
rn
->
c
)
:
isdigit
(
rn
->
c
))
&&
nextc
(
rn
))
count
++
;
return
count
;
}
/*
** Read a number: first reads a valid prefix of a numeral into a buffer.
** Then it calls 'lua_stringtonumber' to check whether the format is
** correct and to convert it to a Lua number
*/
static
int
read_number
(
lua_State
*
L
,
FILE
*
f
)
{
RN
rn
;
int
count
=
0
;
int
hex
=
0
;
char
decp
[
2
];
rn
.
f
=
f
;
rn
.
n
=
0
;
decp
[
0
]
=
lua_getlocaledecpoint
();
/* get decimal point from locale */
decp
[
1
]
=
'.'
;
/* always accept a dot */
l_lockfile
(
rn
.
f
);
do
{
rn
.
c
=
l_getc
(
rn
.
f
);
}
while
(
isspace
(
rn
.
c
));
/* skip spaces */
test2
(
&
rn
,
"-+"
);
/* optional signal */
if
(
test2
(
&
rn
,
"00"
))
{
if
(
test2
(
&
rn
,
"xX"
))
hex
=
1
;
/* numeral is hexadecimal */
else
count
=
1
;
/* count initial '0' as a valid digit */
}
count
+=
readdigits
(
&
rn
,
hex
);
/* integral part */
if
(
test2
(
&
rn
,
decp
))
/* decimal point? */
count
+=
readdigits
(
&
rn
,
hex
);
/* fractional part */
if
(
count
>
0
&&
test2
(
&
rn
,
(
hex
?
"pP"
:
"eE"
)))
{
/* exponent mark? */
test2
(
&
rn
,
"-+"
);
/* exponent signal */
readdigits
(
&
rn
,
0
);
/* exponent digits */
}
ungetc
(
rn
.
c
,
rn
.
f
);
/* unread look-ahead char */
l_unlockfile
(
rn
.
f
);
rn
.
buff
[
rn
.
n
]
=
'\0'
;
/* finish string */
if
(
lua_stringtonumber
(
L
,
rn
.
buff
))
/* is this a valid number? */
return
1
;
/* ok */
else
{
/* invalid format */
lua_pushnil
(
L
);
/* "result" to be removed */
return
0
;
/* read fails */
}
}
static
int
test_eof
(
lua_State
*
L
,
FILE
*
f
)
{
int
c
=
getc
(
f
);
ungetc
(
c
,
f
);
/* no-op when c == EOF */
lua_pushliteral
(
L
,
""
);
return
(
c
!=
EOF
);
}
static
int
read_line
(
lua_State
*
L
,
FILE
*
f
,
int
chop
)
{
luaL_Buffer
b
;
int
c
=
'\0'
;
luaL_buffinit
(
L
,
&
b
);
while
(
c
!=
EOF
&&
c
!=
'\n'
)
{
/* repeat until end of line */
char
*
buff
=
luaL_prepbuffer
(
&
b
);
/* preallocate buffer */
int
i
=
0
;
l_lockfile
(
f
);
/* no memory errors can happen inside the lock */
while
(
i
<
LUAL_BUFFERSIZE
&&
(
c
=
l_getc
(
f
))
!=
EOF
&&
c
!=
'\n'
)
buff
[
i
++
]
=
c
;
l_unlockfile
(
f
);
luaL_addsize
(
&
b
,
i
);
}
if
(
!
chop
&&
c
==
'\n'
)
/* want a newline and have one? */
luaL_addchar
(
&
b
,
c
);
/* add ending newline to result */
luaL_pushresult
(
&
b
);
/* close buffer */
/* return ok if read something (either a newline or something else) */
return
(
c
==
'\n'
||
lua_rawlen
(
L
,
-
1
)
>
0
);
}
static
void
read_all
(
lua_State
*
L
,
FILE
*
f
)
{
size_t
nr
;
luaL_Buffer
b
;
luaL_buffinit
(
L
,
&
b
);
do
{
/* read file in chunks of LUAL_BUFFERSIZE bytes */
char
*
p
=
luaL_prepbuffer
(
&
b
);
nr
=
fread
(
p
,
sizeof
(
char
),
LUAL_BUFFERSIZE
,
f
);
luaL_addsize
(
&
b
,
nr
);
}
while
(
nr
==
LUAL_BUFFERSIZE
);
luaL_pushresult
(
&
b
);
/* close buffer */
}
static
int
read_chars
(
lua_State
*
L
,
FILE
*
f
,
size_t
n
)
{
size_t
nr
;
/* number of chars actually read */
char
*
p
;
luaL_Buffer
b
;
luaL_buffinit
(
L
,
&
b
);
p
=
luaL_prepbuffsize
(
&
b
,
n
);
/* prepare buffer to read whole block */
nr
=
fread
(
p
,
sizeof
(
char
),
n
,
f
);
/* try to read 'n' chars */
luaL_addsize
(
&
b
,
nr
);
luaL_pushresult
(
&
b
);
/* close buffer */
return
(
nr
>
0
);
/* true iff read something */
}
static
int
g_read
(
lua_State
*
L
,
FILE
*
f
,
int
first
)
{
int
nargs
=
lua_gettop
(
L
)
-
1
;
int
success
;
int
n
;
clearerr
(
f
);
if
(
nargs
==
0
)
{
/* no arguments? */
success
=
read_line
(
L
,
f
,
1
);
n
=
first
+
1
;
/* to return 1 result */
}
else
{
/* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack
(
L
,
nargs
+
LUA_MINSTACK
,
"too many arguments"
);
success
=
1
;
for
(
n
=
first
;
nargs
--
&&
success
;
n
++
)
{
if
(
lua_type
(
L
,
n
)
==
LUA_TNUMBER
)
{
size_t
l
=
(
size_t
)
luaL_checkinteger
(
L
,
n
);
success
=
(
l
==
0
)
?
test_eof
(
L
,
f
)
:
read_chars
(
L
,
f
,
l
);
}
else
{
const
char
*
p
=
luaL_checkstring
(
L
,
n
);
if
(
*
p
==
'*'
)
p
++
;
/* skip optional '*' (for compatibility) */
switch
(
*
p
)
{
case
'n'
:
/* number */
success
=
read_number
(
L
,
f
);
break
;
case
'l'
:
/* line */
success
=
read_line
(
L
,
f
,
1
);
break
;
case
'L'
:
/* line with end-of-line */
success
=
read_line
(
L
,
f
,
0
);
break
;
case
'a'
:
/* file */
read_all
(
L
,
f
);
/* read entire file */
success
=
1
;
/* always success */
break
;
default:
return
luaL_argerror
(
L
,
n
,
"invalid format"
);
}
}
}
}
if
(
ferror
(
f
))
return
luaL_fileresult
(
L
,
0
,
NULL
);
if
(
!
success
)
{
lua_pop
(
L
,
1
);
/* remove last result */
lua_pushnil
(
L
);
/* push nil instead */
}
return
n
-
first
;
}
static
int
io_read
(
lua_State
*
L
)
{
return
g_read
(
L
,
getiofile
(
L
,
IO_INPUT
),
1
);
}
static
int
f_read
(
lua_State
*
L
)
{
return
g_read
(
L
,
tofile
(
L
),
2
);
}
static
int
io_readline
(
lua_State
*
L
)
{
LStream
*
p
=
(
LStream
*
)
lua_touserdata
(
L
,
lua_upvalueindex
(
1
));
int
i
;
int
n
=
(
int
)
lua_tointeger
(
L
,
lua_upvalueindex
(
2
));
if
(
isclosed
(
p
))
/* file is already closed? */
return
luaL_error
(
L
,
"file is already closed"
);
lua_settop
(
L
,
1
);
luaL_checkstack
(
L
,
n
,
"too many arguments"
);
for
(
i
=
1
;
i
<=
n
;
i
++
)
/* push arguments to 'g_read' */
lua_pushvalue
(
L
,
lua_upvalueindex
(
3
+
i
));
n
=
g_read
(
L
,
p
->
f
,
2
);
/* 'n' is number of results */
lua_assert
(
n
>
0
);
/* should return at least a nil */
if
(
lua_toboolean
(
L
,
-
n
))
/* read at least one value? */
return
n
;
/* return them */
else
{
/* first result is nil: EOF or error */
if
(
n
>
1
)
{
/* is there error information? */
/* 2nd result is error message */
return
luaL_error
(
L
,
"%s"
,
lua_tostring
(
L
,
-
n
+
1
));
}
if
(
lua_toboolean
(
L
,
lua_upvalueindex
(
3
)))
{
/* generator created file? */
lua_settop
(
L
,
0
);
lua_pushvalue
(
L
,
lua_upvalueindex
(
1
));
aux_close
(
L
);
/* close it */
}
return
0
;
}
}
/* }====================================================== */
static
int
g_write
(
lua_State
*
L
,
FILE
*
f
,
int
arg
)
{
int
nargs
=
lua_gettop
(
L
)
-
arg
;
int
status
=
1
;
for
(;
nargs
--
;
arg
++
)
{
if
(
lua_type
(
L
,
arg
)
==
LUA_TNUMBER
)
{
/* optimization: could be done exactly as for strings */
int
len
=
lua_isinteger
(
L
,
arg
)
?
fprintf
(
f
,
LUA_INTEGER_FMT
,
(
LUAI_UACINT
)
lua_tointeger
(
L
,
arg
))
:
fprintf
(
f
,
LUA_NUMBER_FMT
,
(
LUAI_UACNUMBER
)
lua_tonumber
(
L
,
arg
));
status
=
status
&&
(
len
>
0
);
}
else
{
size_t
l
;
const
char
*
s
=
luaL_checklstring
(
L
,
arg
,
&
l
);
status
=
status
&&
(
fwrite
(
s
,
sizeof
(
char
),
l
,
f
)
==
l
);
}
}
if
(
status
)
return
1
;
/* file handle already on stack top */
else
return
luaL_fileresult
(
L
,
status
,
NULL
);
}
static
int
io_write
(
lua_State
*
L
)
{
return
g_write
(
L
,
getiofile
(
L
,
IO_OUTPUT
),
1
);
}
static
int
f_write
(
lua_State
*
L
)
{
FILE
*
f
=
tofile
(
L
);
lua_pushvalue
(
L
,
1
);
/* push file at the stack top (to be returned) */
return
g_write
(
L
,
f
,
2
);
}
static
int
f_seek
(
lua_State
*
L
)
{
static
const
int
mode
[]
=
{
SEEK_SET
,
SEEK_CUR
,
SEEK_END
};
static
const
char
*
const
modenames
[]
=
{
"set"
,
"cur"
,
"end"
,
NULL
};
FILE
*
f
=
tofile
(
L
);
int
op
=
luaL_checkoption
(
L
,
2
,
"cur"
,
modenames
);
lua_Integer
p3
=
luaL_optinteger
(
L
,
3
,
0
);
l_seeknum
offset
=
(
l_seeknum
)
p3
;
luaL_argcheck
(
L
,
(
lua_Integer
)
offset
==
p3
,
3
,
"not an integer in proper range"
);
op
=
l_fseek
(
f
,
offset
,
mode
[
op
]);
if
(
op
)
return
luaL_fileresult
(
L
,
0
,
NULL
);
/* error */
else
{
lua_pushinteger
(
L
,
(
lua_Integer
)
l_ftell
(
f
));
return
1
;
}
}
static
int
f_setvbuf
(
lua_State
*
L
)
{
static
const
int
mode
[]
=
{
_IONBF
,
_IOFBF
,
_IOLBF
};
static
const
char
*
const
modenames
[]
=
{
"no"
,
"full"
,
"line"
,
NULL
};
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
],
(
size_t
)
sz
);
return
luaL_fileresult
(
L
,
res
==
0
,
NULL
);
}
static
int
io_flush
(
lua_State
*
L
)
{
return
luaL_fileresult
(
L
,
fflush
(
getiofile
(
L
,
IO_OUTPUT
))
==
0
,
NULL
);
}
static
int
f_flush
(
lua_State
*
L
)
{
return
luaL_fileresult
(
L
,
fflush
(
tofile
(
L
))
==
0
,
NULL
);
}
/*
** functions for 'io' library
*/
static
const
luaL_Reg
iolib
[]
=
{
{
"close"
,
io_close
},
{
"flush"
,
io_flush
},
{
"input"
,
io_input
},
{
"lines"
,
io_lines
},
{
"open"
,
io_open
},
{
"output"
,
io_output
},
{
"popen"
,
io_popen
},
{
"read"
,
io_read
},
{
"tmpfile"
,
io_tmpfile
},
{
"type"
,
io_type
},
{
"write"
,
io_write
},
{
NULL
,
NULL
}
};
/*
** methods for file handles
*/
static
const
luaL_Reg
flib
[]
=
{
{
"close"
,
f_close
},
{
"flush"
,
f_flush
},
{
"lines"
,
f_lines
},
{
"read"
,
f_read
},
{
"seek"
,
f_seek
},
{
"setvbuf"
,
f_setvbuf
},
{
"write"
,
f_write
},
{
"__gc"
,
f_gc
},
{
"__tostring"
,
f_tostring
},
{
NULL
,
NULL
}
};
static
void
createmeta
(
lua_State
*
L
)
{
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_setfuncs
(
L
,
flib
,
0
);
/* add file methods to new metatable */
lua_pop
(
L
,
1
);
/* pop new metatable */
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static
int
io_noclose
(
lua_State
*
L
)
{
LStream
*
p
=
tolstream
(
L
);
p
->
closef
=
&
io_noclose
;
/* keep file opened */
lua_pushnil
(
L
);
lua_pushliteral
(
L
,
"cannot close standard file"
);
return
2
;
}
static
void
createstdfile
(
lua_State
*
L
,
FILE
*
f
,
const
char
*
k
,
const
char
*
fname
)
{
LStream
*
p
=
newprefile
(
L
);
p
->
f
=
f
;
p
->
closef
=
&
io_noclose
;
if
(
k
!=
NULL
)
{
lua_pushvalue
(
L
,
-
1
);
lua_setfield
(
L
,
LUA_REGISTRYINDEX
,
k
);
/* add file to registry */
}
lua_setfield
(
L
,
-
2
,
fname
);
/* add file to module */
}
LUAMOD_API
int
luaopen_io
(
lua_State
*
L
)
{
luaL_newlib
(
L
,
iolib
);
/* new module */
createmeta
(
L
);
/* create (and set) default files */
createstdfile
(
L
,
stdin
,
IO_INPUT
,
"stdin"
);
createstdfile
(
L
,
stdout
,
IO_OUTPUT
,
"stdout"
);
createstdfile
(
L
,
stderr
,
NULL
,
"stderr"
);
return
1
;
}
components/lua/lua-5.3/host/loslib.c
0 → 100644
View file @
dba57fa0
/*
** $Id: loslib.c,v 1.65.1.1 2017/04/19 17:29:57 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
#define loslib_c
#define LUA_LIB
#include "lprefix.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** {==================================================================
** List of valid conversion specifiers for the 'strftime' function;
** options are grouped by length; group of length 2 start with '||'.
** ===================================================================
*/
#if !defined(LUA_STRFTIMEOPTIONS)
/* { */
/* options for ANSI C 89 (only 1-char options) */
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy"
/* two-char options */
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"
/* two-char options */
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#else
/* C99 specification */
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
#endif
#endif
/* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for time-related stuff
** ===================================================================
*/
#if !defined(l_time_t)
/* { */
/*
** type to represent time_t in Lua
*/
#define l_timet lua_Integer
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
static
time_t
l_checktime
(
lua_State
*
L
,
int
arg
)
{
lua_Integer
t
=
luaL_checkinteger
(
L
,
arg
);
luaL_argcheck
(
L
,
(
time_t
)
t
==
t
,
arg
,
"time out-of-bounds"
);
return
(
time_t
)
t
;
}
#endif
/* } */
#if !defined(l_gmtime)
/* { */
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_POSIX)
/* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#else
/* }{ */
/* ISO C definitions */
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
#endif
/* } */
#endif
/* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for 'tmpnam':
** By default, Lua uses tmpnam except when POSIX is available, where
** it uses mkstemp.
** ===================================================================
*/
#if !defined(lua_tmpnam)
/* { */
#if defined(__GNUC__)
/* { */
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#if !defined(LUA_TMPNAMTEMPLATE)
#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
#endif
#define lua_tmpnam(b,e) { \
strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#else
/* }{ */
/* ISO C definitions */
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif
/* } */
#endif
/* } */
/* }================================================================== */
static
int
os_execute
(
lua_State
*
L
)
{
const
char
*
cmd
=
luaL_optstring
(
L
,
1
,
NULL
);
int
stat
=
system
(
cmd
);
if
(
cmd
!=
NULL
)
return
luaL_execresult
(
L
,
stat
);
else
{
lua_pushboolean
(
L
,
stat
);
/* true if there is a shell */
return
1
;
}
}
static
int
os_remove
(
lua_State
*
L
)
{
const
char
*
filename
=
luaL_checkstring
(
L
,
1
);
return
luaL_fileresult
(
L
,
remove
(
filename
)
==
0
,
filename
);
}
static
int
os_rename
(
lua_State
*
L
)
{
const
char
*
fromname
=
luaL_checkstring
(
L
,
1
);
const
char
*
toname
=
luaL_checkstring
(
L
,
2
);
return
luaL_fileresult
(
L
,
rename
(
fromname
,
toname
)
==
0
,
NULL
);
}
static
int
os_tmpname
(
lua_State
*
L
)
{
char
buff
[
LUA_TMPNAMBUFSIZE
];
int
err
;
lua_tmpnam
(
buff
,
err
);
if
(
err
)
return
luaL_error
(
L
,
"unable to generate a unique filename"
);
lua_pushstring
(
L
,
buff
);
return
1
;
}
static
int
os_getenv
(
lua_State
*
L
)
{
lua_pushstring
(
L
,
getenv
(
luaL_checkstring
(
L
,
1
)));
/* if NULL push nil */
return
1
;
}
static
int
os_clock
(
lua_State
*
L
)
{
lua_pushnumber
(
L
,
((
lua_Number
)
clock
())
/
(
lua_Number
)
CLOCKS_PER_SEC
);
return
1
;
}
/*
** {======================================================
** Time/Date operations
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
** wday=%w+1, yday=%j, isdst=? }
** =======================================================
*/
static
void
setfield
(
lua_State
*
L
,
const
char
*
key
,
int
value
)
{
lua_pushinteger
(
L
,
value
);
lua_setfield
(
L
,
-
2
,
key
);
}
static
void
setboolfield
(
lua_State
*
L
,
const
char
*
key
,
int
value
)
{
if
(
value
<
0
)
/* undefined? */
return
;
/* does not set field */
lua_pushboolean
(
L
,
value
);
lua_setfield
(
L
,
-
2
,
key
);
}
/*
** Set all fields from structure 'tm' in the table on top of the stack
*/
static
void
setallfields
(
lua_State
*
L
,
struct
tm
*
stm
)
{
setfield
(
L
,
"sec"
,
stm
->
tm_sec
);
setfield
(
L
,
"min"
,
stm
->
tm_min
);
setfield
(
L
,
"hour"
,
stm
->
tm_hour
);
setfield
(
L
,
"day"
,
stm
->
tm_mday
);
setfield
(
L
,
"month"
,
stm
->
tm_mon
+
1
);
setfield
(
L
,
"year"
,
stm
->
tm_year
+
1900
);
setfield
(
L
,
"wday"
,
stm
->
tm_wday
+
1
);
setfield
(
L
,
"yday"
,
stm
->
tm_yday
+
1
);
setboolfield
(
L
,
"isdst"
,
stm
->
tm_isdst
);
}
static
int
getboolfield
(
lua_State
*
L
,
const
char
*
key
)
{
int
res
;
res
=
(
lua_getfield
(
L
,
-
1
,
key
)
==
LUA_TNIL
)
?
-
1
:
lua_toboolean
(
L
,
-
1
);
lua_pop
(
L
,
1
);
return
res
;
}
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
#if !defined(L_MAXDATEFIELD)
#define L_MAXDATEFIELD (INT_MAX / 2)
#endif
static
int
getfield
(
lua_State
*
L
,
const
char
*
key
,
int
d
,
int
delta
)
{
int
isnum
;
int
t
=
lua_getfield
(
L
,
-
1
,
key
);
/* get field and its type */
lua_Integer
res
=
lua_tointegerx
(
L
,
-
1
,
&
isnum
);
if
(
!
isnum
)
{
/* field is not an integer? */
if
(
t
!=
LUA_TNIL
)
/* some other value? */
return
luaL_error
(
L
,
"field '%s' is not an integer"
,
key
);
else
if
(
d
<
0
)
/* absent field; no default? */
return
luaL_error
(
L
,
"field '%s' missing in date table"
,
key
);
res
=
d
;
}
else
{
if
(
!
(
-
L_MAXDATEFIELD
<=
res
&&
res
<=
L_MAXDATEFIELD
))
return
luaL_error
(
L
,
"field '%s' is out-of-bound"
,
key
);
res
-=
delta
;
}
lua_pop
(
L
,
1
);
return
(
int
)
res
;
}
static
const
char
*
checkoption
(
lua_State
*
L
,
const
char
*
conv
,
ptrdiff_t
convlen
,
char
*
buff
)
{
const
char
*
option
=
LUA_STRFTIMEOPTIONS
;
int
oplen
=
1
;
/* length of options being checked */
for
(;
*
option
!=
'\0'
&&
oplen
<=
convlen
;
option
+=
oplen
)
{
if
(
*
option
==
'|'
)
/* next block? */
oplen
++
;
/* will check options with next length (+1) */
else
if
(
memcmp
(
conv
,
option
,
oplen
)
==
0
)
{
/* match? */
memcpy
(
buff
,
conv
,
oplen
);
/* copy valid option to buffer */
buff
[
oplen
]
=
'\0'
;
return
conv
+
oplen
;
/* return next item */
}
}
luaL_argerror
(
L
,
1
,
lua_pushfstring
(
L
,
"invalid conversion specifier '%%%s'"
,
conv
));
return
conv
;
/* to avoid warnings */
}
/* maximum size for an individual 'strftime' item */
#define SIZETIMEFMT 250
static
int
os_date
(
lua_State
*
L
)
{
size_t
slen
;
const
char
*
s
=
luaL_optlstring
(
L
,
1
,
"%c"
,
&
slen
);
time_t
t
=
luaL_opt
(
L
,
l_checktime
,
2
,
time
(
NULL
));
const
char
*
se
=
s
+
slen
;
/* 's' end */
struct
tm
tmr
,
*
stm
;
if
(
*
s
==
'!'
)
{
/* UTC? */
stm
=
l_gmtime
(
&
t
,
&
tmr
);
s
++
;
/* skip '!' */
}
else
stm
=
l_localtime
(
&
t
,
&
tmr
);
if
(
stm
==
NULL
)
/* invalid date? */
return
luaL_error
(
L
,
"time result cannot be represented in this installation"
);
if
(
strcmp
(
s
,
"*t"
)
==
0
)
{
lua_createtable
(
L
,
0
,
9
);
/* 9 = number of fields */
setallfields
(
L
,
stm
);
}
else
{
char
cc
[
4
];
/* buffer for individual conversion specifiers */
luaL_Buffer
b
;
cc
[
0
]
=
'%'
;
luaL_buffinit
(
L
,
&
b
);
while
(
s
<
se
)
{
if
(
*
s
!=
'%'
)
/* not a conversion specifier? */
luaL_addchar
(
&
b
,
*
s
++
);
else
{
size_t
reslen
;
char
*
buff
=
luaL_prepbuffsize
(
&
b
,
SIZETIMEFMT
);
s
++
;
/* skip '%' */
s
=
checkoption
(
L
,
s
,
se
-
s
,
cc
+
1
);
/* copy specifier to 'cc' */
reslen
=
strftime
(
buff
,
SIZETIMEFMT
,
cc
,
stm
);
luaL_addsize
(
&
b
,
reslen
);
}
}
luaL_pushresult
(
&
b
);
}
return
1
;
}
static
int
os_time
(
lua_State
*
L
)
{
time_t
t
;
if
(
lua_isnoneornil
(
L
,
1
))
/* called without args? */
t
=
time
(
NULL
);
/* get current time */
else
{
struct
tm
ts
;
luaL_checktype
(
L
,
1
,
LUA_TTABLE
);
lua_settop
(
L
,
1
);
/* make sure table is at the top */
ts
.
tm_sec
=
getfield
(
L
,
"sec"
,
0
,
0
);
ts
.
tm_min
=
getfield
(
L
,
"min"
,
0
,
0
);
ts
.
tm_hour
=
getfield
(
L
,
"hour"
,
12
,
0
);
ts
.
tm_mday
=
getfield
(
L
,
"day"
,
-
1
,
0
);
ts
.
tm_mon
=
getfield
(
L
,
"month"
,
-
1
,
1
);
ts
.
tm_year
=
getfield
(
L
,
"year"
,
-
1
,
1900
);
ts
.
tm_isdst
=
getboolfield
(
L
,
"isdst"
);
t
=
mktime
(
&
ts
);
setallfields
(
L
,
&
ts
);
/* update fields with normalized values */
}
if
(
t
!=
(
time_t
)(
l_timet
)
t
||
t
==
(
time_t
)(
-
1
))
return
luaL_error
(
L
,
"time result cannot be represented in this installation"
);
l_pushtime
(
L
,
t
);
return
1
;
}
static
int
os_difftime
(
lua_State
*
L
)
{
time_t
t1
=
l_checktime
(
L
,
1
);
time_t
t2
=
l_checktime
(
L
,
2
);
lua_pushnumber
(
L
,
(
lua_Number
)
difftime
(
t1
,
t2
));
return
1
;
}
/* }====================================================== */
static
int
os_setlocale
(
lua_State
*
L
)
{
static
const
int
cat
[]
=
{
LC_ALL
,
LC_COLLATE
,
LC_CTYPE
,
LC_MONETARY
,
LC_NUMERIC
,
LC_TIME
};
static
const
char
*
const
catnames
[]
=
{
"all"
,
"collate"
,
"ctype"
,
"monetary"
,
"numeric"
,
"time"
,
NULL
};
const
char
*
l
=
luaL_optstring
(
L
,
1
,
NULL
);
int
op
=
luaL_checkoption
(
L
,
2
,
"all"
,
catnames
);
lua_pushstring
(
L
,
setlocale
(
cat
[
op
],
l
));
return
1
;
}
static
int
os_exit
(
lua_State
*
L
)
{
int
status
;
if
(
lua_isboolean
(
L
,
1
))
status
=
(
lua_toboolean
(
L
,
1
)
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
else
status
=
(
int
)
luaL_optinteger
(
L
,
1
,
EXIT_SUCCESS
);
if
(
lua_toboolean
(
L
,
2
))
lua_close
(
L
);
if
(
L
)
exit
(
status
);
/* 'if' to avoid warnings for unreachable 'return' */
return
0
;
}
static
const
luaL_Reg
syslib
[]
=
{
{
"clock"
,
os_clock
},
{
"date"
,
os_date
},
{
"difftime"
,
os_difftime
},
{
"execute"
,
os_execute
},
{
"exit"
,
os_exit
},
{
"getenv"
,
os_getenv
},
{
"remove"
,
os_remove
},
{
"rename"
,
os_rename
},
{
"setlocale"
,
os_setlocale
},
{
"time"
,
os_time
},
{
"tmpname"
,
os_tmpname
},
{
NULL
,
NULL
}
};
/* }====================================================== */
LUAMOD_API
int
luaopen_os
(
lua_State
*
L
)
{
luaL_newlib
(
L
,
syslib
);
return
1
;
}
components/lua/lua-5.3/host/luac.c
0 → 100644
View file @
dba57fa0
/*
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
** Lua compiler (saves bytecodes to files; also lists bytecodes)
** See Copyright Notice in lua.h
*/
#define luac_c
#define LUA_CORE
#include "lprefix.h"
#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "ldebug.h"
#include "lnodemcu.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lundump.h"
static
void
PrintFunction
(
const
Proto
*
f
,
int
full
);
#define luaU_print PrintFunction
#define PROGNAME "luac.cross"
/* default program name */
#define OUTPUT PROGNAME ".out"
/* default output file */
static
int
listing
=
0
;
/* list bytecodes? */
static
int
dumping
=
1
;
/* dump bytecodes? */
static
int
stripping
=
0
;
/* strip debug information? */
static
char
Output
[]
=
{
OUTPUT
};
/* default output file name */
static
const
char
*
output
=
Output
;
/* actual output file name */
static
const
char
*
progname
=
PROGNAME
;
/* actual program name */
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
const
char
*
execute
;
/* executed a Lua file */
char
*
LFSimageName
;
#if 0
#define IROM0_SEG 0x40200000ul
#define IROM0_SEGMAX 0x00100000ul
#define IROM_OFFSET(a) (cast(lu_int32, (a)) - IROM0_SEG)
#else
// Safety checks disabled for now; would need to handle ESP32/ESP32S/ESP32C3
#define IROM_OFFSET(a)
#endif
static
void
fatal
(
const
char
*
message
)
{
fprintf
(
stderr
,
"%s: %s
\n
"
,
progname
,
message
);
exit
(
EXIT_FAILURE
);
}
static
void
cannot
(
const
char
*
what
)
{
fprintf
(
stderr
,
"%s: cannot %s %s: %s
\n
"
,
progname
,
what
,
output
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
static
void
usage
(
const
char
*
message
)
{
if
(
*
message
==
'-'
)
fprintf
(
stderr
,
"%s: unrecognized option '%s'
\n
"
,
progname
,
message
);
else
fprintf
(
stderr
,
"%s: %s
\n
"
,
progname
,
message
);
fprintf
(
stderr
,
"usage: %s [options] [filenames]
\n
"
"Available options are:
\n
"
" -l list (use -l -l for full listing)
\n
"
" -o name output to file 'name' (default is
\"
%s
\"
)
\n
"
" -e name execute a lua source file
\n
"
" -f output a flash image file
\n
"
" -F name load a flash image file
\n
"
" -a addr generate an absolute, rather than "
"position independent flash image file
\n
"
" (use with -F LFSimage -o absLFSimage to "
"convert an image to absolute format)
\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
"
" -- stop handling options
\n
"
" - stop handling options and process stdin
\n
"
,
progname
,
Output
);
exit
(
EXIT_FAILURE
);
}
#define IS(s) (strcmp(argv[i],s)==0)
static
int
doargs
(
int
argc
,
char
*
argv
[])
{
int
i
;
int
version
=
0
;
lu_int32
offset
=
0
;
if
(
argv
[
0
]
!=
NULL
&&
*
argv
[
0
]
!=
0
)
progname
=
argv
[
0
];
for
(
i
=
1
;
i
<
argc
;
i
++
)
{
if
(
*
argv
[
i
]
!=
'-'
)
{
/* end of options; keep it */
break
;
}
else
if
(
IS
(
"--"
))
{
/* end of options; skip it */
++
i
;
if
(
version
)
++
version
;
break
;
}
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
(
"
\"
-e
\"
needs a file argument"
);
}
else
if
(
IS
(
"-F"
))
{
/* execute a lua source file file */
LFSimageName
=
argv
[
++
i
];
if
(
LFSimageName
==
NULL
||
*
LFSimageName
==
0
||
*
LFSimageName
==
'-'
)
usage
(
"
\"
-F
\"
needs an LFS image file 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
);
#if 0
offset = IROM_OFFSET(address);
if (offset == 0 || offset > IROM0_SEGMAX)
usage("\"-a\" absolute address must be valid flash address");
#endif
}
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
(
"
\"
-m
\"
maximum size must be a multiple of 4,096"
);
}
else
if
(
IS
(
"-o"
))
{
/* output file */
output
=
argv
[
++
i
];
if
(
output
==
NULL
||
*
output
==
0
||
(
*
output
==
'-'
&&
output
[
1
]
!=
0
))
usage
(
"'-o' needs argument"
);
if
(
IS
(
"-"
))
output
=
NULL
;
}
else
if
(
IS
(
"-p"
))
{
/* parse only */
dumping
=
0
;
}
else
if
(
IS
(
"-s"
))
{
/* strip debug information */
stripping
=
1
;
}
else
if
(
IS
(
"-v"
))
{
/* show version */
++
version
;
}
else
{
/* unknown option */
usage
(
argv
[
i
]);
}
}
if
(
offset
>
0
&&
(
output
==
NULL
||
LFSimageName
==
NULL
||
execute
!=
NULL
||
i
!=
argc
))
usage
(
"'-a' also requires '-o' and '-f' options without lua source files"
);
if
(
i
==
argc
&&
(
listing
||
!
dumping
))
{
dumping
=
0
;
argv
[
--
i
]
=
Output
;
}
if
(
version
)
{
printf
(
"%s
\n
"
,
LUA_COPYRIGHT
);
if
(
version
==
argc
-
1
)
exit
(
EXIT_SUCCESS
);
}
return
i
;
}
static
const
char
*
corename
(
lua_State
*
L
,
const
TString
*
filename
,
int
*
len
)
{
(
void
)
L
;
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
,
'.'
);
if
(
len
)
*
len
=
e
?
e
-
s
:
strlen
(
s
);
return
s
;
}
/*
** 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 is used for LFS image dumps
*/
#define toproto(L, i) getproto(L->top + (i))
static
const
Proto
*
combine
(
lua_State
*
L
,
int
n
,
int
type
)
{
if
(
n
==
1
&&
type
==
0
)
{
return
toproto
(
L
,
-
1
);
}
else
{
Proto
*
f
;
int
i
,
j
;
/*
* Generate a minimal proto with 1 return, emtpy p, k & uv vectors
*/
if
(
luaL_loadbuffer
(
L
,
"
\n
"
,
strlen
(
"
\n
"
),
"=("
PROGNAME
")"
)
!=
LUA_OK
)
fatal
(
lua_tostring
(
L
,
-
1
));
f
=
toproto
(
L
,
-
1
);
/*
* Allocate the vector for and bind the sub-protos
*/
luaM_reallocvector
(
L
,
f
->
p
,
f
->
sizep
,
n
,
Proto
*
);
f
->
sizep
=
n
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
f
->
p
[
i
]
=
toproto
(
L
,
i
-
n
-
1
);
if
(
f
->
p
[
i
]
->
sizeupvalues
>
0
)
f
->
p
[
i
]
->
upvalues
[
0
].
instack
=
0
;
}
f
->
numparams
=
0
;
f
->
maxstacksize
=
1
;
if
(
type
==
1
)
{
/*
* For Type 1 main(), add a k vector of strings naming the corresponding
* protos with the Unixtime of the compile appended.
*/
luaM_reallocvector
(
L
,
f
->
k
,
f
->
sizek
,
n
+
1
,
TValue
);
f
->
sizek
=
n
+
1
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
int
len
;
const
char
*
name
=
corename
(
L
,
f
->
p
[
i
]
->
source
,
&
len
);
TString
*
sname
=
luaS_newlstr
(
L
,
name
,
len
);
for
(
j
=
0
;
j
<
i
;
j
++
)
{
if
(
tsvalue
(
f
->
k
+
j
)
==
sname
)
fatal
(
lua_pushfstring
(
L
,
"Cannot have duplicate files ('%s') in LFS"
,
name
));
}
setsvalue2n
(
L
,
f
->
k
+
i
,
sname
);
}
setivalue
(
f
->
k
+
n
,
(
lua_Integer
)
time
(
NULL
));
}
return
f
;
}
}
static
int
writer
(
lua_State
*
L
,
const
void
*
p
,
size_t
size
,
void
*
u
)
{
UNUSED
(
L
);
return
(
fwrite
(
p
,
size
,
1
,
((
FILE
**
)
u
)[
0
])
!=
1
)
&&
(
size
!=
0
);
}
static
int
msghandler
(
lua_State
*
L
)
{
const
char
*
msg
=
lua_tostring
(
L
,
1
);
if
(
msg
==
NULL
)
/* is error object not a string? */
msg
=
lua_pushfstring
(
L
,
"(error object is a %s value)"
,
luaL_typename
(
L
,
1
));
luaL_traceback
(
L
,
L
,
msg
,
1
);
/* append a standard traceback */
return
1
;
/* return the traceback */
}
static
int
dofile
(
lua_State
*
L
,
const
char
*
name
)
{
int
status
=
luaL_loadfile
(
L
,
name
);
if
(
status
==
LUA_OK
)
{
int
base
=
lua_gettop
(
L
);
lua_pushcfunction
(
L
,
msghandler
);
/* push message handler */
lua_insert
(
L
,
base
);
/* put it under function and args */
status
=
lua_pcall
(
L
,
0
,
0
,
base
);
lua_remove
(
L
,
base
);
/* remove message handler from the stack */
}
if
(
status
!=
LUA_OK
)
{
fprintf
(
stderr
,
"%s: %s
\n
"
,
PROGNAME
,
lua_tostring
(
L
,
-
1
));
lua_pop
(
L
,
1
);
/* remove message */
}
return
status
;
}
/*
** This function is an inintended consequence of constraints in ltable.c
** rotable_findentry(). The file list generates a ROTable in LFS and the
** rule for ROTables is that metavalue entries must be at the head of the
** ROTableentry list so argv file names with basenames starting with "__"
** must be head of the list. This is a botch. Sorry.
*/
static
void
reorderfiles
(
lua_State
*
L
,
int
argc
,
char
**
list
,
char
**
argv
)
{
int
i
,
j
;
for
(
i
=
0
;
i
<
argc
;
i
++
)
{
TString
*
file
=
luaS_new
(
L
,
argv
[
i
]);
if
(
strcmp
(
"__"
,
corename
(
L
,
file
,
NULL
)))
{
list
[
i
]
=
argv
[
i
];
/* add to the end of the new list */
}
else
{
for
(
j
=
0
;
j
<
i
;
j
++
)
list
[
j
+
1
]
=
list
[
j
];
list
[
0
]
=
argv
[
i
];
/* add to the start of the new list */
}
}
}
static
int
pmain
(
lua_State
*
L
)
{
int
argc
=
(
int
)
lua_tointeger
(
L
,
1
);
char
**
argv
=
(
char
**
)
lua_touserdata
(
L
,
2
);
char
**
filelist
=
alloca
(
argc
*
sizeof
(
char
*
));
const
Proto
*
f
;
int
i
,
status
;
if
(
!
lua_checkstack
(
L
,
argc
+
1
))
fatal
(
"too many input files"
);
if
(
execute
||
address
)
{
luaL_openlibs
(
L
);
/* the nodemcu open will throw to signal an LFS reload */
status
=
dofile
(
L
,
execute
);
if
(
status
!=
LUA_OK
)
return
0
;
}
if
(
argc
==
0
)
return
0
;
reorderfiles
(
L
,
argc
,
filelist
,
argv
);
for
(
i
=
0
;
i
<
argc
;
i
++
)
{
const
char
*
filename
=
IS
(
"-"
)
?
NULL
:
filelist
[
i
];
if
(
luaL_loadfile
(
L
,
filename
)
!=
LUA_OK
)
fatal
(
lua_tostring
(
L
,
-
1
));
//TODO: if strip = 2, replace proto->source by basename
}
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
);
if
(
flash
)
{
UNUSED
(
address
);
UNUSED
(
maxSize
);
result
=
luaU_DumpAllProtos
(
L
,
f
,
writer
,
&
D
,
stripping
);
}
else
{
result
=
luaU_dump
(
L
,
f
,
writer
,
cast
(
void
*
,
&
D
),
stripping
);
}
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"
);
if
(
ferror
(
D
))
cannot
(
"write"
);
if
(
fclose
(
D
))
cannot
(
"close"
);
}
return
0
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
lua_State
*
L
;
int
i
=
doargs
(
argc
,
argv
);
int
j
,
status
;
argc
-=
i
;
argv
+=
i
;
if
(
argc
<=
0
&&
execute
==
0
&&
address
==
0
)
usage
(
"no input files given"
);
if
(
address
)
luaN_setabsolute
(
address
);
for
(
j
=
0
;
j
<
2
;
j
++
)
{
L
=
luaL_newstate
();
if
(
L
==
NULL
)
fatal
(
"not enough memory for state"
);
lua_pushcfunction
(
L
,
&
pmain
);
lua_pushinteger
(
L
,
argc
);
lua_pushlightuserdata
(
L
,
argv
);
status
=
lua_pcall
(
L
,
2
,
0
,
0
);
if
(
status
!=
LUA_OK
)
{
const
char
*
res
=
luaL_optstring
(
L
,
-
1
,
""
);
if
(
strcmp
(
res
,
"!LFSrestart!"
)
==
0
)
{
/*An LFS image has been loaded */
if
(
address
)
{
/* write out as absolute image and exit */
lu_int32
size
=
cast
(
LFSHeader
*
,
LFSregion
)
->
flash_size
;
FILE
*
af
=
fopen
(
output
,
"wb"
);
if
(
af
==
NULL
)
cannot
(
"open"
);
if
(
fwrite
(
LFSregion
,
size
,
1
,
af
)
!=
1
)
cannot
(
"write"
);
fclose
(
af
);
exit
(
0
);
}
/*otherwise simulate a restart */
lua_close
(
L
);
continue
;
/* and loop around once more simulating restart */
}
char
*
err
=
strdup
(
lua_tostring
(
L
,
-
1
));
lua_close
(
L
);
fatal
(
err
);
}
lua_close
(
L
);
break
;
}
return
EXIT_SUCCESS
;
}
/*
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#define luac_c
#define LUA_CORE
#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#define VOID(p) ((const void*)(p))
static
void
PrintString
(
const
TString
*
ts
)
{
const
char
*
s
=
getstr
(
ts
);
size_t
i
,
n
=
tsslen
(
ts
);
printf
(
"%c"
,
'"'
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
int
c
=
(
int
)(
unsigned
char
)
s
[
i
];
switch
(
c
)
{
case
'"'
:
printf
(
"
\\\"
"
);
break
;
case
'\\'
:
printf
(
"
\\\\
"
);
break
;
case
'\a'
:
printf
(
"
\\
a"
);
break
;
case
'\b'
:
printf
(
"
\\
b"
);
break
;
case
'\f'
:
printf
(
"
\\
f"
);
break
;
case
'\n'
:
printf
(
"
\\
n"
);
break
;
case
'\r'
:
printf
(
"
\\
r"
);
break
;
case
'\t'
:
printf
(
"
\\
t"
);
break
;
case
'\v'
:
printf
(
"
\\
v"
);
break
;
default:
if
(
isprint
(
c
))
printf
(
"%c"
,
c
);
else
printf
(
"
\\
%03d"
,
c
);
}
}
printf
(
"%c"
,
'"'
);
}
static
void
PrintConstant
(
const
Proto
*
f
,
int
i
)
{
const
TValue
*
o
=&
f
->
k
[
i
];
switch
(
ttype
(
o
))
{
case
LUA_TNIL
:
printf
(
"nil"
);
break
;
case
LUA_TBOOLEAN
:
printf
(
bvalue
(
o
)
?
"true"
:
"false"
);
break
;
case
LUA_TNUMFLT
:
{
char
buff
[
100
];
sprintf
(
buff
,
LUA_NUMBER_FMT
,
fltvalue
(
o
));
printf
(
"%s"
,
buff
);
if
(
buff
[
strspn
(
buff
,
"-0123456789"
)]
==
'\0'
)
printf
(
".0"
);
break
;
}
case
LUA_TNUMINT
:
printf
(
LUA_INTEGER_FMT
,
ivalue
(
o
));
break
;
case
LUA_TSHRSTR
:
case
LUA_TLNGSTR
:
PrintString
(
tsvalue
(
o
));
break
;
default:
/* cannot happen */
printf
(
"? type=%d"
,
ttype
(
o
));
break
;
}
}
#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
#define MYK(x) (-1-(x))
static
void
PrintCode
(
const
Proto
*
f
)
{
const
Instruction
*
code
=
f
->
code
;
int
pc
,
n
=
f
->
sizecode
;
for
(
pc
=
0
;
pc
<
n
;
pc
++
)
{
Instruction
i
=
code
[
pc
];
OpCode
o
=
GET_OPCODE
(
i
);
int
a
=
GETARG_A
(
i
);
int
b
=
GETARG_B
(
i
);
int
c
=
GETARG_C
(
i
);
int
ax
=
GETARG_Ax
(
i
);
int
bx
=
GETARG_Bx
(
i
);
int
sbx
=
GETARG_sBx
(
i
);
int
line
=
getfuncline
(
f
,
pc
);
printf
(
"
\t
%d
\t
"
,
pc
+
1
);
if
(
line
>
0
)
printf
(
"[%d]
\t
"
,
line
);
else
printf
(
"[-]
\t
"
);
printf
(
"%-9s
\t
"
,
luaP_opnames
[
o
]);
switch
(
getOpMode
(
o
))
{
case
iABC
:
printf
(
"%d"
,
a
);
if
(
getBMode
(
o
)
!=
OpArgN
)
printf
(
" %d"
,
ISK
(
b
)
?
(
MYK
(
INDEXK
(
b
)))
:
b
);
if
(
getCMode
(
o
)
!=
OpArgN
)
printf
(
" %d"
,
ISK
(
c
)
?
(
MYK
(
INDEXK
(
c
)))
:
c
);
break
;
case
iABx
:
printf
(
"%d"
,
a
);
if
(
getBMode
(
o
)
==
OpArgK
)
printf
(
" %d"
,
MYK
(
bx
));
if
(
getBMode
(
o
)
==
OpArgU
)
printf
(
" %d"
,
bx
);
break
;
case
iAsBx
:
printf
(
"%d %d"
,
a
,
sbx
);
break
;
case
iAx
:
printf
(
"%d"
,
MYK
(
ax
));
break
;
}
switch
(
o
)
{
case
OP_LOADK
:
printf
(
"
\t
; "
);
PrintConstant
(
f
,
bx
);
break
;
case
OP_GETUPVAL
:
case
OP_SETUPVAL
:
printf
(
"
\t
; %s"
,
UPVALNAME
(
b
));
break
;
case
OP_GETTABUP
:
printf
(
"
\t
; %s"
,
UPVALNAME
(
b
));
if
(
ISK
(
c
))
{
printf
(
" "
);
PrintConstant
(
f
,
INDEXK
(
c
));
}
break
;
case
OP_SETTABUP
:
printf
(
"
\t
; %s"
,
UPVALNAME
(
a
));
if
(
ISK
(
b
))
{
printf
(
" "
);
PrintConstant
(
f
,
INDEXK
(
b
));
}
if
(
ISK
(
c
))
{
printf
(
" "
);
PrintConstant
(
f
,
INDEXK
(
c
));
}
break
;
case
OP_GETTABLE
:
case
OP_SELF
:
if
(
ISK
(
c
))
{
printf
(
"
\t
; "
);
PrintConstant
(
f
,
INDEXK
(
c
));
}
break
;
case
OP_SETTABLE
:
case
OP_ADD
:
case
OP_SUB
:
case
OP_MUL
:
case
OP_MOD
:
case
OP_POW
:
case
OP_DIV
:
case
OP_IDIV
:
case
OP_BAND
:
case
OP_BOR
:
case
OP_BXOR
:
case
OP_SHL
:
case
OP_SHR
:
case
OP_EQ
:
case
OP_LT
:
case
OP_LE
:
if
(
ISK
(
b
)
||
ISK
(
c
))
{
printf
(
"
\t
; "
);
if
(
ISK
(
b
))
PrintConstant
(
f
,
INDEXK
(
b
));
else
printf
(
"-"
);
printf
(
" "
);
if
(
ISK
(
c
))
PrintConstant
(
f
,
INDEXK
(
c
));
else
printf
(
"-"
);
}
break
;
case
OP_JMP
:
case
OP_FORLOOP
:
case
OP_FORPREP
:
case
OP_TFORLOOP
:
printf
(
"
\t
; to %d"
,
sbx
+
pc
+
2
);
break
;
case
OP_CLOSURE
:
printf
(
"
\t
; %p"
,
VOID
(
f
->
p
[
bx
]));
break
;
case
OP_SETLIST
:
if
(
c
==
0
)
printf
(
"
\t
; %d"
,(
int
)
code
[
++
pc
]);
else
printf
(
"
\t
; %d"
,
c
);
break
;
case
OP_EXTRAARG
:
printf
(
"
\t
; "
);
PrintConstant
(
f
,
ax
);
break
;
default:
break
;
}
printf
(
"
\n
"
);
}
}
#define SS(x) ((x==1)?"":"s")
#define S(x) (int)(x),SS(x)
static
void
PrintHeader
(
const
Proto
*
f
)
{
const
char
*
s
=
f
->
source
?
getstr
(
f
->
source
)
:
"=?"
;
if
(
*
s
==
'@'
||
*
s
==
'='
)
s
++
;
else
if
(
*
s
==
LUA_SIGNATURE
[
0
])
s
=
"(bstring)"
;
else
s
=
"(string)"
;
printf
(
"
\n
%s <%s:%d,%d> (%d instruction%s at %p)
\n
"
,
(
f
->
linedefined
==
0
)
?
"main"
:
"function"
,
s
,
f
->
linedefined
,
f
->
lastlinedefined
,
S
(
f
->
sizecode
),
VOID
(
f
));
printf
(
"%d%s param%s, %d slot%s, %d upvalue%s, "
,
(
int
)(
f
->
numparams
),
f
->
is_vararg
?
"+"
:
""
,
SS
(
f
->
numparams
),
S
(
f
->
maxstacksize
),
S
(
f
->
sizeupvalues
));
printf
(
"%d local%s, %d constant%s, %d function%s
\n
"
,
S
(
f
->
sizelocvars
),
S
(
f
->
sizek
),
S
(
f
->
sizep
));
}
static
void
PrintDebug
(
const
Proto
*
f
)
{
int
i
,
n
;
n
=
f
->
sizek
;
printf
(
"constants (%d) for %p:
\n
"
,
n
,
VOID
(
f
));
for
(
i
=
0
;
i
<
n
;
i
++
)
{
printf
(
"
\t
%d
\t
"
,
i
+
1
);
PrintConstant
(
f
,
i
);
printf
(
"
\n
"
);
}
n
=
f
->
sizelocvars
;
printf
(
"locals (%d) for %p:
\n
"
,
n
,
VOID
(
f
));
for
(
i
=
0
;
i
<
n
;
i
++
)
{
printf
(
"
\t
%d
\t
%s
\t
%d
\t
%d
\n
"
,
i
,
getstr
(
f
->
locvars
[
i
].
varname
),
f
->
locvars
[
i
].
startpc
+
1
,
f
->
locvars
[
i
].
endpc
+
1
);
}
n
=
f
->
sizeupvalues
;
printf
(
"upvalues (%d) for %p:
\n
"
,
n
,
VOID
(
f
));
for
(
i
=
0
;
i
<
n
;
i
++
)
{
printf
(
"
\t
%d
\t
%s
\t
%d
\t
%d
\n
"
,
i
,
UPVALNAME
(
i
),
f
->
upvalues
[
i
].
instack
,
f
->
upvalues
[
i
].
idx
);
}
}
static
void
PrintFunction
(
const
Proto
*
f
,
int
full
)
{
int
i
,
n
=
f
->
sizep
;
PrintHeader
(
f
);
PrintCode
(
f
);
if
(
full
)
PrintDebug
(
f
);
for
(
i
=
0
;
i
<
n
;
i
++
)
PrintFunction
(
f
->
p
[
i
],
full
);
}
components/lua/lua-5.3/lapi.c
0 → 100644
View file @
dba57fa0
/*
** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
#define lapi_c
#define LUA_CORE
#include "lprefix.h"
#include <stdarg.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
const
char
lua_ident
[]
=
"$LuaVersion: "
LUA_COPYRIGHT
" $"
"$LuaAuthors: "
LUA_AUTHORS
" $"
;
/* value at a non-valid index */
#define NONVALIDVALUE cast(TValue *, luaO_nilobject)
/* corresponding test */
#define isvalid(o) ((o) != luaO_nilobject)
/* test for pseudo index */
#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX)
/* test for upvalue */
#define isupvalue(i) ((i) < LUA_REGISTRYINDEX)
/* test for valid but not pseudo index */
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index")
#define api_checkstackindex(l, i, o) \
api_check(l, isstackindex(i, o), "index not in the stack")
static
TValue
*
index2addr
(
lua_State
*
L
,
int
idx
)
{
CallInfo
*
ci
=
L
->
ci
;
if
(
idx
>
0
)
{
TValue
*
o
=
ci
->
func
+
idx
;
api_check
(
L
,
idx
<=
ci
->
top
-
(
ci
->
func
+
1
),
"unacceptable index"
);
if
(
o
>=
L
->
top
)
return
NONVALIDVALUE
;
else
return
o
;
}
else
if
(
!
ispseudo
(
idx
))
{
/* negative index */
api_check
(
L
,
idx
!=
0
&&
-
idx
<=
L
->
top
-
(
ci
->
func
+
1
),
"invalid index"
);
return
L
->
top
+
idx
;
}
else
if
(
idx
==
LUA_REGISTRYINDEX
)
return
&
G
(
L
)
->
l_registry
;
else
{
/* upvalues */
idx
=
LUA_REGISTRYINDEX
-
idx
;
api_check
(
L
,
idx
<=
MAXUPVAL
+
1
,
"upvalue index too large"
);
if
(
ttislcf
(
ci
->
func
))
/* light C function? */
return
NONVALIDVALUE
;
/* it has no upvalues */
else
{
CClosure
*
func
=
clCvalue
(
ci
->
func
);
return
(
idx
<=
func
->
nupvalues
)
?
&
func
->
upvalue
[
idx
-
1
]
:
NONVALIDVALUE
;
}
}
}
/*
** to be called by 'lua_checkstack' in protected mode, to grow stack
** capturing memory errors
*/
static
void
growstack
(
lua_State
*
L
,
void
*
ud
)
{
int
size
=
*
(
int
*
)
ud
;
luaD_growstack
(
L
,
size
);
}
LUA_API
int
lua_checkstack
(
lua_State
*
L
,
int
n
)
{
int
res
;
CallInfo
*
ci
=
L
->
ci
;
lua_lock
(
L
);
api_check
(
L
,
n
>=
0
,
"negative 'n'"
);
if
(
L
->
stack_last
-
L
->
top
>
n
)
/* stack large enough? */
res
=
1
;
/* yes; check is OK */
else
{
/* no; need to grow stack */
int
inuse
=
cast_int
(
L
->
top
-
L
->
stack
)
+
EXTRA_STACK
;
if
(
inuse
>
LUAI_MAXSTACK
-
n
)
/* can grow without overflow? */
res
=
0
;
/* no */
else
/* try to grow stack */
res
=
(
luaD_rawrunprotected
(
L
,
&
growstack
,
&
n
)
==
LUA_OK
);
}
if
(
res
&&
ci
->
top
<
L
->
top
+
n
)
ci
->
top
=
L
->
top
+
n
;
/* adjust frame top */
lua_unlock
(
L
);
return
res
;
}
LUA_API
void
lua_xmove
(
lua_State
*
from
,
lua_State
*
to
,
int
n
)
{
int
i
;
if
(
from
==
to
)
return
;
lua_lock
(
to
);
api_checknelems
(
from
,
n
);
api_check
(
from
,
G
(
from
)
==
G
(
to
),
"moving among independent states"
);
api_check
(
from
,
to
->
ci
->
top
-
to
->
top
>=
n
,
"stack overflow"
);
from
->
top
-=
n
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
setobj2s
(
to
,
to
->
top
,
from
->
top
+
i
);
to
->
top
++
;
/* stack already checked by previous 'api_check' */
}
lua_unlock
(
to
);
}
LUA_API
lua_CFunction
lua_atpanic
(
lua_State
*
L
,
lua_CFunction
panicf
)
{
lua_CFunction
old
;
lua_lock
(
L
);
old
=
G
(
L
)
->
panic
;
G
(
L
)
->
panic
=
panicf
;
lua_unlock
(
L
);
return
old
;
}
LUA_API
const
lua_Number
*
lua_version
(
lua_State
*
L
)
{
static
const
lua_Number
version
=
LUA_VERSION_NUM
;
if
(
L
==
NULL
)
return
&
version
;
else
return
G
(
L
)
->
version
;
}
/*
** basic stack manipulation
*/
/*
** convert an acceptable stack index into an absolute index
*/
LUA_API
int
lua_absindex
(
lua_State
*
L
,
int
idx
)
{
return
(
idx
>
0
||
ispseudo
(
idx
))
?
idx
:
cast_int
(
L
->
top
-
L
->
ci
->
func
)
+
idx
;
}
LUA_API
int
lua_gettop
(
lua_State
*
L
)
{
return
cast_int
(
L
->
top
-
(
L
->
ci
->
func
+
1
));
}
LUA_API
void
lua_settop
(
lua_State
*
L
,
int
idx
)
{
StkId
func
=
L
->
ci
->
func
;
lua_lock
(
L
);
if
(
idx
>=
0
)
{
api_check
(
L
,
idx
<=
L
->
stack_last
-
(
func
+
1
),
"new top too large"
);
while
(
L
->
top
<
(
func
+
1
)
+
idx
)
setnilvalue
(
L
->
top
++
);
L
->
top
=
(
func
+
1
)
+
idx
;
}
else
{
api_check
(
L
,
-
(
idx
+
1
)
<=
(
L
->
top
-
(
func
+
1
)),
"invalid new top"
);
L
->
top
+=
idx
+
1
;
/* 'subtract' index (index is negative) */
}
lua_unlock
(
L
);
}
/*
** Reverse the stack segment from 'from' to 'to'
** (auxiliary to 'lua_rotate')
*/
static
void
reverse
(
lua_State
*
L
,
StkId
from
,
StkId
to
)
{
for
(;
from
<
to
;
from
++
,
to
--
)
{
TValue
temp
;
setobj
(
L
,
&
temp
,
from
);
setobjs2s
(
L
,
from
,
to
);
setobj2s
(
L
,
to
,
&
temp
);
}
}
/*
** Let x = AB, where A is a prefix of length 'n'. Then,
** rotate x n == BA. But BA == (A^r . B^r)^r.
*/
LUA_API
void
lua_rotate
(
lua_State
*
L
,
int
idx
,
int
n
)
{
StkId
p
,
t
,
m
;
lua_lock
(
L
);
t
=
L
->
top
-
1
;
/* end of stack segment being rotated */
p
=
index2addr
(
L
,
idx
);
/* start of segment */
api_checkstackindex
(
L
,
idx
,
p
);
api_check
(
L
,
(
n
>=
0
?
n
:
-
n
)
<=
(
t
-
p
+
1
),
"invalid 'n'"
);
m
=
(
n
>=
0
?
t
-
n
:
p
-
n
-
1
);
/* end of prefix */
reverse
(
L
,
p
,
m
);
/* reverse the prefix with length 'n' */
reverse
(
L
,
m
+
1
,
t
);
/* reverse the suffix */
reverse
(
L
,
p
,
t
);
/* reverse the entire segment */
lua_unlock
(
L
);
}
LUA_API
void
lua_copy
(
lua_State
*
L
,
int
fromidx
,
int
toidx
)
{
TValue
*
fr
,
*
to
;
lua_lock
(
L
);
fr
=
index2addr
(
L
,
fromidx
);
to
=
index2addr
(
L
,
toidx
);
api_checkvalidindex
(
L
,
to
);
setobj
(
L
,
to
,
fr
);
if
(
isupvalue
(
toidx
))
/* function upvalue? */
luaC_barrier
(
L
,
clCvalue
(
L
->
ci
->
func
),
fr
);
/* LUA_REGISTRYINDEX does not need gc barrier
(collector revisits it before finishing collection) */
lua_unlock
(
L
);
}
LUA_API
void
lua_pushvalue
(
lua_State
*
L
,
int
idx
)
{
lua_lock
(
L
);
setobj2s
(
L
,
L
->
top
,
index2addr
(
L
,
idx
));
api_incr_top
(
L
);
lua_unlock
(
L
);
}
/*
** access functions (stack -> C)
*/
LUA_API
int
lua_type
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
return
(
isvalid
(
o
)
?
ttnov
(
o
)
:
LUA_TNONE
);
}
LUA_API
const
char
*
lua_typename
(
lua_State
*
L
,
int
t
)
{
UNUSED
(
L
);
api_check
(
L
,
LUA_TNONE
<=
t
&&
t
<
LUA_NUMTAGS
,
"invalid tag"
);
return
ttypename
(
t
);
}
LUA_API
int
lua_iscfunction
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
return
(
ttislcf
(
o
)
||
(
ttisCclosure
(
o
)));
}
LUA_API
int
lua_isinteger
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
return
ttisinteger
(
o
);
}
LUA_API
int
lua_isnumber
(
lua_State
*
L
,
int
idx
)
{
lua_Number
n
;
const
TValue
*
o
=
index2addr
(
L
,
idx
);
return
tonumber
(
o
,
&
n
);
}
LUA_API
int
lua_isstring
(
lua_State
*
L
,
int
idx
)
{
const
TValue
*
o
=
index2addr
(
L
,
idx
);
return
(
ttisstring
(
o
)
||
cvt2str
(
o
));
}
LUA_API
int
lua_isuserdata
(
lua_State
*
L
,
int
idx
)
{
const
TValue
*
o
=
index2addr
(
L
,
idx
);
return
(
ttisfulluserdata
(
o
)
||
ttislightuserdata
(
o
));
}
LUA_API
int
lua_rawequal
(
lua_State
*
L
,
int
index1
,
int
index2
)
{
StkId
o1
=
index2addr
(
L
,
index1
);
StkId
o2
=
index2addr
(
L
,
index2
);
return
(
isvalid
(
o1
)
&&
isvalid
(
o2
))
?
luaV_rawequalobj
(
o1
,
o2
)
:
0
;
}
LUA_API
void
lua_arith
(
lua_State
*
L
,
int
op
)
{
lua_lock
(
L
);
if
(
op
!=
LUA_OPUNM
&&
op
!=
LUA_OPBNOT
)
api_checknelems
(
L
,
2
);
/* all other operations expect two operands */
else
{
/* for unary operations, add fake 2nd operand */
api_checknelems
(
L
,
1
);
setobjs2s
(
L
,
L
->
top
,
L
->
top
-
1
);
api_incr_top
(
L
);
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
luaO_arith
(
L
,
op
,
L
->
top
-
2
,
L
->
top
-
1
,
L
->
top
-
2
);
L
->
top
--
;
/* remove second operand */
lua_unlock
(
L
);
}
LUA_API
int
lua_compare
(
lua_State
*
L
,
int
index1
,
int
index2
,
int
op
)
{
StkId
o1
,
o2
;
int
i
=
0
;
lua_lock
(
L
);
/* may call tag method */
o1
=
index2addr
(
L
,
index1
);
o2
=
index2addr
(
L
,
index2
);
if
(
isvalid
(
o1
)
&&
isvalid
(
o2
))
{
switch
(
op
)
{
case
LUA_OPEQ
:
i
=
luaV_equalobj
(
L
,
o1
,
o2
);
break
;
case
LUA_OPLT
:
i
=
luaV_lessthan
(
L
,
o1
,
o2
);
break
;
case
LUA_OPLE
:
i
=
luaV_lessequal
(
L
,
o1
,
o2
);
break
;
default:
api_check
(
L
,
0
,
"invalid option"
);
}
}
lua_unlock
(
L
);
return
i
;
}
LUA_API
size_t
lua_stringtonumber
(
lua_State
*
L
,
const
char
*
s
)
{
size_t
sz
=
luaO_str2num
(
s
,
L
->
top
);
if
(
sz
!=
0
)
api_incr_top
(
L
);
return
sz
;
}
LUA_API
lua_Number
lua_tonumberx
(
lua_State
*
L
,
int
idx
,
int
*
pisnum
)
{
lua_Number
n
;
const
TValue
*
o
=
index2addr
(
L
,
idx
);
int
isnum
=
tonumber
(
o
,
&
n
);
if
(
!
isnum
)
n
=
0
;
/* call to 'tonumber' may change 'n' even if it fails */
if
(
pisnum
)
*
pisnum
=
isnum
;
return
n
;
}
LUA_API
lua_Integer
lua_tointegerx
(
lua_State
*
L
,
int
idx
,
int
*
pisnum
)
{
lua_Integer
res
;
const
TValue
*
o
=
index2addr
(
L
,
idx
);
int
isnum
=
tointeger
(
o
,
&
res
);
if
(
!
isnum
)
res
=
0
;
/* call to 'tointeger' may change 'n' even if it fails */
if
(
pisnum
)
*
pisnum
=
isnum
;
return
res
;
}
LUA_API
int
lua_toboolean
(
lua_State
*
L
,
int
idx
)
{
const
TValue
*
o
=
index2addr
(
L
,
idx
);
return
!
l_isfalse
(
o
);
}
LUA_API
const
char
*
lua_tolstring
(
lua_State
*
L
,
int
idx
,
size_t
*
len
)
{
StkId
o
=
index2addr
(
L
,
idx
);
if
(
!
ttisstring
(
o
))
{
if
(
!
cvt2str
(
o
))
{
/* not convertible? */
if
(
len
!=
NULL
)
*
len
=
0
;
return
NULL
;
}
lua_lock
(
L
);
/* 'luaO_tostring' may create a new string */
luaO_tostring
(
L
,
o
);
luaC_checkGC
(
L
);
o
=
index2addr
(
L
,
idx
);
/* previous call may reallocate the stack */
lua_unlock
(
L
);
}
if
(
len
!=
NULL
)
*
len
=
vslen
(
o
);
return
svalue
(
o
);
}
LUA_API
size_t
lua_rawlen
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
switch
(
ttype
(
o
))
{
case
LUA_TSHRSTR
:
return
getshrlen
(
tsvalue
(
o
));
case
LUA_TLNGSTR
:
return
tsvalue
(
o
)
->
u
.
lnglen
;
case
LUA_TUSERDATA
:
return
uvalue
(
o
)
->
len
;
case
LUA_TTBLRAM
:
return
luaH_getn
(
hvalue
(
o
));
default:
return
0
;
}
}
LUA_API
lua_CFunction
lua_tocfunction
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
if
(
ttislcf
(
o
))
return
fvalue
(
o
);
else
if
(
ttisCclosure
(
o
))
return
clCvalue
(
o
)
->
f
;
else
return
NULL
;
/* not a C function */
}
LUA_API
void
*
lua_touserdata
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
switch
(
ttnov
(
o
))
{
case
LUA_TUSERDATA
:
return
getudatamem
(
uvalue
(
o
));
case
LUA_TLIGHTUSERDATA
:
return
pvalue
(
o
);
default:
return
NULL
;
}
}
LUA_API
lua_State
*
lua_tothread
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
return
(
!
ttisthread
(
o
))
?
NULL
:
thvalue
(
o
);
}
LUA_API
const
void
*
lua_topointer
(
lua_State
*
L
,
int
idx
)
{
StkId
o
=
index2addr
(
L
,
idx
);
switch
(
ttype
(
o
))
{
case
LUA_TTBLRAM
:
case
LUA_TTBLROF
:
return
hvalue
(
o
);
case
LUA_TLCL
:
return
clLvalue
(
o
);
case
LUA_TCCL
:
return
clCvalue
(
o
);
case
LUA_TLCF
:
return
cast
(
void
*
,
cast
(
size_t
,
fvalue
(
o
)));
case
LUA_TTHREAD
:
return
thvalue
(
o
);
case
LUA_TUSERDATA
:
return
getudatamem
(
uvalue
(
o
));
case
LUA_TLIGHTUSERDATA
:
return
pvalue
(
o
);
default:
return
NULL
;
}
}
/*
** push functions (C -> stack)
*/
LUA_API
void
lua_pushnil
(
lua_State
*
L
)
{
lua_lock
(
L
);
setnilvalue
(
L
->
top
);
api_incr_top
(
L
);
lua_unlock
(
L
);
}
LUA_API
void
lua_pushnumber
(
lua_State
*
L
,
lua_Number
n
)
{
lua_lock
(
L
);
setfltvalue
(
L
->
top
,
n
);
api_incr_top
(
L
);
lua_unlock
(
L
);
}
LUA_API
void
lua_pushinteger
(
lua_State
*
L
,
lua_Integer
n
)
{
lua_lock
(
L
);
setivalue
(
L
->
top
,
n
);
api_incr_top
(
L
);
lua_unlock
(
L
);
}
/*
** Pushes on the stack a string with given length. Avoid using 's' when
** 'len' == 0 (as 's' can be NULL in that case), due to later use of
** 'memcmp' and 'memcpy'.
*/
LUA_API
const
char
*
lua_pushlstring
(
lua_State
*
L
,
const
char
*
s
,
size_t
len
)
{
TString
*
ts
;
lua_lock
(
L
);
ts
=
(
len
==
0
)
?
luaS_new
(
L
,
""
)
:
luaS_newlstr
(
L
,
s
,
len
);
setsvalue2s
(
L
,
L
->
top
,
ts
);
api_incr_top
(
L
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
return
getstr
(
ts
);
}
LUA_API
const
char
*
lua_pushstring
(
lua_State
*
L
,
const
char
*
s
)
{
lua_lock
(
L
);
if
(
s
==
NULL
)
setnilvalue
(
L
->
top
);
else
{
TString
*
ts
;
ts
=
luaS_new
(
L
,
s
);
setsvalue2s
(
L
,
L
->
top
,
ts
);
s
=
getstr
(
ts
);
/* internal copy's address */
}
api_incr_top
(
L
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
return
s
;
}
LUA_API
const
char
*
lua_pushvfstring
(
lua_State
*
L
,
const
char
*
fmt
,
va_list
argp
)
{
const
char
*
ret
;
lua_lock
(
L
);
ret
=
luaO_pushvfstring
(
L
,
fmt
,
argp
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
return
ret
;
}
LUA_API
const
char
*
lua_pushfstring
(
lua_State
*
L
,
const
char
*
fmt
,
...)
{
const
char
*
ret
;
va_list
argp
;
lua_lock
(
L
);
va_start
(
argp
,
fmt
);
ret
=
luaO_pushvfstring
(
L
,
fmt
,
argp
);
va_end
(
argp
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
return
ret
;
}
LUA_API
void
lua_pushcclosure
(
lua_State
*
L
,
lua_CFunction
fn
,
int
n
)
{
lua_lock
(
L
);
if
(
n
==
0
)
{
setfvalue
(
L
->
top
,
fn
);
api_incr_top
(
L
);
}
else
{
CClosure
*
cl
;
api_checknelems
(
L
,
n
);
api_check
(
L
,
n
<=
MAXUPVAL
,
"upvalue index too large"
);
cl
=
luaF_newCclosure
(
L
,
n
);
cl
->
f
=
fn
;
L
->
top
-=
n
;
while
(
n
--
)
{
setobj2n
(
L
,
&
cl
->
upvalue
[
n
],
L
->
top
+
n
);
/* does not need barrier because closure is white */
}
setclCvalue
(
L
,
L
->
top
,
cl
);
api_incr_top
(
L
);
luaC_checkGC
(
L
);
}
lua_unlock
(
L
);
}
LUA_API
void
lua_pushboolean
(
lua_State
*
L
,
int
b
)
{
lua_lock
(
L
);
setbvalue
(
L
->
top
,
(
b
!=
0
));
/* ensure that true is 1 */
api_incr_top
(
L
);
lua_unlock
(
L
);
}
LUA_API
void
lua_pushlightuserdata
(
lua_State
*
L
,
void
*
p
)
{
lua_lock
(
L
);
setpvalue
(
L
->
top
,
p
);
api_incr_top
(
L
);
lua_unlock
(
L
);
}
LUA_API
int
lua_pushthread
(
lua_State
*
L
)
{
lua_lock
(
L
);
setthvalue
(
L
,
L
->
top
,
L
);
api_incr_top
(
L
);
lua_unlock
(
L
);
return
(
G
(
L
)
->
mainthread
==
L
);
}
LUA_API
void
lua_pushrotable
(
lua_State
*
L
,
const
ROTable
*
t
)
{
lua_lock
(
L
);
sethvalue
(
L
,
L
->
top
,
cast
(
Table
*
,
t
));
api_incr_top
(
L
);
lua_unlock
(
L
);
}
/*
** get functions (Lua -> stack)
*/
static
int
auxgetstr
(
lua_State
*
L
,
const
TValue
*
t
,
const
char
*
k
)
{
const
TValue
*
slot
;
TString
*
str
=
luaS_new
(
L
,
k
);
if
(
luaV_fastget
(
L
,
t
,
str
,
slot
,
luaH_getstr
))
{
setobj2s
(
L
,
L
->
top
,
slot
);
api_incr_top
(
L
);
}
else
{
setsvalue2s
(
L
,
L
->
top
,
str
);
api_incr_top
(
L
);
luaV_finishget
(
L
,
t
,
L
->
top
-
1
,
L
->
top
-
1
,
slot
);
}
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
int
lua_getglobal
(
lua_State
*
L
,
const
char
*
name
)
{
Table
*
reg
=
hvalue
(
&
G
(
L
)
->
l_registry
);
lua_lock
(
L
);
return
auxgetstr
(
L
,
luaH_getint
(
reg
,
LUA_RIDX_GLOBALS
),
name
);
}
LUA_API
int
lua_gettable
(
lua_State
*
L
,
int
idx
)
{
StkId
t
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
luaV_gettable
(
L
,
t
,
L
->
top
-
1
,
L
->
top
-
1
);
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
int
lua_getfield
(
lua_State
*
L
,
int
idx
,
const
char
*
k
)
{
lua_lock
(
L
);
return
auxgetstr
(
L
,
index2addr
(
L
,
idx
),
k
);
}
LUA_API
int
lua_geti
(
lua_State
*
L
,
int
idx
,
lua_Integer
n
)
{
StkId
t
;
const
TValue
*
slot
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
if
(
luaV_fastget
(
L
,
t
,
n
,
slot
,
luaH_getint
))
{
setobj2s
(
L
,
L
->
top
,
slot
);
api_incr_top
(
L
);
}
else
{
setivalue
(
L
->
top
,
n
);
api_incr_top
(
L
);
luaV_finishget
(
L
,
t
,
L
->
top
-
1
,
L
->
top
-
1
,
slot
);
}
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
int
lua_rawget
(
lua_State
*
L
,
int
idx
)
{
StkId
t
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttistable
(
t
),
"table expected"
);
setobj2s
(
L
,
L
->
top
-
1
,
luaH_get
(
hvalue
(
t
),
L
->
top
-
1
));
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
int
lua_rawgeti
(
lua_State
*
L
,
int
idx
,
lua_Integer
n
)
{
StkId
t
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttistable
(
t
),
"table expected"
);
setobj2s
(
L
,
L
->
top
,
luaH_getint
(
hvalue
(
t
),
n
));
api_incr_top
(
L
);
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
int
lua_rawgetp
(
lua_State
*
L
,
int
idx
,
const
void
*
p
)
{
StkId
t
;
TValue
k
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttistable
(
t
),
"table expected"
);
setpvalue
(
&
k
,
cast
(
void
*
,
p
));
setobj2s
(
L
,
L
->
top
,
luaH_get
(
hvalue
(
t
),
&
k
));
api_incr_top
(
L
);
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
LUA_API
void
lua_createtable
(
lua_State
*
L
,
int
narray
,
int
nrec
)
{
Table
*
t
;
lua_lock
(
L
);
t
=
luaH_new
(
L
);
sethvalue
(
L
,
L
->
top
,
t
);
api_incr_top
(
L
);
if
(
narray
>
0
||
nrec
>
0
)
luaH_resize
(
L
,
t
,
narray
,
nrec
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
}
LUA_API
int
lua_getmetatable
(
lua_State
*
L
,
int
objindex
)
{
const
TValue
*
obj
;
Table
*
mt
;
int
res
=
0
;
lua_lock
(
L
);
obj
=
index2addr
(
L
,
objindex
);
switch
(
ttnov
(
obj
))
{
case
LUA_TTABLE
:
mt
=
hvalue
(
obj
)
->
metatable
;
break
;
case
LUA_TUSERDATA
:
mt
=
uvalue
(
obj
)
->
metatable
;
break
;
default:
mt
=
G
(
L
)
->
mt
[
ttnov
(
obj
)];
break
;
}
if
(
mt
!=
NULL
)
{
sethvalue
(
L
,
L
->
top
,
mt
);
api_incr_top
(
L
);
res
=
1
;
}
lua_unlock
(
L
);
return
res
;
}
LUA_API
int
lua_getuservalue
(
lua_State
*
L
,
int
idx
)
{
StkId
o
;
lua_lock
(
L
);
o
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttisfulluserdata
(
o
),
"full userdata expected"
);
getuservalue
(
L
,
uvalue
(
o
),
L
->
top
);
api_incr_top
(
L
);
lua_unlock
(
L
);
return
ttnov
(
L
->
top
-
1
);
}
/*
** set functions (stack -> Lua)
*/
/*
** t[k] = value at the top of the stack (where 'k' is a string)
*/
static
void
auxsetstr
(
lua_State
*
L
,
const
TValue
*
t
,
const
char
*
k
)
{
const
TValue
*
slot
;
TString
*
str
=
luaS_new
(
L
,
k
);
api_checknelems
(
L
,
1
);
if
(
luaV_fastset
(
L
,
t
,
str
,
slot
,
luaH_getstr
,
L
->
top
-
1
))
L
->
top
--
;
/* pop value */
else
{
setsvalue2s
(
L
,
L
->
top
,
str
);
/* push 'str' (to make it a TValue) */
api_incr_top
(
L
);
luaV_finishset
(
L
,
t
,
L
->
top
-
1
,
L
->
top
-
2
,
slot
);
L
->
top
-=
2
;
/* pop value and key */
}
lua_unlock
(
L
);
/* lock done by caller */
}
LUA_API
void
lua_setglobal
(
lua_State
*
L
,
const
char
*
name
)
{
Table
*
reg
=
hvalue
(
&
G
(
L
)
->
l_registry
);
lua_lock
(
L
);
/* unlock done in 'auxsetstr' */
auxsetstr
(
L
,
luaH_getint
(
reg
,
LUA_RIDX_GLOBALS
),
name
);
}
LUA_API
void
lua_settable
(
lua_State
*
L
,
int
idx
)
{
StkId
t
;
lua_lock
(
L
);
api_checknelems
(
L
,
2
);
t
=
index2addr
(
L
,
idx
);
luaV_settable
(
L
,
t
,
L
->
top
-
2
,
L
->
top
-
1
);
L
->
top
-=
2
;
/* pop index and value */
lua_unlock
(
L
);
}
LUA_API
void
lua_setfield
(
lua_State
*
L
,
int
idx
,
const
char
*
k
)
{
lua_lock
(
L
);
/* unlock done in 'auxsetstr' */
auxsetstr
(
L
,
index2addr
(
L
,
idx
),
k
);
}
LUA_API
void
lua_seti
(
lua_State
*
L
,
int
idx
,
lua_Integer
n
)
{
StkId
t
;
const
TValue
*
slot
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
t
=
index2addr
(
L
,
idx
);
if
(
luaV_fastset
(
L
,
t
,
n
,
slot
,
luaH_getint
,
L
->
top
-
1
))
L
->
top
--
;
/* pop value */
else
{
setivalue
(
L
->
top
,
n
);
api_incr_top
(
L
);
luaV_finishset
(
L
,
t
,
L
->
top
-
1
,
L
->
top
-
2
,
slot
);
L
->
top
-=
2
;
/* pop value and key */
}
lua_unlock
(
L
);
}
LUA_API
void
lua_rawset
(
lua_State
*
L
,
int
idx
)
{
StkId
o
;
TValue
*
slot
;
lua_lock
(
L
);
api_checknelems
(
L
,
2
);
o
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttisrwtable
(
o
),
"RW table expected"
);
slot
=
luaH_set
(
L
,
hvalue
(
o
),
L
->
top
-
2
);
setobj2t
(
L
,
slot
,
L
->
top
-
1
);
invalidateTMcache
(
hvalue
(
o
));
luaC_barrierback
(
L
,
hvalue
(
o
),
L
->
top
-
1
);
L
->
top
-=
2
;
lua_unlock
(
L
);
}
LUA_API
void
lua_rawseti
(
lua_State
*
L
,
int
idx
,
lua_Integer
n
)
{
StkId
o
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
o
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttisrwtable
(
o
),
"RW table expected"
);
luaH_setint
(
L
,
hvalue
(
o
),
n
,
L
->
top
-
1
);
luaC_barrierback
(
L
,
hvalue
(
o
),
L
->
top
-
1
);
L
->
top
--
;
lua_unlock
(
L
);
}
LUA_API
void
lua_rawsetp
(
lua_State
*
L
,
int
idx
,
const
void
*
p
)
{
StkId
o
;
TValue
k
,
*
slot
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
o
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttisrwtable
(
o
),
"RW table expected"
);
setpvalue
(
&
k
,
cast
(
void
*
,
p
));
slot
=
luaH_set
(
L
,
hvalue
(
o
),
&
k
);
setobj2t
(
L
,
slot
,
L
->
top
-
1
);
luaC_barrierback
(
L
,
hvalue
(
o
),
L
->
top
-
1
);
L
->
top
--
;
lua_unlock
(
L
);
}
LUA_API
int
lua_setmetatable
(
lua_State
*
L
,
int
objindex
)
{
TValue
*
obj
;
Table
*
mt
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
obj
=
index2addr
(
L
,
objindex
);
if
(
ttisnil
(
L
->
top
-
1
))
mt
=
NULL
;
else
{
api_check
(
L
,
ttistable
(
L
->
top
-
1
),
"table expected"
);
mt
=
hvalue
(
L
->
top
-
1
);
}
switch
(
ttype
(
obj
))
{
case
LUA_TTBLRAM
:
{
hvalue
(
obj
)
->
metatable
=
mt
;
if
(
mt
)
{
luaC_objbarrier
(
L
,
gcvalue
(
obj
),
mt
);
luaC_checkfinalizer
(
L
,
gcvalue
(
obj
),
mt
);
}
break
;
}
case
LUA_TTBLROF
:
{
luai_apicheck
(
L
,
"RW table expected"
);
}
case
LUA_TUSERDATA
:
{
uvalue
(
obj
)
->
metatable
=
mt
;
if
(
mt
)
{
luaC_objbarrier
(
L
,
uvalue
(
obj
),
mt
);
luaC_checkfinalizer
(
L
,
gcvalue
(
obj
),
mt
);
}
break
;
}
default:
{
G
(
L
)
->
mt
[
ttnov
(
obj
)]
=
mt
;
break
;
}
}
L
->
top
--
;
lua_unlock
(
L
);
return
1
;
}
LUA_API
void
lua_setuservalue
(
lua_State
*
L
,
int
idx
)
{
StkId
o
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
o
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttisfulluserdata
(
o
),
"full userdata expected"
);
setuservalue
(
L
,
uvalue
(
o
),
L
->
top
-
1
);
luaC_barrier
(
L
,
gcvalue
(
o
),
L
->
top
-
1
);
L
->
top
--
;
lua_unlock
(
L
);
}
/*
** 'load' and 'call' functions (run Lua code)
*/
#define checkresults(L,na,nr) \
api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
"results from function overflow current stack size")
LUA_API
void
lua_callk
(
lua_State
*
L
,
int
nargs
,
int
nresults
,
lua_KContext
ctx
,
lua_KFunction
k
)
{
StkId
func
;
lua_lock
(
L
);
api_check
(
L
,
k
==
NULL
||
!
isLua
(
L
->
ci
),
"cannot use continuations inside hooks"
);
api_checknelems
(
L
,
nargs
+
1
);
api_check
(
L
,
L
->
status
==
LUA_OK
,
"cannot do calls on non-normal thread"
);
checkresults
(
L
,
nargs
,
nresults
);
func
=
L
->
top
-
(
nargs
+
1
);
if
(
k
!=
NULL
&&
L
->
nny
==
0
)
{
/* need to prepare continuation? */
L
->
ci
->
u
.
c
.
k
=
k
;
/* save continuation */
L
->
ci
->
u
.
c
.
ctx
=
ctx
;
/* save context */
luaD_call
(
L
,
func
,
nresults
);
/* do the call */
}
else
/* no continuation or no yieldable */
luaD_callnoyield
(
L
,
func
,
nresults
);
/* just do the call */
adjustresults
(
L
,
nresults
);
lua_unlock
(
L
);
}
/*
** Execute a protected call.
*/
struct
CallS
{
/* data to 'f_call' */
StkId
func
;
int
nresults
;
};
static
void
f_call
(
lua_State
*
L
,
void
*
ud
)
{
struct
CallS
*
c
=
cast
(
struct
CallS
*
,
ud
);
luaD_callnoyield
(
L
,
c
->
func
,
c
->
nresults
);
}
LUA_API
int
lua_pcallk
(
lua_State
*
L
,
int
nargs
,
int
nresults
,
int
errfunc
,
lua_KContext
ctx
,
lua_KFunction
k
)
{
struct
CallS
c
;
int
status
;
ptrdiff_t
func
;
lua_lock
(
L
);
api_check
(
L
,
k
==
NULL
||
!
isLua
(
L
->
ci
),
"cannot use continuations inside hooks"
);
api_checknelems
(
L
,
nargs
+
1
);
api_check
(
L
,
L
->
status
==
LUA_OK
,
"cannot do calls on non-normal thread"
);
checkresults
(
L
,
nargs
,
nresults
);
if
(
errfunc
==
0
)
func
=
0
;
else
{
StkId
o
=
index2addr
(
L
,
errfunc
);
api_checkstackindex
(
L
,
errfunc
,
o
);
func
=
savestack
(
L
,
o
);
}
c
.
func
=
L
->
top
-
(
nargs
+
1
);
/* function to be called */
if
(
k
==
NULL
||
L
->
nny
>
0
)
{
/* no continuation or no yieldable? */
c
.
nresults
=
nresults
;
/* do a 'conventional' protected call */
status
=
luaD_pcall
(
L
,
f_call
,
&
c
,
savestack
(
L
,
c
.
func
),
func
);
}
else
{
/* prepare continuation (call is already protected by 'resume') */
CallInfo
*
ci
=
L
->
ci
;
ci
->
u
.
c
.
k
=
k
;
/* save continuation */
ci
->
u
.
c
.
ctx
=
ctx
;
/* save context */
/* save information for error recovery */
ci
->
extra
=
savestack
(
L
,
c
.
func
);
ci
->
u
.
c
.
old_errfunc
=
L
->
errfunc
;
L
->
errfunc
=
func
;
setoah
(
ci
->
callstatus
,
L
->
allowhook
);
/* save value of 'allowhook' */
ci
->
callstatus
|=
CIST_YPCALL
;
/* function can do error recovery */
luaD_call
(
L
,
c
.
func
,
nresults
);
/* do the call */
ci
->
callstatus
&=
~
CIST_YPCALL
;
L
->
errfunc
=
ci
->
u
.
c
.
old_errfunc
;
status
=
LUA_OK
;
/* if it is here, there were no errors */
}
adjustresults
(
L
,
nresults
);
lua_unlock
(
L
);
return
status
;
}
LUA_API
int
lua_load
(
lua_State
*
L
,
lua_Reader
reader
,
void
*
data
,
const
char
*
chunkname
,
const
char
*
mode
)
{
ZIO
z
;
int
status
;
lua_lock
(
L
);
if
(
!
chunkname
)
chunkname
=
"?"
;
luaZ_init
(
L
,
&
z
,
reader
,
data
);
status
=
luaD_protectedparser
(
L
,
&
z
,
chunkname
,
mode
);
if
(
status
==
LUA_OK
)
{
/* no errors? */
LClosure
*
f
=
clLvalue
(
L
->
top
-
1
);
/* get newly created function */
if
(
f
->
nupvalues
>=
1
)
{
/* does it have an upvalue? */
/* get global table from registry */
Table
*
reg
=
hvalue
(
&
G
(
L
)
->
l_registry
);
const
TValue
*
gt
=
luaH_getint
(
reg
,
LUA_RIDX_GLOBALS
);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj
(
L
,
f
->
upvals
[
0
]
->
v
,
gt
);
luaC_upvalbarrier
(
L
,
f
->
upvals
[
0
]);
}
}
lua_unlock
(
L
);
return
status
;
}
LUA_API
int
lua_dump
(
lua_State
*
L
,
lua_Writer
writer
,
void
*
data
,
int
strip
)
{
int
status
;
TValue
*
o
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
o
=
L
->
top
-
1
;
if
(
strip
==
-
1
)
strip
=
G
(
L
)
->
stripdefault
;
if
(
isLfunction
(
o
))
status
=
luaU_dump
(
L
,
getproto
(
o
),
writer
,
data
,
strip
);
else
status
=
1
;
lua_unlock
(
L
);
return
status
;
}
LUA_API
int
lua_stripdebug
(
lua_State
*
L
,
int
stripping
){
TValue
*
o
=
L
->
top
-
1
;
Proto
*
p
=
NULL
;
int
res
=
-
1
;
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
if
(
isLfunction
(
o
))
{
p
=
getproto
(
o
);
if
(
p
&&
!
isLFSobj
(
p
)
&&
(
unsigned
)
stripping
<
3
)
{
// found a valid proto to strip
res
=
luaU_stripdebug
(
L
,
p
,
stripping
,
1
);
}
}
else
if
(
ttisnil
(
L
->
top
-
1
))
{
// get or set the default strip level
if
((
unsigned
)
stripping
<
3
)
G
(
L
)
->
stripdefault
=
stripping
;
res
=
G
(
L
)
->
stripdefault
;
}
L
->
top
--
;
lua_unlock
(
L
);
return
res
;
}
LUA_API
int
lua_status
(
lua_State
*
L
)
{
return
L
->
status
;
}
/*
** Garbage-collection function
*/
LUA_API
int
lua_gc
(
lua_State
*
L
,
int
what
,
int
data
)
{
int
res
=
0
;
global_State
*
g
;
lua_lock
(
L
);
g
=
G
(
L
);
switch
(
what
)
{
case
LUA_GCSTOP
:
{
g
->
gcrunning
=
0
;
break
;
}
case
LUA_GCRESTART
:
{
luaE_setdebt
(
g
,
0
);
g
->
gcrunning
=
1
;
break
;
}
case
LUA_GCCOLLECT
:
{
luaC_fullgc
(
L
,
0
);
break
;
}
case
LUA_GCCOUNT
:
{
/* GC values are expressed in Kbytes: #bytes/2^10 */
res
=
cast_int
(
gettotalbytes
(
g
)
>>
10
);
break
;
}
case
LUA_GCCOUNTB
:
{
res
=
cast_int
(
gettotalbytes
(
g
)
&
0x3ff
);
break
;
}
case
LUA_GCSTEP
:
{
l_mem
debt
=
1
;
/* =1 to signal that it did an actual step */
lu_byte
oldrunning
=
g
->
gcrunning
;
g
->
gcrunning
=
1
;
/* allow GC to run */
if
(
data
==
0
)
{
luaE_setdebt
(
g
,
-
GCSTEPSIZE
);
/* to do a "small" step */
luaC_step
(
L
);
}
else
{
/* add 'data' to total debt */
debt
=
cast
(
l_mem
,
data
)
*
1024
+
g
->
GCdebt
;
luaE_setdebt
(
g
,
debt
);
luaC_checkGC
(
L
);
}
g
->
gcrunning
=
oldrunning
;
/* restore previous state */
if
(
debt
>
0
&&
g
->
gcstate
==
GCSpause
)
/* end of cycle? */
res
=
1
;
/* signal it */
break
;
}
case
LUA_GCSETPAUSE
:
{
res
=
g
->
gcpause
;
g
->
gcpause
=
data
;
break
;
}
case
LUA_GCSETSTEPMUL
:
{
res
=
g
->
gcstepmul
;
if
(
data
<
40
)
data
=
40
;
/* avoid ridiculous low values (and 0) */
g
->
gcstepmul
=
data
;
break
;
}
case
LUA_GCSETMEMLIMIT
:
{
/* GC values are expressed in Kbytes: #bytes/2^10 */
l_mem
new_memlimit
=
cast
(
l_mem
,
data
)
<<
10
;
if
(
new_memlimit
>
lua_freeheap
())
/* run a full GC */
luaC_fullgc
(
L
,
0
);
g
->
gcmemfreeboard
=
new_memlimit
;
/* new memlimit might be > then requested memlimit. */
res
=
cast_int
(
new_memlimit
>>
10
);
break
;
}
case
LUA_GCISRUNNING
:
{
res
=
g
->
gcrunning
;
break
;
}
default:
res
=
-
1
;
/* invalid option */
}
lua_unlock
(
L
);
return
res
;
}
/*
** miscellaneous functions
*/
LUA_API
int
lua_error
(
lua_State
*
L
)
{
lua_lock
(
L
);
api_checknelems
(
L
,
1
);
luaG_errormsg
(
L
);
/* code unreachable; will unlock when control actually leaves the kernel */
return
0
;
/* to avoid warnings */
}
LUA_API
int
lua_next
(
lua_State
*
L
,
int
idx
)
{
StkId
t
;
int
more
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
api_check
(
L
,
ttistable
(
t
),
"table expected"
);
more
=
luaH_next
(
L
,
hvalue
(
t
),
L
->
top
-
1
);
if
(
more
)
{
api_incr_top
(
L
);
}
else
/* no more elements */
L
->
top
-=
1
;
/* remove key */
lua_unlock
(
L
);
return
more
;
}
LUA_API
void
lua_concat
(
lua_State
*
L
,
int
n
)
{
lua_lock
(
L
);
api_checknelems
(
L
,
n
);
if
(
n
>=
2
)
{
luaV_concat
(
L
,
n
);
}
else
if
(
n
==
0
)
{
/* push empty string */
setsvalue2s
(
L
,
L
->
top
,
luaS_newlstr
(
L
,
""
,
0
));
api_incr_top
(
L
);
}
/* else n == 1; nothing to do */
luaC_checkGC
(
L
);
lua_unlock
(
L
);
}
LUA_API
void
lua_len
(
lua_State
*
L
,
int
idx
)
{
StkId
t
;
lua_lock
(
L
);
t
=
index2addr
(
L
,
idx
);
luaV_objlen
(
L
,
L
->
top
,
t
);
api_incr_top
(
L
);
lua_unlock
(
L
);
}
LUA_API
lua_Alloc
lua_getallocf
(
lua_State
*
L
,
void
**
ud
)
{
lua_Alloc
f
;
lua_lock
(
L
);
if
(
ud
)
*
ud
=
G
(
L
)
->
ud
;
f
=
G
(
L
)
->
frealloc
;
lua_unlock
(
L
);
return
f
;
}
LUA_API
void
lua_setallocf
(
lua_State
*
L
,
lua_Alloc
f
,
void
*
ud
)
{
lua_lock
(
L
);
G
(
L
)
->
ud
=
ud
;
G
(
L
)
->
frealloc
=
f
;
lua_unlock
(
L
);
}
LUA_API
void
*
lua_newuserdata
(
lua_State
*
L
,
size_t
size
)
{
Udata
*
u
;
lua_lock
(
L
);
u
=
luaS_newudata
(
L
,
size
);
setuvalue
(
L
,
L
->
top
,
u
);
api_incr_top
(
L
);
luaC_checkGC
(
L
);
lua_unlock
(
L
);
return
getudatamem
(
u
);
}
static
const
char
*
aux_upvalue
(
StkId
fi
,
int
n
,
TValue
**
val
,
CClosure
**
owner
,
UpVal
**
uv
)
{
switch
(
ttype
(
fi
))
{
case
LUA_TCCL
:
{
/* C closure */
CClosure
*
f
=
clCvalue
(
fi
);
if
(
!
(
1
<=
n
&&
n
<=
f
->
nupvalues
))
return
NULL
;
*
val
=
&
f
->
upvalue
[
n
-
1
];
if
(
owner
)
*
owner
=
f
;
return
""
;
}
case
LUA_TLCL
:
{
/* Lua closure */
LClosure
*
f
=
clLvalue
(
fi
);
TString
*
name
;
Proto
*
p
=
f
->
p
;
if
(
!
(
1
<=
n
&&
n
<=
p
->
sizeupvalues
))
return
NULL
;
*
val
=
f
->
upvals
[
n
-
1
]
->
v
;
if
(
uv
)
*
uv
=
f
->
upvals
[
n
-
1
];
name
=
p
->
upvalues
[
n
-
1
].
name
;
return
(
name
==
NULL
)
?
"(*no name)"
:
getstr
(
name
);
}
default:
return
NULL
;
/* not a closure */
}
}
LUA_API
const
char
*
lua_getupvalue
(
lua_State
*
L
,
int
funcindex
,
int
n
)
{
const
char
*
name
;
TValue
*
val
=
NULL
;
/* to avoid warnings */
lua_lock
(
L
);
name
=
aux_upvalue
(
index2addr
(
L
,
funcindex
),
n
,
&
val
,
NULL
,
NULL
);
if
(
name
)
{
setobj2s
(
L
,
L
->
top
,
val
);
api_incr_top
(
L
);
}
lua_unlock
(
L
);
return
name
;
}
LUA_API
const
char
*
lua_setupvalue
(
lua_State
*
L
,
int
funcindex
,
int
n
)
{
const
char
*
name
;
TValue
*
val
=
NULL
;
/* to avoid warnings */
CClosure
*
owner
=
NULL
;
UpVal
*
uv
=
NULL
;
StkId
fi
;
lua_lock
(
L
);
fi
=
index2addr
(
L
,
funcindex
);
api_checknelems
(
L
,
1
);
name
=
aux_upvalue
(
fi
,
n
,
&
val
,
&
owner
,
&
uv
);
if
(
name
)
{
L
->
top
--
;
setobj
(
L
,
val
,
L
->
top
);
if
(
owner
)
{
luaC_barrier
(
L
,
owner
,
L
->
top
);
}
else
if
(
uv
)
{
luaC_upvalbarrier
(
L
,
uv
);
}
}
lua_unlock
(
L
);
return
name
;
}
static
UpVal
**
getupvalref
(
lua_State
*
L
,
int
fidx
,
int
n
,
LClosure
**
pf
)
{
LClosure
*
f
;
StkId
fi
=
index2addr
(
L
,
fidx
);
api_check
(
L
,
ttisLclosure
(
fi
),
"Lua function expected"
);
f
=
clLvalue
(
fi
);
api_check
(
L
,
(
1
<=
n
&&
n
<=
f
->
p
->
sizeupvalues
),
"invalid upvalue index"
);
if
(
pf
)
*
pf
=
f
;
return
&
f
->
upvals
[
n
-
1
];
/* get its upvalue pointer */
}
LUA_API
void
*
lua_upvalueid
(
lua_State
*
L
,
int
fidx
,
int
n
)
{
StkId
fi
=
index2addr
(
L
,
fidx
);
switch
(
ttype
(
fi
))
{
case
LUA_TLCL
:
{
/* lua closure */
return
*
getupvalref
(
L
,
fidx
,
n
,
NULL
);
}
case
LUA_TCCL
:
{
/* C closure */
CClosure
*
f
=
clCvalue
(
fi
);
api_check
(
L
,
1
<=
n
&&
n
<=
f
->
nupvalues
,
"invalid upvalue index"
);
return
&
f
->
upvalue
[
n
-
1
];
}
default:
{
api_check
(
L
,
0
,
"closure expected"
);
return
NULL
;
}
}
}
LUA_API
void
lua_upvaluejoin
(
lua_State
*
L
,
int
fidx1
,
int
n1
,
int
fidx2
,
int
n2
)
{
LClosure
*
f1
;
UpVal
**
up1
=
getupvalref
(
L
,
fidx1
,
n1
,
&
f1
);
UpVal
**
up2
=
getupvalref
(
L
,
fidx2
,
n2
,
NULL
);
luaC_upvdeccount
(
L
,
*
up1
);
*
up1
=
*
up2
;
(
*
up1
)
->
refcount
++
;
if
(
upisopen
(
*
up1
))
(
*
up1
)
->
u
.
open
.
touched
=
1
;
luaC_upvalbarrier
(
L
,
*
up1
);
}
components/lua/lua-5.3/lapi.h
0 → 100644
View file @
dba57fa0
/*
** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "llimits.h"
#include "lstate.h"
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
#endif
components/lua/lua-5.3/lauxlib.c
0 → 100644
View file @
dba57fa0
/*
** $Id: lauxlib.c,v 1.289.1.1 2017/04/19 17:20:42 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#define lauxlib_c
#include "lprefix.h"
#if defined(LUA_USE_HOST) && defined(_MSC_VER)
#undef errno //msvc #defines errno, which interferes with our #include macro
#else
#include <errno.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
** This file uses only the official API of Lua.
** Any function declared here could be written as an application function.
*/
#include "lua.h"
#include "lauxlib.h"
#include "lpanic.h"
#define LUA_LIB
#ifdef LUA_USE_ESP
#include "platform.h"
#include "vfs.h"
#include <fcntl.h>
#endif
/*
** {======================================================
** Traceback
** =======================================================
*/
#define LEVELS1 10
/* size of the first part of the stack */
#define LEVELS2 11
/* size of the second part of the stack */
/*
** search for 'objidx' in table at index -1.
** return 1 + string at top if find a good name.
*/
static
int
findfield
(
lua_State
*
L
,
int
objidx
,
int
level
)
{
if
(
level
==
0
||
!
lua_istable
(
L
,
-
1
))
return
0
;
/* not found */
lua_pushnil
(
L
);
/* start 'next' loop */
while
(
lua_next
(
L
,
-
2
))
{
/* for each pair in table */
if
(
lua_type
(
L
,
-
2
)
==
LUA_TSTRING
)
{
/* ignore non-string keys */
if
(
lua_rawequal
(
L
,
objidx
,
-
1
))
{
/* found object? */
lua_pop
(
L
,
1
);
/* remove value (but keep name) */
return
1
;
}
else
if
(
findfield
(
L
,
objidx
,
level
-
1
))
{
/* try recursively */
lua_remove
(
L
,
-
2
);
/* remove table (but keep name) */
lua_pushliteral
(
L
,
"."
);
lua_insert
(
L
,
-
2
);
/* place '.' between the two names */
lua_concat
(
L
,
3
);
return
1
;
}
}
lua_pop
(
L
,
1
);
/* remove value */
}
return
0
;
/* not found */
}
/*
** Search for a name for a function in all loaded and ROM modules
*/
static
int
pushglobalfuncname
(
lua_State
*
L
,
lua_Debug
*
ar
)
{
int
top
=
lua_gettop
(
L
);
lua_getinfo
(
L
,
"f"
,
ar
);
/* push function */
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
LUA_LOADED_TABLE
);
if
(
!
findfield
(
L
,
top
+
1
,
2
))
{
lua_settop
(
L
,
top
+
1
);
/* remove global table */
lua_getglobal
(
L
,
"ROM"
);
if
(
!
findfield
(
L
,
top
+
1
,
2
))
{
lua_settop
(
L
,
top
);
/* remove function and global table */
return
0
;
}
}
const
char
*
name
=
lua_tostring
(
L
,
-
1
);
if
(
strncmp
(
name
,
"_G."
,
3
)
==
0
)
{
/* name start with '_G.'? */
lua_pushstring
(
L
,
name
+
3
);
/* push name without prefix */
lua_remove
(
L
,
-
2
);
/* remove original name */
}
lua_copy
(
L
,
-
1
,
top
+
1
);
/* move name to proper place */
lua_pop
(
L
,
2
);
/* remove pushed values */
return
1
;
}
static
void
pushfuncname
(
lua_State
*
L
,
lua_Debug
*
ar
)
{
if
(
pushglobalfuncname
(
L
,
ar
))
{
/* try first a global name */
lua_pushfstring
(
L
,
"function '%s'"
,
lua_tostring
(
L
,
-
1
));
lua_remove
(
L
,
-
2
);
/* remove name */
}
else
if
(
*
ar
->
namewhat
!=
'\0'
)
/* is there a name from code? */
lua_pushfstring
(
L
,
"%s '%s'"
,
ar
->
namewhat
,
ar
->
name
);
/* use it */
else
if
(
*
ar
->
what
==
'm'
)
/* main? */
lua_pushliteral
(
L
,
"main chunk"
);
else
if
(
*
ar
->
what
!=
'C'
)
/* for Lua functions, use <file:line> */
lua_pushfstring
(
L
,
"function <%s:%d>"
,
ar
->
short_src
,
ar
->
linedefined
);
else
/* nothing left... */
lua_pushliteral
(
L
,
"?"
);
}
static
int
lastlevel
(
lua_State
*
L
)
{
lua_Debug
ar
;
int
li
=
1
,
le
=
1
;
/* find an upper bound */
while
(
lua_getstack
(
L
,
le
,
&
ar
))
{
li
=
le
;
le
*=
2
;
}
/* do a binary search */
while
(
li
<
le
)
{
int
m
=
(
li
+
le
)
/
2
;
if
(
lua_getstack
(
L
,
m
,
&
ar
))
li
=
m
+
1
;
else
le
=
m
;
}
return
le
-
1
;
}
LUALIB_API
void
luaL_traceback
(
lua_State
*
L
,
lua_State
*
L1
,
const
char
*
msg
,
int
level
)
{
lua_Debug
ar
;
int
top
=
lua_gettop
(
L
);
int
last
=
lastlevel
(
L1
);
int
n1
=
(
last
-
level
>
LEVELS1
+
LEVELS2
)
?
LEVELS1
:
-
1
;
if
(
msg
)
lua_pushfstring
(
L
,
"%s
\n
"
,
msg
);
luaL_checkstack
(
L
,
10
,
NULL
);
lua_pushliteral
(
L
,
"stack traceback:"
);
while
(
lua_getstack
(
L1
,
level
++
,
&
ar
))
{
if
(
n1
--
==
0
)
{
/* too many levels? */
lua_pushliteral
(
L
,
"
\n\t
..."
);
/* add a '...' */
level
=
last
-
LEVELS2
+
1
;
/* and skip to last ones */
}
else
{
lua_getinfo
(
L1
,
"Slnt"
,
&
ar
);
lua_pushfstring
(
L
,
"
\n\t
%s:"
,
ar
.
short_src
);
if
(
ar
.
currentline
>
0
)
lua_pushfstring
(
L
,
"%d:"
,
ar
.
currentline
);
lua_pushliteral
(
L
,
" in "
);
pushfuncname
(
L
,
&
ar
);
if
(
ar
.
istailcall
)
lua_pushliteral
(
L
,
"
\n\t
(...tail calls...)"
);
lua_concat
(
L
,
lua_gettop
(
L
)
-
top
);
}
}
lua_concat
(
L
,
lua_gettop
(
L
)
-
top
);
}
/* }====================================================== */
/*
** {======================================================
** Error-report functions
** =======================================================
*/
LUALIB_API
int
luaL_argerror
(
lua_State
*
L
,
int
arg
,
const
char
*
extramsg
)
{
lua_Debug
ar
;
if
(
!
lua_getstack
(
L
,
0
,
&
ar
))
/* no stack frame? */
return
luaL_error
(
L
,
"bad argument #%d (%s)"
,
arg
,
extramsg
);
lua_getinfo
(
L
,
"n"
,
&
ar
);
if
(
strcmp
(
ar
.
namewhat
,
"method"
)
==
0
)
{
arg
--
;
/* do not count 'self' */
if
(
arg
==
0
)
/* error is in the self argument itself? */
return
luaL_error
(
L
,
"calling '%s' on bad self (%s)"
,
ar
.
name
,
extramsg
);
}
if
(
ar
.
name
==
NULL
)
ar
.
name
=
(
pushglobalfuncname
(
L
,
&
ar
))
?
lua_tostring
(
L
,
-
1
)
:
"?"
;
return
luaL_error
(
L
,
"bad argument #%d to '%s' (%s)"
,
arg
,
ar
.
name
,
extramsg
);
}
static
int
typeerror
(
lua_State
*
L
,
int
arg
,
const
char
*
tname
)
{
const
char
*
msg
;
const
char
*
typearg
;
/* name for the type of the actual argument */
if
(
luaL_getmetafield
(
L
,
arg
,
"__name"
)
==
LUA_TSTRING
)
typearg
=
lua_tostring
(
L
,
-
1
);
/* use the given type name */
else
if
(
lua_type
(
L
,
arg
)
==
LUA_TLIGHTUSERDATA
)
typearg
=
"light userdata"
;
/* special name for messages */
else
typearg
=
luaL_typename
(
L
,
arg
);
/* standard name */
msg
=
lua_pushfstring
(
L
,
"%s expected, got %s"
,
tname
,
typearg
);
return
luaL_argerror
(
L
,
arg
,
msg
);
}
static
void
tag_error
(
lua_State
*
L
,
int
arg
,
int
tag
)
{
typeerror
(
L
,
arg
,
lua_typename
(
L
,
tag
));
}
/*
** The use of 'lua_pushfstring' ensures this function does not
** need reserved stack space when called.
*/
LUALIB_API
void
luaL_where
(
lua_State
*
L
,
int
level
)
{
lua_Debug
ar
;
if
(
lua_getstack
(
L
,
level
,
&
ar
))
{
/* check function at level */
lua_getinfo
(
L
,
"Sl"
,
&
ar
);
/* get info about it */
if
(
ar
.
currentline
>
0
)
{
/* is there info? */
lua_pushfstring
(
L
,
"%s:%d: "
,
ar
.
short_src
,
ar
.
currentline
);
return
;
}
}
lua_pushfstring
(
L
,
""
);
/* else, no information available... */
}
/*
** Again, the use of 'lua_pushvfstring' ensures this function does
** not need reserved stack space when called. (At worst, it generates
** an error with "stack overflow" instead of the given message.)
*/
LUALIB_API
int
luaL_error
(
lua_State
*
L
,
const
char
*
fmt
,
...)
{
va_list
argp
;
va_start
(
argp
,
fmt
);
luaL_where
(
L
,
1
);
lua_pushvfstring
(
L
,
fmt
,
argp
);
va_end
(
argp
);
lua_concat
(
L
,
2
);
return
lua_error
(
L
);
}
LUALIB_API
int
luaL_fileresult
(
lua_State
*
L
,
int
stat
,
const
char
*
fname
)
{
int
en
=
errno
;
/* calls to Lua API may change this value */
if
(
stat
)
{
lua_pushboolean
(
L
,
1
);
return
1
;
}
else
{
lua_pushnil
(
L
);
if
(
fname
)
lua_pushfstring
(
L
,
"%s: %s"
,
fname
,
strerror
(
en
));
else
lua_pushstring
(
L
,
strerror
(
en
));
lua_pushinteger
(
L
,
en
);
return
3
;
}
}
#if !defined(l_inspectstat)
/* { */
#if defined(LUA_USE_POSIX)
#include <sys/wait.h>
/*
** use appropriate macros to interpret 'pclose' return status
*/
#define l_inspectstat(stat,what) \
if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
#else
#define l_inspectstat(stat,what)
/* no op */
#endif
#endif
/* } */
LUALIB_API
int
luaL_execresult
(
lua_State
*
L
,
int
stat
)
{
const
char
*
what
=
"exit"
;
/* type of termination */
if
(
stat
==
-
1
)
/* error? */
return
luaL_fileresult
(
L
,
0
,
NULL
);
else
{
l_inspectstat
(
stat
,
what
);
/* interpret result */
if
(
*
what
==
'e'
&&
stat
==
0
)
/* successful termination? */
lua_pushboolean
(
L
,
1
);
else
lua_pushnil
(
L
);
lua_pushstring
(
L
,
what
);
lua_pushinteger
(
L
,
stat
);
return
3
;
/* return true/nil,what,code */
}
}
/* }====================================================== */
/*
** {======================================================
** Userdata's metatable manipulation
** =======================================================
*/
LUALIB_API
int
luaL_newmetatable
(
lua_State
*
L
,
const
char
*
tname
)
{
if
(
luaL_getmetatable
(
L
,
tname
)
!=
LUA_TNIL
)
/* name already in use? */
return
0
;
/* leave previous value on top, but return 0 */
lua_pop
(
L
,
1
);
lua_createtable
(
L
,
0
,
2
);
/* create metatable */
lua_pushstring
(
L
,
tname
);
lua_setfield
(
L
,
-
2
,
"__name"
);
/* metatable.__name = tname */
lua_pushvalue
(
L
,
-
1
);
lua_setfield
(
L
,
LUA_REGISTRYINDEX
,
tname
);
/* registry.name = metatable */
return
1
;
}
LUALIB_API
void
luaL_setmetatable
(
lua_State
*
L
,
const
char
*
tname
)
{
luaL_getmetatable
(
L
,
tname
);
lua_setmetatable
(
L
,
-
2
);
}
LUALIB_API
void
*
luaL_testudata
(
lua_State
*
L
,
int
ud
,
const
char
*
tname
)
{
void
*
p
=
lua_touserdata
(
L
,
ud
);
if
(
p
!=
NULL
)
{
/* value is a userdata? */
if
(
lua_getmetatable
(
L
,
ud
))
{
/* does it have a metatable? */
luaL_getmetatable
(
L
,
tname
);
/* get correct metatable */
if
(
!
lua_rawequal
(
L
,
-
1
,
-
2
))
/* not the same? */
p
=
NULL
;
/* value is a userdata with wrong metatable */
lua_pop
(
L
,
2
);
/* remove both metatables */
return
p
;
}
}
return
NULL
;
/* value is not a userdata with a metatable */
}
LUALIB_API
int
luaL_rometatable
(
lua_State
*
L
,
const
char
*
tname
,
const
ROTable
*
p
)
{
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
tname
);
/* get registry.name */
if
(
!
lua_isnil
(
L
,
-
1
))
/* name already in use? */
return
0
;
/* leave previous value on top, but return 0 */
lua_pop
(
L
,
1
);
lua_pushrotable
(
L
,
p
);
lua_pushvalue
(
L
,
-
1
);
lua_setfield
(
L
,
LUA_REGISTRYINDEX
,
tname
);
/* registry.name = metatable */
return
1
;
}
LUALIB_API
void
*
luaL_checkudata
(
lua_State
*
L
,
int
ud
,
const
char
*
tname
)
{
void
*
p
=
luaL_testudata
(
L
,
ud
,
tname
);
if
(
p
==
NULL
)
typeerror
(
L
,
ud
,
tname
);
return
p
;
}
/* }====================================================== */
/*
** {======================================================
** Argument check functions
** =======================================================
*/
LUALIB_API
int
luaL_checkoption
(
lua_State
*
L
,
int
arg
,
const
char
*
def
,
const
char
*
const
lst
[])
{
const
char
*
name
=
(
def
)
?
luaL_optstring
(
L
,
arg
,
def
)
:
luaL_checkstring
(
L
,
arg
);
int
i
;
for
(
i
=
0
;
lst
[
i
];
i
++
)
if
(
strcmp
(
lst
[
i
],
name
)
==
0
)
return
i
;
return
luaL_argerror
(
L
,
arg
,
lua_pushfstring
(
L
,
"invalid option '%s'"
,
name
));
}
/*
** Ensures the stack has at least 'space' extra slots, raising an error
** if it cannot fulfill the request. (The error handling needs a few
** extra slots to format the error message. In case of an error without
** this extra space, Lua will generate the same 'stack overflow' error,
** but without 'msg'.)
*/
LUALIB_API
void
luaL_checkstack
(
lua_State
*
L
,
int
space
,
const
char
*
msg
)
{
if
(
!
lua_checkstack
(
L
,
space
))
{
if
(
msg
)
luaL_error
(
L
,
"stack overflow (%s)"
,
msg
);
else
luaL_error
(
L
,
"stack overflow"
);
}
}
LUALIB_API
void
luaL_checktype
(
lua_State
*
L
,
int
arg
,
int
t
)
{
if
(
lua_type
(
L
,
arg
)
!=
t
)
tag_error
(
L
,
arg
,
t
);
}
LUALIB_API
void
luaL_checkany
(
lua_State
*
L
,
int
arg
)
{
if
(
lua_type
(
L
,
arg
)
==
LUA_TNONE
)
luaL_argerror
(
L
,
arg
,
"value expected"
);
}
LUALIB_API
const
char
*
luaL_checklstring
(
lua_State
*
L
,
int
arg
,
size_t
*
len
)
{
const
char
*
s
=
lua_tolstring
(
L
,
arg
,
len
);
if
(
!
s
)
tag_error
(
L
,
arg
,
LUA_TSTRING
);
return
s
;
}
LUALIB_API
const
char
*
luaL_optlstring
(
lua_State
*
L
,
int
arg
,
const
char
*
def
,
size_t
*
len
)
{
if
(
lua_isnoneornil
(
L
,
arg
))
{
if
(
len
)
*
len
=
(
def
?
strlen
(
def
)
:
0
);
return
def
;
}
else
return
luaL_checklstring
(
L
,
arg
,
len
);
}
LUALIB_API
lua_Number
luaL_checknumber
(
lua_State
*
L
,
int
arg
)
{
int
isnum
;
lua_Number
d
=
lua_tonumberx
(
L
,
arg
,
&
isnum
);
if
(
!
isnum
)
tag_error
(
L
,
arg
,
LUA_TNUMBER
);
return
d
;
}
LUALIB_API
lua_Number
luaL_optnumber
(
lua_State
*
L
,
int
arg
,
lua_Number
def
)
{
return
luaL_opt
(
L
,
luaL_checknumber
,
arg
,
def
);
}
static
void
interror
(
lua_State
*
L
,
int
arg
)
{
if
(
lua_isnumber
(
L
,
arg
))
luaL_argerror
(
L
,
arg
,
"number has no integer representation"
);
else
tag_error
(
L
,
arg
,
LUA_TNUMBER
);
}
LUALIB_API
lua_Integer
luaL_checkinteger
(
lua_State
*
L
,
int
arg
)
{
int
isnum
;
lua_Integer
d
=
lua_tointegerx
(
L
,
arg
,
&
isnum
);
if
(
!
isnum
)
{
interror
(
L
,
arg
);
}
return
d
;
}
LUALIB_API
lua_Integer
luaL_optinteger
(
lua_State
*
L
,
int
arg
,
lua_Integer
def
)
{
return
luaL_opt
(
L
,
luaL_checkinteger
,
arg
,
def
);
}
/* }====================================================== */
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
/* userdata to box arbitrary data */
typedef
struct
UBox
{
void
*
box
;
size_t
bsize
;
}
UBox
;
static
void
*
resizebox
(
lua_State
*
L
,
int
idx
,
size_t
newsize
)
{
void
*
ud
;
lua_Alloc
allocf
=
lua_getallocf
(
L
,
&
ud
);
UBox
*
box
=
(
UBox
*
)
lua_touserdata
(
L
,
idx
);
void
*
temp
=
allocf
(
ud
,
box
->
box
,
box
->
bsize
,
newsize
);
if
(
temp
==
NULL
&&
newsize
>
0
)
{
/* allocation error? */
resizebox
(
L
,
idx
,
0
);
/* free buffer */
luaL_error
(
L
,
"not enough memory for buffer allocation"
);
}
box
->
box
=
temp
;
box
->
bsize
=
newsize
;
return
temp
;
}
static
int
boxgc
(
lua_State
*
L
)
{
resizebox
(
L
,
1
,
0
);
return
0
;
}
static
void
*
newbox
(
lua_State
*
L
,
size_t
newsize
)
{
UBox
*
box
=
(
UBox
*
)
lua_newuserdata
(
L
,
sizeof
(
UBox
));
box
->
box
=
NULL
;
box
->
bsize
=
0
;
if
(
luaL_newmetatable
(
L
,
"LUABOX"
))
{
/* creating metatable? */
lua_pushcfunction
(
L
,
boxgc
);
lua_setfield
(
L
,
-
2
,
"__gc"
);
/* metatable.__gc = boxgc */
}
lua_setmetatable
(
L
,
-
2
);
return
resizebox
(
L
,
-
1
,
newsize
);
}
/*
** check whether buffer is using a userdata on the stack as a temporary
** buffer
*/
#define buffonstack(B) ((B)->b != (B)->initb)
/*
** returns a pointer to a free area with at least 'sz' bytes
*/
LUALIB_API
char
*
luaL_prepbuffsize
(
luaL_Buffer
*
B
,
size_t
sz
)
{
lua_State
*
L
=
B
->
L
;
if
(
B
->
size
-
B
->
n
<
sz
)
{
/* not enough space? */
char
*
newbuff
;
size_t
newsize
=
B
->
size
*
2
;
/* double buffer size */
if
(
newsize
-
B
->
n
<
sz
)
/* not big enough? */
newsize
=
B
->
n
+
sz
;
if
(
newsize
<
B
->
n
||
newsize
-
B
->
n
<
sz
)
luaL_error
(
L
,
"buffer too large"
);
/* create larger buffer */
if
(
buffonstack
(
B
))
newbuff
=
(
char
*
)
resizebox
(
L
,
-
1
,
newsize
);
else
{
/* no buffer yet */
newbuff
=
(
char
*
)
newbox
(
L
,
newsize
);
memcpy
(
newbuff
,
B
->
b
,
B
->
n
*
sizeof
(
char
));
/* copy original content */
}
B
->
b
=
newbuff
;
B
->
size
=
newsize
;
}
return
&
B
->
b
[
B
->
n
];
}
LUALIB_API
void
luaL_addlstring
(
luaL_Buffer
*
B
,
const
char
*
s
,
size_t
l
)
{
if
(
l
>
0
)
{
/* avoid 'memcpy' when 's' can be NULL */
char
*
b
=
luaL_prepbuffsize
(
B
,
l
);
memcpy
(
b
,
s
,
l
*
sizeof
(
char
));
luaL_addsize
(
B
,
l
);
}
}
LUALIB_API
void
luaL_addstring
(
luaL_Buffer
*
B
,
const
char
*
s
)
{
luaL_addlstring
(
B
,
s
,
strlen
(
s
));
}
LUALIB_API
void
luaL_pushresult
(
luaL_Buffer
*
B
)
{
lua_State
*
L
=
B
->
L
;
lua_pushlstring
(
L
,
B
->
b
,
B
->
n
);
if
(
buffonstack
(
B
))
{
resizebox
(
L
,
-
2
,
0
);
/* delete old buffer */
lua_remove
(
L
,
-
2
);
/* remove its header from the stack */
}
}
LUALIB_API
void
luaL_pushresultsize
(
luaL_Buffer
*
B
,
size_t
sz
)
{
luaL_addsize
(
B
,
sz
);
luaL_pushresult
(
B
);
}
LUALIB_API
void
luaL_addvalue
(
luaL_Buffer
*
B
)
{
lua_State
*
L
=
B
->
L
;
size_t
l
;
const
char
*
s
=
lua_tolstring
(
L
,
-
1
,
&
l
);
if
(
buffonstack
(
B
))
lua_insert
(
L
,
-
2
);
/* put value below buffer */
luaL_addlstring
(
B
,
s
,
l
);
lua_remove
(
L
,
(
buffonstack
(
B
))
?
-
2
:
-
1
);
/* remove value */
}
LUALIB_API
void
luaL_buffinit
(
lua_State
*
L
,
luaL_Buffer
*
B
)
{
B
->
L
=
L
;
B
->
b
=
B
->
initb
;
B
->
n
=
0
;
B
->
size
=
LUAL_BUFFERSIZE
;
}
LUALIB_API
char
*
luaL_buffinitsize
(
lua_State
*
L
,
luaL_Buffer
*
B
,
size_t
sz
)
{
luaL_buffinit
(
L
,
B
);
return
luaL_prepbuffsize
(
B
,
sz
);
}
/* }====================================================== */
/*
** {======================================================
** Reference system
** =======================================================
*/
/* index of free-list header */
#define freelist 0
LUALIB_API
int
luaL_ref
(
lua_State
*
L
,
int
t
)
{
int
ref
;
if
(
lua_isnil
(
L
,
-
1
))
{
lua_pop
(
L
,
1
);
/* remove from stack */
return
LUA_REFNIL
;
/* 'nil' has a unique fixed reference */
}
t
=
lua_absindex
(
L
,
t
);
lua_rawgeti
(
L
,
t
,
freelist
);
/* get first free element */
ref
=
(
int
)
lua_tointeger
(
L
,
-
1
);
/* ref = t[freelist] */
lua_pop
(
L
,
1
);
/* remove it from stack */
if
(
ref
!=
0
)
{
/* any free element? */
lua_rawgeti
(
L
,
t
,
ref
);
/* remove it from list */
lua_rawseti
(
L
,
t
,
freelist
);
/* (t[freelist] = t[ref]) */
}
else
/* no free elements */
ref
=
(
int
)
lua_rawlen
(
L
,
t
)
+
1
;
/* get a new reference */
lua_rawseti
(
L
,
t
,
ref
);
return
ref
;
}
LUALIB_API
void
luaL_unref
(
lua_State
*
L
,
int
t
,
int
ref
)
{
if
(
ref
>=
0
)
{
t
=
lua_absindex
(
L
,
t
);
lua_rawgeti
(
L
,
t
,
freelist
);
lua_rawseti
(
L
,
t
,
ref
);
/* t[ref] = t[freelist] */
lua_pushinteger
(
L
,
ref
);
lua_rawseti
(
L
,
t
,
freelist
);
/* t[freelist] = ref */
}
}
LUALIB_API
void
(
luaL_reref
)
(
lua_State
*
L
,
int
t
,
int
*
ref
)
{
/*
* If the ref is positive and the entry in table t exists then
* overwrite the value otherwise fall through to luaL_ref()
*/
if
(
ref
)
{
if
(
*
ref
>=
0
)
{
t
=
lua_absindex
(
L
,
t
);
int
reft
=
lua_rawgeti
(
L
,
t
,
*
ref
);
lua_pop
(
L
,
1
);
if
(
reft
!=
LUA_TNIL
)
{
lua_rawseti
(
L
,
t
,
*
ref
);
return
;
}
}
*
ref
=
luaL_ref
(
L
,
t
);
}
}
/* }====================================================== */
/*
** {======================================================
** Load functions
** =======================================================
*/
#ifdef LUA_CROSS_COMPILER
# define file(f) FILE *f
# define freopen_bin(f,fn) freopen(f,"rb",fn)
# define read_buff(b,f) fread(b, 1, sizeof (b), f)
#else
/* map stdio API and macros to vfs */
# undef feof
# undef fopen
# undef getc
# undef ungetc
# define file(f) int f
# define strerror(n) ""
# define feof(f) vfs_eof(f)
# define fopen(f, m) vfs_open(f, m)
# define freopen_bin(fn,f) ((void) vfs_close(f), vfs_open(fn, "r"))
# define getc(f) vfs_getc(f)
# define ungetc(c,f) vfs_ungetc(c, f)
# define read_buff(b,f) vfs_read(f, b, sizeof (b))
#endif
#define LAUXLIB_TYPE 0
typedef
struct
LoadF
{
int
type
;
int
n
;
/* number of pre-read characters */
file
(
f
);
/* file being read */
char
buff
[
BUFSIZ
];
/* area for reading file */
}
LoadF
;
static
const
char
*
getF
(
lua_State
*
L
,
void
*
ud
,
size_t
*
size
)
{
LoadF
*
lf
=
(
LoadF
*
)
ud
;
(
void
)
L
;
/* not used */
if
(
lf
->
n
>
0
)
{
/* are there pre-read characters to be read? */
*
size
=
lf
->
n
;
/* return them (chars already in buffer) */
lf
->
n
=
0
;
/* no more pre-read characters */
}
else
{
/* read a block from file */
/* 'fread' can return > 0 *and* set the EOF flag. If next call to
'getF' called 'fread', it might still wait for user input.
The next check avoids this problem. */
if
(
feof
(
lf
->
f
))
return
NULL
;
*
size
=
read_buff
(
lf
->
buff
,
lf
->
f
);
/* read block */
}
return
lf
->
buff
;
}
static
int
errfile
(
lua_State
*
L
,
const
char
*
what
,
int
fnameindex
)
{
const
char
*
serr
=
strerror
(
errno
);
const
char
*
filename
=
lua_tostring
(
L
,
fnameindex
)
+
1
;
lua_pushfstring
(
L
,
"cannot %s %s: %s"
,
what
,
filename
,
serr
);
lua_remove
(
L
,
fnameindex
);
return
LUA_ERRFILE
;
}
static
int
skipBOM
(
LoadF
*
lf
)
{
const
char
*
p
=
"
\xEF\xBB\xBF
"
;
/* UTF-8 BOM mark */
int
c
;
lf
->
n
=
0
;
do
{
c
=
getc
(
lf
->
f
);
if
(
c
==
EOF
||
c
!=
*
(
const
unsigned
char
*
)
p
++
)
return
c
;
lf
->
buff
[
lf
->
n
++
]
=
c
;
/* to be read by the parser */
}
while
(
*
p
!=
'\0'
);
lf
->
n
=
0
;
/* prefix matched; discard it */
return
getc
(
lf
->
f
);
/* return next character */
}
/*
** reads the first character of file 'f' and skips an optional BOM mark
** in its beginning plus its first line if it starts with '#'. Returns
** true if it skipped the first line. In any case, '*cp' has the
** first "valid" character of the file (after the optional BOM and
** a first-line comment).
*/
static
int
skipcomment
(
LoadF
*
lf
,
int
*
cp
)
{
int
c
=
*
cp
=
skipBOM
(
lf
);
if
(
c
==
'#'
)
{
/* first line is a comment (Unix exec. file)? */
do
{
/* skip first line */
c
=
getc
(
lf
->
f
);
}
while
(
c
!=
EOF
&&
c
!=
'\n'
);
*
cp
=
getc
(
lf
->
f
);
/* skip end-of-line, if present */
return
1
;
/* there was a comment */
}
else
return
0
;
/* no comment */
}
LUALIB_API
int
luaL_loadfilex
(
lua_State
*
L
,
const
char
*
filename
,
const
char
*
mode
)
{
LoadF
lf
;
int
status
,
readstatus
;
int
c
;
int
fnameindex
=
lua_gettop
(
L
)
+
1
;
/* index of filename on the stack */
if
(
filename
==
NULL
)
{
#ifdef LUA_CROSS_COMPILER
lua_pushliteral
(
L
,
"=stdin"
);
lf
.
f
=
stdin
;
#else
return
luaL_error
(
L
,
"filename is NULL"
);
#endif
}
else
{
lua_pushfstring
(
L
,
"@%s"
,
filename
);
lf
.
f
=
fopen
(
filename
,
"r"
);
if
(
!
lf
.
f
)
return
errfile
(
L
,
"open"
,
fnameindex
);
}
lf
.
type
=
0
;
if
(
skipcomment
(
&
lf
,
&
c
))
/* read initial portion */
lf
.
buff
[
lf
.
n
++
]
=
'\n'
;
/* add line to correct line numbers */
if
(
c
==
LUA_SIGNATURE
[
0
]
&&
filename
)
{
/* binary file? */
lf
.
f
=
freopen_bin
(
filename
,
lf
.
f
);
/* reopen in binary mode */
if
(
!
lf
.
f
)
return
errfile
(
L
,
"reopen"
,
fnameindex
);
skipcomment
(
&
lf
,
&
c
);
/* re-read initial portion */
}
if
(
c
!=
EOF
)
lf
.
buff
[
lf
.
n
++
]
=
c
;
/* 'c' is the first character of the stream */
status
=
lua_load
(
L
,
getF
,
&
lf
,
lua_tostring
(
L
,
-
1
),
mode
);
#ifdef LUA_CROSS_COMPILER
readstatus
=
ferror
(
lf
.
f
);
if
(
filename
)
fclose
(
lf
.
f
);
/* close file (even in case of errors) */
if
(
readstatus
)
{
lua_settop
(
L
,
fnameindex
);
/* ignore results from 'lua_load' */
return
errfile
(
L
,
"read"
,
fnameindex
);
}
#else
(
void
)
readstatus
;
/* avoid compile error */
if
(
filename
)
vfs_close
(
lf
.
f
);
/* close file (even in case of errors) */
#endif
lua_remove
(
L
,
fnameindex
);
return
status
;
}
typedef
struct
LoadS
{
const
char
*
s
;
size_t
size
;
}
LoadS
;
static
const
char
*
getS
(
lua_State
*
L
,
void
*
ud
,
size_t
*
size
)
{
LoadS
*
ls
=
(
LoadS
*
)
ud
;
(
void
)
L
;
/* not used */
if
(
ls
->
size
==
0
)
return
NULL
;
*
size
=
ls
->
size
;
ls
->
size
=
0
;
return
ls
->
s
;
}
LUALIB_API
int
luaL_loadbufferx
(
lua_State
*
L
,
const
char
*
buff
,
size_t
size
,
const
char
*
name
,
const
char
*
mode
)
{
LoadS
ls
;
ls
.
s
=
buff
;
ls
.
size
=
size
;
return
lua_load
(
L
,
getS
,
&
ls
,
name
,
mode
);
}
LUALIB_API
int
luaL_loadstring
(
lua_State
*
L
,
const
char
*
s
)
{
return
luaL_loadbuffer
(
L
,
s
,
strlen
(
s
),
s
);
}
/* }====================================================== */
LUALIB_API
int
luaL_getmetafield
(
lua_State
*
L
,
int
obj
,
const
char
*
event
)
{
if
(
!
lua_getmetatable
(
L
,
obj
))
/* no metatable? */
return
LUA_TNIL
;
else
{
int
tt
;
lua_pushstring
(
L
,
event
);
tt
=
lua_rawget
(
L
,
-
2
);
if
(
tt
==
LUA_TNIL
)
/* is metafield nil? */
lua_pop
(
L
,
2
);
/* remove metatable and metafield */
else
lua_remove
(
L
,
-
2
);
/* remove only metatable */
return
tt
;
/* return metafield type */
}
}
LUALIB_API
int
luaL_callmeta
(
lua_State
*
L
,
int
obj
,
const
char
*
event
)
{
obj
=
lua_absindex
(
L
,
obj
);
if
(
luaL_getmetafield
(
L
,
obj
,
event
)
==
LUA_TNIL
)
/* no metafield? */
return
0
;
lua_pushvalue
(
L
,
obj
);
lua_call
(
L
,
1
,
1
);
return
1
;
}
LUALIB_API
lua_Integer
luaL_len
(
lua_State
*
L
,
int
idx
)
{
lua_Integer
l
;
int
isnum
;
lua_len
(
L
,
idx
);
l
=
lua_tointegerx
(
L
,
-
1
,
&
isnum
);
if
(
!
isnum
)
luaL_error
(
L
,
"object length is not an integer"
);
lua_pop
(
L
,
1
);
/* remove object */
return
l
;
}
LUALIB_API
const
char
*
luaL_tolstring
(
lua_State
*
L
,
int
idx
,
size_t
*
len
)
{
if
(
luaL_callmeta
(
L
,
idx
,
"__tostring"
))
{
/* metafield? */
if
(
!
lua_isstring
(
L
,
-
1
))
luaL_error
(
L
,
"'__tostring' must return a string"
);
}
else
{
switch
(
lua_type
(
L
,
idx
))
{
case
LUA_TNUMBER
:
{
if
(
lua_isinteger
(
L
,
idx
))
lua_pushfstring
(
L
,
"%I"
,
(
LUAI_UACINT
)
lua_tointeger
(
L
,
idx
));
else
lua_pushfstring
(
L
,
"%f"
,
(
LUAI_UACNUMBER
)
lua_tonumber
(
L
,
idx
));
break
;
}
case
LUA_TSTRING
:
lua_pushvalue
(
L
,
idx
);
break
;
case
LUA_TBOOLEAN
:
lua_pushstring
(
L
,
(
lua_toboolean
(
L
,
idx
)
?
"true"
:
"false"
));
break
;
case
LUA_TNIL
:
lua_pushliteral
(
L
,
"nil"
);
break
;
default:
{
int
tt
=
luaL_getmetafield
(
L
,
idx
,
"__name"
);
/* try name */
const
char
*
kind
=
(
tt
==
LUA_TSTRING
)
?
lua_tostring
(
L
,
-
1
)
:
luaL_typename
(
L
,
idx
);
lua_pushfstring
(
L
,
"%s: %p"
,
kind
,
lua_topointer
(
L
,
idx
));
if
(
tt
!=
LUA_TNIL
)
lua_remove
(
L
,
-
2
);
/* remove '__name' */
break
;
}
}
}
return
lua_tolstring
(
L
,
-
1
,
len
);
}
/*
** {======================================================
** Compatibility with 5.1 module functions
** =======================================================
*/
#if defined(LUA_COMPAT_MODULE)
static
const
char
*
luaL_findtable
(
lua_State
*
L
,
int
idx
,
const
char
*
fname
,
int
szhint
)
{
const
char
*
e
;
if
(
idx
)
lua_pushvalue
(
L
,
idx
);
do
{
e
=
strchr
(
fname
,
'.'
);
if
(
e
==
NULL
)
e
=
fname
+
strlen
(
fname
);
lua_pushlstring
(
L
,
fname
,
e
-
fname
);
if
(
lua_rawget
(
L
,
-
2
)
==
LUA_TNIL
)
{
/* no such field? */
lua_pop
(
L
,
1
);
/* remove this nil */
lua_createtable
(
L
,
0
,
(
*
e
==
'.'
?
1
:
szhint
));
/* new table for field */
lua_pushlstring
(
L
,
fname
,
e
-
fname
);
lua_pushvalue
(
L
,
-
2
);
lua_settable
(
L
,
-
4
);
/* set new table into field */
}
else
if
(
!
lua_istable
(
L
,
-
1
))
{
/* field has a non-table value? */
lua_pop
(
L
,
2
);
/* remove table and value */
return
fname
;
/* return problematic part of the name */
}
lua_remove
(
L
,
-
2
);
/* remove previous table */
fname
=
e
+
1
;
}
while
(
*
e
==
'.'
);
return
NULL
;
}
/*
** Count number of elements in a luaL_Reg list.
*/
static
int
libsize
(
const
luaL_Reg
*
l
)
{
int
size
=
0
;
for
(;
l
&&
l
->
name
;
l
++
)
size
++
;
return
size
;
}
/*
** Find or create a module table with a given name. The function
** first looks at the LOADED table and, if that fails, try a
** global variable with that name. In any case, leaves on the stack
** the module table.
*/
LUALIB_API
void
luaL_pushmodule
(
lua_State
*
L
,
const
char
*
modname
,
int
sizehint
)
{
luaL_findtable
(
L
,
LUA_REGISTRYINDEX
,
LUA_LOADED_TABLE
,
1
);
if
(
lua_getfield
(
L
,
-
1
,
modname
)
!=
LUA_TTABLE
)
{
/* no LOADED[modname]? */
lua_pop
(
L
,
1
);
/* remove previous result */
/* try global variable (and create one if it does not exist) */
lua_pushglobaltable
(
L
);
if
(
luaL_findtable
(
L
,
0
,
modname
,
sizehint
)
!=
NULL
)
luaL_error
(
L
,
"name conflict for module '%s'"
,
modname
);
lua_pushvalue
(
L
,
-
1
);
lua_setfield
(
L
,
-
3
,
modname
);
/* LOADED[modname] = new table */
}
lua_remove
(
L
,
-
2
);
/* remove LOADED table */
}
LUALIB_API
void
luaL_openlib
(
lua_State
*
L
,
const
char
*
libname
,
const
luaL_Reg
*
l
,
int
nup
)
{
luaL_checkversion
(
L
);
if
(
libname
)
{
luaL_pushmodule
(
L
,
libname
,
libsize
(
l
));
/* get/create library table */
lua_insert
(
L
,
-
(
nup
+
1
));
/* move library table to below upvalues */
}
if
(
l
)
luaL_setfuncs
(
L
,
l
,
nup
);
else
lua_pop
(
L
,
nup
);
/* remove upvalues */
}
#endif
/* }====================================================== */
/*
** set functions from list 'l' into table at top - 'nup'; each
** function gets the 'nup' elements at the top as upvalues.
** Returns with only the table at the stack.
*/
LUALIB_API
void
luaL_setfuncs
(
lua_State
*
L
,
const
luaL_Reg
*
l
,
int
nup
)
{
luaL_checkstack
(
L
,
nup
,
"too many upvalues"
);
for
(;
l
->
name
!=
NULL
;
l
++
)
{
/* fill the table with given functions */
int
i
;
for
(
i
=
0
;
i
<
nup
;
i
++
)
/* copy upvalues to the top */
lua_pushvalue
(
L
,
-
nup
);
lua_pushcclosure
(
L
,
l
->
func
,
nup
);
/* closure with those upvalues */
lua_setfield
(
L
,
-
(
nup
+
2
),
l
->
name
);
}
lua_pop
(
L
,
nup
);
/* remove upvalues */
}
/*
** ensure that stack[idx][fname] has a table and push that table
** into the stack
*/
LUALIB_API
int
luaL_getsubtable
(
lua_State
*
L
,
int
idx
,
const
char
*
fname
)
{
if
(
lua_getfield
(
L
,
idx
,
fname
)
==
LUA_TTABLE
)
return
1
;
/* table already there */
else
{
lua_pop
(
L
,
1
);
/* remove previous result */
idx
=
lua_absindex
(
L
,
idx
);
lua_newtable
(
L
);
lua_pushvalue
(
L
,
-
1
);
/* copy to be left at top */
lua_setfield
(
L
,
idx
,
fname
);
/* assign new table to field */
return
0
;
/* false, because did not find table there */
}
}
/*
** Stripped-down 'require' used in linit.c and ltests.c. After checking
** "loaded" and ROM tables, calls 'openf' to open a module, registers the
** result in 'package.loaded' table and, if 'glb' is true, also registers
** the result in the global table. Leaves resulting module on the top.
*/
LUALIB_API
void
luaL_requiref
(
lua_State
*
L
,
const
char
*
modname
,
lua_CFunction
openf
,
int
glb
)
{
int
inROM
=
0
;
luaL_getsubtable
(
L
,
LUA_REGISTRYINDEX
,
LUA_LOADED_TABLE
);
lua_getfield
(
L
,
-
1
,
modname
);
/* LOADED[modname] */
if
(
!
lua_toboolean
(
L
,
-
1
))
{
/* package not in LOADED table? */
lua_getglobal
(
L
,
"ROM"
);
/* try the ROM entry */
if
(
!
lua_isnil
(
L
,
-
1
))
{
lua_getfield
(
L
,
-
1
,
modname
);
/* ROM[name] */
inROM
=
lua_toboolean
(
L
,
-
1
);
lua_pop
(
L
,
3
);
}
else
lua_pop
(
L
,
2
);
if
(
inROM
)
/* package is in ROM */
glb
=
0
;
/* suppress setting _G entry */
lua_pushcfunction
(
L
,
openf
);
lua_pushstring
(
L
,
modname
);
/* argument to open function */
lua_call
(
L
,
1
,
1
);
/* call 'openf' to open module */
if
(
lua_toboolean
(
L
,
-
1
)
&&
!
inROM
)
{
/* if not in ROM & result is returned */
lua_pushvalue
(
L
,
-
1
);
/* make copy of module (call result) */
lua_setfield
(
L
,
-
3
,
modname
);
/* LOADED[modname] = module */
}
}
lua_remove
(
L
,
-
2
);
/* remove LOADED table */
if
(
glb
)
{
lua_pushvalue
(
L
,
-
1
);
/* copy of module */
lua_setglobal
(
L
,
modname
);
/* _G[modname] = module */
}
}
LUALIB_API
const
char
*
luaL_gsub
(
lua_State
*
L
,
const
char
*
s
,
const
char
*
p
,
const
char
*
r
)
{
const
char
*
wild
;
size_t
l
=
strlen
(
p
);
luaL_Buffer
b
;
luaL_buffinit
(
L
,
&
b
);
while
((
wild
=
strstr
(
s
,
p
))
!=
NULL
)
{
luaL_addlstring
(
&
b
,
s
,
wild
-
s
);
/* push prefix */
luaL_addstring
(
&
b
,
r
);
/* push replacement in place of pattern */
s
=
wild
+
l
;
/* continue after 'p' */
}
luaL_addstring
(
&
b
,
s
);
/* push last suffix */
luaL_pushresult
(
&
b
);
return
lua_tostring
(
L
,
-
1
);
}
static
void
*
l_alloc
(
void
*
ud
,
void
*
ptr
,
size_t
osize
,
size_t
nsize
)
{
(
void
)
ud
;
(
void
)
osize
;
/* not used */
if
(
nsize
==
0
)
{
free
(
ptr
);
return
NULL
;
}
else
return
realloc
(
ptr
,
nsize
);
}
LUALIB_API
lua_State
*
luaL_newstate
(
void
)
{
lua_State
*
L
=
lua_newstate
(
l_alloc
,
NULL
);
if
(
L
)
lua_atpanic
(
L
,
lpanic
);
return
L
;
}
LUALIB_API
void
luaL_checkversion_
(
lua_State
*
L
,
lua_Number
ver
,
size_t
sz
)
{
const
lua_Number
*
v
=
lua_version
(
L
);
if
(
sz
!=
LUAL_NUMSIZES
)
/* check numeric types */
luaL_error
(
L
,
"core and library have incompatible numeric types"
);
if
(
v
!=
lua_version
(
NULL
))
luaL_error
(
L
,
"multiple Lua VMs detected"
);
else
if
(
*
v
!=
ver
)
luaL_error
(
L
,
"version mismatch: app. needs %f, Lua core provides %f"
,
(
LUAI_UACNUMBER
)
ver
,
(
LUAI_UACNUMBER
)
*
v
);
}
#ifdef LUA_USE_ESP
/*
** Error Reporting Task. We can't pass a string parameter to the error reporter
** directly through the task interface the call is wrapped in a C closure with
** the error string as an Upval and this is posted to call the Lua reporter.
*/
static
int
errhandler_aux
(
lua_State
*
L
)
{
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
"onerror"
);
if
(
!
lua_isfunction
(
L
,
-
1
))
{
lua_pop
(
L
,
1
);
lua_getglobal
(
L
,
"print"
);
}
lua_pushvalue
(
L
,
lua_upvalueindex
(
1
));
lua_call
(
L
,
1
,
0
);
/* Using an error handler would cause an infinite loop! */
return
0
;
}
/*
** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
** argument -- the thrown error. This plus depth=2 is passed to debug.traceback()
** to convert into an error message which it handles in a separate posted task.
*/
static
int
errhandler
(
lua_State
*
L
)
{
lua_getglobal
(
L
,
"debug"
);
lua_getfield
(
L
,
-
1
,
"traceback"
);
if
(
lua_isfunction
(
L
,
-
1
))
{
lua_insert
(
L
,
1
);
/* insert tracback function above error */
lua_pop
(
L
,
1
);
/* dump the debug table entry */
lua_pushinteger
(
L
,
2
);
/* skip this function and traceback */
lua_call
(
L
,
2
,
1
);
/* call debug.traceback and return it as a string */
lua_pushcclosure
(
L
,
errhandler_aux
,
1
);
/* report with str as upval */
luaL_posttask
(
L
,
LUA_TASK_HIGH
);
}
return
0
;
}
/*
** Extended interface to 'lua_pcall', which sets appropriate message and Lua
** stack trackback. On error a separate task is posted to report the error.
*/
LUALIB_API
int
luaL_pcallx
(
lua_State
*
L
,
int
narg
,
int
nres
)
{
int
status
;
int
base
=
lua_gettop
(
L
)
-
narg
;
/* function index */
lua_pushcfunction
(
L
,
errhandler
);
/* push message handler */
lua_insert
(
L
,
base
);
/* put it under function and args */
status
=
lua_pcall
(
L
,
narg
,
nres
,
base
);
lua_remove
(
L
,
base
);
/* remove message handler from the stack */
if
(
status
!=
LUA_OK
&&
status
!=
LUA_ERRRUN
)
{
lua_gc
(
L
,
LUA_GCCOLLECT
,
0
);
/* call onerror directly if handler failed */
lua_pushliteral
(
L
,
"out of memory"
);
lua_pushcclosure
(
L
,
errhandler_aux
,
1
);
/* report EOM as upval */
luaL_posttask
(
L
,
LUA_TASK_HIGH
);
}
return
status
;
}
#endif
components/lua/lua-5.3/lauxlib.h
0 → 100644
View file @
dba57fa0
/*
** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
#ifdef LUA_LIB
#include "lnodemcu.h"
#endif
/* extra error code for 'luaL_loadfilex' */
#define LUA_ERRFILE (LUA_ERRERR+1)
/* key, in the registry, for table of loaded modules */
#define LUA_LOADED_TABLE "_LOADED"
/* key, in the registry, for table of preloaded loaders */
#define LUA_PRELOAD_TABLE "_PRELOAD"
typedef
struct
luaL_Reg
{
const
char
*
name
;
lua_CFunction
func
;
}
luaL_Reg
;
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
LUALIB_API
void
(
luaL_checkversion_
)
(
lua_State
*
L
,
lua_Number
ver
,
size_t
sz
);
#define luaL_checkversion(L) \
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
LUALIB_API
int
(
luaL_getmetafield
)
(
lua_State
*
L
,
int
obj
,
const
char
*
e
);
LUALIB_API
int
(
luaL_callmeta
)
(
lua_State
*
L
,
int
obj
,
const
char
*
e
);
LUALIB_API
const
char
*
(
luaL_tolstring
)
(
lua_State
*
L
,
int
idx
,
size_t
*
len
);
LUALIB_API
int
(
luaL_argerror
)
(
lua_State
*
L
,
int
arg
,
const
char
*
extramsg
);
LUALIB_API
const
char
*
(
luaL_checklstring
)
(
lua_State
*
L
,
int
arg
,
size_t
*
l
);
LUALIB_API
const
char
*
(
luaL_optlstring
)
(
lua_State
*
L
,
int
arg
,
const
char
*
def
,
size_t
*
l
);
LUALIB_API
lua_Number
(
luaL_checknumber
)
(
lua_State
*
L
,
int
arg
);
LUALIB_API
lua_Number
(
luaL_optnumber
)
(
lua_State
*
L
,
int
arg
,
lua_Number
def
);
LUALIB_API
lua_Integer
(
luaL_checkinteger
)
(
lua_State
*
L
,
int
arg
);
LUALIB_API
lua_Integer
(
luaL_optinteger
)
(
lua_State
*
L
,
int
arg
,
lua_Integer
def
);
LUALIB_API
void
(
luaL_checkstack
)
(
lua_State
*
L
,
int
sz
,
const
char
*
msg
);
LUALIB_API
void
(
luaL_checktype
)
(
lua_State
*
L
,
int
arg
,
int
t
);
LUALIB_API
void
(
luaL_checkany
)
(
lua_State
*
L
,
int
arg
);
LUALIB_API
int
(
luaL_newmetatable
)
(
lua_State
*
L
,
const
char
*
tname
);
LUALIB_API
void
(
luaL_setmetatable
)
(
lua_State
*
L
,
const
char
*
tname
);
LUALIB_API
void
*
(
luaL_testudata
)
(
lua_State
*
L
,
int
ud
,
const
char
*
tname
);
LUALIB_API
void
*
(
luaL_checkudata
)
(
lua_State
*
L
,
int
ud
,
const
char
*
tname
);
LUALIB_API
int
(
luaL_rometatable
)
(
lua_State
*
L
,
const
char
*
tname
,
const
ROTable
*
p
);
LUALIB_API
void
(
luaL_where
)
(
lua_State
*
L
,
int
lvl
);
LUALIB_API
int
(
luaL_error
)
(
lua_State
*
L
,
const
char
*
fmt
,
...);
LUALIB_API
int
(
luaL_checkoption
)
(
lua_State
*
L
,
int
arg
,
const
char
*
def
,
const
char
*
const
lst
[]);
LUALIB_API
int
(
luaL_fileresult
)
(
lua_State
*
L
,
int
stat
,
const
char
*
fname
);
LUALIB_API
int
(
luaL_execresult
)
(
lua_State
*
L
,
int
stat
);
/* predefined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API
int
(
luaL_ref
)
(
lua_State
*
L
,
int
t
);
LUALIB_API
void
(
luaL_unref
)
(
lua_State
*
L
,
int
t
,
int
ref
);
#define luaL_unref2(l,t,r) do {luaL_unref(L, (t), (r)); r = LUA_NOREF;} while (0)
LUALIB_API
void
(
luaL_reref
)
(
lua_State
*
L
,
int
t
,
int
*
ref
);
LUALIB_API
int
(
luaL_loadfilex
)
(
lua_State
*
L
,
const
char
*
filename
,
const
char
*
mode
);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API
int
(
luaL_loadbufferx
)
(
lua_State
*
L
,
const
char
*
buff
,
size_t
sz
,
const
char
*
name
,
const
char
*
mode
);
LUALIB_API
int
(
luaL_loadstring
)
(
lua_State
*
L
,
const
char
*
s
);
LUALIB_API
lua_State
*
(
luaL_newstate
)
(
void
);
LUALIB_API
lua_Integer
(
luaL_len
)
(
lua_State
*
L
,
int
idx
);
LUALIB_API
const
char
*
(
luaL_gsub
)
(
lua_State
*
L
,
const
char
*
s
,
const
char
*
p
,
const
char
*
r
);
LUALIB_API
void
(
luaL_setfuncs
)
(
lua_State
*
L
,
const
luaL_Reg
*
l
,
int
nup
);
LUALIB_API
int
(
luaL_getsubtable
)
(
lua_State
*
L
,
int
idx
,
const
char
*
fname
);
LUALIB_API
void
(
luaL_traceback
)
(
lua_State
*
L
,
lua_State
*
L1
,
const
char
*
msg
,
int
level
);
LUALIB_API
void
(
luaL_requiref
)
(
lua_State
*
L
,
const
char
*
modname
,
lua_CFunction
openf
,
int
glb
);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) \
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,arg,extramsg) \
((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
#define luaL_checkfunction(L,n) luaL_checktype(L, (n), LUA_TFUNCTION);
#define luaL_checktable(L,n) luaL_checktype(L, (n), LUA_TTABLE);
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef
struct
luaL_Buffer
{
char
*
b
;
/* buffer address */
size_t
size
;
/* buffer size */
size_t
n
;
/* number of characters in buffer */
lua_State
*
L
;
char
initb
[
LUAL_BUFFERSIZE
];
/* initial buffer */
}
luaL_Buffer
;
#define luaL_addchar(B,c) \
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,s) ((B)->n += (s))
LUALIB_API
void
(
luaL_buffinit
)
(
lua_State
*
L
,
luaL_Buffer
*
B
);
LUALIB_API
char
*
(
luaL_prepbuffsize
)
(
luaL_Buffer
*
B
,
size_t
sz
);
LUALIB_API
void
(
luaL_addlstring
)
(
luaL_Buffer
*
B
,
const
char
*
s
,
size_t
l
);
LUALIB_API
void
(
luaL_addstring
)
(
luaL_Buffer
*
B
,
const
char
*
s
);
LUALIB_API
void
(
luaL_addvalue
)
(
luaL_Buffer
*
B
);
LUALIB_API
void
(
luaL_pushresult
)
(
luaL_Buffer
*
B
);
LUALIB_API
void
(
luaL_pushresultsize
)
(
luaL_Buffer
*
B
,
size_t
sz
);
LUALIB_API
char
*
(
luaL_buffinitsize
)
(
lua_State
*
L
,
luaL_Buffer
*
B
,
size_t
sz
);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */
/*
** {======================================================
** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef
struct
luaL_Stream
{
FILE
*
f
;
/* stream (NULL for incompletely created streams) */
lua_CFunction
closef
;
/* to close stream (NULL for closed streams) */
}
luaL_Stream
;
/* }====================================================== */
LUALIB_API
int
(
luaL_rometatable
)
(
lua_State
*
L
,
const
char
*
tname
,
const
ROTable
*
t
);
/* }====================================================== */
/* compatibility with old module system */
#if defined(LUA_COMPAT_MODULE)
LUALIB_API
void
(
luaL_pushmodule
)
(
lua_State
*
L
,
const
char
*
modname
,
int
sizehint
);
LUALIB_API
void
(
luaL_openlib
)
(
lua_State
*
L
,
const
char
*
libname
,
const
luaL_Reg
*
l
,
int
nup
);
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
#endif
/*
** {==================================================================
** "Abstraction Layer" for basic report of messages and errors
** ===================================================================
*/
/* print a string */
#if !defined(lua_writestring)
#ifdef LUA_USE_ESP
void
output_redirect
(
const
char
*
str
,
size_t
l
);
#define lua_writestring(s,l) output_redirect((s),(l))
#else
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#endif
#endif
/* print a newline and flush the output */
#if !defined(lua_writeline)
#ifdef LUA_USE_ESP8266
#define lua_writeline() lua_writestring("\n", 1)
#else
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
#endif
#endif
/* print an error message. This is a primitive error output */
#if !defined(lua_writestringerror)
#ifdef LUA_USE_ESP8266
extern
void
dbg_printf
(
const
char
*
fmt
,
...);
#define lua_writestringerror(s,p) dbg_printf((s), (p))
#else
#define lua_writestringerror(s,p) (fprintf(stderr, (s), (p)), fflush(stderr))
#endif
#endif
/* }================================================================== */
/*
** {============================================================
** Compatibility with deprecated conversions
** =============================================================
*/
#if defined(LUA_COMPAT_APIINTCASTS)
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
#define luaL_optunsigned(L,a,d) \
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#endif
/* }============================================================ */
/*
** {==================================================================
** NodeMCU extensions
** ===================================================================
*/
#define LUA_TASK_LOW 0
#define LUA_TASK_MEDIUM 1
#define LUA_TASK_HIGH 2
LUALIB_API
int
(
luaL_pushlfsmodules
)
(
lua_State
*
L
);
LUALIB_API
int
(
luaL_pushlfsdts
)
(
lua_State
*
L
);
LUALIB_API
void
(
luaL_lfsreload
)
(
lua_State
*
L
);
LUALIB_API
int
(
luaL_posttask
)
(
lua_State
*
L
,
int
prio
);
LUALIB_API
int
(
luaL_pcallx
)
(
lua_State
*
L
,
int
narg
,
int
nres
);
#define luaL_pushlfsmodule(l) lua_pushlfsfunc(L)
/* }============================================================ */
#ifndef LUA_CROSS_COMPILER
int
panic_get_nvval
(
void
);
void
panic_clear_nvval
(
void
);
#endif
#endif
components/lua/lua-5.3/lbaselib.c
0 → 100644
View file @
dba57fa0
/*
** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
#define lbaselib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static
int
luaB_print
(
lua_State
*
L
)
{
int
n
=
lua_gettop
(
L
);
/* number of arguments */
int
i
;
lua_getglobal
(
L
,
"tostring"
);
for
(
i
=
1
;
i
<=
n
;
i
++
)
{
const
char
*
s
;
size_t
l
;
lua_pushvalue
(
L
,
-
1
);
/* function to be called */
lua_pushvalue
(
L
,
i
);
/* value to print */
lua_call
(
L
,
1
,
1
);
s
=
lua_tolstring
(
L
,
-
1
,
&
l
);
/* get result */
if
(
s
==
NULL
)
return
luaL_error
(
L
,
"'tostring' must return a string to 'print'"
);
if
(
i
>
1
)
lua_writestring
(
"
\t
"
,
1
);
lua_writestring
(
s
,
l
);
lua_pop
(
L
,
1
);
/* pop result */
}
lua_writeline
();
return
0
;
}
#define SPACECHARS " \f\n\r\t\v"
static
const
char
*
b_str2int
(
const
char
*
s
,
int
base
,
lua_Integer
*
pn
)
{
lua_Unsigned
n
=
0
;
int
neg
=
0
;
s
+=
strspn
(
s
,
SPACECHARS
);
/* skip initial spaces */
if
(
*
s
==
'-'
)
{
s
++
;
neg
=
1
;
}
/* handle signal */
else
if
(
*
s
==
'+'
)
s
++
;
if
(
!
isalnum
((
unsigned
char
)
*
s
))
/* no digit? */
return
NULL
;
do
{
int
digit
=
(
isdigit
((
unsigned
char
)
*
s
))
?
*
s
-
'0'
:
(
toupper
((
unsigned
char
)
*
s
)
-
'A'
)
+
10
;
if
(
digit
>=
base
)
return
NULL
;
/* invalid numeral */
n
=
n
*
base
+
digit
;
s
++
;
}
while
(
isalnum
((
unsigned
char
)
*
s
));
s
+=
strspn
(
s
,
SPACECHARS
);
/* skip trailing spaces */
*
pn
=
(
lua_Integer
)((
neg
)
?
(
0u
-
n
)
:
n
);
return
s
;
}
static
int
luaB_tonumber
(
lua_State
*
L
)
{
if
(
lua_isnoneornil
(
L
,
2
))
{
/* standard conversion? */
luaL_checkany
(
L
,
1
);
if
(
lua_type
(
L
,
1
)
==
LUA_TNUMBER
)
{
/* already a number? */
lua_settop
(
L
,
1
);
/* yes; return it */
return
1
;
}
else
{
size_t
l
;
const
char
*
s
=
lua_tolstring
(
L
,
1
,
&
l
);
if
(
s
!=
NULL
&&
lua_stringtonumber
(
L
,
s
)
==
l
+
1
)
return
1
;
/* successful conversion to number */
/* else not a number */
}
}
else
{
size_t
l
;
const
char
*
s
;
lua_Integer
n
=
0
;
/* to avoid warnings */
lua_Integer
base
=
luaL_checkinteger
(
L
,
2
);
luaL_checktype
(
L
,
1
,
LUA_TSTRING
);
/* no numbers as strings */
s
=
lua_tolstring
(
L
,
1
,
&
l
);
luaL_argcheck
(
L
,
2
<=
base
&&
base
<=
36
,
2
,
"base out of range"
);
if
(
b_str2int
(
s
,
(
int
)
base
,
&
n
)
==
s
+
l
)
{
lua_pushinteger
(
L
,
n
);
return
1
;
}
/* else not a number */
}
/* else not a number */
lua_pushnil
(
L
);
/* not a number */
return
1
;
}
static
int
luaB_error
(
lua_State
*
L
)
{
int
level
=
(
int
)
luaL_optinteger
(
L
,
2
,
1
);
lua_settop
(
L
,
1
);
if
(
lua_type
(
L
,
1
)
==
LUA_TSTRING
&&
level
>
0
)
{
luaL_where
(
L
,
level
);
/* add extra information */
lua_pushvalue
(
L
,
1
);
lua_concat
(
L
,
2
);
}
return
lua_error
(
L
);
}
static
int
luaB_getmetatable
(
lua_State
*
L
)
{
luaL_checkany
(
L
,
1
);
if
(
!
lua_getmetatable
(
L
,
1
))
{
lua_pushnil
(
L
);
return
1
;
/* no metatable */
}
luaL_getmetafield
(
L
,
1
,
"__metatable"
);
return
1
;
/* returns either __metatable field (if present) or metatable */
}
static
int
luaB_setmetatable
(
lua_State
*
L
)
{
int
t
=
lua_type
(
L
,
2
);
luaL_checktype
(
L
,
1
,
LUA_TTABLE
);
luaL_argcheck
(
L
,
t
==
LUA_TNIL
||
t
==
LUA_TTABLE
,
2
,
"nil or table expected"
);
if
(
luaL_getmetafield
(
L
,
1
,
"__metatable"
)
!=
LUA_TNIL
)
return
luaL_error
(
L
,
"cannot change a protected metatable"
);
lua_settop
(
L
,
2
);
lua_setmetatable
(
L
,
1
);
return
1
;
}
static
int
luaB_rawequal
(
lua_State
*
L
)
{
luaL_checkany
(
L
,
1
);
luaL_checkany
(
L
,
2
);
lua_pushboolean
(
L
,
lua_rawequal
(
L
,
1
,
2
));
return
1
;
}
static
int
luaB_rawlen
(
lua_State
*
L
)
{
int
t
=
lua_type
(
L
,
1
);
luaL_argcheck
(
L
,
t
==
LUA_TTABLE
||
t
==
LUA_TSTRING
,
1
,
"table or string expected"
);
lua_pushinteger
(
L
,
lua_rawlen
(
L
,
1
));
return
1
;
}
static
int
luaB_rawget
(
lua_State
*
L
)
{
luaL_checktype
(
L
,
1
,
LUA_TTABLE
);
luaL_checkany
(
L
,
2
);
lua_settop
(
L
,
2
);
lua_rawget
(
L
,
1
);
return
1
;
}
static
int
luaB_rawset
(
lua_State
*
L
)
{
luaL_checktype
(
L
,
1
,
LUA_TTABLE
);
luaL_checkany
(
L
,
2
);
luaL_checkany
(
L
,
3
);
lua_settop
(
L
,
3
);
lua_rawset
(
L
,
1
);
return
1
;
}
static
int
luaB_collectgarbage
(
lua_State
*
L
)
{
static
const
char
*
const
opts
[]
=
{
"stop"
,
"restart"
,
"collect"
,
"count"
,
"step"
,
"setpause"
,
"setstepmul"
,
"setmemlimit"
,
"isrunning"
,
NULL
};
static
const
int
optsnum
[]
=
{
LUA_GCSTOP
,
LUA_GCRESTART
,
LUA_GCCOLLECT
,
LUA_GCCOUNT
,
LUA_GCSTEP
,
LUA_GCSETPAUSE
,
LUA_GCSETSTEPMUL
,
LUA_GCISRUNNING
};
int
o
=
optsnum
[
luaL_checkoption
(
L
,
1
,
"collect"
,
opts
)];
int
ex
=
(
int
)
luaL_optinteger
(
L
,
2
,
0
);
int
res
=
lua_gc
(
L
,
o
,
ex
);
switch
(
o
)
{
case
LUA_GCCOUNT
:
{
int
b
=
lua_gc
(
L
,
LUA_GCCOUNTB
,
0
);
lua_pushnumber
(
L
,
(
lua_Number
)
res
+
((
lua_Number
)
b
/
1024
));
return
1
;
}
case
LUA_GCSTEP
:
case
LUA_GCISRUNNING
:
{
lua_pushboolean
(
L
,
res
);
return
1
;
}
default:
{
lua_pushinteger
(
L
,
res
);
return
1
;
}
}
}
static
int
luaB_type
(
lua_State
*
L
)
{
int
t
=
lua_type
(
L
,
1
);
luaL_argcheck
(
L
,
t
!=
LUA_TNONE
,
1
,
"value expected"
);
lua_pushstring
(
L
,
lua_typename
(
L
,
t
));
return
1
;
}
static
int
pairsmeta
(
lua_State
*
L
,
const
char
*
method
,
int
iszero
,
lua_CFunction
iter
)
{
luaL_checkany
(
L
,
1
);
if
(
luaL_getmetafield
(
L
,
1
,
method
)
==
LUA_TNIL
)
{
/* no metamethod? */
lua_pushcfunction
(
L
,
iter
);
/* will return generator, */
lua_pushvalue
(
L
,
1
);
/* state, */
if
(
iszero
)
lua_pushinteger
(
L
,
0
);
/* and initial value */
else
lua_pushnil
(
L
);
}
else
{
lua_pushvalue
(
L
,
1
);
/* argument 'self' to metamethod */
lua_call
(
L
,
1
,
3
);
/* get 3 values from metamethod */
}
return
3
;
}
static
int
luaB_next
(
lua_State
*
L
)
{
luaL_checktype
(
L
,
1
,
LUA_TTABLE
);
lua_settop
(
L
,
2
);
/* create a 2nd argument if there isn't one */
if
(
lua_next
(
L
,
1
))
return
2
;
else
{
lua_pushnil
(
L
);
return
1
;
}
}
static
int
luaB_pairs
(
lua_State
*
L
)
{
return
pairsmeta
(
L
,
"__pairs"
,
0
,
luaB_next
);
}
/*
** Traversal function for 'ipairs'
*/
static
int
ipairsaux
(
lua_State
*
L
)
{
lua_Integer
i
=
luaL_checkinteger
(
L
,
2
)
+
1
;
lua_pushinteger
(
L
,
i
);
return
(
lua_geti
(
L
,
1
,
i
)
==
LUA_TNIL
)
?
1
:
2
;
}
/*
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** (The given "table" may not be a table.)
*/
static
int
luaB_ipairs
(
lua_State
*
L
)
{
#if defined(LUA_COMPAT_IPAIRS)
return
pairsmeta
(
L
,
"__ipairs"
,
1
,
ipairsaux
);
#else
luaL_checkany
(
L
,
1
);
lua_pushcfunction
(
L
,
ipairsaux
);
/* iteration function */
lua_pushvalue
(
L
,
1
);
/* state */
lua_pushinteger
(
L
,
0
);
/* initial value */
return
3
;
#endif
}
static
int
load_aux
(
lua_State
*
L
,
int
status
,
int
envidx
)
{
if
(
status
==
LUA_OK
)
{
if
(
envidx
!=
0
)
{
/* 'env' parameter? */
lua_pushvalue
(
L
,
envidx
);
/* environment for loaded function */
if
(
!
lua_setupvalue
(
L
,
-
2
,
1
))
/* set it as 1st upvalue */
lua_pop
(
L
,
1
);
/* remove 'env' if not used by previous call */
}
return
1
;
}
else
{
/* error (message is on top of the stack) */
lua_pushnil
(
L
);
lua_insert
(
L
,
-
2
);
/* put before error message */
return
2
;
/* return nil plus error message */
}
}
static
int
luaB_loadfile
(
lua_State
*
L
)
{
const
char
*
fname
=
luaL_optstring
(
L
,
1
,
NULL
);
const
char
*
mode
=
luaL_optstring
(
L
,
2
,
NULL
);
int
env
=
(
!
lua_isnone
(
L
,
3
)
?
3
:
0
);
/* 'env' index or 0 if no 'env' */
int
status
=
luaL_loadfilex
(
L
,
fname
,
mode
);
return
load_aux
(
L
,
status
,
env
);
}
/*
** {======================================================
** Generic Read function
** =======================================================
*/
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic 'load' function: 'lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static
const
char
*
generic_reader
(
lua_State
*
L
,
void
*
ud
,
size_t
*
size
)
{
(
void
)(
ud
);
/* not used */
luaL_checkstack
(
L
,
2
,
"too many nested functions"
);
lua_pushvalue
(
L
,
1
);
/* get function */
lua_call
(
L
,
0
,
1
);
/* call it */
if
(
lua_isnil
(
L
,
-
1
))
{
lua_pop
(
L
,
1
);
/* pop result */
*
size
=
0
;
return
NULL
;
}
else
if
(
!
lua_isstring
(
L
,
-
1
))
luaL_error
(
L
,
"reader function must return a string"
);
lua_replace
(
L
,
RESERVEDSLOT
);
/* save string in reserved slot */
return
lua_tolstring
(
L
,
RESERVEDSLOT
,
size
);
}
static
int
luaB_load
(
lua_State
*
L
)
{
int
status
;
size_t
l
;
const
char
*
s
=
lua_tolstring
(
L
,
1
,
&
l
);
const
char
*
mode
=
luaL_optstring
(
L
,
3
,
"bt"
);
int
env
=
(
!
lua_isnone
(
L
,
4
)
?
4
:
0
);
/* 'env' index or 0 if no 'env' */
if
(
s
!=
NULL
)
{
/* loading a string? */
const
char
*
chunkname
=
luaL_optstring
(
L
,
2
,
s
);
status
=
luaL_loadbufferx
(
L
,
s
,
l
,
chunkname
,
mode
);
}
else
{
/* loading from a reader function */
const
char
*
chunkname
=
luaL_optstring
(
L
,
2
,
"=(load)"
);
luaL_checktype
(
L
,
1
,
LUA_TFUNCTION
);
lua_settop
(
L
,
RESERVEDSLOT
);
/* create reserved slot */
status
=
lua_load
(
L
,
generic_reader
,
NULL
,
chunkname
,
mode
);
}
return
load_aux
(
L
,
status
,
env
);
}
/* }====================================================== */
static
int
dofilecont
(
lua_State
*
L
,
int
d1
,
lua_KContext
d2
)
{
(
void
)
d1
;
(
void
)
d2
;
/* only to match 'lua_Kfunction' prototype */
return
lua_gettop
(
L
)
-
1
;
}
static
int
luaB_dofile
(
lua_State
*
L
)
{
const
char
*
fname
=
luaL_optstring
(
L
,
1
,
NULL
);
lua_settop
(
L
,
1
);
if
(
luaL_loadfile
(
L
,
fname
)
!=
LUA_OK
)
return
lua_error
(
L
);
lua_callk
(
L
,
0
,
LUA_MULTRET
,
0
,
dofilecont
);
return
dofilecont
(
L
,
0
,
0
);
}
static
int
luaB_assert
(
lua_State
*
L
)
{
if
(
lua_toboolean
(
L
,
1
))
/* condition is true? */
return
lua_gettop
(
L
);
/* return all arguments */
else
{
/* error */
luaL_checkany
(
L
,
1
);
/* there must be a condition */
lua_remove
(
L
,
1
);
/* remove it */
lua_pushliteral
(
L
,
"assertion failed!"
);
/* default message */
lua_settop
(
L
,
1
);
/* leave only message (default if no other one) */
return
luaB_error
(
L
);
/* call 'error' */
}
}
static
int
luaB_select
(
lua_State
*
L
)
{
int
n
=
lua_gettop
(
L
);
if
(
lua_type
(
L
,
1
)
==
LUA_TSTRING
&&
*
lua_tostring
(
L
,
1
)
==
'#'
)
{
lua_pushinteger
(
L
,
n
-
1
);
return
1
;
}
else
{
lua_Integer
i
=
luaL_checkinteger
(
L
,
1
);
if
(
i
<
0
)
i
=
n
+
i
;
else
if
(
i
>
n
)
i
=
n
;
luaL_argcheck
(
L
,
1
<=
i
,
1
,
"index out of range"
);
return
n
-
(
int
)
i
;
}
}
/*
** Continuation function for 'pcall' and 'xpcall'. Both functions
** already pushed a 'true' before doing the call, so in case of success
** 'finishpcall' only has to return everything in the stack minus
** 'extra' values (where 'extra' is exactly the number of items to be
** ignored).
*/
static
int
finishpcall
(
lua_State
*
L
,
int
status
,
lua_KContext
extra
)
{
if
(
status
!=
LUA_OK
&&
status
!=
LUA_YIELD
)
{
/* error? */
lua_pushboolean
(
L
,
0
);
/* first result (false) */
lua_pushvalue
(
L
,
-
2
);
/* error message */
return
2
;
/* return false, msg */
}
else
return
lua_gettop
(
L
)
-
(
int
)
extra
;
/* return all results */
}
static
int
luaB_pcall
(
lua_State
*
L
)
{
int
status
;
luaL_checkany
(
L
,
1
);
lua_pushboolean
(
L
,
1
);
/* first result if no errors */
lua_insert
(
L
,
1
);
/* put it in place */
status
=
lua_pcallk
(
L
,
lua_gettop
(
L
)
-
2
,
LUA_MULTRET
,
0
,
0
,
finishpcall
);
return
finishpcall
(
L
,
status
,
0
);
}
/*
** Do a protected call with error handling. After 'lua_rotate', the
** stack will have <f, err, true, f, [args...]>; so, the function passes
** 2 to 'finishpcall' to skip the 2 first values when returning results.
*/
static
int
luaB_xpcall
(
lua_State
*
L
)
{
int
status
;
int
n
=
lua_gettop
(
L
);
luaL_checktype
(
L
,
2
,
LUA_TFUNCTION
);
/* check error function */
lua_pushboolean
(
L
,
1
);
/* first result */
lua_pushvalue
(
L
,
1
);
/* function */
lua_rotate
(
L
,
3
,
2
);
/* move them below function's arguments */
status
=
lua_pcallk
(
L
,
n
-
2
,
LUA_MULTRET
,
2
,
2
,
finishpcall
);
return
finishpcall
(
L
,
status
,
2
);
}
static
int
luaB_tostring
(
lua_State
*
L
)
{
luaL_checkany
(
L
,
1
);
luaL_tolstring
(
L
,
1
,
NULL
);
return
1
;
}
#if defined(LUA_COMPAT_UNPACK)
static
int
luaB_unpack
(
lua_State
*
L
)
{
int
n
=
lua_gettop
(
L
);
/* number of elements to pack */
lua_getglobal
(
L
,
"table"
);
lua_getfield
(
L
,
-
1
,
"unpack"
);
lua_insert
(
L
,
1
);
lua_pop
(
L
,
1
);
lua_call
(
L
,
n
,
LUA_MULTRET
);
return
lua_gettop
(
L
);
}
#endif
/*
** ESP builds use specific linker directives to marshal all the ROTable entries
** for the library modules including the base library into an entry vector in
** the PSECT ".lua_rotable" including the base library entries; this is bound
** into a ROTable in linit.c which then hooked into the __index metaentry for
** _G so that base library and ROM tables are directly resolved through _G.
**
** The host-based luac.cross builds which must use a standard GNU link or
** MSVC so this linker-specfic assembly approach can't be used. In this case
** luaopen_base returns a base_func ROTable so a two cascade resolution. See
** description in init.c for further details.
*/
#ifdef LUA_CROSS_COMPILER
LROT_BEGIN
(
base_func
,
NULL
,
0
)
#else
LROT_ENTRIES_IN_SECTION
(
base_func
,
rotable
)
#endif
LROT_FUNCENTRY
(
assert
,
luaB_assert
)
LROT_FUNCENTRY
(
collectgarbage
,
luaB_collectgarbage
)
LROT_FUNCENTRY
(
dofile
,
luaB_dofile
)
LROT_FUNCENTRY
(
error
,
luaB_error
)
LROT_FUNCENTRY
(
getmetatable
,
luaB_getmetatable
)
LROT_FUNCENTRY
(
ipairs
,
luaB_ipairs
)
LROT_FUNCENTRY
(
loadfile
,
luaB_loadfile
)
LROT_FUNCENTRY
(
load
,
luaB_load
)
#if defined(LUA_COMPAT_LOADSTRING)
LROT_FUNCENTRY
(
loadstring
,
luaB_load
)
#endif
LROT_FUNCENTRY
(
next
,
luaB_next
)
LROT_FUNCENTRY
(
pairs
,
luaB_pairs
)
LROT_FUNCENTRY
(
pcall
,
luaB_pcall
)
LROT_FUNCENTRY
(
print
,
luaB_print
)
LROT_FUNCENTRY
(
rawequal
,
luaB_rawequal
)
LROT_FUNCENTRY
(
rawlen
,
luaB_rawlen
)
LROT_FUNCENTRY
(
rawget
,
luaB_rawget
)
LROT_FUNCENTRY
(
rawset
,
luaB_rawset
)
LROT_FUNCENTRY
(
select
,
luaB_select
)
LROT_FUNCENTRY
(
setmetatable
,
luaB_setmetatable
)
LROT_FUNCENTRY
(
tonumber
,
luaB_tonumber
)
LROT_FUNCENTRY
(
tostring
,
luaB_tostring
)
LROT_FUNCENTRY
(
type
,
luaB_type
)
#if defined(LUA_COMPAT_UNPACK)
LROT_FUNCENTRY
(
unpack
,
luaB_unpack
)
#endif
LROT_FUNCENTRY
(
xpcall
,
luaB_xpcall
)
#ifdef LUA_CROSS_COMPILER
LROT_END
(
base_func
,
NULL
,
0
)
#else
LROT_BREAK
(
base_func
)
#endif
extern
LROT_TABLE
(
rotables
);
LUAMOD_API
int
luaopen_base
(
lua_State
*
L
)
{
lua_pushglobaltable
(
L
);
/* set global _G */
lua_pushliteral
(
L
,
LUA_VERSION
);
/* set global _VERSION */
lua_setfield
(
L
,
-
2
,
"_VERSION"
);
lua_createtable
(
L
,
0
,
1
);
/* mt for _G */
lua_pushrotable
(
L
,
LROT_TABLEREF
(
rotables
));
lua_setfield
(
L
,
-
2
,
"__index"
);
/* mt.__index=ROM table */
lua_setmetatable
(
L
,
-
2
);
return
1
;
/* returns _G */
}
components/lua/lua-5.3/lbitlib.c
0 → 100644
View file @
dba57fa0
/*
** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
#define lbitlib_c
#define LUA_LIB
#include "lprefix.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if defined(LUA_COMPAT_BITLIB)
/* { */
#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))
/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
#endif
/*
** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
** be made in two parts to avoid problems when LUA_NBITS is equal to the
** number of bits in a lua_Unsigned.)
*/
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
static
lua_Unsigned
andaux
(
lua_State
*
L
)
{
int
i
,
n
=
lua_gettop
(
L
);
lua_Unsigned
r
=
~
(
lua_Unsigned
)
0
;
for
(
i
=
1
;
i
<=
n
;
i
++
)
r
&=
checkunsigned
(
L
,
i
);
return
trim
(
r
);
}
static
int
b_and
(
lua_State
*
L
)
{
lua_Unsigned
r
=
andaux
(
L
);
pushunsigned
(
L
,
r
);
return
1
;
}
static
int
b_test
(
lua_State
*
L
)
{
lua_Unsigned
r
=
andaux
(
L
);
lua_pushboolean
(
L
,
r
!=
0
);
return
1
;
}
static
int
b_or
(
lua_State
*
L
)
{
int
i
,
n
=
lua_gettop
(
L
);
lua_Unsigned
r
=
0
;
for
(
i
=
1
;
i
<=
n
;
i
++
)
r
|=
checkunsigned
(
L
,
i
);
pushunsigned
(
L
,
trim
(
r
));
return
1
;
}
static
int
b_xor
(
lua_State
*
L
)
{
int
i
,
n
=
lua_gettop
(
L
);
lua_Unsigned
r
=
0
;
for
(
i
=
1
;
i
<=
n
;
i
++
)
r
^=
checkunsigned
(
L
,
i
);
pushunsigned
(
L
,
trim
(
r
));
return
1
;
}
static
int
b_not
(
lua_State
*
L
)
{
lua_Unsigned
r
=
~
checkunsigned
(
L
,
1
);
pushunsigned
(
L
,
trim
(
r
));
return
1
;
}
static
int
b_shift
(
lua_State
*
L
,
lua_Unsigned
r
,
lua_Integer
i
)
{
if
(
i
<
0
)
{
/* shift right? */
i
=
-
i
;
r
=
trim
(
r
);
if
(
i
>=
LUA_NBITS
)
r
=
0
;
else
r
>>=
i
;
}
else
{
/* shift left */
if
(
i
>=
LUA_NBITS
)
r
=
0
;
else
r
<<=
i
;
r
=
trim
(
r
);
}
pushunsigned
(
L
,
r
);
return
1
;
}
static
int
b_lshift
(
lua_State
*
L
)
{
return
b_shift
(
L
,
checkunsigned
(
L
,
1
),
luaL_checkinteger
(
L
,
2
));
}
static
int
b_rshift
(
lua_State
*
L
)
{
return
b_shift
(
L
,
checkunsigned
(
L
,
1
),
-
luaL_checkinteger
(
L
,
2
));
}
static
int
b_arshift
(
lua_State
*
L
)
{
lua_Unsigned
r
=
checkunsigned
(
L
,
1
);
lua_Integer
i
=
luaL_checkinteger
(
L
,
2
);
if
(
i
<
0
||
!
(
r
&
((
lua_Unsigned
)
1
<<
(
LUA_NBITS
-
1
))))
return
b_shift
(
L
,
r
,
-
i
);
else
{
/* arithmetic shift for 'negative' number */
if
(
i
>=
LUA_NBITS
)
r
=
ALLONES
;
else
r
=
trim
((
r
>>
i
)
|
~
(
trim
(
~
(
lua_Unsigned
)
0
)
>>
i
));
/* add signal bit */
pushunsigned
(
L
,
r
);
return
1
;
}
}
static
int
b_rot
(
lua_State
*
L
,
lua_Integer
d
)
{
lua_Unsigned
r
=
checkunsigned
(
L
,
1
);
int
i
=
d
&
(
LUA_NBITS
-
1
);
/* i = d % NBITS */
r
=
trim
(
r
);
if
(
i
!=
0
)
/* avoid undefined shift of LUA_NBITS when i == 0 */
r
=
(
r
<<
i
)
|
(
r
>>
(
LUA_NBITS
-
i
));
pushunsigned
(
L
,
trim
(
r
));
return
1
;
}
static
int
b_lrot
(
lua_State
*
L
)
{
return
b_rot
(
L
,
luaL_checkinteger
(
L
,
2
));
}
static
int
b_rrot
(
lua_State
*
L
)
{
return
b_rot
(
L
,
-
luaL_checkinteger
(
L
,
2
));
}
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static
int
fieldargs
(
lua_State
*
L
,
int
farg
,
int
*
width
)
{
lua_Integer
f
=
luaL_checkinteger
(
L
,
farg
);
lua_Integer
w
=
luaL_optinteger
(
L
,
farg
+
1
,
1
);
luaL_argcheck
(
L
,
0
<=
f
,
farg
,
"field cannot be negative"
);
luaL_argcheck
(
L
,
0
<
w
,
farg
+
1
,
"width must be positive"
);
if
(
f
+
w
>
LUA_NBITS
)
luaL_error
(
L
,
"trying to access non-existent bits"
);
*
width
=
(
int
)
w
;
return
(
int
)
f
;
}
static
int
b_extract
(
lua_State
*
L
)
{
int
w
;
lua_Unsigned
r
=
trim
(
checkunsigned
(
L
,
1
));
int
f
=
fieldargs
(
L
,
2
,
&
w
);
r
=
(
r
>>
f
)
&
mask
(
w
);
pushunsigned
(
L
,
r
);
return
1
;
}
static
int
b_replace
(
lua_State
*
L
)
{
int
w
;
lua_Unsigned
r
=
trim
(
checkunsigned
(
L
,
1
));
lua_Unsigned
v
=
trim
(
checkunsigned
(
L
,
2
));
int
f
=
fieldargs
(
L
,
3
,
&
w
);
lua_Unsigned
m
=
mask
(
w
);
r
=
(
r
&
~
(
m
<<
f
))
|
((
v
&
m
)
<<
f
);
pushunsigned
(
L
,
r
);
return
1
;
}
static
const
luaL_Reg
bitlib
[]
=
{
{
"arshift"
,
b_arshift
},
{
"band"
,
b_and
},
{
"bnot"
,
b_not
},
{
"bor"
,
b_or
},
{
"bxor"
,
b_xor
},
{
"btest"
,
b_test
},
{
"extract"
,
b_extract
},
{
"lrotate"
,
b_lrot
},
{
"lshift"
,
b_lshift
},
{
"replace"
,
b_replace
},
{
"rrotate"
,
b_rrot
},
{
"rshift"
,
b_rshift
},
{
NULL
,
NULL
}
};
LUAMOD_API
int
luaopen_bit32
(
lua_State
*
L
)
{
luaL_newlib
(
L
,
bitlib
);
return
0
;
}
#else
/* }{ */
LUAMOD_API
int
luaopen_bit32
(
lua_State
*
L
)
{
return
luaL_error
(
L
,
"library 'bit32' has been deprecated"
);
}
#endif
/* } */
Prev
1
2
3
4
5
6
7
8
9
…
12
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