Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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
Show 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
);
#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,9 +274,7 @@ 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_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
...
...
@@ -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
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
);
char
*
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
);
}
}
}
...
...
@@ -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
->
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
);
}
}
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) */
...
...
@@ -140,20 +138,11 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
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
++
;
...
...
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