mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 04:33:05 +00:00
Compare commits
142 Commits
v1.0.0-alp
...
v1.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2935ba3521 | ||
|
|
5c8ea6f09f | ||
|
|
c16ae57639 | ||
|
|
1c7d44fd4d | ||
|
|
e9cfdba22a | ||
|
|
704b016f2c | ||
|
|
3b48beb428 | ||
|
|
4cbead28d5 | ||
|
|
b3f966bcaa | ||
|
|
7b54e37d12 | ||
|
|
e87ac18b84 | ||
|
|
05af87ce8e | ||
|
|
0ee61de22c | ||
|
|
1da8a6b38d | ||
|
|
b2d8237363 | ||
|
|
39f9a96b6c | ||
|
|
588c4a3508 | ||
|
|
d6734890e0 | ||
|
|
4ebb139c2b | ||
|
|
20476d2280 | ||
|
|
3131bca6ef | ||
|
|
3f91484791 | ||
|
|
a0ecd51230 | ||
|
|
dba1db9cc4 | ||
|
|
538414408d | ||
|
|
4cf05fb2e7 | ||
|
|
d9ad981c8c | ||
|
|
21c941fe63 | ||
|
|
ea2437e138 | ||
|
|
86bbc9c701 | ||
|
|
95e1d9f45f | ||
|
|
55cf9375fc | ||
|
|
654f732cd5 | ||
|
|
d4023c8b63 | ||
|
|
375f8606b4 | ||
|
|
d17e6f59fe | ||
|
|
a77d36911d | ||
|
|
4352dc4047 | ||
|
|
172356be19 | ||
|
|
08dabd51c8 | ||
|
|
bd55a58515 | ||
|
|
b646a1b8a3 | ||
|
|
6b312fa09a | ||
|
|
dad66010cd | ||
|
|
27ae0a7500 | ||
|
|
6001d9c2eb | ||
|
|
728abeaeb8 | ||
|
|
2fa130997f | ||
|
|
8c57ec192a | ||
|
|
0fb2b21ed5 | ||
|
|
1fd2c3de81 | ||
|
|
f3536bfc53 | ||
|
|
57999456ef | ||
|
|
35b35f686c | ||
|
|
5d9142110e | ||
|
|
2086e13a46 | ||
|
|
f36b173155 | ||
|
|
7fa1d548ed | ||
|
|
039235b3a3 | ||
|
|
57d43a588e | ||
|
|
8214c53891 | ||
|
|
5e642b15a4 | ||
|
|
ac093c7142 | ||
|
|
01dcc45827 | ||
|
|
d3ac522dc6 | ||
|
|
55d0d57d5c | ||
|
|
1fec2e6063 | ||
|
|
cc4756de35 | ||
|
|
7fb109dbb0 | ||
|
|
7f578be649 | ||
|
|
69946d75c5 | ||
|
|
24f6994b50 | ||
|
|
07dbfd8651 | ||
|
|
ca50a5f518 | ||
|
|
b8c54cbac2 | ||
|
|
3a2c43e9e0 | ||
|
|
205824ab12 | ||
|
|
4ac047b274 | ||
|
|
987a90af8b | ||
|
|
250531c9a7 | ||
|
|
7b471ae27d | ||
|
|
4f93054f3a | ||
|
|
65fad89794 | ||
|
|
286c0f2c23 | ||
|
|
de57064b96 | ||
|
|
6c43e90708 | ||
|
|
1f25b79722 | ||
|
|
6a9080157f | ||
|
|
5cc2ef3ac8 | ||
|
|
3baeb62b0b | ||
|
|
9e27f59033 | ||
|
|
82fa2f979c | ||
|
|
07d7324332 | ||
|
|
d92adda2c9 | ||
|
|
0587400e2d | ||
|
|
35c8c63793 | ||
|
|
c7f5145e9e | ||
|
|
9452169f0a | ||
|
|
a15f43e0f8 | ||
|
|
0eb4754b31 | ||
|
|
f987ff8199 | ||
|
|
64a5d1ca24 | ||
|
|
fa17081012 | ||
|
|
856cb0737d | ||
|
|
f61e3f46e8 | ||
|
|
6b6b943b73 | ||
|
|
75d9b07158 | ||
|
|
8682f7f82f | ||
|
|
35a5b99bed | ||
|
|
98af25d109 | ||
|
|
cd3391461c | ||
|
|
e3b7f86075 | ||
|
|
86d5865457 | ||
|
|
7b783076e5 | ||
|
|
57c0ad694c | ||
|
|
f55a31c24f | ||
|
|
843095afc6 | ||
|
|
a6bad52181 | ||
|
|
012d98380d | ||
|
|
0298997d23 | ||
|
|
678a94bf71 | ||
|
|
03399e86a9 | ||
|
|
22364bac89 | ||
|
|
9188b5451c | ||
|
|
c7ed527911 | ||
|
|
5a1132101b | ||
|
|
ca33bf8b3e | ||
|
|
7d8c80c9a0 | ||
|
|
c6f993428e | ||
|
|
f6118b858d | ||
|
|
ec1bca238e | ||
|
|
6b87f159b4 | ||
|
|
41b447d41a | ||
|
|
c512b5f59a | ||
|
|
fc9b32b4bd | ||
|
|
36ed8679b8 | ||
|
|
a9b1993686 | ||
|
|
05b458ddb2 | ||
|
|
8d8add3710 | ||
|
|
65e7da9793 | ||
|
|
7e5d9b7399 | ||
|
|
92b7b7beff |
@@ -130,68 +130,68 @@ solaris:
|
|||||||
# DO NOT DELETE
|
# DO NOT DELETE
|
||||||
|
|
||||||
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
|
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
|
||||||
ltable.h lundump.h lvm.h
|
ltable.h lundump.h lvm.h
|
||||||
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
|
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
|
||||||
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||||
ldo.h lgc.h lstring.h ltable.h lvm.h
|
ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||||
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
|
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
|
||||||
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||||
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
|
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
|
||||||
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
|
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
|
||||||
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
|
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
|
||||||
lparser.h lstring.h ltable.h lundump.h lvm.h
|
lparser.h lstring.h ltable.h lundump.h lvm.h
|
||||||
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
|
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
|
||||||
ltm.h lzio.h lmem.h lundump.h
|
ltm.h lzio.h lmem.h lundump.h
|
||||||
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
|
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
|
||||||
lgc.h lstate.h ltm.h lzio.h lmem.h
|
lgc.h lstate.h ltm.h lzio.h lmem.h
|
||||||
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
|
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
|
||||||
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
|
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
|
||||||
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldo.h \
|
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
|
||||||
lobject.h lstate.h ltm.h lzio.h lmem.h lgc.h llex.h lparser.h lstring.h \
|
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
|
||||||
ltable.h
|
lstring.h ltable.h
|
||||||
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
|
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
|
||||||
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
|
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
|
||||||
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
|
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
|
||||||
lvm.h
|
lvm.h
|
||||||
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
|
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
|
||||||
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||||
ldo.h lfunc.h lstring.h lgc.h ltable.h
|
ldo.h lfunc.h lstring.h lgc.h ltable.h
|
||||||
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
|
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
|
||||||
lstring.h ltable.h
|
lstring.h ltable.h
|
||||||
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
|
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
|
||||||
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||||
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||||
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
|
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
|
||||||
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
|
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
|
||||||
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
|
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
|
||||||
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
|
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
|
||||||
lundump.h
|
lundump.h
|
||||||
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||||
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
|
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
|
||||||
ltable.h lvm.h
|
ltable.h lvm.h
|
||||||
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
|
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
|
||||||
lobject.h ltm.h lzio.h
|
lobject.h ltm.h lzio.h
|
||||||
|
|
||||||
# (end of Makefile)
|
# (end of Makefile)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
This is a modify version of lua 5.3.0 (http://www.lua.org/ftp/lua-5.3.0.tar.gz) .
|
This is a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
|
||||||
|
|
||||||
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||||
|
|
||||||
|
|||||||
126
3rd/lua/lapi.c
126
3rd/lua/lapi.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $
|
** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -52,29 +52,29 @@ const char lua_ident[] =
|
|||||||
/* test for valid but not pseudo index */
|
/* test for valid but not pseudo index */
|
||||||
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
|
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
|
||||||
|
|
||||||
#define api_checkvalidindex(o) api_check(isvalid(o), "invalid index")
|
#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index")
|
||||||
|
|
||||||
#define api_checkstackindex(i, o) \
|
#define api_checkstackindex(l, i, o) \
|
||||||
api_check(isstackindex(i, o), "index not in the stack")
|
api_check(l, isstackindex(i, o), "index not in the stack")
|
||||||
|
|
||||||
|
|
||||||
static TValue *index2addr (lua_State *L, int idx) {
|
static TValue *index2addr (lua_State *L, int idx) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
TValue *o = ci->func + idx;
|
TValue *o = ci->func + idx;
|
||||||
api_check(idx <= ci->top - (ci->func + 1), "unacceptable index");
|
api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
|
||||||
if (o >= L->top) return NONVALIDVALUE;
|
if (o >= L->top) return NONVALIDVALUE;
|
||||||
else return o;
|
else return o;
|
||||||
}
|
}
|
||||||
else if (!ispseudo(idx)) { /* negative index */
|
else if (!ispseudo(idx)) { /* negative index */
|
||||||
api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
|
api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
|
||||||
return L->top + idx;
|
return L->top + idx;
|
||||||
}
|
}
|
||||||
else if (idx == LUA_REGISTRYINDEX)
|
else if (idx == LUA_REGISTRYINDEX)
|
||||||
return &G(L)->l_registry;
|
return &G(L)->l_registry;
|
||||||
else { /* upvalues */
|
else { /* upvalues */
|
||||||
idx = LUA_REGISTRYINDEX - idx;
|
idx = LUA_REGISTRYINDEX - idx;
|
||||||
api_check(idx <= MAXUPVAL + 1, "upvalue index too large");
|
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
|
||||||
if (ttislcf(ci->func)) /* light C function? */
|
if (ttislcf(ci->func)) /* light C function? */
|
||||||
return NONVALIDVALUE; /* it has no upvalues */
|
return NONVALIDVALUE; /* it has no upvalues */
|
||||||
else {
|
else {
|
||||||
@@ -99,7 +99,7 @@ LUA_API int lua_checkstack (lua_State *L, int n) {
|
|||||||
int res;
|
int res;
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_check(n >= 0, "negative 'n'");
|
api_check(L, n >= 0, "negative 'n'");
|
||||||
if (L->stack_last - L->top > n) /* stack large enough? */
|
if (L->stack_last - L->top > n) /* stack large enough? */
|
||||||
res = 1; /* yes; check is OK */
|
res = 1; /* yes; check is OK */
|
||||||
else { /* no; need to grow stack */
|
else { /* no; need to grow stack */
|
||||||
@@ -121,11 +121,12 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
|
|||||||
if (from == to) return;
|
if (from == to) return;
|
||||||
lua_lock(to);
|
lua_lock(to);
|
||||||
api_checknelems(from, n);
|
api_checknelems(from, n);
|
||||||
api_check(G(from) == G(to), "moving among independent states");
|
api_check(from, G(from) == G(to), "moving among independent states");
|
||||||
api_check(to->ci->top - to->top >= n, "not enough elements to move");
|
api_check(from, to->ci->top - to->top >= n, "not enough elements to move");
|
||||||
from->top -= n;
|
from->top -= n;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
setobj2s(to, to->top++, from->top + i);
|
setobj2s(to, to->top, from->top + i);
|
||||||
|
api_incr_top(to);
|
||||||
}
|
}
|
||||||
lua_unlock(to);
|
lua_unlock(to);
|
||||||
}
|
}
|
||||||
@@ -160,7 +161,7 @@ LUA_API const lua_Number *lua_version (lua_State *L) {
|
|||||||
LUA_API int lua_absindex (lua_State *L, int idx) {
|
LUA_API int lua_absindex (lua_State *L, int idx) {
|
||||||
return (idx > 0 || ispseudo(idx))
|
return (idx > 0 || ispseudo(idx))
|
||||||
? idx
|
? idx
|
||||||
: cast_int(L->top - L->ci->func + idx);
|
: cast_int(L->top - L->ci->func) + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,13 +174,13 @@ LUA_API void lua_settop (lua_State *L, int idx) {
|
|||||||
StkId func = L->ci->func;
|
StkId func = L->ci->func;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
api_check(idx <= L->stack_last - (func + 1), "new top too large");
|
api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
|
||||||
while (L->top < (func + 1) + idx)
|
while (L->top < (func + 1) + idx)
|
||||||
setnilvalue(L->top++);
|
setnilvalue(L->top++);
|
||||||
L->top = (func + 1) + idx;
|
L->top = (func + 1) + idx;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top");
|
api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
|
||||||
L->top += idx+1; /* 'subtract' index (index is negative) */
|
L->top += idx+1; /* 'subtract' index (index is negative) */
|
||||||
}
|
}
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -209,8 +210,8 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = L->top - 1; /* end of stack segment being rotated */
|
t = L->top - 1; /* end of stack segment being rotated */
|
||||||
p = index2addr(L, idx); /* start of segment */
|
p = index2addr(L, idx); /* start of segment */
|
||||||
api_checkstackindex(idx, p);
|
api_checkstackindex(L, idx, p);
|
||||||
api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
|
api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
|
||||||
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
|
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
|
||||||
reverse(L, p, m); /* reverse the prefix with length 'n' */
|
reverse(L, p, m); /* reverse the prefix with length 'n' */
|
||||||
reverse(L, m + 1, t); /* reverse the suffix */
|
reverse(L, m + 1, t); /* reverse the suffix */
|
||||||
@@ -224,7 +225,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
fr = index2addr(L, fromidx);
|
fr = index2addr(L, fromidx);
|
||||||
to = index2addr(L, toidx);
|
to = index2addr(L, toidx);
|
||||||
api_checkvalidindex(to);
|
api_checkvalidindex(L, to);
|
||||||
setobj(L, to, fr);
|
setobj(L, to, fr);
|
||||||
if (isupvalue(toidx)) /* function upvalue? */
|
if (isupvalue(toidx)) /* function upvalue? */
|
||||||
luaC_barrier(L, clCvalue(L->ci->func), fr);
|
luaC_barrier(L, clCvalue(L->ci->func), fr);
|
||||||
@@ -256,7 +257,7 @@ LUA_API int lua_type (lua_State *L, int idx) {
|
|||||||
|
|
||||||
LUA_API const char *lua_typename (lua_State *L, int t) {
|
LUA_API const char *lua_typename (lua_State *L, int t) {
|
||||||
UNUSED(L);
|
UNUSED(L);
|
||||||
api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
|
api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
|
||||||
return ttypename(t);
|
return ttypename(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ LUA_API void lua_arith (lua_State *L, int op) {
|
|||||||
else { /* for unary operations, add fake 2nd operand */
|
else { /* for unary operations, add fake 2nd operand */
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
setobjs2s(L, L->top, L->top - 1);
|
setobjs2s(L, L->top, L->top - 1);
|
||||||
L->top++;
|
api_incr_top(L);
|
||||||
}
|
}
|
||||||
/* first operand at top - 2, second at top - 1; result go to top - 2 */
|
/* 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);
|
luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
|
||||||
@@ -326,7 +327,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
|
|||||||
case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
|
case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
|
||||||
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
|
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
|
||||||
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
|
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
|
||||||
default: api_check(0, "invalid option");
|
default: api_check(L, 0, "invalid option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -383,15 +384,17 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
|||||||
luaO_tostring(L, o);
|
luaO_tostring(L, o);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
if (len != NULL) *len = tsvalue(o)->len;
|
if (len != NULL)
|
||||||
|
*len = vslen(o);
|
||||||
return svalue(o);
|
return svalue(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
|
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
|
||||||
StkId o = index2addr(L, idx);
|
StkId o = index2addr(L, idx);
|
||||||
switch (ttnov(o)) {
|
switch (ttype(o)) {
|
||||||
case LUA_TSTRING: return tsvalue(o)->len;
|
case LUA_TSHRSTR: return tsvalue(o)->shrlen;
|
||||||
|
case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
|
||||||
case LUA_TUSERDATA: return uvalue(o)->len;
|
case LUA_TUSERDATA: return uvalue(o)->len;
|
||||||
case LUA_TTABLE: return luaH_getn(hvalue(o));
|
case LUA_TTABLE: return luaH_getn(hvalue(o));
|
||||||
default: return 0;
|
default: return 0;
|
||||||
@@ -432,9 +435,8 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
|||||||
case LUA_TCCL: return clCvalue(o);
|
case LUA_TCCL: return clCvalue(o);
|
||||||
case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
|
case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
|
||||||
case LUA_TTHREAD: return thvalue(o);
|
case LUA_TTHREAD: return thvalue(o);
|
||||||
case LUA_TUSERDATA:
|
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
||||||
case LUA_TLIGHTUSERDATA:
|
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
||||||
return lua_touserdata(L, idx);
|
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,20 +485,19 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
|
|||||||
|
|
||||||
|
|
||||||
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
|
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
|
||||||
if (s == NULL) {
|
lua_lock(L);
|
||||||
lua_pushnil(L);
|
if (s == NULL)
|
||||||
return NULL;
|
setnilvalue(L->top);
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
lua_lock(L);
|
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
ts = luaS_new(L, s);
|
ts = luaS_new(L, s);
|
||||||
setsvalue2s(L, L->top, ts);
|
setsvalue2s(L, L->top, ts);
|
||||||
api_incr_top(L);
|
s = getstr(ts); /* internal copy's address */
|
||||||
lua_unlock(L);
|
|
||||||
return getstr(ts);
|
|
||||||
}
|
}
|
||||||
|
api_incr_top(L);
|
||||||
|
lua_unlock(L);
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -532,7 +533,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
|||||||
else {
|
else {
|
||||||
CClosure *cl;
|
CClosure *cl;
|
||||||
api_checknelems(L, n);
|
api_checknelems(L, n);
|
||||||
api_check(n <= MAXUPVAL, "upvalue index too large");
|
api_check(L, n <= MAXUPVAL, "upvalue index too large");
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
cl = luaF_newCclosure(L, n);
|
cl = luaF_newCclosure(L, n);
|
||||||
cl->f = fn;
|
cl->f = fn;
|
||||||
@@ -584,7 +585,8 @@ LUA_API int lua_getglobal (lua_State *L, const char *name) {
|
|||||||
const TValue *gt; /* global table */
|
const TValue *gt; /* global table */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
|
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
|
||||||
setsvalue2s(L, L->top++, luaS_new(L, name));
|
setsvalue2s(L, L->top, luaS_new(L, name));
|
||||||
|
api_incr_top(L);
|
||||||
luaV_gettable(L, gt, L->top - 1, L->top - 1);
|
luaV_gettable(L, gt, L->top - 1, L->top - 1);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return ttnov(L->top - 1);
|
return ttnov(L->top - 1);
|
||||||
@@ -629,7 +631,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) {
|
|||||||
StkId t;
|
StkId t;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
api_check(ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return ttnov(L->top - 1);
|
return ttnov(L->top - 1);
|
||||||
@@ -640,7 +642,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
StkId t;
|
StkId t;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
api_check(ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
|
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -653,7 +655,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
|
|||||||
TValue k;
|
TValue k;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
api_check(ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setpvalue(&k, cast(void *, p));
|
setpvalue(&k, cast(void *, p));
|
||||||
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
|
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
@@ -706,7 +708,7 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
|
|||||||
StkId o;
|
StkId o;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
o = index2addr(L, idx);
|
o = index2addr(L, idx);
|
||||||
api_check(ttisfulluserdata(o), "full userdata expected");
|
api_check(L, ttisfulluserdata(o), "full userdata expected");
|
||||||
getuservalue(L, uvalue(o), L->top);
|
getuservalue(L, uvalue(o), L->top);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -725,7 +727,8 @@ LUA_API void lua_setglobal (lua_State *L, const char *name) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
|
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
|
||||||
setsvalue2s(L, L->top++, luaS_new(L, name));
|
setsvalue2s(L, L->top, luaS_new(L, name));
|
||||||
|
api_incr_top(L);
|
||||||
luaV_settable(L, gt, L->top - 1, L->top - 2);
|
luaV_settable(L, gt, L->top - 1, L->top - 2);
|
||||||
L->top -= 2; /* pop value and key */
|
L->top -= 2; /* pop value and key */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -748,7 +751,8 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
setsvalue2s(L, L->top++, luaS_new(L, k));
|
setsvalue2s(L, L->top, luaS_new(L, k));
|
||||||
|
api_incr_top(L);
|
||||||
luaV_settable(L, t, L->top - 1, L->top - 2);
|
luaV_settable(L, t, L->top - 1, L->top - 2);
|
||||||
L->top -= 2; /* pop value and key */
|
L->top -= 2; /* pop value and key */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -760,7 +764,8 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
setivalue(L->top++, n);
|
setivalue(L->top, n);
|
||||||
|
api_incr_top(L);
|
||||||
luaV_settable(L, t, L->top - 1, L->top - 2);
|
luaV_settable(L, t, L->top - 1, L->top - 2);
|
||||||
L->top -= 2; /* pop value and key */
|
L->top -= 2; /* pop value and key */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
@@ -773,7 +778,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 2);
|
api_checknelems(L, 2);
|
||||||
o = index2addr(L, idx);
|
o = index2addr(L, idx);
|
||||||
api_check(ttistable(o), "table expected");
|
api_check(L, ttistable(o), "table expected");
|
||||||
t = hvalue(o);
|
t = hvalue(o);
|
||||||
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
|
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
|
||||||
invalidateTMcache(t);
|
invalidateTMcache(t);
|
||||||
@@ -789,7 +794,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
o = index2addr(L, idx);
|
o = index2addr(L, idx);
|
||||||
api_check(ttistable(o), "table expected");
|
api_check(L, ttistable(o), "table expected");
|
||||||
t = hvalue(o);
|
t = hvalue(o);
|
||||||
luaH_setint(L, t, n, L->top - 1);
|
luaH_setint(L, t, n, L->top - 1);
|
||||||
luaC_barrierback(L, t, L->top-1);
|
luaC_barrierback(L, t, L->top-1);
|
||||||
@@ -805,7 +810,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
o = index2addr(L, idx);
|
o = index2addr(L, idx);
|
||||||
api_check(ttistable(o), "table expected");
|
api_check(L, ttistable(o), "table expected");
|
||||||
t = hvalue(o);
|
t = hvalue(o);
|
||||||
setpvalue(&k, cast(void *, p));
|
setpvalue(&k, cast(void *, p));
|
||||||
setobj2t(L, luaH_set(L, t, &k), L->top - 1);
|
setobj2t(L, luaH_set(L, t, &k), L->top - 1);
|
||||||
@@ -824,7 +829,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
|||||||
if (ttisnil(L->top - 1))
|
if (ttisnil(L->top - 1))
|
||||||
mt = NULL;
|
mt = NULL;
|
||||||
else {
|
else {
|
||||||
api_check(ttistable(L->top - 1), "table expected");
|
api_check(L, ttistable(L->top - 1), "table expected");
|
||||||
mt = hvalue(L->top - 1);
|
mt = hvalue(L->top - 1);
|
||||||
}
|
}
|
||||||
switch (ttnov(obj)) {
|
switch (ttnov(obj)) {
|
||||||
@@ -860,7 +865,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
o = index2addr(L, idx);
|
o = index2addr(L, idx);
|
||||||
api_check(ttisfulluserdata(o), "full userdata expected");
|
api_check(L, ttisfulluserdata(o), "full userdata expected");
|
||||||
setuservalue(L, uvalue(o), L->top - 1);
|
setuservalue(L, uvalue(o), L->top - 1);
|
||||||
luaC_barrier(L, gcvalue(o), L->top - 1);
|
luaC_barrier(L, gcvalue(o), L->top - 1);
|
||||||
L->top--;
|
L->top--;
|
||||||
@@ -874,7 +879,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
|
|||||||
|
|
||||||
|
|
||||||
#define checkresults(L,na,nr) \
|
#define checkresults(L,na,nr) \
|
||||||
api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
|
api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
|
||||||
"results from function overflow current stack size")
|
"results from function overflow current stack size")
|
||||||
|
|
||||||
|
|
||||||
@@ -882,10 +887,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
|
|||||||
lua_KContext ctx, lua_KFunction k) {
|
lua_KContext ctx, lua_KFunction k) {
|
||||||
StkId func;
|
StkId func;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_check(k == NULL || !isLua(L->ci),
|
api_check(L, k == NULL || !isLua(L->ci),
|
||||||
"cannot use continuations inside hooks");
|
"cannot use continuations inside hooks");
|
||||||
api_checknelems(L, nargs+1);
|
api_checknelems(L, nargs+1);
|
||||||
api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
|
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
|
||||||
checkresults(L, nargs, nresults);
|
checkresults(L, nargs, nresults);
|
||||||
func = L->top - (nargs+1);
|
func = L->top - (nargs+1);
|
||||||
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
|
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
|
||||||
@@ -923,16 +928,16 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
|
|||||||
int status;
|
int status;
|
||||||
ptrdiff_t func;
|
ptrdiff_t func;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_check(k == NULL || !isLua(L->ci),
|
api_check(L, k == NULL || !isLua(L->ci),
|
||||||
"cannot use continuations inside hooks");
|
"cannot use continuations inside hooks");
|
||||||
api_checknelems(L, nargs+1);
|
api_checknelems(L, nargs+1);
|
||||||
api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
|
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
|
||||||
checkresults(L, nargs, nresults);
|
checkresults(L, nargs, nresults);
|
||||||
if (errfunc == 0)
|
if (errfunc == 0)
|
||||||
func = 0;
|
func = 0;
|
||||||
else {
|
else {
|
||||||
StkId o = index2addr(L, errfunc);
|
StkId o = index2addr(L, errfunc);
|
||||||
api_checkstackindex(errfunc, o);
|
api_checkstackindex(L, errfunc, o);
|
||||||
func = savestack(L, o);
|
func = savestack(L, o);
|
||||||
}
|
}
|
||||||
c.func = L->top - (nargs+1); /* function to be called */
|
c.func = L->top - (nargs+1); /* function to be called */
|
||||||
@@ -984,7 +989,6 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Proto * cloneproto (lua_State *L, const Proto *src) {
|
static Proto * cloneproto (lua_State *L, const Proto *src) {
|
||||||
/* copy constants and nested proto */
|
/* copy constants and nested proto */
|
||||||
int i,n;
|
int i,n;
|
||||||
@@ -996,7 +1000,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
|
|||||||
const TValue *s=&src->k[i];
|
const TValue *s=&src->k[i];
|
||||||
TValue *o=&f->k[i];
|
TValue *o=&f->k[i];
|
||||||
if (ttisstring(s)) {
|
if (ttisstring(s)) {
|
||||||
TString * str = luaS_newlstr(L,svalue(s),tsvalue(s)->len);
|
TString * str = luaS_newlstr(L,svalue(s),vslen(s));
|
||||||
setsvalue2n(L,o,str);
|
setsvalue2n(L,o,str);
|
||||||
} else {
|
} else {
|
||||||
setobj(L,o,s);
|
setobj(L,o,s);
|
||||||
@@ -1150,7 +1154,7 @@ LUA_API int lua_next (lua_State *L, int idx) {
|
|||||||
int more;
|
int more;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
api_check(ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
more = luaH_next(L, hvalue(t), L->top - 1);
|
more = luaH_next(L, hvalue(t), L->top - 1);
|
||||||
if (more) {
|
if (more) {
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
@@ -1282,9 +1286,9 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
|
|||||||
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
|
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
|
||||||
LClosure *f;
|
LClosure *f;
|
||||||
StkId fi = index2addr(L, fidx);
|
StkId fi = index2addr(L, fidx);
|
||||||
api_check(ttisLclosure(fi), "Lua function expected");
|
api_check(L, ttisLclosure(fi), "Lua function expected");
|
||||||
f = clLvalue(fi);
|
f = clLvalue(fi);
|
||||||
api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
|
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
|
||||||
if (pf) *pf = f;
|
if (pf) *pf = f;
|
||||||
return &f->upvals[n - 1]; /* get its upvalue pointer */
|
return &f->upvals[n - 1]; /* get its upvalue pointer */
|
||||||
}
|
}
|
||||||
@@ -1298,11 +1302,11 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
|
|||||||
}
|
}
|
||||||
case LUA_TCCL: { /* C closure */
|
case LUA_TCCL: { /* C closure */
|
||||||
CClosure *f = clCvalue(fi);
|
CClosure *f = clCvalue(fi);
|
||||||
api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index");
|
api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
|
||||||
return &f->upvalue[n - 1];
|
return &f->upvalue[n - 1];
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
api_check(0, "closure expected");
|
api_check(L, 0, "closure expected");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $
|
** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
|
||||||
** Auxiliary functions from Lua API
|
** Auxiliary functions from Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -11,13 +11,13 @@
|
|||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
||||||
#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \
|
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||||
"stack overflow");}
|
"stack overflow");}
|
||||||
|
|
||||||
#define adjustresults(L,nres) \
|
#define adjustresults(L,nres) \
|
||||||
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||||
|
|
||||||
#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \
|
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||||
"not enough elements in the stack")
|
"not enough elements in the stack")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $
|
** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 roberto Exp $
|
||||||
** Auxiliary functions for building Lua libraries
|
** Auxiliary functions for building Lua libraries
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -286,7 +286,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
||||||
if (luaL_getmetatable(L, tname)) /* name already in use? */
|
if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
|
||||||
return 0; /* leave previous value on top, but return 0 */
|
return 0; /* leave previous value on top, but return 0 */
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_newtable(L); /* create metatable */
|
lua_newtable(L); /* create metatable */
|
||||||
@@ -1089,4 +1089,4 @@ LUAMOD_API int luaopen_cache(lua_State *L) {
|
|||||||
lua_getglobal(L, "loadfile");
|
lua_getglobal(L, "loadfile");
|
||||||
lua_setfield(L, -2, "loadfile");
|
lua_setfield(L, -2, "loadfile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $
|
** $Id: lbaselib.c,v 1.310 2015/03/28 19:14:47 roberto Exp $
|
||||||
** Basic library
|
** Basic library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -55,7 +55,7 @@ static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
do {
|
do {
|
||||||
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
||||||
: toupper((unsigned char)*s) - 'A' + 10;
|
: (toupper((unsigned char)*s) - 'A') + 10;
|
||||||
if (digit >= base) return NULL; /* invalid numeral */
|
if (digit >= base) return NULL; /* invalid numeral */
|
||||||
n = n * base + digit;
|
n = n * base + digit;
|
||||||
s++;
|
s++;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $
|
** $Id: lcode.c,v 2.101 2015/04/29 18:24:11 roberto Exp $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
#include "lvm.h"
|
#include "lvm.h"
|
||||||
|
|
||||||
|
|
||||||
/* Maximum number of registers in a Lua function */
|
/* Maximum number of registers in a Lua function (must fit in 8 bits) */
|
||||||
#define MAXREGS 250
|
#define MAXREGS 255
|
||||||
|
|
||||||
|
|
||||||
#define hasjumps(e) ((e)->t != (e)->f)
|
#define hasjumps(e) ((e)->t != (e)->f)
|
||||||
@@ -279,7 +279,8 @@ void luaK_checkstack (FuncState *fs, int n) {
|
|||||||
int newstack = fs->freereg + n;
|
int newstack = fs->freereg + n;
|
||||||
if (newstack > fs->f->sp->maxstacksize) {
|
if (newstack > fs->f->sp->maxstacksize) {
|
||||||
if (newstack >= MAXREGS)
|
if (newstack >= MAXREGS)
|
||||||
luaX_syntaxerror(fs->ls, "function or expression too complex");
|
luaX_syntaxerror(fs->ls,
|
||||||
|
"function or expression needs too many registers");
|
||||||
fs->f->sp->maxstacksize = cast_byte(newstack);
|
fs->f->sp->maxstacksize = cast_byte(newstack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,8 +574,8 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
|||||||
case VKFLT: {
|
case VKFLT: {
|
||||||
e->u.info = luaK_numberK(fs, e->u.nval);
|
e->u.info = luaK_numberK(fs, e->u.nval);
|
||||||
e->k = VK;
|
e->k = VK;
|
||||||
/* go through */
|
|
||||||
}
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
case VK: {
|
case VK: {
|
||||||
vk:
|
vk:
|
||||||
if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
|
if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
|
||||||
@@ -793,7 +794,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
|
|||||||
static void codeexpval (FuncState *fs, OpCode op,
|
static void codeexpval (FuncState *fs, OpCode op,
|
||||||
expdesc *e1, expdesc *e2, int line) {
|
expdesc *e1, expdesc *e2, int line) {
|
||||||
lua_assert(op >= OP_ADD);
|
lua_assert(op >= OP_ADD);
|
||||||
if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2))
|
if (op <= OP_BNOT && constfolding(fs, (op - OP_ADD) + LUA_OPADD, e1, e2))
|
||||||
return; /* result has been folded */
|
return; /* result has been folded */
|
||||||
else {
|
else {
|
||||||
int o1, o2;
|
int o1, o2;
|
||||||
@@ -920,11 +921,11 @@ void luaK_posfix (FuncState *fs, BinOpr op,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPR_EQ: case OPR_LT: case OPR_LE: {
|
case OPR_EQ: case OPR_LT: case OPR_LE: {
|
||||||
codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
|
codecomp(fs, cast(OpCode, (op - OPR_EQ) + OP_EQ), 1, e1, e2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPR_NE: case OPR_GT: case OPR_GE: {
|
case OPR_NE: case OPR_GT: case OPR_GE: {
|
||||||
codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
|
codecomp(fs, cast(OpCode, (op - OPR_NE) + OP_EQ), 0, e1, e2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp $
|
** $Id: ldblib.c,v 1.149 2015/02/19 17:06:21 roberto Exp $
|
||||||
** Interface from Lua to its debug API
|
** Interface from Lua to its debug API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +27,17 @@
|
|||||||
static const int HOOKKEY = 0;
|
static const int HOOKKEY = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If L1 != L, L1 can be in any state, and therefore there is no
|
||||||
|
** garanties about its stack space; any push in L1 must be
|
||||||
|
** checked.
|
||||||
|
*/
|
||||||
|
static void checkstack (lua_State *L, lua_State *L1, int n) {
|
||||||
|
if (L != L1 && !lua_checkstack(L1, n))
|
||||||
|
luaL_error(L, "stack overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int db_getregistry (lua_State *L) {
|
static int db_getregistry (lua_State *L) {
|
||||||
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -127,12 +138,16 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Calls 'lua_getinfo' and collects all results in a new table.
|
** Calls 'lua_getinfo' and collects all results in a new table.
|
||||||
|
** L1 needs stack space for an optional input (function) plus
|
||||||
|
** two optional outputs (function and line table) from function
|
||||||
|
** 'lua_getinfo'.
|
||||||
*/
|
*/
|
||||||
static int db_getinfo (lua_State *L) {
|
static int db_getinfo (lua_State *L) {
|
||||||
lua_Debug ar;
|
lua_Debug ar;
|
||||||
int arg;
|
int arg;
|
||||||
lua_State *L1 = getthread(L, &arg);
|
lua_State *L1 = getthread(L, &arg);
|
||||||
const char *options = luaL_optstring(L, arg+2, "flnStu");
|
const char *options = luaL_optstring(L, arg+2, "flnStu");
|
||||||
|
checkstack(L, L1, 3);
|
||||||
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
|
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
|
||||||
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
|
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
|
||||||
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
|
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
|
||||||
@@ -190,6 +205,7 @@ static int db_getlocal (lua_State *L) {
|
|||||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||||
if (!lua_getstack(L1, level, &ar)) /* out of range? */
|
if (!lua_getstack(L1, level, &ar)) /* out of range? */
|
||||||
return luaL_argerror(L, arg+1, "level out of range");
|
return luaL_argerror(L, arg+1, "level out of range");
|
||||||
|
checkstack(L, L1, 1);
|
||||||
name = lua_getlocal(L1, &ar, nvar);
|
name = lua_getlocal(L1, &ar, nvar);
|
||||||
if (name) {
|
if (name) {
|
||||||
lua_xmove(L1, L, 1); /* move local value */
|
lua_xmove(L1, L, 1); /* move local value */
|
||||||
@@ -216,6 +232,7 @@ static int db_setlocal (lua_State *L) {
|
|||||||
return luaL_argerror(L, arg+1, "level out of range");
|
return luaL_argerror(L, arg+1, "level out of range");
|
||||||
luaL_checkany(L, arg+3);
|
luaL_checkany(L, arg+3);
|
||||||
lua_settop(L, arg+3);
|
lua_settop(L, arg+3);
|
||||||
|
checkstack(L, L1, 1);
|
||||||
lua_xmove(L, L1, 1);
|
lua_xmove(L, L1, 1);
|
||||||
name = lua_setlocal(L1, &ar, nvar);
|
name = lua_setlocal(L1, &ar, nvar);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
@@ -350,6 +367,7 @@ static int db_sethook (lua_State *L) {
|
|||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
|
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
|
||||||
}
|
}
|
||||||
|
checkstack(L, L1, 1);
|
||||||
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
|
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
|
||||||
lua_pushvalue(L, arg + 1); /* value (hook function) */
|
lua_pushvalue(L, arg + 1); /* value (hook function) */
|
||||||
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
|
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
|
||||||
@@ -370,6 +388,7 @@ static int db_gethook (lua_State *L) {
|
|||||||
lua_pushliteral(L, "external hook");
|
lua_pushliteral(L, "external hook");
|
||||||
else { /* hook table must exist */
|
else { /* hook table must exist */
|
||||||
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
|
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
|
||||||
|
checkstack(L, L1, 1);
|
||||||
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
||||||
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
|
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
|
||||||
lua_remove(L, -2); /* remove hook table */
|
lua_remove(L, -2); /* remove hook table */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp $
|
** $Id: ldebug.c,v 2.115 2015/05/22 17:45:56 roberto Exp $
|
||||||
** Debug Interface
|
** Debug Interface
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +34,10 @@
|
|||||||
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
|
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
|
||||||
|
|
||||||
|
|
||||||
|
/* Active Lua function (given call info) */
|
||||||
|
#define ci_func(ci) (clLvalue((ci)->func))
|
||||||
|
|
||||||
|
|
||||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
|
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +126,7 @@ static const char *upvalname (Proto *p, int uv) {
|
|||||||
|
|
||||||
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
|
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
|
||||||
int nparams = clLvalue(ci->func)->p->sp->numparams;
|
int nparams = clLvalue(ci->func)->p->sp->numparams;
|
||||||
if (n >= ci->u.l.base - ci->func - nparams)
|
if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
|
||||||
return NULL; /* no such vararg */
|
return NULL; /* no such vararg */
|
||||||
else {
|
else {
|
||||||
*pos = ci->func + nparams + n;
|
*pos = ci->func + nparams + n;
|
||||||
@@ -168,7 +172,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
|||||||
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
|
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
|
||||||
}
|
}
|
||||||
else { /* active function; get information through 'ar' */
|
else { /* active function; get information through 'ar' */
|
||||||
StkId pos = 0; /* to avoid warnings */
|
StkId pos = NULL; /* to avoid warnings */
|
||||||
name = findlocal(L, ar->i_ci, n, &pos);
|
name = findlocal(L, ar->i_ci, n, &pos);
|
||||||
if (name) {
|
if (name) {
|
||||||
setobj2s(L, L->top, pos);
|
setobj2s(L, L->top, pos);
|
||||||
@@ -182,7 +186,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
|||||||
|
|
||||||
|
|
||||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||||
StkId pos = 0; /* to avoid warnings */
|
StkId pos = NULL; /* to avoid warnings */
|
||||||
const char *name;
|
const char *name;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
swapextra(L);
|
swapextra(L);
|
||||||
@@ -295,7 +299,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
|||||||
if (*what == '>') {
|
if (*what == '>') {
|
||||||
ci = NULL;
|
ci = NULL;
|
||||||
func = L->top - 1;
|
func = L->top - 1;
|
||||||
api_check(ttisfunction(func), "function expected");
|
api_check(L, ttisfunction(func), "function expected");
|
||||||
what++; /* skip the '>' */
|
what++; /* skip the '>' */
|
||||||
L->top--; /* pop function */
|
L->top--; /* pop function */
|
||||||
}
|
}
|
||||||
@@ -595,19 +599,16 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void addinfo (lua_State *L, const char *msg) {
|
/* add src:line information to 'msg' */
|
||||||
CallInfo *ci = L->ci;
|
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
|
||||||
if (isLua(ci)) { /* is Lua code? */
|
int line) {
|
||||||
char buff[LUA_IDSIZE]; /* add file:line information */
|
char buff[LUA_IDSIZE];
|
||||||
int line = currentline(ci);
|
if (src)
|
||||||
TString *src = ci_func(ci)->p->sp->source;
|
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
|
||||||
if (src)
|
else { /* no source available; use "?" instead */
|
||||||
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
|
buff[0] = '?'; buff[1] = '\0';
|
||||||
else { /* no source available; use "?" instead */
|
|
||||||
buff[0] = '?'; buff[1] = '\0';
|
|
||||||
}
|
|
||||||
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
|
||||||
}
|
}
|
||||||
|
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -624,10 +625,14 @@ l_noret luaG_errormsg (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||||
|
CallInfo *ci = L->ci;
|
||||||
|
const char *msg;
|
||||||
va_list argp;
|
va_list argp;
|
||||||
va_start(argp, fmt);
|
va_start(argp, fmt);
|
||||||
addinfo(L, luaO_pushvfstring(L, fmt, argp));
|
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
|
||||||
va_end(argp);
|
va_end(argp);
|
||||||
|
if (isLua(ci)) /* if Lua function, add source:line information */
|
||||||
|
luaG_addinfo(L, msg, ci_func(ci)->p->sp->source, currentline(ci));
|
||||||
luaG_errormsg(L);
|
luaG_errormsg(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldebug.h,v 2.12 2014/11/10 14:46:05 roberto Exp $
|
** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
|
||||||
** Auxiliary functions from Debug Interface module
|
** Auxiliary functions from Debug Interface module
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||||
|
|
||||||
/* Active Lua function (given call info) */
|
|
||||||
#define ci_func(ci) (clLvalue((ci)->func))
|
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
||||||
const char *opname);
|
const char *opname);
|
||||||
@@ -33,6 +30,8 @@ LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
|
|||||||
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
||||||
const TValue *p2);
|
const TValue *p2);
|
||||||
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||||
|
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
||||||
|
TString *src, int line);
|
||||||
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||||
LUAI_FUNC void luaG_traceexec (lua_State *L);
|
LUAI_FUNC void luaG_traceexec (lua_State *L);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.135 2014/11/11 17:13:39 roberto Exp $
|
** $Id: ldo.c,v 2.138 2015/05/22 17:48:19 roberto Exp $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -323,6 +323,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
case LUA_TCCL: { /* C closure */
|
case LUA_TCCL: { /* C closure */
|
||||||
f = clCvalue(func)->f;
|
f = clCvalue(func)->f;
|
||||||
Cfunc:
|
Cfunc:
|
||||||
|
luaC_checkGC(L); /* stack grow uses memory */
|
||||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||||
ci = next_ci(L); /* now 'enter' new function */
|
ci = next_ci(L); /* now 'enter' new function */
|
||||||
ci->nresults = nresults;
|
ci->nresults = nresults;
|
||||||
@@ -330,20 +331,20 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
ci->top = L->top + LUA_MINSTACK;
|
ci->top = L->top + LUA_MINSTACK;
|
||||||
lua_assert(ci->top <= L->stack_last);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
ci->callstatus = 0;
|
ci->callstatus = 0;
|
||||||
luaC_checkGC(L); /* stack grow uses memory */
|
|
||||||
if (L->hookmask & LUA_MASKCALL)
|
if (L->hookmask & LUA_MASKCALL)
|
||||||
luaD_hook(L, LUA_HOOKCALL, -1);
|
luaD_hook(L, LUA_HOOKCALL, -1);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
n = (*f)(L); /* do the actual call */
|
n = (*f)(L); /* do the actual call */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, n);
|
api_checknelems(L, n);
|
||||||
luaD_poscall(L, L->top - n);
|
luaD_poscall(L, L->top - n, n);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case LUA_TLCL: { /* Lua function: prepare its call */
|
case LUA_TLCL: { /* Lua function: prepare its call */
|
||||||
StkId base;
|
StkId base;
|
||||||
SharedProto *p = clLvalue(func)->p->sp;
|
SharedProto *p = clLvalue(func)->p->sp;
|
||||||
n = cast_int(L->top - func) - 1; /* number of real arguments */
|
n = cast_int(L->top - func) - 1; /* number of real arguments */
|
||||||
|
luaC_checkGC(L); /* stack grow uses memory */
|
||||||
luaD_checkstack(L, p->maxstacksize);
|
luaD_checkstack(L, p->maxstacksize);
|
||||||
for (; n < p->numparams; n++)
|
for (; n < p->numparams; n++)
|
||||||
setnilvalue(L->top++); /* complete missing arguments */
|
setnilvalue(L->top++); /* complete missing arguments */
|
||||||
@@ -364,7 +365,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->callstatus = CIST_LUA;
|
ci->callstatus = CIST_LUA;
|
||||||
L->top = ci->top;
|
L->top = ci->top;
|
||||||
luaC_checkGC(L); /* stack grow uses memory */
|
|
||||||
if (L->hookmask & LUA_MASKCALL)
|
if (L->hookmask & LUA_MASKCALL)
|
||||||
callhook(L, ci);
|
callhook(L, ci);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -379,7 +379,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int luaD_poscall (lua_State *L, StkId firstResult) {
|
int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
|
||||||
StkId res;
|
StkId res;
|
||||||
int wanted, i;
|
int wanted, i;
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
@@ -393,9 +393,9 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
|
|||||||
}
|
}
|
||||||
res = ci->func; /* res == final position of 1st result */
|
res = ci->func; /* res == final position of 1st result */
|
||||||
wanted = ci->nresults;
|
wanted = ci->nresults;
|
||||||
L->ci = ci = ci->previous; /* back to caller */
|
L->ci = ci->previous; /* back to caller */
|
||||||
/* move results to correct place */
|
/* move results to correct place */
|
||||||
for (i = wanted; i != 0 && firstResult < L->top; i--)
|
for (i = wanted; i != 0 && nres-- > 0; i--)
|
||||||
setobjs2s(L, res++, firstResult++);
|
setobjs2s(L, res++, firstResult++);
|
||||||
while (i-- > 0)
|
while (i-- > 0)
|
||||||
setnilvalue(res++);
|
setnilvalue(res++);
|
||||||
@@ -449,7 +449,7 @@ static void finishCcall (lua_State *L, int status) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, n);
|
api_checknelems(L, n);
|
||||||
/* finish 'luaD_precall' */
|
/* finish 'luaD_precall' */
|
||||||
luaD_poscall(L, L->top - n);
|
luaD_poscall(L, L->top - n, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -533,7 +533,8 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
|
|||||||
*/
|
*/
|
||||||
static void resume (lua_State *L, void *ud) {
|
static void resume (lua_State *L, void *ud) {
|
||||||
int nCcalls = L->nCcalls;
|
int nCcalls = L->nCcalls;
|
||||||
StkId firstArg = cast(StkId, ud);
|
int n = *(cast(int*, ud)); /* number of arguments */
|
||||||
|
StkId firstArg = L->top - n; /* first argument */
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (nCcalls >= LUAI_MAXCCALLS)
|
if (nCcalls >= LUAI_MAXCCALLS)
|
||||||
resume_error(L, "C stack overflow", firstArg);
|
resume_error(L, "C stack overflow", firstArg);
|
||||||
@@ -553,14 +554,13 @@ static void resume (lua_State *L, void *ud) {
|
|||||||
luaV_execute(L); /* just continue running Lua code */
|
luaV_execute(L); /* just continue running Lua code */
|
||||||
else { /* 'common' yield */
|
else { /* 'common' yield */
|
||||||
if (ci->u.c.k != NULL) { /* does it have a continuation function? */
|
if (ci->u.c.k != NULL) { /* does it have a continuation function? */
|
||||||
int n;
|
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
|
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, n);
|
api_checknelems(L, n);
|
||||||
firstArg = L->top - n; /* yield results come from continuation */
|
firstArg = L->top - n; /* yield results come from continuation */
|
||||||
}
|
}
|
||||||
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
|
luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */
|
||||||
}
|
}
|
||||||
unroll(L, NULL); /* run continuation */
|
unroll(L, NULL); /* run continuation */
|
||||||
}
|
}
|
||||||
@@ -576,7 +576,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
|||||||
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
|
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
|
||||||
L->nny = 0; /* allow yields */
|
L->nny = 0; /* allow yields */
|
||||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||||
status = luaD_rawrunprotected(L, resume, L->top - nargs);
|
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||||
if (status == -1) /* error calling 'lua_resume'? */
|
if (status == -1) /* error calling 'lua_resume'? */
|
||||||
status = LUA_ERRRUN;
|
status = LUA_ERRRUN;
|
||||||
else { /* continue running after recoverable errors */
|
else { /* continue running after recoverable errors */
|
||||||
@@ -619,7 +619,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
|
|||||||
L->status = LUA_YIELD;
|
L->status = LUA_YIELD;
|
||||||
ci->extra = savestack(L, ci->func); /* save current 'func' */
|
ci->extra = savestack(L, ci->func); /* save current 'func' */
|
||||||
if (isLua(ci)) { /* inside a hook? */
|
if (isLua(ci)) { /* inside a hook? */
|
||||||
api_check(k == NULL, "hooks cannot continue after yielding");
|
api_check(L, k == NULL, "hooks cannot continue after yielding");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp $
|
** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +34,7 @@ LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
|
|||||||
int allowyield);
|
int allowyield);
|
||||||
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||||
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
|
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres);
|
||||||
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
|
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
|
||||||
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
|
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
|
||||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp $
|
** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp $
|
||||||
** save precompiled Lua chunks
|
** save precompiled Lua chunks
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -74,14 +74,15 @@ static void DumpString (const TString *s, DumpState *D) {
|
|||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
DumpByte(0, D);
|
DumpByte(0, D);
|
||||||
else {
|
else {
|
||||||
size_t size = s->len + 1; /* include trailing '\0' */
|
size_t size = tsslen(s) + 1; /* include trailing '\0' */
|
||||||
|
const char *str = getstr(s);
|
||||||
if (size < 0xFF)
|
if (size < 0xFF)
|
||||||
DumpByte(cast_int(size), D);
|
DumpByte(cast_int(size), D);
|
||||||
else {
|
else {
|
||||||
DumpByte(0xFF, D);
|
DumpByte(0xFF, D);
|
||||||
DumpVar(size, D);
|
DumpVar(size, D);
|
||||||
}
|
}
|
||||||
DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */
|
DumpVector(str, size - 1, D); /* no need to save '\0' */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ Proto *luaF_newproto (lua_State *L, SharedProto *sp) {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void freesharedproto (lua_State *L, SharedProto *f) {
|
static void freesharedproto (lua_State *L, SharedProto *f) {
|
||||||
if (f == NULL || G(L) != f->l_G)
|
if (f == NULL || G(L) != f->l_G)
|
||||||
return;
|
return;
|
||||||
@@ -134,10 +135,8 @@ static void freesharedproto (lua_State *L, SharedProto *f) {
|
|||||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
|
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
|
||||||
luaM_freearray(L, f->locvars, f->sizelocvars);
|
luaM_freearray(L, f->locvars, f->sizelocvars);
|
||||||
luaM_freearray(L, f->upvalues, f->sizeupvalues);
|
luaM_freearray(L, f->upvalues, f->sizeupvalues);
|
||||||
luaM_free(L, f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaF_freeproto (lua_State *L, Proto *f) {
|
void luaF_freeproto (lua_State *L, Proto *f) {
|
||||||
luaM_freearray(L, f->p, f->sp->sizep);
|
luaM_freearray(L, f->p, f->sp->sizep);
|
||||||
luaM_freearray(L, f->k, f->sp->sizek);
|
luaM_freearray(L, f->k, f->sp->sizek);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $
|
** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
|
||||||
** Auxiliary functions to manipulate prototypes and closures
|
** Auxiliary functions to manipulate prototypes and closures
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -22,6 +22,13 @@
|
|||||||
#define isintwups(L) (L->twups != L)
|
#define isintwups(L) (L->twups != L)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** maximum number of upvalues in a closure (both C and Lua). (Value
|
||||||
|
** must fit in a VM register.)
|
||||||
|
*/
|
||||||
|
#define MAXUPVAL 255
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Upvalues for Lua closures
|
** Upvalues for Lua closures
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp $
|
** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -83,8 +83,13 @@
|
|||||||
#define markvalue(g,o) { checkconsistency(o); \
|
#define markvalue(g,o) { checkconsistency(o); \
|
||||||
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
|
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
|
||||||
|
|
||||||
#define markobject(g,t) \
|
#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
|
||||||
{ if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); }
|
|
||||||
|
/*
|
||||||
|
** mark an object that can be NULL (either because it is really optional,
|
||||||
|
** or it was stripped as debug info, or inside an uncompleted structure)
|
||||||
|
*/
|
||||||
|
#define markobjectN(g,t) { if (t) markobject(g,t); }
|
||||||
|
|
||||||
static void reallymarkobject (global_State *g, GCObject *o);
|
static void reallymarkobject (global_State *g, GCObject *o);
|
||||||
|
|
||||||
@@ -226,15 +231,19 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
|||||||
reentry:
|
reentry:
|
||||||
white2gray(o);
|
white2gray(o);
|
||||||
switch (o->tt) {
|
switch (o->tt) {
|
||||||
case LUA_TSHRSTR:
|
case LUA_TSHRSTR: {
|
||||||
|
gray2black(o);
|
||||||
|
g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case LUA_TLNGSTR: {
|
case LUA_TLNGSTR: {
|
||||||
gray2black(o);
|
gray2black(o);
|
||||||
g->GCmemtrav += sizestring(gco2ts(o));
|
g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TUSERDATA: {
|
case LUA_TUSERDATA: {
|
||||||
TValue uvalue;
|
TValue uvalue;
|
||||||
markobject(g, gco2u(o)->metatable); /* mark its metatable */
|
markobjectN(g, gco2u(o)->metatable); /* mark its metatable */
|
||||||
gray2black(o);
|
gray2black(o);
|
||||||
g->GCmemtrav += sizeudata(gco2u(o));
|
g->GCmemtrav += sizeudata(gco2u(o));
|
||||||
getuservalue(g->mainthread, gco2u(o), &uvalue);
|
getuservalue(g->mainthread, gco2u(o), &uvalue);
|
||||||
@@ -275,7 +284,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
|||||||
static void markmt (global_State *g) {
|
static void markmt (global_State *g) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i < LUA_NUMTAGS; i++)
|
for (i=0; i < LUA_NUMTAGS; i++)
|
||||||
markobject(g, g->mt[i]);
|
markobjectN(g, g->mt[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -437,7 +446,7 @@ static void traversestrongtable (global_State *g, Table *h) {
|
|||||||
static lu_mem traversetable (global_State *g, Table *h) {
|
static lu_mem traversetable (global_State *g, Table *h) {
|
||||||
const char *weakkey, *weakvalue;
|
const char *weakkey, *weakvalue;
|
||||||
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
||||||
markobject(g, h->metatable);
|
markobjectN(g, h->metatable);
|
||||||
if (mode && ttisstring(mode) && /* is there a weak mode? */
|
if (mode && ttisstring(mode) && /* is there a weak mode? */
|
||||||
((weakkey = strchr(svalue(mode), 'k')),
|
((weakkey = strchr(svalue(mode), 'k')),
|
||||||
(weakvalue = strchr(svalue(mode), 'v')),
|
(weakvalue = strchr(svalue(mode), 'v')),
|
||||||
@@ -460,17 +469,22 @@ static int marksharedproto (global_State *g, SharedProto *f) {
|
|||||||
int i;
|
int i;
|
||||||
if (g != f->l_G)
|
if (g != f->l_G)
|
||||||
return 0;
|
return 0;
|
||||||
markobject(g, f->source);
|
markobjectN(g, f->source);
|
||||||
for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */
|
for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */
|
||||||
markobject(g, f->upvalues[i].name);
|
markobjectN(g, f->upvalues[i].name);
|
||||||
for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
|
for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
|
||||||
markobject(g, f->locvars[i].varname);
|
markobjectN(g, f->locvars[i].varname);
|
||||||
return sizeof(Instruction) * f->sizecode +
|
return sizeof(Instruction) * f->sizecode +
|
||||||
sizeof(int) * f->sizelineinfo +
|
sizeof(int) * f->sizelineinfo +
|
||||||
sizeof(LocVar) * f->sizelocvars +
|
sizeof(LocVar) * f->sizelocvars +
|
||||||
sizeof(Upvaldesc) * f->sizeupvalues;
|
sizeof(Upvaldesc) * f->sizeupvalues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Traverse a prototype. (While a prototype is being build, its
|
||||||
|
** arrays can be larger than needed; the extra slots are filled with
|
||||||
|
** NULL, so the use of 'markobjectN')
|
||||||
|
*/
|
||||||
static int traverseproto (global_State *g, Proto *f) {
|
static int traverseproto (global_State *g, Proto *f) {
|
||||||
int i;
|
int i;
|
||||||
if (f->cache && iswhite(f->cache))
|
if (f->cache && iswhite(f->cache))
|
||||||
@@ -478,7 +492,7 @@ static int traverseproto (global_State *g, Proto *f) {
|
|||||||
for (i = 0; i < f->sp->sizek; i++) /* mark literals */
|
for (i = 0; i < f->sp->sizek; i++) /* mark literals */
|
||||||
markvalue(g, &f->k[i]);
|
markvalue(g, &f->k[i]);
|
||||||
for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */
|
for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */
|
||||||
markobject(g, f->p[i]);
|
markobjectN(g, f->p[i]);
|
||||||
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep +
|
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep +
|
||||||
sizeof(TValue) * f->sp->sizek +
|
sizeof(TValue) * f->sp->sizek +
|
||||||
marksharedproto(g, f->sp);
|
marksharedproto(g, f->sp);
|
||||||
@@ -500,7 +514,7 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
|
|||||||
*/
|
*/
|
||||||
static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
|
static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
|
||||||
int i;
|
int i;
|
||||||
markobject(g, cl->p); /* mark its prototype */
|
markobjectN(g, cl->p); /* mark its prototype */
|
||||||
for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */
|
for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */
|
||||||
UpVal *uv = cl->upvals[i];
|
UpVal *uv = cl->upvals[i];
|
||||||
if (uv != NULL) {
|
if (uv != NULL) {
|
||||||
@@ -695,9 +709,10 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
|
case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
|
||||||
case LUA_TSHRSTR:
|
case LUA_TSHRSTR:
|
||||||
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
|
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
|
||||||
/* go through */
|
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
|
||||||
|
break;
|
||||||
case LUA_TLNGSTR: {
|
case LUA_TLNGSTR: {
|
||||||
luaM_freemem(L, o, sizestring(gco2ts(o)));
|
luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
@@ -1008,6 +1023,7 @@ static l_mem atomic (lua_State *L) {
|
|||||||
/* clear values from resurrected weak tables */
|
/* clear values from resurrected weak tables */
|
||||||
clearvalues(g, g->weak, origweak);
|
clearvalues(g, g->weak, origweak);
|
||||||
clearvalues(g, g->allweak, origall);
|
clearvalues(g, g->allweak, origall);
|
||||||
|
luaS_clearcache(g);
|
||||||
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
||||||
work += g->GCmemtrav; /* complete counting */
|
work += g->GCmemtrav; /* complete counting */
|
||||||
return work; /* estimate of memory marked by 'atomic' */
|
return work; /* estimate of memory marked by 'atomic' */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $
|
** $Id: liolib.c,v 2.144 2015/04/03 18:41:57 roberto Exp $
|
||||||
** Standard I/O (and system) library
|
** Standard I/O (and system) library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -410,12 +410,6 @@ static int readdigits (RN *rn, int hex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* access to locale "radix character" (decimal point) */
|
|
||||||
#if !defined(l_getlocaledecpoint)
|
|
||||||
#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Read a number: first reads a valid prefix of a numeral into a buffer.
|
** 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
|
** Then it calls 'lua_stringtonumber' to check whether the format is
|
||||||
@@ -425,9 +419,10 @@ static int read_number (lua_State *L, FILE *f) {
|
|||||||
RN rn;
|
RN rn;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int hex = 0;
|
int hex = 0;
|
||||||
char decp[2] = ".";
|
char decp[2];
|
||||||
rn.f = f; rn.n = 0;
|
rn.f = f; rn.n = 0;
|
||||||
decp[0] = l_getlocaledecpoint(); /* get decimal point from locale */
|
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
|
||||||
|
decp[1] = '\0';
|
||||||
l_lockfile(rn.f);
|
l_lockfile(rn.f);
|
||||||
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
||||||
test2(&rn, "-+"); /* optional signal */
|
test2(&rn, "-+"); /* optional signal */
|
||||||
@@ -457,7 +452,7 @@ static int read_number (lua_State *L, FILE *f) {
|
|||||||
static int test_eof (lua_State *L, FILE *f) {
|
static int test_eof (lua_State *L, FILE *f) {
|
||||||
int c = getc(f);
|
int c = getc(f);
|
||||||
ungetc(c, f); /* no-op when c == EOF */
|
ungetc(c, f); /* no-op when c == EOF */
|
||||||
lua_pushlstring(L, NULL, 0);
|
lua_pushliteral(L, "");
|
||||||
return (c != EOF);
|
return (c != EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: llex.c,v 2.89 2014/11/14 16:06:09 roberto Exp $
|
** $Id: llex.c,v 2.93 2015/05/22 17:45:56 roberto Exp $
|
||||||
** Lexical Analyzer
|
** Lexical Analyzer
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
#include "lctype.h"
|
#include "lctype.h"
|
||||||
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
#include "lgc.h"
|
#include "lgc.h"
|
||||||
#include "llex.h"
|
#include "llex.h"
|
||||||
@@ -68,7 +69,7 @@ static void save (LexState *ls, int c) {
|
|||||||
|
|
||||||
void luaX_init (lua_State *L) {
|
void luaX_init (lua_State *L) {
|
||||||
int i;
|
int i;
|
||||||
TString *e = luaS_new(L, LUA_ENV); /* create env name */
|
TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */
|
||||||
luaC_fix(L, obj2gco(e)); /* never collect this name */
|
luaC_fix(L, obj2gco(e)); /* never collect this name */
|
||||||
for (i=0; i<NUM_RESERVED; i++) {
|
for (i=0; i<NUM_RESERVED; i++) {
|
||||||
TString *ts = luaS_new(L, luaX_tokens[i]);
|
TString *ts = luaS_new(L, luaX_tokens[i]);
|
||||||
@@ -106,9 +107,7 @@ static const char *txtToken (LexState *ls, int token) {
|
|||||||
|
|
||||||
|
|
||||||
static l_noret lexerror (LexState *ls, const char *msg, int token) {
|
static l_noret lexerror (LexState *ls, const char *msg, int token) {
|
||||||
char buff[LUA_IDSIZE];
|
msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber);
|
||||||
luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
|
|
||||||
msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
|
|
||||||
if (token)
|
if (token)
|
||||||
luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
|
luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
|
||||||
luaD_throw(ls->L, LUA_ERRSYNTAX);
|
luaD_throw(ls->L, LUA_ERRSYNTAX);
|
||||||
@@ -172,7 +171,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
|
|||||||
ls->linenumber = 1;
|
ls->linenumber = 1;
|
||||||
ls->lastline = 1;
|
ls->lastline = 1;
|
||||||
ls->source = source;
|
ls->source = source;
|
||||||
ls->envn = luaS_new(L, LUA_ENV); /* get env name */
|
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */
|
||||||
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
|
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +220,6 @@ static void buffreplace (LexState *ls, char from, char to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if !defined(l_getlocaledecpoint)
|
|
||||||
#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
|
#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -234,7 +228,7 @@ static void buffreplace (LexState *ls, char from, char to) {
|
|||||||
*/
|
*/
|
||||||
static void trydecpoint (LexState *ls, TValue *o) {
|
static void trydecpoint (LexState *ls, TValue *o) {
|
||||||
char old = ls->decpoint;
|
char old = ls->decpoint;
|
||||||
ls->decpoint = l_getlocaledecpoint();
|
ls->decpoint = lua_getlocaledecpoint();
|
||||||
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
|
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
|
||||||
if (!buff2num(ls->buff, o)) {
|
if (!buff2num(ls->buff, o)) {
|
||||||
/* format error with correct decimal point: no more options */
|
/* format error with correct decimal point: no more options */
|
||||||
@@ -283,8 +277,9 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
|
** skip a sequence '[=*[' or ']=*]'; if sequence is wellformed, return
|
||||||
** -1 if sequence is malformed
|
** its number of '='s; otherwise, return a negative number (-1 iff there
|
||||||
|
** are no '='s after initial bracket)
|
||||||
*/
|
*/
|
||||||
static int skip_sep (LexState *ls) {
|
static int skip_sep (LexState *ls) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -501,8 +496,9 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
|||||||
read_long_string(ls, seminfo, sep);
|
read_long_string(ls, seminfo, sep);
|
||||||
return TK_STRING;
|
return TK_STRING;
|
||||||
}
|
}
|
||||||
else if (sep == -1) return '[';
|
else if (sep != -1) /* '[=...' missing second bracket */
|
||||||
else lexerror(ls, "invalid long string delimiter", TK_STRING);
|
lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||||
|
return '[';
|
||||||
}
|
}
|
||||||
case '=': {
|
case '=': {
|
||||||
next(ls);
|
next(ls);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: llimits.h,v 1.125 2014/12/19 13:30:23 roberto Exp $
|
** $Id: llimits.h,v 1.135 2015/06/09 14:21:00 roberto Exp $
|
||||||
** Limits, basic types, and some other 'installation-dependent' definitions
|
** Limits, basic types, and some other 'installation-dependent' definitions
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -52,11 +52,11 @@ typedef unsigned char lu_byte;
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** conversion of pointer to integer:
|
** conversion of pointer to unsigned integer:
|
||||||
** this is for hashing only; there is no problem if the integer
|
** this is for hashing only; there is no problem if the integer
|
||||||
** cannot hold the whole pointer value
|
** cannot hold the whole pointer value
|
||||||
*/
|
*/
|
||||||
#define point2int(p) ((unsigned int)((size_t)(p) & UINT_MAX))
|
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -88,22 +88,20 @@ typedef LUAI_UACINT l_uacInt;
|
|||||||
/*
|
/*
|
||||||
** assertion for checking API calls
|
** assertion for checking API calls
|
||||||
*/
|
*/
|
||||||
#if defined(LUA_USE_APICHECK)
|
#if !defined(luai_apicheck)
|
||||||
#include <assert.h>
|
#define luai_apicheck(l,e) lua_assert(e)
|
||||||
#define luai_apicheck(e) assert(e)
|
|
||||||
#else
|
|
||||||
#define luai_apicheck(e) lua_assert(e)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
|
||||||
#define api_check(e,msg) luai_apicheck((e) && msg)
|
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to avoid warnings about unused variables */
|
||||||
#if !defined(UNUSED)
|
#if !defined(UNUSED)
|
||||||
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
|
#define UNUSED(x) ((void)(x))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* type casts (a macro highlights casts in the code) */
|
||||||
#define cast(t, exp) ((t)(exp))
|
#define cast(t, exp) ((t)(exp))
|
||||||
|
|
||||||
#define cast_void(i) cast(void, (i))
|
#define cast_void(i) cast(void, (i))
|
||||||
@@ -149,11 +147,6 @@ typedef LUAI_UACINT l_uacInt;
|
|||||||
#define LUAI_MAXCCALLS 200
|
#define LUAI_MAXCCALLS 200
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
** maximum number of upvalues in a closure (both C and Lua). (Value
|
|
||||||
** must fit in an unsigned char.)
|
|
||||||
*/
|
|
||||||
#define MAXUPVAL UCHAR_MAX
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -168,10 +161,33 @@ typedef unsigned long Instruction;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Maximum length for short strings, that is, strings that are
|
||||||
|
** internalized. (Cannot be smaller than reserved words or tags for
|
||||||
|
** metamethods, as these strings must be internalized;
|
||||||
|
** #("function") = 8, #("__newindex") = 10.)
|
||||||
|
*/
|
||||||
|
#if !defined(LUAI_MAXSHORTLEN)
|
||||||
|
#define LUAI_MAXSHORTLEN 40
|
||||||
|
#endif
|
||||||
|
|
||||||
/* minimum size for the string table (must be power of 2) */
|
|
||||||
|
/*
|
||||||
|
** Initial size for the string table (must be power of 2).
|
||||||
|
** The Lua core alone registers ~50 strings (reserved words +
|
||||||
|
** metaevent keys + a few others). Libraries would typically add
|
||||||
|
** a few dozens more.
|
||||||
|
*/
|
||||||
#if !defined(MINSTRTABSIZE)
|
#if !defined(MINSTRTABSIZE)
|
||||||
#define MINSTRTABSIZE 64 /* minimum size for "predefined" strings */
|
#define MINSTRTABSIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Size of cache for strings in the API (better be a prime)
|
||||||
|
*/
|
||||||
|
#if !defined(STRCACHE_SIZE)
|
||||||
|
#define STRCACHE_SIZE 127
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -181,11 +197,19 @@ typedef unsigned long Instruction;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macros that are executed whenether program enters the Lua core
|
||||||
|
** ('lua_lock') and leaves the core ('lua_unlock')
|
||||||
|
*/
|
||||||
#if !defined(lua_lock)
|
#if !defined(lua_lock)
|
||||||
#define lua_lock(L) ((void) 0)
|
#define lua_lock(L) ((void) 0)
|
||||||
#define lua_unlock(L) ((void) 0)
|
#define lua_unlock(L) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro executed during Lua functions at points where the
|
||||||
|
** function can yield.
|
||||||
|
*/
|
||||||
#if !defined(luai_threadyield)
|
#if !defined(luai_threadyield)
|
||||||
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
|
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
|
||||||
#endif
|
#endif
|
||||||
@@ -222,6 +246,53 @@ typedef unsigned long Instruction;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The luai_num* macros define the primitive operations over numbers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* floor division (defined as 'floor(a/b)') */
|
||||||
|
#if !defined(luai_numidiv)
|
||||||
|
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* float division */
|
||||||
|
#if !defined(luai_numdiv)
|
||||||
|
#define luai_numdiv(L,a,b) ((a)/(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
|
||||||
|
** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
|
||||||
|
** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
|
||||||
|
** ~= floor(a/b)'. That happens when the division has a non-integer
|
||||||
|
** negative result, which is equivalent to the test below.
|
||||||
|
*/
|
||||||
|
#if !defined(luai_nummod)
|
||||||
|
#define luai_nummod(L,a,b,m) \
|
||||||
|
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* exponentiation */
|
||||||
|
#if !defined(luai_numpow)
|
||||||
|
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the others are quite standard operations */
|
||||||
|
#if !defined(luai_numadd)
|
||||||
|
#define luai_numadd(L,a,b) ((a)+(b))
|
||||||
|
#define luai_numsub(L,a,b) ((a)-(b))
|
||||||
|
#define luai_nummul(L,a,b) ((a)*(b))
|
||||||
|
#define luai_numunm(L,a) (-(a))
|
||||||
|
#define luai_numeq(a,b) ((a)==(b))
|
||||||
|
#define luai_numlt(a,b) ((a)<(b))
|
||||||
|
#define luai_numle(a,b) ((a)<=(b))
|
||||||
|
#define luai_numisnan(a) (!luai_numeq((a), (a)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** macro to control inclusion of some hard tests on stack reallocation
|
** macro to control inclusion of some hard tests on stack reallocation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp $
|
** $Id: lmathlib.c,v 1.115 2015/03/12 14:04:04 roberto Exp $
|
||||||
** Standard mathematical library
|
** Standard mathematical library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -183,6 +183,9 @@ static int math_log (lua_State *L) {
|
|||||||
res = l_mathop(log)(x);
|
res = l_mathop(log)(x);
|
||||||
else {
|
else {
|
||||||
lua_Number base = luaL_checknumber(L, 2);
|
lua_Number base = luaL_checknumber(L, 2);
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
if (base == 2.0) res = l_mathop(log2)(x); else
|
||||||
|
#endif
|
||||||
if (base == 10.0) res = l_mathop(log10)(x);
|
if (base == 10.0) res = l_mathop(log10)(x);
|
||||||
else res = l_mathop(log)(x)/l_mathop(log)(base);
|
else res = l_mathop(log)(x)/l_mathop(log)(base);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lmem.c,v 1.89 2014/11/02 19:33:33 roberto Exp $
|
** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
|
||||||
** Interface to Memory Manager
|
** Interface to Memory Manager
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -85,10 +85,11 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
|
|||||||
#endif
|
#endif
|
||||||
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
|
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
|
||||||
if (newblock == NULL && nsize > 0) {
|
if (newblock == NULL && nsize > 0) {
|
||||||
api_check( nsize > realosize,
|
lua_assert(nsize > realosize); /* cannot fail when shrinking a block */
|
||||||
"realloc cannot fail when shrinking a block");
|
if (g->version) { /* is state fully built? */
|
||||||
luaC_fullgc(L, 1); /* try to free some memory... */
|
luaC_fullgc(L, 1); /* try to free some memory... */
|
||||||
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
|
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
|
||||||
|
}
|
||||||
if (newblock == NULL)
|
if (newblock == NULL)
|
||||||
luaD_throw(L, LUA_ERRMEM);
|
luaD_throw(L, LUA_ERRMEM);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: loadlib.c,v 1.124 2015/01/05 13:51:39 roberto Exp $
|
** $Id: loadlib.c,v 1.126 2015/02/16 13:14:33 roberto Exp $
|
||||||
** Dynamic library loader for Lua
|
** Dynamic library loader for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
**
|
**
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -136,8 +137,8 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Macro to covert pointer to void* to pointer to function. This cast
|
** Macro to convert pointer-to-void* to pointer-to-function. This cast
|
||||||
** is undefined according to ISO C, but POSIX assumes that it must work.
|
** is undefined according to ISO C, but POSIX assumes that it works.
|
||||||
** (The '__extension__' in gnu compilers is only to avoid warnings.)
|
** (The '__extension__' in gnu compilers is only to avoid warnings.)
|
||||||
*/
|
*/
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lobject.c,v 2.101 2014/12/26 14:43:45 roberto Exp $
|
** $Id: lobject.c,v 2.104 2015/04/11 18:30:08 roberto Exp $
|
||||||
** Some generic functions over Lua objects
|
** Some generic functions over Lua objects
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -39,8 +41,12 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
|
|||||||
int luaO_int2fb (unsigned int x) {
|
int luaO_int2fb (unsigned int x) {
|
||||||
int e = 0; /* exponent */
|
int e = 0; /* exponent */
|
||||||
if (x < 8) return x;
|
if (x < 8) return x;
|
||||||
while (x >= 0x10) {
|
while (x >= (8 << 4)) { /* coarse steps */
|
||||||
x = (x+1) >> 1;
|
x = (x + 0xf) >> 4; /* x = ceil(x / 16) */
|
||||||
|
e += 4;
|
||||||
|
}
|
||||||
|
while (x >= (8 << 1)) { /* fine steps */
|
||||||
|
x = (x + 1) >> 1; /* x = ceil(x / 2) */
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
return ((e+1) << 3) | (cast_int(x) - 8);
|
return ((e+1) << 3) | (cast_int(x) - 8);
|
||||||
@@ -55,8 +61,11 @@ int luaO_fb2int (int x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Computes ceil(log2(x))
|
||||||
|
*/
|
||||||
int luaO_ceillog2 (unsigned int x) {
|
int luaO_ceillog2 (unsigned int x) {
|
||||||
static const lu_byte log_2[256] = {
|
static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */
|
||||||
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||||
@@ -149,13 +158,13 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
|
|||||||
}
|
}
|
||||||
/* could not perform raw operation; try metamethod */
|
/* could not perform raw operation; try metamethod */
|
||||||
lua_assert(L != NULL); /* should not fail when folding (compile time) */
|
lua_assert(L != NULL); /* should not fail when folding (compile time) */
|
||||||
luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
|
luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int luaO_hexavalue (int c) {
|
int luaO_hexavalue (int c) {
|
||||||
if (lisdigit(c)) return c - '0';
|
if (lisdigit(c)) return c - '0';
|
||||||
else return ltolower(c) - 'a' + 10;
|
else return (ltolower(c) - 'a') + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -172,9 +181,8 @@ static int isneg (const char **s) {
|
|||||||
** Lua's implementation for 'lua_strx2number'
|
** Lua's implementation for 'lua_strx2number'
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
#if !defined(lua_strx2number)
|
|
||||||
|
|
||||||
#include <math.h>
|
#if !defined(lua_strx2number)
|
||||||
|
|
||||||
/* maximum number of significant digits to read (to avoid overflows
|
/* maximum number of significant digits to read (to avoid overflows
|
||||||
even with single floats) */
|
even with single floats) */
|
||||||
@@ -185,21 +193,22 @@ static int isneg (const char **s) {
|
|||||||
** C99 specification for 'strtod'
|
** C99 specification for 'strtod'
|
||||||
*/
|
*/
|
||||||
static lua_Number lua_strx2number (const char *s, char **endptr) {
|
static lua_Number lua_strx2number (const char *s, char **endptr) {
|
||||||
|
int dot = lua_getlocaledecpoint();
|
||||||
lua_Number r = 0.0; /* result (accumulator) */
|
lua_Number r = 0.0; /* result (accumulator) */
|
||||||
int sigdig = 0; /* number of significant digits */
|
int sigdig = 0; /* number of significant digits */
|
||||||
int nosigdig = 0; /* number of non-significant digits */
|
int nosigdig = 0; /* number of non-significant digits */
|
||||||
int e = 0; /* exponent correction */
|
int e = 0; /* exponent correction */
|
||||||
int neg; /* 1 if number is negative */
|
int neg; /* 1 if number is negative */
|
||||||
int dot = 0; /* true after seen a dot */
|
int hasdot = 0; /* true after seen a dot */
|
||||||
*endptr = cast(char *, s); /* nothing is valid yet */
|
*endptr = cast(char *, s); /* nothing is valid yet */
|
||||||
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
|
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
|
||||||
neg = isneg(&s); /* check signal */
|
neg = isneg(&s); /* check signal */
|
||||||
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
|
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
|
||||||
return 0.0; /* invalid format (no '0x') */
|
return 0.0; /* invalid format (no '0x') */
|
||||||
for (s += 2; ; s++) { /* skip '0x' and read numeral */
|
for (s += 2; ; s++) { /* skip '0x' and read numeral */
|
||||||
if (*s == '.') {
|
if (*s == dot) {
|
||||||
if (dot) break; /* second dot? stop loop */
|
if (hasdot) break; /* second dot? stop loop */
|
||||||
else dot = 1;
|
else hasdot = 1;
|
||||||
}
|
}
|
||||||
else if (lisxdigit(cast_uchar(*s))) {
|
else if (lisxdigit(cast_uchar(*s))) {
|
||||||
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
|
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
|
||||||
@@ -207,7 +216,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
|||||||
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
|
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
|
||||||
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
|
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
|
||||||
else e++; /* too many digits; ignore, but still count for exponent */
|
else e++; /* too many digits; ignore, but still count for exponent */
|
||||||
if (dot) e--; /* decimal digit? correct exponent */
|
if (hasdot) e--; /* decimal digit? correct exponent */
|
||||||
}
|
}
|
||||||
else break; /* neither a dot nor a digit */
|
else break; /* neither a dot nor a digit */
|
||||||
}
|
}
|
||||||
@@ -244,7 +253,7 @@ static const char *l_str2d (const char *s, lua_Number *result) {
|
|||||||
*result = lua_strx2number(s, &endptr);
|
*result = lua_strx2number(s, &endptr);
|
||||||
else
|
else
|
||||||
*result = lua_str2number(s, &endptr);
|
*result = lua_str2number(s, &endptr);
|
||||||
if (endptr == s) return 0; /* nothing recognized */
|
if (endptr == s) return NULL; /* nothing recognized */
|
||||||
while (lisspace(cast_uchar(*endptr))) endptr++;
|
while (lisspace(cast_uchar(*endptr))) endptr++;
|
||||||
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
|
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
|
||||||
}
|
}
|
||||||
@@ -290,7 +299,7 @@ size_t luaO_str2num (const char *s, TValue *o) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0; /* conversion failed */
|
return 0; /* conversion failed */
|
||||||
return (e - s + 1); /* success; return string size */
|
return (e - s) + 1; /* success; return string size */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -329,7 +338,7 @@ void luaO_tostring (lua_State *L, StkId obj) {
|
|||||||
len = lua_number2str(buff, fltvalue(obj));
|
len = lua_number2str(buff, fltvalue(obj));
|
||||||
#if !defined(LUA_COMPAT_FLOATSTRING)
|
#if !defined(LUA_COMPAT_FLOATSTRING)
|
||||||
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
|
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
|
||||||
buff[len++] = '.';
|
buff[len++] = lua_getlocaledecpoint();
|
||||||
buff[len++] = '0'; /* adds '.0' to result */
|
buff[len++] = '0'; /* adds '.0' to result */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $
|
** $Id: lobject.h,v 2.111 2015/06/09 14:21:42 roberto Exp $
|
||||||
** Type definitions for Lua objects
|
** Type definitions for Lua objects
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -35,8 +35,6 @@
|
|||||||
** bit 6: whether value is collectable
|
** bit 6: whether value is collectable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VARBITS (3 << 4)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** LUA_TFUNCTION variants:
|
** LUA_TFUNCTION variants:
|
||||||
@@ -190,9 +188,15 @@ typedef struct lua_TValue TValue;
|
|||||||
#define setfltvalue(obj,x) \
|
#define setfltvalue(obj,x) \
|
||||||
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
|
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
|
||||||
|
|
||||||
|
#define chgfltvalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
|
||||||
|
|
||||||
#define setivalue(obj,x) \
|
#define setivalue(obj,x) \
|
||||||
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
|
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
|
||||||
|
|
||||||
|
#define chgivalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
|
||||||
|
|
||||||
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
|
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
|
||||||
|
|
||||||
#define setfvalue(obj,x) \
|
#define setfvalue(obj,x) \
|
||||||
@@ -303,9 +307,12 @@ typedef TValue *StkId; /* index to stack elements */
|
|||||||
typedef struct TString {
|
typedef struct TString {
|
||||||
CommonHeader;
|
CommonHeader;
|
||||||
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
||||||
|
lu_byte shrlen; /* length for short strings */
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
size_t len; /* number of characters in string */
|
union {
|
||||||
struct TString *hnext; /* linked list for hash table */
|
size_t lnglen; /* length for long strings */
|
||||||
|
struct TString *hnext; /* linked list for hash table */
|
||||||
|
} u;
|
||||||
} TString;
|
} TString;
|
||||||
|
|
||||||
|
|
||||||
@@ -329,6 +336,12 @@ typedef union UTString {
|
|||||||
/* get the actual string (array of bytes) from a Lua value */
|
/* get the actual string (array of bytes) from a Lua value */
|
||||||
#define svalue(o) getstr(tsvalue(o))
|
#define svalue(o) getstr(tsvalue(o))
|
||||||
|
|
||||||
|
/* get string length from 'TString *s' */
|
||||||
|
#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
|
||||||
|
|
||||||
|
/* get string length from 'TValue *o' */
|
||||||
|
#define vslen(o) tsslen(tsvalue(o))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Header for userdata; memory area follows the end of this structure
|
** Header for userdata; memory area follows the end of this structure
|
||||||
@@ -361,13 +374,13 @@ typedef union UUdata {
|
|||||||
|
|
||||||
#define setuservalue(L,u,o) \
|
#define setuservalue(L,u,o) \
|
||||||
{ const TValue *io=(o); Udata *iu = (u); \
|
{ const TValue *io=(o); Udata *iu = (u); \
|
||||||
iu->user_ = io->value_; iu->ttuv_ = io->tt_; \
|
iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
|
||||||
checkliveness(G(L),io); }
|
checkliveness(G(L),io); }
|
||||||
|
|
||||||
|
|
||||||
#define getuservalue(L,u,o) \
|
#define getuservalue(L,u,o) \
|
||||||
{ TValue *io=(o); const Udata *iu = (u); \
|
{ TValue *io=(o); const Udata *iu = (u); \
|
||||||
io->value_ = iu->user_; io->tt_ = iu->ttuv_; \
|
io->value_ = iu->user_; settt_(io, iu->ttuv_); \
|
||||||
checkliveness(G(L),io); }
|
checkliveness(G(L),io); }
|
||||||
|
|
||||||
|
|
||||||
@@ -376,7 +389,7 @@ typedef union UUdata {
|
|||||||
*/
|
*/
|
||||||
typedef struct Upvaldesc {
|
typedef struct Upvaldesc {
|
||||||
TString *name; /* upvalue name (for debug information) */
|
TString *name; /* upvalue name (for debug information) */
|
||||||
lu_byte instack; /* whether it is in stack */
|
lu_byte instack; /* whether it is in stack (register) */
|
||||||
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
|
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
|
||||||
} Upvaldesc;
|
} Upvaldesc;
|
||||||
|
|
||||||
@@ -391,11 +404,10 @@ typedef struct LocVar {
|
|||||||
int endpc; /* first point where variable is dead */
|
int endpc; /* first point where variable is dead */
|
||||||
} LocVar;
|
} LocVar;
|
||||||
|
|
||||||
|
|
||||||
typedef struct SharedProto {
|
typedef struct SharedProto {
|
||||||
lu_byte numparams; /* number of fixed parameters */
|
lu_byte numparams; /* number of fixed parameters */
|
||||||
lu_byte is_vararg;
|
lu_byte is_vararg;
|
||||||
lu_byte maxstacksize; /* maximum stack used by this function */
|
lu_byte maxstacksize; /* number of registers needed by this function */
|
||||||
int sizeupvalues; /* size of 'upvalues' */
|
int sizeupvalues; /* size of 'upvalues' */
|
||||||
int sizek; /* size of 'k' */
|
int sizek; /* size of 'k' */
|
||||||
int sizecode;
|
int sizecode;
|
||||||
@@ -405,7 +417,7 @@ typedef struct SharedProto {
|
|||||||
int linedefined;
|
int linedefined;
|
||||||
int lastlinedefined;
|
int lastlinedefined;
|
||||||
void *l_G; /* global state belongs to */
|
void *l_G; /* global state belongs to */
|
||||||
Instruction *code;
|
Instruction *code; /* opcodes */
|
||||||
int *lineinfo; /* map from opcodes to source lines (debug information) */
|
int *lineinfo; /* map from opcodes to source lines (debug information) */
|
||||||
LocVar *locvars; /* information about local variables (debug information) */
|
LocVar *locvars; /* information about local variables (debug information) */
|
||||||
Upvaldesc *upvalues; /* upvalue information */
|
Upvaldesc *upvalues; /* upvalue information */
|
||||||
@@ -420,7 +432,7 @@ typedef struct Proto {
|
|||||||
struct SharedProto *sp;
|
struct SharedProto *sp;
|
||||||
TValue *k; /* constants used by the function */
|
TValue *k; /* constants used by the function */
|
||||||
struct Proto **p; /* functions defined inside the function */
|
struct Proto **p; /* functions defined inside the function */
|
||||||
struct LClosure *cache; /* last created closure with this prototype */
|
struct LClosure *cache; /* last-created closure with this prototype */
|
||||||
GCObject *gclist;
|
GCObject *gclist;
|
||||||
} Proto;
|
} Proto;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: loslib.c,v 1.54 2014/12/26 14:46:07 roberto Exp $
|
** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp $
|
||||||
** Standard Operating System library
|
** Standard Operating System library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -22,10 +22,12 @@
|
|||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
|
||||||
|
|
||||||
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
|
|
||||||
/*
|
/*
|
||||||
|
** {==================================================================
|
||||||
** list of valid conversion specifiers for the 'strftime' function
|
** list of valid conversion specifiers for the 'strftime' function
|
||||||
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
|
||||||
|
|
||||||
#if defined(LUA_USE_C89)
|
#if defined(LUA_USE_C89)
|
||||||
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
|
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
|
||||||
@@ -37,8 +39,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Configuration for time-related stuff
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
#if !defined(l_time_t) /* { */
|
#if !defined(l_time_t) /* { */
|
||||||
/*
|
/*
|
||||||
@@ -51,15 +59,41 @@
|
|||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(l_gmtime) /* { */
|
||||||
#if !defined(lua_tmpnam) /* { */
|
|
||||||
/*
|
/*
|
||||||
** By default, Lua uses tmpnam except when POSIX is available, where it
|
** By default, Lua uses gmtime/localtime, except when POSIX is available,
|
||||||
** uses mkstemp.
|
** where it uses gmtime_r/localtime_r
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(LUA_USE_POSIX) /* { */
|
#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(LUA_USE_POSIX) /* { */
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define LUA_TMPNAMBUFSIZE 32
|
#define LUA_TMPNAMBUFSIZE 32
|
||||||
@@ -83,31 +117,10 @@
|
|||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
#endif /* } */
|
#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 /* } */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int os_execute (lua_State *L) {
|
static int os_execute (lua_State *L) {
|
||||||
const char *cmd = luaL_optstring(L, 1, NULL);
|
const char *cmd = luaL_optstring(L, 1, NULL);
|
||||||
@@ -287,7 +300,7 @@ static int os_time (lua_State *L) {
|
|||||||
t = mktime(&ts);
|
t = mktime(&ts);
|
||||||
}
|
}
|
||||||
if (t != (time_t)(l_timet)t)
|
if (t != (time_t)(l_timet)t)
|
||||||
luaL_error(L, "time result cannot be represented in this Lua instalation");
|
luaL_error(L, "time result cannot be represented in this Lua installation");
|
||||||
else if (t == (time_t)(-1))
|
else if (t == (time_t)(-1))
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
else
|
else
|
||||||
@@ -297,8 +310,9 @@ static int os_time (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
static int os_difftime (lua_State *L) {
|
static int os_difftime (lua_State *L) {
|
||||||
double res = difftime((l_checktime(L, 1)), (l_checktime(L, 2)));
|
time_t t1 = l_checktime(L, 1);
|
||||||
lua_pushnumber(L, (lua_Number)res);
|
time_t t2 = l_checktime(L, 2);
|
||||||
|
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp $
|
** $Id: lstate.c,v 2.128 2015/03/04 13:31:21 roberto Exp $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -37,9 +37,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define MEMERRMSG "not enough memory"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** a macro to help the creation of a unique random seed when a state is
|
** a macro to help the creation of a unique random seed when a state is
|
||||||
** created; the seed is used to randomize hashes.
|
** created; the seed is used to randomize hashes.
|
||||||
@@ -200,12 +197,9 @@ static void f_luaopen (lua_State *L, void *ud) {
|
|||||||
UNUSED(ud);
|
UNUSED(ud);
|
||||||
stack_init(L, L); /* init stack */
|
stack_init(L, L); /* init stack */
|
||||||
init_registry(L, g);
|
init_registry(L, g);
|
||||||
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
|
luaS_init(L);
|
||||||
luaT_init(L);
|
luaT_init(L);
|
||||||
luaX_init(L);
|
luaX_init(L);
|
||||||
/* pre-create memory-error message */
|
|
||||||
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
|
|
||||||
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
|
|
||||||
g->gcrunning = 1; /* allow gc */
|
g->gcrunning = 1; /* allow gc */
|
||||||
g->version = lua_version(NULL);
|
g->version = lua_version(NULL);
|
||||||
luai_userstateopen(L);
|
luai_userstateopen(L);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp $
|
** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -94,6 +94,7 @@ typedef struct CallInfo {
|
|||||||
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
|
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
|
||||||
#define CIST_TAIL (1<<5) /* call was tail called */
|
#define CIST_TAIL (1<<5) /* call was tail called */
|
||||||
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
||||||
|
#define CIST_LEQ (1<<7) /* using __lt for __le */
|
||||||
|
|
||||||
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
|
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ typedef struct global_State {
|
|||||||
TString *memerrmsg; /* memory-error message */
|
TString *memerrmsg; /* memory-error message */
|
||||||
TString *tmname[TM_N]; /* array with tag-method names */
|
TString *tmname[TM_N]; /* array with tag-method names */
|
||||||
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
|
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
|
||||||
|
TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */
|
||||||
} global_State;
|
} global_State;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
|
** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $
|
||||||
** String table (keeps all strings handled by Lua)
|
** String table (keeps all strings handled by Lua)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MEMERRMSG "not enough memory"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
|
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
|
||||||
@@ -36,10 +38,10 @@
|
|||||||
** equality for long strings
|
** equality for long strings
|
||||||
*/
|
*/
|
||||||
int luaS_eqlngstr (TString *a, TString *b) {
|
int luaS_eqlngstr (TString *a, TString *b) {
|
||||||
size_t len = a->len;
|
size_t len = a->u.lnglen;
|
||||||
lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
|
lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
|
||||||
return (a == b) || /* same instance or... */
|
return (a == b) || /* same instance or... */
|
||||||
((len == b->len) && /* equal length and ... */
|
((len == b->u.lnglen) && /* equal length and ... */
|
||||||
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
|
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +71,9 @@ void luaS_resize (lua_State *L, int newsize) {
|
|||||||
TString *p = tb->hash[i];
|
TString *p = tb->hash[i];
|
||||||
tb->hash[i] = NULL;
|
tb->hash[i] = NULL;
|
||||||
while (p) { /* for each node in the list */
|
while (p) { /* for each node in the list */
|
||||||
TString *hnext = p->hnext; /* save next */
|
TString *hnext = p->u.hnext; /* save next */
|
||||||
unsigned int h = lmod(p->hash, newsize); /* new position */
|
unsigned int h = lmod(p->hash, newsize); /* new position */
|
||||||
p->hnext = tb->hash[h]; /* chain it */
|
p->u.hnext = tb->hash[h]; /* chain it */
|
||||||
tb->hash[h] = p;
|
tb->hash[h] = p;
|
||||||
p = hnext;
|
p = hnext;
|
||||||
}
|
}
|
||||||
@@ -85,6 +87,34 @@ void luaS_resize (lua_State *L, int newsize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Clear API string cache. (Entries cannot be empty, so fill them with
|
||||||
|
** a non-collectable string.)
|
||||||
|
*/
|
||||||
|
void luaS_clearcache (global_State *g) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < STRCACHE_SIZE; i++) {
|
||||||
|
if (iswhite(g->strcache[i][0])) /* will entry be collected? */
|
||||||
|
g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Initialize the string table and the string cache
|
||||||
|
*/
|
||||||
|
void luaS_init (lua_State *L) {
|
||||||
|
global_State *g = G(L);
|
||||||
|
int i;
|
||||||
|
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
|
||||||
|
/* pre-create memory-error message */
|
||||||
|
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
|
||||||
|
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
|
||||||
|
for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */
|
||||||
|
g->strcache[i][0] = g->memerrmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** creates a new string object
|
** creates a new string object
|
||||||
@@ -97,7 +127,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
|
|||||||
totalsize = sizelstring(l);
|
totalsize = sizelstring(l);
|
||||||
o = luaC_newobj(L, tag, totalsize);
|
o = luaC_newobj(L, tag, totalsize);
|
||||||
ts = gco2ts(o);
|
ts = gco2ts(o);
|
||||||
ts->len = l;
|
|
||||||
ts->hash = h;
|
ts->hash = h;
|
||||||
ts->extra = 0;
|
ts->extra = 0;
|
||||||
memcpy(getaddrstr(ts), str, l * sizeof(char));
|
memcpy(getaddrstr(ts), str, l * sizeof(char));
|
||||||
@@ -110,8 +139,8 @@ void luaS_remove (lua_State *L, TString *ts) {
|
|||||||
stringtable *tb = &G(L)->strt;
|
stringtable *tb = &G(L)->strt;
|
||||||
TString **p = &tb->hash[lmod(ts->hash, tb->size)];
|
TString **p = &tb->hash[lmod(ts->hash, tb->size)];
|
||||||
while (*p != ts) /* find previous element */
|
while (*p != ts) /* find previous element */
|
||||||
p = &(*p)->hnext;
|
p = &(*p)->u.hnext;
|
||||||
*p = (*p)->hnext; /* remove element from its list */
|
*p = (*p)->u.hnext; /* remove element from its list */
|
||||||
tb->nuse--;
|
tb->nuse--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +153,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
unsigned int h = luaS_hash(str, l, g->seed);
|
unsigned int h = luaS_hash(str, l, g->seed);
|
||||||
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
|
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
|
||||||
for (ts = *list; ts != NULL; ts = ts->hnext) {
|
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
||||||
if (l == ts->len &&
|
if (l == ts->shrlen &&
|
||||||
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
|
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
|
||||||
/* found! */
|
/* found! */
|
||||||
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
||||||
@@ -138,7 +167,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
|
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
|
||||||
}
|
}
|
||||||
ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
|
ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
|
||||||
ts->hnext = *list;
|
ts->shrlen = cast_byte(l);
|
||||||
|
ts->u.hnext = *list;
|
||||||
*list = ts;
|
*list = ts;
|
||||||
g->strt.nuse++;
|
g->strt.nuse++;
|
||||||
return ts;
|
return ts;
|
||||||
@@ -152,18 +182,32 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
|
|||||||
if (l <= LUAI_MAXSHORTLEN) /* short string? */
|
if (l <= LUAI_MAXSHORTLEN) /* short string? */
|
||||||
return internshrstr(L, str, l);
|
return internshrstr(L, str, l);
|
||||||
else {
|
else {
|
||||||
|
TString *ts;
|
||||||
if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
|
if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
|
||||||
luaM_toobig(L);
|
luaM_toobig(L);
|
||||||
return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
|
ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
|
||||||
|
ts->u.lnglen = l;
|
||||||
|
return ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** new zero-terminated string
|
** Create or reuse a zero-terminated string, first checking in the
|
||||||
|
** cache (using the string address as a key). The cache can contain
|
||||||
|
** only zero-terminated strings, so it is safe to use 'strcmp' to
|
||||||
|
** check hits.
|
||||||
*/
|
*/
|
||||||
TString *luaS_new (lua_State *L, const char *str) {
|
TString *luaS_new (lua_State *L, const char *str) {
|
||||||
return luaS_newlstr(L, str, strlen(str));
|
unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */
|
||||||
|
TString **p = G(L)->strcache[i];
|
||||||
|
if (strcmp(str, getstr(p[0])) == 0) /* hit? */
|
||||||
|
return p[0]; /* that it is */
|
||||||
|
else { /* normal route */
|
||||||
|
TString *s = luaS_newlstr(L, str, strlen(str));
|
||||||
|
p[0] = s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $
|
** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp $
|
||||||
** String table (keep all strings handled by Lua)
|
** String table (keep all strings handled by Lua)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char))
|
#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char))
|
||||||
#define sizestring(s) sizelstring((s)->len)
|
|
||||||
|
|
||||||
#define sizeludata(l) (sizeof(union UUdata) + (l))
|
#define sizeludata(l) (sizeof(union UUdata) + (l))
|
||||||
#define sizeudata(u) sizeludata((u)->len)
|
#define sizeudata(u) sizeludata((u)->len)
|
||||||
@@ -37,6 +36,8 @@
|
|||||||
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
|
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
|
||||||
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
|
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
|
||||||
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
||||||
|
LUAI_FUNC void luaS_clearcache (global_State *g);
|
||||||
|
LUAI_FUNC void luaS_init (lua_State *L);
|
||||||
LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
|
LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
|
||||||
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
|
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
|
||||||
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
|
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $
|
** $Id: lstrlib.c,v 1.229 2015/05/20 17:39:23 roberto Exp $
|
||||||
** Standard library for string operations and pattern-matching
|
** Standard library for string operations and pattern-matching
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <float.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -70,7 +71,7 @@ static int str_sub (lua_State *L) {
|
|||||||
if (start < 1) start = 1;
|
if (start < 1) start = 1;
|
||||||
if (end > (lua_Integer)l) end = l;
|
if (end > (lua_Integer)l) end = l;
|
||||||
if (start <= end)
|
if (start <= end)
|
||||||
lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1));
|
lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
|
||||||
else lua_pushliteral(L, "");
|
else lua_pushliteral(L, "");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -149,9 +150,9 @@ static int str_byte (lua_State *L) {
|
|||||||
if (posi < 1) posi = 1;
|
if (posi < 1) posi = 1;
|
||||||
if (pose > (lua_Integer)l) pose = l;
|
if (pose > (lua_Integer)l) pose = l;
|
||||||
if (posi > pose) return 0; /* empty interval; return no values */
|
if (posi > pose) return 0; /* empty interval; return no values */
|
||||||
n = (int)(pose - posi + 1);
|
if (pose - posi >= INT_MAX) /* arithmetic overflow? */
|
||||||
if (posi + n <= pose) /* arithmetic overflow? */
|
|
||||||
return luaL_error(L, "string slice too long");
|
return luaL_error(L, "string slice too long");
|
||||||
|
n = (int)(pose - posi) + 1;
|
||||||
luaL_checkstack(L, n, "string slice too long");
|
luaL_checkstack(L, n, "string slice too long");
|
||||||
for (i=0; i<n; i++)
|
for (i=0; i<n; i++)
|
||||||
lua_pushinteger(L, uchar(s[posi+i-1]));
|
lua_pushinteger(L, uchar(s[posi+i-1]));
|
||||||
@@ -499,7 +500,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
|
|||||||
}
|
}
|
||||||
case '+': /* 1 or more repetitions */
|
case '+': /* 1 or more repetitions */
|
||||||
s++; /* 1 match already done */
|
s++; /* 1 match already done */
|
||||||
/* go through */
|
/* FALLTHROUGH */
|
||||||
case '*': /* 0 or more repetitions */
|
case '*': /* 0 or more repetitions */
|
||||||
s = max_expand(ms, s, p, ep);
|
s = max_expand(ms, s, p, ep);
|
||||||
break;
|
break;
|
||||||
@@ -554,7 +555,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s,
|
|||||||
ptrdiff_t l = ms->capture[i].len;
|
ptrdiff_t l = ms->capture[i].len;
|
||||||
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
|
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
|
||||||
if (l == CAP_POSITION)
|
if (l == CAP_POSITION)
|
||||||
lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
|
lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
|
||||||
else
|
else
|
||||||
lua_pushlstring(ms->L, ms->capture[i].init, l);
|
lua_pushlstring(ms->L, ms->capture[i].init, l);
|
||||||
}
|
}
|
||||||
@@ -598,8 +599,8 @@ static int str_find_aux (lua_State *L, int find) {
|
|||||||
/* do a plain search */
|
/* do a plain search */
|
||||||
const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
|
const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
|
||||||
if (s2) {
|
if (s2) {
|
||||||
lua_pushinteger(L, s2 - s + 1);
|
lua_pushinteger(L, (s2 - s) + 1);
|
||||||
lua_pushinteger(L, s2 - s + lp);
|
lua_pushinteger(L, (s2 - s) + lp);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,7 +622,7 @@ static int str_find_aux (lua_State *L, int find) {
|
|||||||
lua_assert(ms.matchdepth == MAXCCALLS);
|
lua_assert(ms.matchdepth == MAXCCALLS);
|
||||||
if ((res=match(&ms, s1, p)) != NULL) {
|
if ((res=match(&ms, s1, p)) != NULL) {
|
||||||
if (find) {
|
if (find) {
|
||||||
lua_pushinteger(L, s1 - s + 1); /* start */
|
lua_pushinteger(L, (s1 - s) + 1); /* start */
|
||||||
lua_pushinteger(L, res - s); /* end */
|
lua_pushinteger(L, res - s); /* end */
|
||||||
return push_captures(&ms, NULL, 0) + 2;
|
return push_captures(&ms, NULL, 0) + 2;
|
||||||
}
|
}
|
||||||
@@ -797,17 +798,100 @@ static int str_gsub (lua_State *L) {
|
|||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
|
#if !defined(lua_number2strx) /* { */
|
||||||
#define MAX_ITEM 512
|
|
||||||
|
/*
|
||||||
|
** Hexadecimal floating-point formatter
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Number of bits that goes into the first digit. It can be any value
|
||||||
|
** between 1 and 4; the following definition tries to align the number
|
||||||
|
** to nibble boundaries by making what is left after that first digit a
|
||||||
|
** multiple of 4.
|
||||||
|
*/
|
||||||
|
#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add integer part of 'x' to buffer and return new 'x'
|
||||||
|
*/
|
||||||
|
static lua_Number adddigit (char *buff, int n, lua_Number x) {
|
||||||
|
lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
|
||||||
|
int d = (int)dd;
|
||||||
|
buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
|
||||||
|
return x - dd; /* return what is left */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int num2straux (char *buff, lua_Number x) {
|
||||||
|
if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */
|
||||||
|
return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */
|
||||||
|
else if (x == 0) { /* can be -0... */
|
||||||
|
sprintf(buff, LUA_NUMBER_FMT, x);
|
||||||
|
strcat(buff, "x0p+0"); /* reuses '0/-0' from 'sprintf'... */
|
||||||
|
return strlen(buff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int e;
|
||||||
|
lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
|
||||||
|
int n = 0; /* character count */
|
||||||
|
if (m < 0) { /* is number negative? */
|
||||||
|
buff[n++] = '-'; /* add signal */
|
||||||
|
m = -m; /* make it positive */
|
||||||
|
}
|
||||||
|
buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
|
||||||
|
m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
|
||||||
|
e -= L_NBFD; /* this digit goes before the radix point */
|
||||||
|
if (m > 0) { /* more digits? */
|
||||||
|
buff[n++] = lua_getlocaledecpoint(); /* add radix point */
|
||||||
|
do { /* add as many digits as needed */
|
||||||
|
m = adddigit(buff, n++, m * 16);
|
||||||
|
} while (m > 0);
|
||||||
|
}
|
||||||
|
n += sprintf(buff + n, "p%+d", e); /* add exponent */
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int lua_number2strx (lua_State *L, char *buff, const char *fmt,
|
||||||
|
lua_Number x) {
|
||||||
|
int n = num2straux(buff, x);
|
||||||
|
if (fmt[SIZELENMOD] == 'A') {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
buff[i] = toupper(uchar(buff[i]));
|
||||||
|
}
|
||||||
|
else if (fmt[SIZELENMOD] != 'a')
|
||||||
|
luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Maximum size of each formatted item. This maximum size is produced
|
||||||
|
** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') +
|
||||||
|
** number of decimal digits to represent minfloat.
|
||||||
|
*/
|
||||||
|
#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
|
||||||
|
|
||||||
|
|
||||||
/* valid flags in a format specification */
|
/* valid flags in a format specification */
|
||||||
#define FLAGS "-+ #0"
|
#define FLAGS "-+ #0"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** maximum size of each format specification (such as "%-099.99d")
|
** maximum size of each format specification (such as "%-099.99d")
|
||||||
** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error)
|
|
||||||
*/
|
*/
|
||||||
#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10)
|
#define MAX_FORMAT 32
|
||||||
|
|
||||||
|
|
||||||
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||||
@@ -849,8 +933,8 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
|
|||||||
if (isdigit(uchar(*p)))
|
if (isdigit(uchar(*p)))
|
||||||
luaL_error(L, "invalid format (width or precision too long)");
|
luaL_error(L, "invalid format (width or precision too long)");
|
||||||
*(form++) = '%';
|
*(form++) = '%';
|
||||||
memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
|
memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
|
||||||
form += p - strfrmt + 1;
|
form += (p - strfrmt) + 1;
|
||||||
*form = '\0';
|
*form = '\0';
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -901,9 +985,10 @@ static int str_format (lua_State *L) {
|
|||||||
nb = sprintf(buff, form, n);
|
nb = sprintf(buff, form, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if defined(LUA_USE_AFORMAT)
|
|
||||||
case 'a': case 'A':
|
case 'a': case 'A':
|
||||||
#endif
|
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||||
|
nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg));
|
||||||
|
break;
|
||||||
case 'e': case 'E': case 'f':
|
case 'e': case 'E': case 'f':
|
||||||
case 'g': case 'G': {
|
case 'g': case 'G': {
|
||||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||||
@@ -921,13 +1006,12 @@ static int str_format (lua_State *L) {
|
|||||||
/* no precision and string is too long to be formatted;
|
/* no precision and string is too long to be formatted;
|
||||||
keep original string */
|
keep original string */
|
||||||
luaL_addvalue(&b);
|
luaL_addvalue(&b);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nb = sprintf(buff, form, s);
|
nb = sprintf(buff, form, s);
|
||||||
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
|
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default: { /* also treat cases 'pnLlh' */
|
default: { /* also treat cases 'pnLlh' */
|
||||||
return luaL_error(L, "invalid option '%%%c' to 'format'",
|
return luaL_error(L, "invalid option '%%%c' to 'format'",
|
||||||
@@ -1249,7 +1333,7 @@ static int str_pack (lua_State *L) {
|
|||||||
totalsize += len + 1;
|
totalsize += len + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */
|
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */
|
||||||
case Kpaddalign: case Knop:
|
case Kpaddalign: case Knop:
|
||||||
arg--; /* undo increment */
|
arg--; /* undo increment */
|
||||||
break;
|
break;
|
||||||
|
|||||||
123
3rd/lua/ltable.c
123
3rd/lua/ltable.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp $
|
** $Id: ltable.c,v 2.111 2015/06/09 14:21:13 roberto Exp $
|
||||||
** Lua tables (hash)
|
** Lua tables (hash)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
** Implementation of tables (aka arrays, objects, or hash tables).
|
** Implementation of tables (aka arrays, objects, or hash tables).
|
||||||
** Tables keep its elements in two parts: an array part and a hash part.
|
** Tables keep its elements in two parts: an array part and a hash part.
|
||||||
** Non-negative integer keys are all candidates to be kept in the array
|
** Non-negative integer keys are all candidates to be kept in the array
|
||||||
** part. The actual size of the array is the largest 'n' such that at
|
** part. The actual size of the array is the largest 'n' such that
|
||||||
** least half the slots between 0 and n are in use.
|
** more than half the slots between 1 and n are in use.
|
||||||
** Hash uses a mix of chained scatter table with Brent's variation.
|
** Hash uses a mix of chained scatter table with Brent's variation.
|
||||||
** A main invariant of these tables is that, if an element is not
|
** A main invariant of these tables is that, if an element is not
|
||||||
** in its main position (i.e. the 'original' position that its hash gives
|
** in its main position (i.e. the 'original' position that its hash gives
|
||||||
@@ -23,9 +23,7 @@
|
|||||||
** Hence even when the load factor reaches 100%, performance remains good.
|
** Hence even when the load factor reaches 100%, performance remains good.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
@@ -71,7 +69,7 @@
|
|||||||
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
|
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
|
||||||
|
|
||||||
|
|
||||||
#define hashpointer(t,p) hashmod(t, point2int(p))
|
#define hashpointer(t,p) hashmod(t, point2uint(p))
|
||||||
|
|
||||||
|
|
||||||
#define dummynode (&dummynode_)
|
#define dummynode (&dummynode_)
|
||||||
@@ -85,31 +83,33 @@ static const Node dummynode_ = {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Checks whether a float has a value representable as a lua_Integer
|
** Hash for floating-point numbers.
|
||||||
** (and does the conversion if so)
|
** The main computation should be just
|
||||||
|
** n = frepx(n, &i); return (n * INT_MAX) + i
|
||||||
|
** but there are some numerical subtleties.
|
||||||
|
** In a two-complement representation, INT_MAX does not has an exact
|
||||||
|
** representation as a float, but INT_MIN does; because the absolute
|
||||||
|
** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
|
||||||
|
** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
|
||||||
|
** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when
|
||||||
|
** adding 'i'; the use of '~u' (instead of '-u') avoids problems with
|
||||||
|
** INT_MIN.
|
||||||
*/
|
*/
|
||||||
static int numisinteger (lua_Number x, lua_Integer *p) {
|
#if !defined(l_hashfloat)
|
||||||
if ((x) == l_floor(x)) /* integral value? */
|
static int l_hashfloat (lua_Number n) {
|
||||||
return lua_numbertointeger(x, p); /* try as an integer */
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** hash for floating-point numbers
|
|
||||||
*/
|
|
||||||
static Node *hashfloat (const Table *t, lua_Number n) {
|
|
||||||
int i;
|
int i;
|
||||||
n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP);
|
lua_Integer ni;
|
||||||
i += cast_int(n);
|
n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN);
|
||||||
if (i < 0) {
|
if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */
|
||||||
if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
|
lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL);
|
||||||
i = 0; /* handle INT_MIN */
|
return 0;
|
||||||
i = -i; /* must be a positive value */
|
}
|
||||||
|
else { /* normal case */
|
||||||
|
unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni);
|
||||||
|
return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u);
|
||||||
}
|
}
|
||||||
return hashmod(t, i);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -121,13 +121,13 @@ static Node *mainposition (const Table *t, const TValue *key) {
|
|||||||
case LUA_TNUMINT:
|
case LUA_TNUMINT:
|
||||||
return hashint(t, ivalue(key));
|
return hashint(t, ivalue(key));
|
||||||
case LUA_TNUMFLT:
|
case LUA_TNUMFLT:
|
||||||
return hashfloat(t, fltvalue(key));
|
return hashmod(t, l_hashfloat(fltvalue(key)));
|
||||||
case LUA_TSHRSTR:
|
case LUA_TSHRSTR:
|
||||||
return hashstr(t, tsvalue(key));
|
return hashstr(t, tsvalue(key));
|
||||||
case LUA_TLNGSTR: {
|
case LUA_TLNGSTR: {
|
||||||
TString *s = tsvalue(key);
|
TString *s = tsvalue(key);
|
||||||
if (s->extra == 0) { /* no hash? */
|
if (s->extra == 0) { /* no hash? */
|
||||||
s->hash = luaS_hash(getstr(s), s->len, s->hash);
|
s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash);
|
||||||
s->extra = 1; /* now it has its hash */
|
s->extra = 1; /* now it has its hash */
|
||||||
}
|
}
|
||||||
return hashstr(t, tsvalue(key));
|
return hashstr(t, tsvalue(key));
|
||||||
@@ -219,28 +219,29 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
|
|||||||
/*
|
/*
|
||||||
** Compute the optimal size for the array part of table 't'. 'nums' is a
|
** Compute the optimal size for the array part of table 't'. 'nums' is a
|
||||||
** "count array" where 'nums[i]' is the number of integers in the table
|
** "count array" where 'nums[i]' is the number of integers in the table
|
||||||
** between 2^(i - 1) + 1 and 2^i. Put in '*narray' the optimal size, and
|
** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of
|
||||||
** return the number of elements that will go to that part.
|
** integer keys in the table and leaves with the number of keys that
|
||||||
|
** will go to the array part; return the optimal size.
|
||||||
*/
|
*/
|
||||||
static unsigned int computesizes (unsigned int nums[], unsigned int *narray) {
|
static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
|
||||||
int i;
|
int i;
|
||||||
unsigned int twotoi; /* 2^i */
|
unsigned int twotoi; /* 2^i (candidate for optimal size) */
|
||||||
unsigned int a = 0; /* number of elements smaller than 2^i */
|
unsigned int a = 0; /* number of elements smaller than 2^i */
|
||||||
unsigned int na = 0; /* number of elements to go to array part */
|
unsigned int na = 0; /* number of elements to go to array part */
|
||||||
unsigned int n = 0; /* optimal size for array part */
|
unsigned int optimal = 0; /* optimal size for array part */
|
||||||
for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
|
/* loop while keys can fill more than half of total size */
|
||||||
|
for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) {
|
||||||
if (nums[i] > 0) {
|
if (nums[i] > 0) {
|
||||||
a += nums[i];
|
a += nums[i];
|
||||||
if (a > twotoi/2) { /* more than half elements present? */
|
if (a > twotoi/2) { /* more than half elements present? */
|
||||||
n = twotoi; /* optimal size (till now) */
|
optimal = twotoi; /* optimal size (till now) */
|
||||||
na = a; /* all elements up to 'n' will go to array part */
|
na = a; /* all elements up to 'optimal' will go to array part */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (a == *narray) break; /* all elements already counted */
|
|
||||||
}
|
}
|
||||||
*narray = n;
|
lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal);
|
||||||
lua_assert(*narray/2 <= na && na <= *narray);
|
*pna = na;
|
||||||
return na;
|
return optimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,6 +256,11 @@ static int countint (const TValue *key, unsigned int *nums) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Count keys in array part of table 't': Fill 'nums[i]' with
|
||||||
|
** number of keys that will go into corresponding slice and return
|
||||||
|
** total number of non-nil keys.
|
||||||
|
*/
|
||||||
static unsigned int numusearray (const Table *t, unsigned int *nums) {
|
static unsigned int numusearray (const Table *t, unsigned int *nums) {
|
||||||
int lg;
|
int lg;
|
||||||
unsigned int ttlg; /* 2^lg */
|
unsigned int ttlg; /* 2^lg */
|
||||||
@@ -281,8 +287,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int numusehash (const Table *t, unsigned int *nums,
|
static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
|
||||||
unsigned int *pnasize) {
|
|
||||||
int totaluse = 0; /* total number of elements */
|
int totaluse = 0; /* total number of elements */
|
||||||
int ause = 0; /* elements added to 'nums' (can go to array part) */
|
int ause = 0; /* elements added to 'nums' (can go to array part) */
|
||||||
int i = sizenode(t);
|
int i = sizenode(t);
|
||||||
@@ -293,7 +298,7 @@ static int numusehash (const Table *t, unsigned int *nums,
|
|||||||
totaluse++;
|
totaluse++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*pnasize += ause;
|
*pna += ause;
|
||||||
return totaluse;
|
return totaluse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +368,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isdummy(nold))
|
if (!isdummy(nold))
|
||||||
luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */
|
luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -376,21 +381,22 @@ void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
|
|||||||
** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
|
** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
|
||||||
*/
|
*/
|
||||||
static void rehash (lua_State *L, Table *t, const TValue *ek) {
|
static void rehash (lua_State *L, Table *t, const TValue *ek) {
|
||||||
unsigned int nasize, na;
|
unsigned int asize; /* optimal size for array part */
|
||||||
|
unsigned int na; /* number of keys in the array part */
|
||||||
unsigned int nums[MAXABITS + 1];
|
unsigned int nums[MAXABITS + 1];
|
||||||
int i;
|
int i;
|
||||||
int totaluse;
|
int totaluse;
|
||||||
for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
|
for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
|
||||||
nasize = numusearray(t, nums); /* count keys in array part */
|
na = numusearray(t, nums); /* count keys in array part */
|
||||||
totaluse = nasize; /* all those keys are integer keys */
|
totaluse = na; /* all those keys are integer keys */
|
||||||
totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
|
totaluse += numusehash(t, nums, &na); /* count keys in hash part */
|
||||||
/* count extra key */
|
/* count extra key */
|
||||||
nasize += countint(ek, nums);
|
na += countint(ek, nums);
|
||||||
totaluse++;
|
totaluse++;
|
||||||
/* compute new size for array part */
|
/* compute new size for array part */
|
||||||
na = computesizes(nums, &nasize);
|
asize = computesizes(nums, &na);
|
||||||
/* resize the table to new computed sizes */
|
/* resize the table to new computed sizes */
|
||||||
luaH_resize(L, t, nasize, totaluse - na);
|
luaH_resize(L, t, asize, totaluse - na);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -443,14 +449,13 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|||||||
TValue aux;
|
TValue aux;
|
||||||
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
|
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
|
||||||
else if (ttisfloat(key)) {
|
else if (ttisfloat(key)) {
|
||||||
lua_Number n = fltvalue(key);
|
|
||||||
lua_Integer k;
|
lua_Integer k;
|
||||||
if (luai_numisnan(n))
|
if (luaV_tointeger(key, &k, 0)) { /* index is int? */
|
||||||
luaG_runerror(L, "table index is NaN");
|
|
||||||
if (numisinteger(n, &k)) { /* index is int? */
|
|
||||||
setivalue(&aux, k);
|
setivalue(&aux, k);
|
||||||
key = &aux; /* insert it as an integer */
|
key = &aux; /* insert it as an integer */
|
||||||
}
|
}
|
||||||
|
else if (luai_numisnan(fltvalue(key)))
|
||||||
|
luaG_runerror(L, "table index is NaN");
|
||||||
}
|
}
|
||||||
mp = mainposition(t, key);
|
mp = mainposition(t, key);
|
||||||
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
|
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
|
||||||
@@ -544,10 +549,10 @@ const TValue *luaH_get (Table *t, const TValue *key) {
|
|||||||
case LUA_TNIL: return luaO_nilobject;
|
case LUA_TNIL: return luaO_nilobject;
|
||||||
case LUA_TNUMFLT: {
|
case LUA_TNUMFLT: {
|
||||||
lua_Integer k;
|
lua_Integer k;
|
||||||
if (numisinteger(fltvalue(key), &k)) /* index is int? */
|
if (luaV_tointeger(key, &k, 0)) /* index is int? */
|
||||||
return luaH_getint(t, k); /* use specialized version */
|
return luaH_getint(t, k); /* use specialized version */
|
||||||
/* else go through */
|
/* else... */
|
||||||
}
|
} /* FALLTHROUGH */
|
||||||
default: {
|
default: {
|
||||||
Node *n = mainposition(t, key);
|
Node *n = mainposition(t, key);
|
||||||
for (;;) { /* check whether 'key' is somewhere in the chain */
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $
|
** $Id: ltablib.c,v 1.80 2015/01/13 16:27:29 roberto Exp $
|
||||||
** Library for Table Manipulation
|
** Library for Table Manipulation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -124,8 +124,6 @@ static int tmove (lua_State *L) {
|
|||||||
lua_Integer e = luaL_checkinteger(L, 3);
|
lua_Integer e = luaL_checkinteger(L, 3);
|
||||||
lua_Integer t = luaL_checkinteger(L, 4);
|
lua_Integer t = luaL_checkinteger(L, 4);
|
||||||
int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
|
int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
|
||||||
/* the following restriction avoids several problems with overflows */
|
|
||||||
luaL_argcheck(L, f > 0, 2, "initial position must be positive");
|
|
||||||
if (e >= f) { /* otherwise, nothing to move */
|
if (e >= f) { /* otherwise, nothing to move */
|
||||||
lua_Integer n, i;
|
lua_Integer n, i;
|
||||||
ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
|
ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
|
||||||
@@ -134,7 +132,11 @@ static int tmove (lua_State *L) {
|
|||||||
ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
|
ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
|
||||||
? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
|
? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
|
||||||
: lua_seti;
|
: lua_seti;
|
||||||
|
luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
|
||||||
|
"too many elements to move");
|
||||||
n = e - f + 1; /* number of elements to move */
|
n = e - f + 1; /* number of elements to move */
|
||||||
|
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
|
||||||
|
"destination wrap around");
|
||||||
if (t > f) {
|
if (t > f) {
|
||||||
for (i = n - 1; i >= 0; i--) {
|
for (i = n - 1; i >= 0; i--) {
|
||||||
(*ta.geti)(L, 1, f + i);
|
(*ta.geti)(L, 1, f + i);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp $
|
** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -117,6 +117,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
case TM_CONCAT:
|
case TM_CONCAT:
|
||||||
luaG_concaterror(L, p1, p2);
|
luaG_concaterror(L, p1, p2);
|
||||||
|
/* call never returns, but to avoid warnings: *//* FALLTHROUGH */
|
||||||
case TM_BAND: case TM_BOR: case TM_BXOR:
|
case TM_BAND: case TM_BOR: case TM_BXOR:
|
||||||
case TM_SHL: case TM_SHR: case TM_BNOT: {
|
case TM_SHL: case TM_SHR: case TM_BNOT: {
|
||||||
lua_Number dummy;
|
lua_Number dummy;
|
||||||
@@ -124,8 +125,8 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
|||||||
luaG_tointerror(L, p1, p2);
|
luaG_tointerror(L, p1, p2);
|
||||||
else
|
else
|
||||||
luaG_opinterror(L, p1, p2, "perform bitwise operation on");
|
luaG_opinterror(L, p1, p2, "perform bitwise operation on");
|
||||||
/* else go through */
|
|
||||||
}
|
}
|
||||||
|
/* calls never return, but to avoid warnings: *//* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
luaG_opinterror(L, p1, p2, "perform arithmetic on");
|
luaG_opinterror(L, p1, p2, "perform arithmetic on");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lua.c,v 1.222 2014/11/11 19:41:27 roberto Exp $
|
** $Id: lua.c,v 1.225 2015/03/30 15:42:59 roberto Exp $
|
||||||
** Lua stand-alone interpreter
|
** Lua stand-alone interpreter
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -80,9 +80,7 @@
|
|||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
||||||
#define lua_saveline(L,idx) \
|
#define lua_saveline(L,line) ((void)L, add_history(line))
|
||||||
if (lua_rawlen(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))
|
#define lua_freeline(L,b) ((void)L, free(b))
|
||||||
|
|
||||||
#else /* }{ */
|
#else /* }{ */
|
||||||
@@ -90,7 +88,7 @@
|
|||||||
#define lua_readline(L,b,p) \
|
#define lua_readline(L,b,p) \
|
||||||
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
||||||
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
|
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
|
||||||
#define lua_saveline(L,idx) { (void)L; (void)idx; }
|
#define lua_saveline(L,line) { (void)L; (void)line; }
|
||||||
#define lua_freeline(L,b) { (void)L; (void)b; }
|
#define lua_freeline(L,b) { (void)L; (void)b; }
|
||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
@@ -315,11 +313,11 @@ static int pushline (lua_State *L, int firstline) {
|
|||||||
lua_pop(L, 1); /* remove prompt */
|
lua_pop(L, 1); /* remove prompt */
|
||||||
l = strlen(b);
|
l = strlen(b);
|
||||||
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
|
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
|
||||||
b[l-1] = '\0'; /* remove it */
|
b[--l] = '\0'; /* remove it */
|
||||||
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
|
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
|
||||||
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
|
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
|
||||||
else
|
else
|
||||||
lua_pushstring(L, b);
|
lua_pushlstring(L, b, l);
|
||||||
lua_freeline(L, b);
|
lua_freeline(L, b);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -336,8 +334,12 @@ static int addreturn (lua_State *L) {
|
|||||||
lua_pushvalue(L, -2); /* duplicate line */
|
lua_pushvalue(L, -2); /* duplicate line */
|
||||||
lua_concat(L, 2); /* new line is "return ..." */
|
lua_concat(L, 2); /* new line is "return ..." */
|
||||||
line = lua_tolstring(L, -1, &len);
|
line = lua_tolstring(L, -1, &len);
|
||||||
if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK)
|
if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) {
|
||||||
lua_remove(L, -3); /* remove original line */
|
lua_remove(L, -3); /* remove original line */
|
||||||
|
line += sizeof("return")/sizeof(char); /* remove 'return' for history */
|
||||||
|
if (line[0] != '\0') /* non empty? */
|
||||||
|
lua_saveline(L, line); /* keep history */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */
|
lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */
|
||||||
return status;
|
return status;
|
||||||
@@ -352,8 +354,10 @@ static int multiline (lua_State *L) {
|
|||||||
size_t len;
|
size_t len;
|
||||||
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
|
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
|
||||||
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
|
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
|
||||||
if (!incomplete(L, status) || !pushline(L, 0))
|
if (!incomplete(L, status) || !pushline(L, 0)) {
|
||||||
|
lua_saveline(L, line); /* keep history */
|
||||||
return status; /* cannot or should not try to add continuation line */
|
return status; /* cannot or should not try to add continuation line */
|
||||||
|
}
|
||||||
lua_pushliteral(L, "\n"); /* add newline... */
|
lua_pushliteral(L, "\n"); /* add newline... */
|
||||||
lua_insert(L, -2); /* ...between the two lines */
|
lua_insert(L, -2); /* ...between the two lines */
|
||||||
lua_concat(L, 3); /* join them */
|
lua_concat(L, 3); /* join them */
|
||||||
@@ -374,7 +378,6 @@ static int loadline (lua_State *L) {
|
|||||||
return -1; /* no input */
|
return -1; /* no input */
|
||||||
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
|
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
|
||||||
status = multiline(L); /* try as command, maybe with continuation lines */
|
status = multiline(L); /* try as command, maybe with continuation lines */
|
||||||
lua_saveline(L, 1); /* keep history */
|
|
||||||
lua_remove(L, 1); /* remove line from the stack */
|
lua_remove(L, 1); /* remove line from the stack */
|
||||||
lua_assert(lua_gettop(L) == 1);
|
lua_assert(lua_gettop(L) == 1);
|
||||||
return status;
|
return status;
|
||||||
@@ -482,14 +485,14 @@ static int collectargs (char **argv, int *first) {
|
|||||||
args |= has_E;
|
args |= has_E;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
args |= has_i; /* goes through (-i implies -v) */
|
args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
|
||||||
case 'v':
|
case 'v':
|
||||||
if (argv[i][2] != '\0') /* extra characters after 1st? */
|
if (argv[i][2] != '\0') /* extra characters after 1st? */
|
||||||
return has_error; /* invalid option */
|
return has_error; /* invalid option */
|
||||||
args |= has_v;
|
args |= has_v;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
args |= has_e; /* go through */
|
args |= has_e; /* FALLTHROUGH */
|
||||||
case 'l': /* both options need an argument */
|
case 'l': /* both options need an argument */
|
||||||
if (argv[i][2] == '\0') { /* no concatenated argument? */
|
if (argv[i][2] == '\0') { /* no concatenated argument? */
|
||||||
i++; /* try next 'argv' */
|
i++; /* try next 'argv' */
|
||||||
@@ -513,17 +516,16 @@ static int collectargs (char **argv, int *first) {
|
|||||||
static int runargs (lua_State *L, char **argv, int n) {
|
static int runargs (lua_State *L, char **argv, int n) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i < n; i++) {
|
for (i = 1; i < n; i++) {
|
||||||
int status;
|
|
||||||
int option = argv[i][1];
|
int option = argv[i][1];
|
||||||
lua_assert(argv[i][0] == '-'); /* already checked */
|
lua_assert(argv[i][0] == '-'); /* already checked */
|
||||||
if (option == 'e' || option == 'l') {
|
if (option == 'e' || option == 'l') {
|
||||||
|
int status;
|
||||||
const char *extra = argv[i] + 2; /* both options need an argument */
|
const char *extra = argv[i] + 2; /* both options need an argument */
|
||||||
if (*extra == '\0') extra = argv[++i];
|
if (*extra == '\0') extra = argv[++i];
|
||||||
lua_assert(extra != NULL);
|
lua_assert(extra != NULL);
|
||||||
if (option == 'e')
|
status = (option == 'e')
|
||||||
status = dostring(L, extra, "=(command line)");
|
? dostring(L, extra, "=(command line)")
|
||||||
else
|
: dolibrary(L, extra);
|
||||||
status = dolibrary(L, extra);
|
|
||||||
if (status != LUA_OK) return 0;
|
if (status != LUA_OK) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lua.h,v 1.325 2014/12/26 17:24:27 roberto Exp $
|
** $Id: lua.h,v 1.328 2015/06/03 13:03:38 roberto Exp $
|
||||||
** Lua - A Scripting Language
|
** Lua - A Scripting Language
|
||||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||||
** See Copyright Notice at the end of this file
|
** See Copyright Notice at the end of this file
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
#define LUA_VERSION_MAJOR "5"
|
#define LUA_VERSION_MAJOR "5"
|
||||||
#define LUA_VERSION_MINOR "3"
|
#define LUA_VERSION_MINOR "3"
|
||||||
#define LUA_VERSION_NUM 503
|
#define LUA_VERSION_NUM 503
|
||||||
#define LUA_VERSION_RELEASE "0"
|
#define LUA_VERSION_RELEASE "1"
|
||||||
|
|
||||||
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||||
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
||||||
@@ -35,9 +35,11 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** pseudo-indices
|
** Pseudo-indices
|
||||||
|
** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
|
||||||
|
** space after that to help overflow detection)
|
||||||
*/
|
*/
|
||||||
#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX
|
#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
|
||||||
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
|
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
|
||||||
|
|
||||||
|
|
||||||
@@ -282,6 +284,7 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
|
|||||||
|
|
||||||
LUA_API void (lua_clonefunction) (lua_State *L, const void *eL);
|
LUA_API void (lua_clonefunction) (lua_State *L, const void *eL);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** coroutine functions
|
** coroutine functions
|
||||||
*/
|
*/
|
||||||
@@ -357,8 +360,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
|
|||||||
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
|
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
|
||||||
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
||||||
|
|
||||||
#define lua_pushliteral(L, s) \
|
#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||||
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
|
|
||||||
|
|
||||||
#define lua_pushglobaltable(L) \
|
#define lua_pushglobaltable(L) \
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
|
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
|
||||||
@@ -460,7 +462,7 @@ struct lua_Debug {
|
|||||||
|
|
||||||
/* Add by skynet */
|
/* Add by skynet */
|
||||||
|
|
||||||
extern lua_State * skynet_sig_L;
|
LUA_API lua_State * skynet_sig_L;
|
||||||
LUA_API void (lua_checksig_)(lua_State *L);
|
LUA_API void (lua_checksig_)(lua_State *L);
|
||||||
#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); }
|
#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); }
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: luac.c,v 1.72 2015/01/06 03:09:13 lhf Exp $
|
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
|
||||||
** Lua compiler (saves bytecodes to files; also lists bytecodes)
|
** Lua compiler (saves bytecodes to files; also lists bytecodes)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -206,7 +206,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** $Id: print.c,v 1.76 2015/01/05 16:12:50 lhf Exp $
|
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
|
||||||
** print bytecodes
|
** print bytecodes
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -226,7 +226,7 @@ int main(int argc, char* argv[])
|
|||||||
static void PrintString(const TString* ts)
|
static void PrintString(const TString* ts)
|
||||||
{
|
{
|
||||||
const char* s=getstr(ts);
|
const char* s=getstr(ts);
|
||||||
size_t i,n=ts->len;
|
size_t i,n=tsslen(ts);
|
||||||
printf("%c",'"');
|
printf("%c",'"');
|
||||||
for (i=0; i<n; i++)
|
for (i=0; i<n; i++)
|
||||||
{
|
{
|
||||||
@@ -287,9 +287,8 @@ static void PrintConstant(const Proto* f, int i)
|
|||||||
|
|
||||||
static void PrintCode(const Proto* f)
|
static void PrintCode(const Proto* f)
|
||||||
{
|
{
|
||||||
const SharedProto *sp = f->sp;
|
const Instruction* code=f->sp->code;
|
||||||
const Instruction* code=sp->code;
|
int pc,n=f->sp->sizecode;
|
||||||
int pc,n=sp->sizecode;
|
|
||||||
for (pc=0; pc<n; pc++)
|
for (pc=0; pc<n; pc++)
|
||||||
{
|
{
|
||||||
Instruction i=code[pc];
|
Instruction i=code[pc];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $
|
** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $
|
||||||
** Configuration file for Lua
|
** Configuration file for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -96,10 +96,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for
|
@@ LUA_INT_TYPE defines the type for Lua integers.
|
||||||
** Lua integers.
|
@@ LUA_FLOAT_TYPE defines the type for Lua floats.
|
||||||
@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines
|
|
||||||
** the type for Lua floats.
|
|
||||||
** Lua should work fine with any mix of these options (if supported
|
** Lua should work fine with any mix of these options (if supported
|
||||||
** by your C compiler). The usual configurations are 64-bit integers
|
** by your C compiler). The usual configurations are 64-bit integers
|
||||||
** and 'double' (the default), 32-bit integers and 'float' (for
|
** and 'double' (the default), 32-bit integers and 'float' (for
|
||||||
@@ -107,31 +105,46 @@
|
|||||||
** compliant with C99, which may not have support for 'long long').
|
** compliant with C99, which may not have support for 'long long').
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* predefined options for LUA_INT_TYPE */
|
||||||
|
#define LUA_INT_INT 1
|
||||||
|
#define LUA_INT_LONG 2
|
||||||
|
#define LUA_INT_LONGLONG 3
|
||||||
|
|
||||||
|
/* predefined options for LUA_FLOAT_TYPE */
|
||||||
|
#define LUA_FLOAT_FLOAT 1
|
||||||
|
#define LUA_FLOAT_DOUBLE 2
|
||||||
|
#define LUA_FLOAT_LONGDOUBLE 3
|
||||||
|
|
||||||
#if defined(LUA_32BITS) /* { */
|
#if defined(LUA_32BITS) /* { */
|
||||||
/*
|
/*
|
||||||
** 32-bit integers and 'float'
|
** 32-bit integers and 'float'
|
||||||
*/
|
*/
|
||||||
#if LUAI_BITSINT >= 32 /* use 'int' if big enough */
|
#if LUAI_BITSINT >= 32 /* use 'int' if big enough */
|
||||||
#define LUA_INT_INT
|
#define LUA_INT_TYPE LUA_INT_INT
|
||||||
#else /* otherwise use 'long' */
|
#else /* otherwise use 'long' */
|
||||||
#define LUA_INT_LONG
|
#define LUA_INT_TYPE LUA_INT_LONG
|
||||||
#endif
|
#endif
|
||||||
#define LUA_REAL_FLOAT
|
#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
|
||||||
|
|
||||||
#elif defined(LUA_C89_NUMBERS) /* }{ */
|
#elif defined(LUA_C89_NUMBERS) /* }{ */
|
||||||
/*
|
/*
|
||||||
** largest types available for C89 ('long' and 'double')
|
** largest types available for C89 ('long' and 'double')
|
||||||
*/
|
*/
|
||||||
#define LUA_INT_LONG
|
#define LUA_INT_TYPE LUA_INT_LONG
|
||||||
#define LUA_REAL_DOUBLE
|
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
#else /* }{ */
|
|
||||||
/*
|
/*
|
||||||
** default configuration for 64-bit Lua ('long long' and 'double')
|
** default configuration for 64-bit Lua ('long long' and 'double')
|
||||||
*/
|
*/
|
||||||
#define LUA_INT_LONGLONG
|
#if !defined(LUA_INT_TYPE)
|
||||||
#define LUA_REAL_DOUBLE
|
#define LUA_INT_TYPE LUA_INT_LONGLONG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LUA_FLOAT_TYPE)
|
||||||
|
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
@@ -155,7 +168,7 @@
|
|||||||
** non-conventional directories.
|
** non-conventional directories.
|
||||||
*/
|
*/
|
||||||
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||||
#if defined(_WIN32) /* { */
|
#if defined(_WIN32) /* { */
|
||||||
/*
|
/*
|
||||||
** In Windows, any exclamation mark ('!') in the path is replaced by the
|
** In Windows, any exclamation mark ('!') in the path is replaced by the
|
||||||
** path of the directory of the executable file of the current process.
|
** path of the directory of the executable file of the current process.
|
||||||
@@ -300,20 +313,15 @@
|
|||||||
*/
|
*/
|
||||||
#define LUA_COMPAT_APIINTCASTS
|
#define LUA_COMPAT_APIINTCASTS
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
|
|
||||||
@@ a float mark ('.0').
|
|
||||||
** This macro is not on by default even in compatibility mode,
|
|
||||||
** because this is not really an incompatibility.
|
|
||||||
*/
|
|
||||||
/* #define LUA_COMPAT_FLOATSTRING */
|
|
||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
#if defined(LUA_COMPAT_5_1) /* { */
|
#if defined(LUA_COMPAT_5_1) /* { */
|
||||||
|
|
||||||
|
/* Incompatibilities from 5.2 -> 5.3 */
|
||||||
|
#define LUA_COMPAT_MATHLIB
|
||||||
|
#define LUA_COMPAT_APIINTCASTS
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
|
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
|
||||||
** You can replace it with 'table.unpack'.
|
** You can replace it with 'table.unpack'.
|
||||||
@@ -373,6 +381,15 @@
|
|||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
|
||||||
|
@@ a float mark ('.0').
|
||||||
|
** This macro is not on by default even in compatibility mode,
|
||||||
|
** because this is not really an incompatibility.
|
||||||
|
*/
|
||||||
|
/* #define LUA_COMPAT_FLOATSTRING */
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
@@ -380,30 +397,30 @@
|
|||||||
/*
|
/*
|
||||||
** {==================================================================
|
** {==================================================================
|
||||||
** Configuration for Numbers.
|
** Configuration for Numbers.
|
||||||
** Change these definitions if no predefined LUA_REAL_* / LUA_INT_*
|
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
|
||||||
** satisfy your needs.
|
** satisfy your needs.
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_NUMBER is the floating-point type used by Lua.
|
@@ LUA_NUMBER is the floating-point type used by Lua.
|
||||||
**
|
|
||||||
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
|
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
|
||||||
@@ over a floating number.
|
@@ over a floating number.
|
||||||
**
|
@@ l_mathlim(x) corrects limit name 'x' to the proper float type
|
||||||
|
** by prefixing it with one of FLT/DBL/LDBL.
|
||||||
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
|
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
|
||||||
@@ LUA_NUMBER_FMT is the format for writing floats.
|
@@ LUA_NUMBER_FMT is the format for writing floats.
|
||||||
@@ lua_number2str converts a float to a string.
|
@@ lua_number2str converts a float to a string.
|
||||||
**
|
|
||||||
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
|
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
|
||||||
**
|
|
||||||
@@ lua_str2number converts a decimal numeric string to a number.
|
@@ lua_str2number converts a decimal numeric string to a number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(LUA_REAL_FLOAT) /* { single float */
|
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
|
||||||
|
|
||||||
#define LUA_NUMBER float
|
#define LUA_NUMBER float
|
||||||
|
|
||||||
|
#define l_mathlim(n) (FLT_##n)
|
||||||
|
|
||||||
#define LUAI_UACNUMBER double
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN ""
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
@@ -414,10 +431,12 @@
|
|||||||
#define lua_str2number(s,p) strtof((s), (p))
|
#define lua_str2number(s,p) strtof((s), (p))
|
||||||
|
|
||||||
|
|
||||||
#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */
|
#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
|
||||||
|
|
||||||
#define LUA_NUMBER long double
|
#define LUA_NUMBER long double
|
||||||
|
|
||||||
|
#define l_mathlim(n) (LDBL_##n)
|
||||||
|
|
||||||
#define LUAI_UACNUMBER long double
|
#define LUAI_UACNUMBER long double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN "L"
|
#define LUA_NUMBER_FRMLEN "L"
|
||||||
@@ -427,10 +446,12 @@
|
|||||||
|
|
||||||
#define lua_str2number(s,p) strtold((s), (p))
|
#define lua_str2number(s,p) strtold((s), (p))
|
||||||
|
|
||||||
#elif defined(LUA_REAL_DOUBLE) /* }{ double */
|
#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
|
||||||
|
|
||||||
#define LUA_NUMBER double
|
#define LUA_NUMBER double
|
||||||
|
|
||||||
|
#define l_mathlim(n) (DBL_##n)
|
||||||
|
|
||||||
#define LUAI_UACNUMBER double
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN ""
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
@@ -440,9 +461,9 @@
|
|||||||
|
|
||||||
#define lua_str2number(s,p) strtod((s), (p))
|
#define lua_str2number(s,p) strtod((s), (p))
|
||||||
|
|
||||||
#else /* }{ */
|
#else /* }{ */
|
||||||
|
|
||||||
#error "numeric real type not defined"
|
#error "numeric float type not defined"
|
||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
||||||
@@ -466,46 +487,6 @@
|
|||||||
(*(p) = (LUA_INTEGER)(n), 1))
|
(*(p) = (LUA_INTEGER)(n), 1))
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ The luai_num* macros define the primitive operations over numbers.
|
|
||||||
** They should work for any size of floating numbers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* the following operations need the math library */
|
|
||||||
#if defined(lobject_c) || defined(lvm_c)
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
/* floor division (defined as 'floor(a/b)') */
|
|
||||||
#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)(luai_numdiv(L,a,b)))
|
|
||||||
|
|
||||||
/*
|
|
||||||
** module: defined as 'a - floor(a/b)*b'; the previous definition gives
|
|
||||||
** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the
|
|
||||||
** result of 'a - trunc(a/b)*b', and therefore must be corrected when
|
|
||||||
** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
|
|
||||||
** non-integer negative result, which is equivalent to the test below
|
|
||||||
*/
|
|
||||||
#define luai_nummod(L,a,b,m) \
|
|
||||||
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
|
|
||||||
|
|
||||||
/* exponentiation */
|
|
||||||
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* these are quite standard operations */
|
|
||||||
#if defined(LUA_CORE)
|
|
||||||
#define luai_numadd(L,a,b) ((a)+(b))
|
|
||||||
#define luai_numsub(L,a,b) ((a)-(b))
|
|
||||||
#define luai_nummul(L,a,b) ((a)*(b))
|
|
||||||
#define luai_numdiv(L,a,b) ((a)/(b))
|
|
||||||
#define luai_numunm(L,a) (-(a))
|
|
||||||
#define luai_numeq(a,b) ((a)==(b))
|
|
||||||
#define luai_numlt(a,b) ((a)<(b))
|
|
||||||
#define luai_numle(a,b) ((a)<=(b))
|
|
||||||
#define luai_numisnan(a) (!luai_numeq((a), (a)))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_INTEGER is the integer type used by Lua.
|
@@ LUA_INTEGER is the integer type used by Lua.
|
||||||
@@ -538,7 +519,7 @@
|
|||||||
|
|
||||||
/* now the variable definitions */
|
/* now the variable definitions */
|
||||||
|
|
||||||
#if defined(LUA_INT_INT) /* { int */
|
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
|
||||||
|
|
||||||
#define LUA_INTEGER int
|
#define LUA_INTEGER int
|
||||||
#define LUA_INTEGER_FRMLEN ""
|
#define LUA_INTEGER_FRMLEN ""
|
||||||
@@ -546,7 +527,7 @@
|
|||||||
#define LUA_MAXINTEGER INT_MAX
|
#define LUA_MAXINTEGER INT_MAX
|
||||||
#define LUA_MININTEGER INT_MIN
|
#define LUA_MININTEGER INT_MIN
|
||||||
|
|
||||||
#elif defined(LUA_INT_LONG) /* }{ long */
|
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
|
||||||
|
|
||||||
#define LUA_INTEGER long
|
#define LUA_INTEGER long
|
||||||
#define LUA_INTEGER_FRMLEN "l"
|
#define LUA_INTEGER_FRMLEN "l"
|
||||||
@@ -554,7 +535,7 @@
|
|||||||
#define LUA_MAXINTEGER LONG_MAX
|
#define LUA_MAXINTEGER LONG_MAX
|
||||||
#define LUA_MININTEGER LONG_MIN
|
#define LUA_MININTEGER LONG_MIN
|
||||||
|
|
||||||
#elif defined(LUA_INT_LONGLONG) /* }{ long long */
|
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
|
||||||
|
|
||||||
#if defined(LLONG_MAX) /* { */
|
#if defined(LLONG_MAX) /* { */
|
||||||
/* use ISO C99 stuff */
|
/* use ISO C99 stuff */
|
||||||
@@ -592,13 +573,13 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** {==================================================================
|
** {==================================================================
|
||||||
** Dependencies with C99
|
** Dependencies with C99 and other C details
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ lua_strx2number converts an hexadecimal numeric string to a number.
|
@@ lua_strx2number converts an hexadecimal numeric string to a number.
|
||||||
** In C99, 'strtod' does both conversions. Otherwise, you can
|
** In C99, 'strtod' does that conversion. Otherwise, you can
|
||||||
** leave 'lua_strx2number' undefined and Lua will provide its own
|
** leave 'lua_strx2number' undefined and Lua will provide its own
|
||||||
** implementation.
|
** implementation.
|
||||||
*/
|
*/
|
||||||
@@ -608,12 +589,13 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format'
|
@@ lua_number2strx converts a float to an hexadecimal numeric string.
|
||||||
** Enable it if the C function 'printf' supports these specifiers.
|
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
|
||||||
** (C99 demands it and Windows also supports it.)
|
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
|
||||||
|
** provide its own implementation.
|
||||||
*/
|
*/
|
||||||
#if !defined(LUA_USE_C89) || defined(LUA_USE_WINDOWS)
|
#if !defined(LUA_USE_C89)
|
||||||
#define LUA_USE_AFORMAT
|
#define lua_number2strx(L,b,f,n) sprintf(b,f,n)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -642,12 +624,50 @@
|
|||||||
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
|
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
|
||||||
__STDC_VERSION__ >= 199901L
|
__STDC_VERSION__ >= 199901L
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#if defined (INTPTR_MAX) /* even in C99 this type is optional */
|
#if defined(INTPTR_MAX) /* even in C99 this type is optional */
|
||||||
#undef LUA_KCONTEXT
|
#undef LUA_KCONTEXT
|
||||||
#define LUA_KCONTEXT intptr_t
|
#define LUA_KCONTEXT intptr_t
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
|
||||||
|
** Change that if you do not want to use C locales. (Code using this
|
||||||
|
** macro must include header 'locale.h'.)
|
||||||
|
*/
|
||||||
|
#if !defined(lua_getlocaledecpoint)
|
||||||
|
#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Language Variations
|
||||||
|
** =====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
|
||||||
|
** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
|
||||||
|
** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
|
||||||
|
** coercion from strings to numbers.
|
||||||
|
*/
|
||||||
|
/* #define LUA_NOCVTN2S */
|
||||||
|
/* #define LUA_NOCVTS2N */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
|
||||||
|
** Define it as a help when debugging C code.
|
||||||
|
*/
|
||||||
|
#if defined(LUA_USE_APICHECK)
|
||||||
|
#include <assert.h>
|
||||||
|
#define luai_apicheck(l,e) assert(e)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
@@ -671,9 +691,6 @@
|
|||||||
#define LUAI_MAXSTACK 15000
|
#define LUAI_MAXSTACK 15000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reserve some space for error handling */
|
|
||||||
#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
|
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
|
||||||
@@ -691,20 +708,18 @@
|
|||||||
#define LUA_IDSIZE 60
|
#define LUA_IDSIZE 60
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
|
|
||||||
** strings that are internalized. (Cannot be smaller than reserved words
|
|
||||||
** or tags for metamethods, as these strings must be internalized;
|
|
||||||
** #("function") = 8, #("__newindex") = 10.)
|
|
||||||
*/
|
|
||||||
#define LUAI_MAXSHORTLEN 40
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
|
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
|
||||||
** CHANGE it if it uses too much C-stack space.
|
** CHANGE it if it uses too much C-stack space. (For long double,
|
||||||
|
** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a
|
||||||
|
** smaller buffer would force a memory allocation for each call to
|
||||||
|
** 'string.format'.)
|
||||||
*/
|
*/
|
||||||
#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
|
#if defined(LUA_FLOAT_LONGDOUBLE)
|
||||||
|
#define LUAL_BUFFERSIZE 8192
|
||||||
|
#else
|
||||||
|
#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $
|
** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $
|
||||||
** Standard library for UTF-8 manipulation
|
** Standard library for UTF-8 manipulation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
|
|||||||
** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
|
** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
|
||||||
*/
|
*/
|
||||||
static const char *utf8_decode (const char *o, int *val) {
|
static const char *utf8_decode (const char *o, int *val) {
|
||||||
static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
|
static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
|
||||||
const unsigned char *s = (const unsigned char *)o;
|
const unsigned char *s = (const unsigned char *)o;
|
||||||
unsigned int c = s[0];
|
unsigned int c = s[0];
|
||||||
unsigned int res = 0; /* final result */
|
unsigned int res = 0; /* final result */
|
||||||
@@ -106,9 +107,9 @@ static int codepoint (lua_State *L) {
|
|||||||
luaL_argcheck(L, posi >= 1, 2, "out of range");
|
luaL_argcheck(L, posi >= 1, 2, "out of range");
|
||||||
luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
|
luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
|
||||||
if (posi > pose) return 0; /* empty interval; return no values */
|
if (posi > pose) return 0; /* empty interval; return no values */
|
||||||
n = (int)(pose - posi + 1);
|
if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */
|
||||||
if (posi + n <= pose) /* (lua_Integer -> int) overflow? */
|
|
||||||
return luaL_error(L, "string slice too long");
|
return luaL_error(L, "string slice too long");
|
||||||
|
n = (int)(pose - posi) + 1;
|
||||||
luaL_checkstack(L, n, "string slice too long");
|
luaL_checkstack(L, n, "string slice too long");
|
||||||
n = 0;
|
n = 0;
|
||||||
se = s + pose;
|
se = s + pose;
|
||||||
@@ -234,7 +235,7 @@ static int iter_codes (lua_State *L) {
|
|||||||
#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
|
#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
|
||||||
|
|
||||||
|
|
||||||
static struct luaL_Reg funcs[] = {
|
static const luaL_Reg funcs[] = {
|
||||||
{"offset", byteoffset},
|
{"offset", byteoffset},
|
||||||
{"codepoint", codepoint},
|
{"codepoint", codepoint},
|
||||||
{"char", utfchar},
|
{"char", utfchar},
|
||||||
@@ -248,7 +249,7 @@ static struct luaL_Reg funcs[] = {
|
|||||||
|
|
||||||
LUAMOD_API int luaopen_utf8 (lua_State *L) {
|
LUAMOD_API int luaopen_utf8 (lua_State *L) {
|
||||||
luaL_newlib(L, funcs);
|
luaL_newlib(L, funcs);
|
||||||
lua_pushliteral(L, UTF8PATT);
|
lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
|
||||||
lua_setfield(L, -2, "charpattern");
|
lua_setfield(L, -2, "charpattern");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
263
3rd/lua/lvm.c
263
3rd/lua/lvm.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp $
|
** $Id: lvm.c,v 2.245 2015/06/09 15:53:35 roberto Exp $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -9,8 +9,9 @@
|
|||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -30,19 +31,38 @@
|
|||||||
#include "lvm.h"
|
#include "lvm.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** You can define LUA_FLOORN2I if you want to convert floats to integers
|
|
||||||
** by flooring them (instead of raising an error if they are not
|
|
||||||
** integral values)
|
|
||||||
*/
|
|
||||||
#if !defined(LUA_FLOORN2I)
|
|
||||||
#define LUA_FLOORN2I 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* limit for table tag-method chains (to avoid loops) */
|
/* limit for table tag-method chains (to avoid loops) */
|
||||||
#define MAXTAGLOOP 2000
|
#define MAXTAGLOOP 2000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'l_intfitsf' checks whether a given integer can be converted to a
|
||||||
|
** float without rounding. Used in comparisons. Left undefined if
|
||||||
|
** all integers fit in a float precisely.
|
||||||
|
*/
|
||||||
|
#if !defined(l_intfitsf)
|
||||||
|
|
||||||
|
/* number of bits in the mantissa of a float */
|
||||||
|
#define NBM (l_mathlim(MANT_DIG))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether some integers may not fit in a float, that is, whether
|
||||||
|
** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger).
|
||||||
|
** (The shifts are done in parts to avoid shifting by more than the size
|
||||||
|
** of an integer. In a worst case, NBM == 113 for long double and
|
||||||
|
** sizeof(integer) == 32.)
|
||||||
|
*/
|
||||||
|
#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
|
||||||
|
>> (NBM - (3 * (NBM / 4)))) > 0
|
||||||
|
|
||||||
|
#define l_intfitsf(i) \
|
||||||
|
(-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Add by skynet */
|
/* Add by skynet */
|
||||||
lua_State * skynet_sig_L = NULL;
|
lua_State * skynet_sig_L = NULL;
|
||||||
|
|
||||||
@@ -55,24 +75,6 @@ lua_checksig_(lua_State *L) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Similar to 'tonumber', but does not attempt to convert strings and
|
|
||||||
** ensure correct precision (no extra bits). Used in comparisons.
|
|
||||||
*/
|
|
||||||
static int tofloat (const TValue *obj, lua_Number *n) {
|
|
||||||
if (ttisfloat(obj)) *n = fltvalue(obj);
|
|
||||||
else if (ttisinteger(obj)) {
|
|
||||||
volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */
|
|
||||||
*n = x;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*n = 0; /* to avoid warnings */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Try to convert a value to a float. The float case is already handled
|
** Try to convert a value to a float. The float case is already handled
|
||||||
** by the macro 'tonumber'.
|
** by the macro 'tonumber'.
|
||||||
@@ -84,7 +86,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (cvt2num(obj) && /* string convertible to number? */
|
else if (cvt2num(obj) && /* string convertible to number? */
|
||||||
luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
|
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
|
||||||
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
|
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -99,7 +101,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
|
|||||||
** mode == 1: takes the floor of the number
|
** mode == 1: takes the floor of the number
|
||||||
** mode == 2: takes the ceil of the number
|
** mode == 2: takes the ceil of the number
|
||||||
*/
|
*/
|
||||||
static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
|
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
||||||
TValue v;
|
TValue v;
|
||||||
again:
|
again:
|
||||||
if (ttisfloat(obj)) {
|
if (ttisfloat(obj)) {
|
||||||
@@ -117,7 +119,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (cvt2num(obj) &&
|
else if (cvt2num(obj) &&
|
||||||
luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
|
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
|
||||||
obj = &v;
|
obj = &v;
|
||||||
goto again; /* convert result from 'luaO_str2num' to an integer */
|
goto again; /* convert result from 'luaO_str2num' to an integer */
|
||||||
}
|
}
|
||||||
@@ -125,14 +127,6 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** try to convert a value to an integer
|
|
||||||
*/
|
|
||||||
int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
|
|
||||||
return tointeger_aux(obj, p, LUA_FLOORN2I);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Try to convert a 'for' limit to an integer, preserving the
|
** Try to convert a 'for' limit to an integer, preserving the
|
||||||
** semantics of the loop.
|
** semantics of the loop.
|
||||||
@@ -151,11 +145,11 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
|
|||||||
static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
||||||
int *stopnow) {
|
int *stopnow) {
|
||||||
*stopnow = 0; /* usually, let loops run */
|
*stopnow = 0; /* usually, let loops run */
|
||||||
if (!tointeger_aux(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
|
if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
|
||||||
lua_Number n; /* try to convert to float */
|
lua_Number n; /* try to convert to float */
|
||||||
if (!tonumber(obj, &n)) /* cannot convert to float? */
|
if (!tonumber(obj, &n)) /* cannot convert to float? */
|
||||||
return 0; /* not a number */
|
return 0; /* not a number */
|
||||||
if (n > 0) { /* if true, float is larger than max integer */
|
if (luai_numlt(0, n)) { /* if true, float is larger than max integer */
|
||||||
*p = LUA_MAXINTEGER;
|
*p = LUA_MAXINTEGER;
|
||||||
if (step < 0) *stopnow = 1;
|
if (step < 0) *stopnow = 1;
|
||||||
}
|
}
|
||||||
@@ -250,9 +244,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
|
|||||||
*/
|
*/
|
||||||
static int l_strcmp (const TString *ls, const TString *rs) {
|
static int l_strcmp (const TString *ls, const TString *rs) {
|
||||||
const char *l = getstr(ls);
|
const char *l = getstr(ls);
|
||||||
size_t ll = ls->len;
|
size_t ll = tsslen(ls);
|
||||||
const char *r = getstr(rs);
|
const char *r = getstr(rs);
|
||||||
size_t lr = rs->len;
|
size_t lr = tsslen(rs);
|
||||||
for (;;) { /* for each segment */
|
for (;;) { /* for each segment */
|
||||||
int temp = strcoll(l, r);
|
int temp = strcoll(l, r);
|
||||||
if (temp != 0) /* not equal? */
|
if (temp != 0) /* not equal? */
|
||||||
@@ -271,16 +265,103 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether integer 'i' is less than float 'f'. If 'i' has an
|
||||||
|
** exact representation as a float ('l_intfitsf'), compare numbers as
|
||||||
|
** floats. Otherwise, if 'f' is outside the range for integers, result
|
||||||
|
** is trivial. Otherwise, compare them as integers. (When 'i' has no
|
||||||
|
** float representation, either 'f' is "far away" from 'i' or 'f' has
|
||||||
|
** no precision left for a fractional part; either way, how 'f' is
|
||||||
|
** truncated is irrelevant.) When 'f' is NaN, comparisons must result
|
||||||
|
** in false.
|
||||||
|
*/
|
||||||
|
static int LTintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
#if defined(l_intfitsf)
|
||||||
|
if (!l_intfitsf(i)) {
|
||||||
|
if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
|
||||||
|
return 1; /* f >= maxint + 1 > i */
|
||||||
|
else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */
|
||||||
|
return (i < cast(lua_Integer, f)); /* compare them as integers */
|
||||||
|
else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether integer 'i' is less than or equal to float 'f'.
|
||||||
|
** See comments on previous function.
|
||||||
|
*/
|
||||||
|
static int LEintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
#if defined(l_intfitsf)
|
||||||
|
if (!l_intfitsf(i)) {
|
||||||
|
if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
|
||||||
|
return 1; /* f >= maxint + 1 > i */
|
||||||
|
else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */
|
||||||
|
return (i <= cast(lua_Integer, f)); /* compare them as integers */
|
||||||
|
else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return luai_numle(cast_num(i), f); /* compare them as floats */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return 'l < r', for numbers.
|
||||||
|
*/
|
||||||
|
static int LTnum (const TValue *l, const TValue *r) {
|
||||||
|
if (ttisinteger(l)) {
|
||||||
|
lua_Integer li = ivalue(l);
|
||||||
|
if (ttisinteger(r))
|
||||||
|
return li < ivalue(r); /* both are integers */
|
||||||
|
else /* 'l' is int and 'r' is float */
|
||||||
|
return LTintfloat(li, fltvalue(r)); /* l < r ? */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_Number lf = fltvalue(l); /* 'l' must be float */
|
||||||
|
if (ttisfloat(r))
|
||||||
|
return luai_numlt(lf, fltvalue(r)); /* both are float */
|
||||||
|
else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
|
||||||
|
return 0; /* NaN < i is always false */
|
||||||
|
else /* without NaN, (l < r) <--> not(r <= l) */
|
||||||
|
return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return 'l <= r', for numbers.
|
||||||
|
*/
|
||||||
|
static int LEnum (const TValue *l, const TValue *r) {
|
||||||
|
if (ttisinteger(l)) {
|
||||||
|
lua_Integer li = ivalue(l);
|
||||||
|
if (ttisinteger(r))
|
||||||
|
return li <= ivalue(r); /* both are integers */
|
||||||
|
else /* 'l' is int and 'r' is float */
|
||||||
|
return LEintfloat(li, fltvalue(r)); /* l <= r ? */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_Number lf = fltvalue(l); /* 'l' must be float */
|
||||||
|
if (ttisfloat(r))
|
||||||
|
return luai_numle(lf, fltvalue(r)); /* both are float */
|
||||||
|
else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
|
||||||
|
return 0; /* NaN <= i is always false */
|
||||||
|
else /* without NaN, (l <= r) <--> not(r < l) */
|
||||||
|
return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Main operation less than; return 'l < r'.
|
** Main operation less than; return 'l < r'.
|
||||||
*/
|
*/
|
||||||
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
|
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
|
||||||
int res;
|
int res;
|
||||||
lua_Number nl, nr;
|
if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
|
||||||
if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
|
return LTnum(l, r);
|
||||||
return (ivalue(l) < ivalue(r));
|
|
||||||
else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
|
|
||||||
return luai_numlt(nl, nr);
|
|
||||||
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
|
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
|
||||||
return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
|
return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
|
||||||
else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
|
else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
|
||||||
@@ -290,27 +371,34 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Main operation less than or equal to; return 'l <= r'.
|
** Main operation less than or equal to; return 'l <= r'. If it needs
|
||||||
|
** a metamethod and there is no '__le', try '__lt', based on
|
||||||
|
** l <= r iff !(r < l) (assuming a total order). If the metamethod
|
||||||
|
** yields during this substitution, the continuation has to know
|
||||||
|
** about it (to negate the result of r<l); bit CIST_LEQ in the call
|
||||||
|
** status keeps that information.
|
||||||
*/
|
*/
|
||||||
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
|
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
|
||||||
int res;
|
int res;
|
||||||
lua_Number nl, nr;
|
if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
|
||||||
if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
|
return LEnum(l, r);
|
||||||
return (ivalue(l) <= ivalue(r));
|
|
||||||
else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
|
|
||||||
return luai_numle(nl, nr);
|
|
||||||
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
|
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
|
||||||
return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
|
return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
|
||||||
else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */
|
else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */
|
||||||
return res;
|
return res;
|
||||||
else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */
|
else { /* try 'lt': */
|
||||||
luaG_ordererror(L, l, r);
|
L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
|
||||||
return !res;
|
res = luaT_callorderTM(L, r, l, TM_LT);
|
||||||
|
L->ci->callstatus ^= CIST_LEQ; /* clear mark */
|
||||||
|
if (res < 0)
|
||||||
|
luaG_ordererror(L, l, r);
|
||||||
|
return !res; /* result is negated */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Main operation for equality of Lua values; return 't1 == t2'.
|
** Main operation for equality of Lua values; return 't1 == t2'.
|
||||||
** L == NULL means raw equality (no metamethods)
|
** L == NULL means raw equality (no metamethods)
|
||||||
*/
|
*/
|
||||||
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
||||||
@@ -319,10 +407,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|||||||
if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
|
if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
|
||||||
return 0; /* only numbers can be equal with different variants */
|
return 0; /* only numbers can be equal with different variants */
|
||||||
else { /* two numbers with different variants */
|
else { /* two numbers with different variants */
|
||||||
lua_Number n1, n2; /* compare them as floats */
|
lua_Integer i1, i2; /* compare them as integers */
|
||||||
lua_assert(ttisnumber(t1) && ttisnumber(t2));
|
return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
|
||||||
cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
|
|
||||||
return luai_numeq(n1, n2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* values have same type and same variant */
|
/* values have same type and same variant */
|
||||||
@@ -365,6 +451,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|||||||
#define tostring(L,o) \
|
#define tostring(L,o) \
|
||||||
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
|
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
|
||||||
|
|
||||||
|
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Main operation for concatenation: concat 'total' values in the stack,
|
** Main operation for concatenation: concat 'total' values in the stack,
|
||||||
** from 'L->top - total' up to 'L->top - 1'.
|
** from 'L->top - total' up to 'L->top - 1'.
|
||||||
@@ -376,19 +464,19 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
int n = 2; /* number of elements handled in this pass (at least 2) */
|
int n = 2; /* number of elements handled in this pass (at least 2) */
|
||||||
if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
|
if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
|
||||||
luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
|
luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
|
||||||
else if (tsvalue(top-1)->len == 0) /* second operand is empty? */
|
else if (isemptystr(top - 1)) /* second operand is empty? */
|
||||||
cast_void(tostring(L, top - 2)); /* result is first operand */
|
cast_void(tostring(L, top - 2)); /* result is first operand */
|
||||||
else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
|
else if (isemptystr(top - 2)) { /* first operand is an empty string? */
|
||||||
setobjs2s(L, top - 2, top - 1); /* result is second op. */
|
setobjs2s(L, top - 2, top - 1); /* result is second op. */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* at least two non-empty string values; get as many as possible */
|
/* at least two non-empty string values; get as many as possible */
|
||||||
size_t tl = tsvalue(top-1)->len;
|
size_t tl = vslen(top - 1);
|
||||||
char *buffer;
|
char *buffer;
|
||||||
int i;
|
int i;
|
||||||
/* collect total length */
|
/* collect total length */
|
||||||
for (i = 1; i < total && tostring(L, top-i-1); i++) {
|
for (i = 1; i < total && tostring(L, top-i-1); i++) {
|
||||||
size_t l = tsvalue(top-i-1)->len;
|
size_t l = vslen(top - i - 1);
|
||||||
if (l >= (MAX_SIZE/sizeof(char)) - tl)
|
if (l >= (MAX_SIZE/sizeof(char)) - tl)
|
||||||
luaG_runerror(L, "string length overflow");
|
luaG_runerror(L, "string length overflow");
|
||||||
tl += l;
|
tl += l;
|
||||||
@@ -397,7 +485,7 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
tl = 0;
|
tl = 0;
|
||||||
n = i;
|
n = i;
|
||||||
do { /* copy all strings to buffer */
|
do { /* copy all strings to buffer */
|
||||||
size_t l = tsvalue(top-i)->len;
|
size_t l = vslen(top - i);
|
||||||
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
|
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
|
||||||
tl += l;
|
tl += l;
|
||||||
} while (--i > 0);
|
} while (--i > 0);
|
||||||
@@ -414,7 +502,7 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
*/
|
*/
|
||||||
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
||||||
const TValue *tm;
|
const TValue *tm;
|
||||||
switch (ttnov(rb)) {
|
switch (ttype(rb)) {
|
||||||
case LUA_TTABLE: {
|
case LUA_TTABLE: {
|
||||||
Table *h = hvalue(rb);
|
Table *h = hvalue(rb);
|
||||||
tm = fasttm(L, h->metatable, TM_LEN);
|
tm = fasttm(L, h->metatable, TM_LEN);
|
||||||
@@ -422,8 +510,12 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
|||||||
setivalue(ra, luaH_getn(h)); /* else primitive len */
|
setivalue(ra, luaH_getn(h)); /* else primitive len */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_TSTRING: {
|
case LUA_TSHRSTR: {
|
||||||
setivalue(ra, tsvalue(rb)->len);
|
setivalue(ra, tsvalue(rb)->shrlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TLNGSTR: {
|
||||||
|
setivalue(ra, tsvalue(rb)->u.lnglen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default: { /* try metamethod */
|
default: { /* try metamethod */
|
||||||
@@ -459,7 +551,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Integer modulus; return 'm % n'. (Assume that C '%' with
|
** Integer modulus; return 'm % n'. (Assume that C '%' with
|
||||||
** negative operands follows C99 behavior. See previous comment
|
** negative operands follows C99 behavior. See previous comment
|
||||||
** about luaV_div.)
|
** about luaV_div.)
|
||||||
*/
|
*/
|
||||||
@@ -564,11 +656,11 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
case OP_LE: case OP_LT: case OP_EQ: {
|
case OP_LE: case OP_LT: case OP_EQ: {
|
||||||
int res = !l_isfalse(L->top - 1);
|
int res = !l_isfalse(L->top - 1);
|
||||||
L->top--;
|
L->top--;
|
||||||
/* metamethod should not be called when operand is K */
|
if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */
|
||||||
lua_assert(!ISK(GETARG_B(inst)));
|
lua_assert(op == OP_LE);
|
||||||
if (op == OP_LE && /* "<=" using "<" instead? */
|
ci->callstatus ^= CIST_LEQ; /* clear mark */
|
||||||
ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
|
res = !res; /* negate result */
|
||||||
res = !res; /* invert result */
|
}
|
||||||
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
|
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
|
||||||
if (res != GETARG_A(inst)) /* condition failed? */
|
if (res != GETARG_A(inst)) /* condition failed? */
|
||||||
ci->u.l.savedpc++; /* skip jump instruction */
|
ci->u.l.savedpc++; /* skip jump instruction */
|
||||||
@@ -618,7 +710,7 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
** some macros for common tasks in 'luaV_execute'
|
** some macros for common tasks in 'luaV_execute'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined luai_runtimecheck
|
#if !defined(luai_runtimecheck)
|
||||||
#define luai_runtimecheck(L, c) /* void */
|
#define luai_runtimecheck(L, c) /* void */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -754,7 +846,7 @@ void luaV_execute (lua_State *L) {
|
|||||||
Protect(luaV_gettable(L, rb, RKC(i), ra));
|
Protect(luaV_gettable(L, rb, RKC(i), ra));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_ADD) {
|
vmcase(OP_ADD) {
|
||||||
TValue *rb = RKB(i);
|
TValue *rb = RKB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
lua_Number nb; lua_Number nc;
|
lua_Number nb; lua_Number nc;
|
||||||
@@ -939,7 +1031,7 @@ void luaV_execute (lua_State *L) {
|
|||||||
L->top = base + c + 1; /* mark the end of concat operands */
|
L->top = base + c + 1; /* mark the end of concat operands */
|
||||||
Protect(luaV_concat(L, c - b + 1));
|
Protect(luaV_concat(L, c - b + 1));
|
||||||
ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */
|
ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */
|
||||||
rb = b + base;
|
rb = base + b;
|
||||||
setobjs2s(L, ra, rb);
|
setobjs2s(L, ra, rb);
|
||||||
checkGC(L, (ra >= rb ? ra + 1 : rb));
|
checkGC(L, (ra >= rb ? ra + 1 : rb));
|
||||||
L->top = ci->top; /* restore top */
|
L->top = ci->top; /* restore top */
|
||||||
@@ -1045,9 +1137,8 @@ void luaV_execute (lua_State *L) {
|
|||||||
}
|
}
|
||||||
vmcase(OP_RETURN) {
|
vmcase(OP_RETURN) {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
if (b != 0) L->top = ra+b-1;
|
|
||||||
if (cl->p->sp->sizep > 0) luaF_close(L, base);
|
if (cl->p->sp->sizep > 0) luaF_close(L, base);
|
||||||
b = luaD_poscall(L, ra);
|
b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
|
||||||
if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
|
if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
|
||||||
return; /* external invocation: return */
|
return; /* external invocation: return */
|
||||||
else { /* invocation via reentry: continue execution */
|
else { /* invocation via reentry: continue execution */
|
||||||
@@ -1065,7 +1156,7 @@ void luaV_execute (lua_State *L) {
|
|||||||
lua_Integer limit = ivalue(ra + 1);
|
lua_Integer limit = ivalue(ra + 1);
|
||||||
if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
|
if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
|
||||||
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||||
setivalue(ra, idx); /* update internal index... */
|
chgivalue(ra, idx); /* update internal index... */
|
||||||
setivalue(ra + 3, idx); /* ...and external index */
|
setivalue(ra + 3, idx); /* ...and external index */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1076,7 +1167,7 @@ void luaV_execute (lua_State *L) {
|
|||||||
if (luai_numlt(0, step) ? luai_numle(idx, limit)
|
if (luai_numlt(0, step) ? luai_numle(idx, limit)
|
||||||
: luai_numle(limit, idx)) {
|
: luai_numle(limit, idx)) {
|
||||||
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||||
setfltvalue(ra, idx); /* update internal index... */
|
chgfltvalue(ra, idx); /* update internal index... */
|
||||||
setfltvalue(ra + 3, idx); /* ...and external index */
|
setfltvalue(ra + 3, idx); /* ...and external index */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp $
|
** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -27,11 +27,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** You can define LUA_FLOORN2I if you want to convert floats to integers
|
||||||
|
** by flooring them (instead of raising an error if they are not
|
||||||
|
** integral values)
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_FLOORN2I)
|
||||||
|
#define LUA_FLOORN2I 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define tonumber(o,n) \
|
#define tonumber(o,n) \
|
||||||
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
|
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
|
||||||
|
|
||||||
#define tointeger(o,i) \
|
#define tointeger(o,i) \
|
||||||
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
|
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
|
||||||
|
|
||||||
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
|
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
|
||||||
|
|
||||||
@@ -42,7 +52,7 @@ LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
|||||||
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
|
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_lessequal (lua_State *L, const TValue *l, const TValue *r);
|
||||||
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
||||||
LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p);
|
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
|
||||||
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
|
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
|
||||||
StkId val);
|
StkId val);
|
||||||
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
|
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
|
||||||
|
|||||||
64
HISTORY.md
64
HISTORY.md
@@ -1,3 +1,67 @@
|
|||||||
|
v1.0.0-alpha9 (2015-8-10)
|
||||||
|
-----------
|
||||||
|
* Improve lua serialization , support pairs metamethod.
|
||||||
|
* Bugfix : sproto (See commits log of sproto)
|
||||||
|
* Add user log service support (In config)
|
||||||
|
* Remove the size limit of cluster RPC message.
|
||||||
|
* Remove the size limit of local message.
|
||||||
|
* Other minor bugfix (See commits log)
|
||||||
|
|
||||||
|
v1.0.0-alpha8 (2015-6-29)
|
||||||
|
-----------
|
||||||
|
* Update lua 5.3.1
|
||||||
|
* Bugfix: skynet exit issue
|
||||||
|
* Bugfix: timer race condition
|
||||||
|
* Use atom increment in bson object id
|
||||||
|
* remove assert when write to a listen fd
|
||||||
|
* sproto encode doesn't use raw table api
|
||||||
|
|
||||||
|
v1.0.0-alpha7 (2015-6-8)
|
||||||
|
-----------
|
||||||
|
* console support launch snax service
|
||||||
|
* Add cluster.snax
|
||||||
|
* Add nodelay in clusterd
|
||||||
|
* Merge sproto bugfix patch
|
||||||
|
* Move some skynet api into skynet.manager
|
||||||
|
* DNS support underscore
|
||||||
|
* Add logservice in config file for user defined log service
|
||||||
|
* skynet.fork returns coroutine
|
||||||
|
* Fix a few of bugs , see the commits log
|
||||||
|
|
||||||
|
v1.0.0-alpha6 (2015-5-18)
|
||||||
|
-----------
|
||||||
|
* bugfix: httpc.get
|
||||||
|
* bugfix: seri lib stack overflow
|
||||||
|
* bugfix: udp send
|
||||||
|
* bugfix: udp address
|
||||||
|
* bugfix: sproto dump
|
||||||
|
* add: sproto default
|
||||||
|
* improve: skynet.wakeup (can wakeup skynet.call by raise an error)
|
||||||
|
* improve: skynet.exit (raise error when uncall response)
|
||||||
|
* remove: task overload warning
|
||||||
|
* move: some skynet api move into skynet.manager
|
||||||
|
|
||||||
|
v1.0.0-alpha5 (2015-4-27)
|
||||||
|
-----------
|
||||||
|
* merge lua 5.3 offical bugfix
|
||||||
|
* improve sproto rpc api
|
||||||
|
* fix a deadlock bug when service retire
|
||||||
|
* improve cluster config reload
|
||||||
|
* add skynet.pcall for calling a function with `require`
|
||||||
|
* better error log in loginserver
|
||||||
|
|
||||||
|
v1.0.0-alpha4 (2015-4-13)
|
||||||
|
-----------
|
||||||
|
* sproto can share c struct between states
|
||||||
|
* udp api changed (use lua string now)
|
||||||
|
* fix memory leak in dns module
|
||||||
|
|
||||||
|
v1.0.0-alpha3 (2015-3-30)
|
||||||
|
-----------
|
||||||
|
* Update sproto (bugfix)
|
||||||
|
* Add async dns query
|
||||||
|
* improve httpc
|
||||||
|
|
||||||
v1.0.0-alpha2 (2015-3-16)
|
v1.0.0-alpha2 (2015-3-16)
|
||||||
-----------
|
-----------
|
||||||
* Update examples client to lua 5.3
|
* Update examples client to lua 5.3
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2012-2014 codingnow.com
|
Copyright (c) 2012-2015 codingnow.com
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -130,6 +130,9 @@ clean :
|
|||||||
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
||||||
|
|
||||||
cleanall: clean
|
cleanall: clean
|
||||||
|
ifneq (,$(wildcard 3rd/jemalloc/Makefile))
|
||||||
cd 3rd/jemalloc && $(MAKE) clean
|
cd 3rd/jemalloc && $(MAKE) clean
|
||||||
|
endif
|
||||||
|
cd 3rd/lua && $(MAKE) clean
|
||||||
rm -f $(LUA_STATICLIB)
|
rm -f $(LUA_STATICLIB)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ Run these in different console
|
|||||||
|
|
||||||
## About Lua
|
## About Lua
|
||||||
|
|
||||||
Skynet now use Lua 5.3.0 final, http://www.lua.org/ftp/lua-5.3.0.tar.gz
|
Skynet now use a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
|
||||||
|
|
||||||
|
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||||
|
|
||||||
You can also use the other official Lua version , edit the makefile by yourself .
|
You can also use the other official Lua version , edit the makefile by yourself .
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager" -- import skynet.abort
|
||||||
|
|
||||||
skynet.abort()
|
skynet.abort()
|
||||||
@@ -4,6 +4,7 @@ local socket = require "socket"
|
|||||||
local sproto = require "sproto"
|
local sproto = require "sproto"
|
||||||
local sprotoloader = require "sprotoloader"
|
local sprotoloader = require "sprotoloader"
|
||||||
|
|
||||||
|
local WATCHDOG
|
||||||
local host
|
local host
|
||||||
local send_request
|
local send_request
|
||||||
|
|
||||||
@@ -26,6 +27,10 @@ function REQUEST:handshake()
|
|||||||
return { msg = "Welcome to skynet, I will send heartbeat every 5 sec." }
|
return { msg = "Welcome to skynet, I will send heartbeat every 5 sec." }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function REQUEST:quit()
|
||||||
|
skynet.call(WATCHDOG, "lua", "close", client_fd)
|
||||||
|
end
|
||||||
|
|
||||||
local function request(name, args, response)
|
local function request(name, args, response)
|
||||||
local f = assert(REQUEST[name])
|
local f = assert(REQUEST[name])
|
||||||
local r = f(args)
|
local r = f(args)
|
||||||
@@ -62,7 +67,10 @@ skynet.register_protocol {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
function CMD.start(gate, fd)
|
function CMD.start(conf)
|
||||||
|
local fd = conf.client
|
||||||
|
local gate = conf.gate
|
||||||
|
WATCHDOG = conf.watchdog
|
||||||
-- slot 1,2 set at main.lua
|
-- slot 1,2 set at main.lua
|
||||||
host = sprotoloader.load(1):host "package"
|
host = sprotoloader.load(1):host "package"
|
||||||
send_request = host:attach(sprotoloader.load(2))
|
send_request = host:attach(sprotoloader.load(2))
|
||||||
@@ -77,6 +85,11 @@ function CMD.start(gate, fd)
|
|||||||
skynet.call(gate, "lua", "forward", fd)
|
skynet.call(gate, "lua", "forward", fd)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function CMD.disconnect()
|
||||||
|
-- todo: do something before exit
|
||||||
|
skynet.exit()
|
||||||
|
end
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
skynet.dispatch("lua", function(_,_, command, ...)
|
skynet.dispatch("lua", function(_,_, command, ...)
|
||||||
local f = CMD[command]
|
local f = CMD[command]
|
||||||
|
|||||||
@@ -104,7 +104,11 @@ while true do
|
|||||||
dispatch_package()
|
dispatch_package()
|
||||||
local cmd = socket.readstdin()
|
local cmd = socket.readstdin()
|
||||||
if cmd then
|
if cmd then
|
||||||
send_request("get", { what = cmd })
|
if cmd == "quit" then
|
||||||
|
send_request("quit")
|
||||||
|
else
|
||||||
|
send_request("get", { what = cmd })
|
||||||
|
end
|
||||||
else
|
else
|
||||||
socket.usleep(100)
|
socket.usleep(100)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
local cluster = require "cluster"
|
local cluster = require "cluster"
|
||||||
|
require "skynet.manager" -- import skynet.name
|
||||||
|
local snax = require "snax"
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
local sdb = skynet.newservice("simpledb")
|
local sdb = skynet.newservice("simpledb")
|
||||||
skynet.name(".simpledb", sdb)
|
skynet.name(".simpledb", sdb)
|
||||||
print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
|
print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
|
||||||
|
print(skynet.call(".simpledb", "lua", "SET", "b", "foobar2"))
|
||||||
print(skynet.call(".simpledb", "lua", "GET", "a"))
|
print(skynet.call(".simpledb", "lua", "GET", "a"))
|
||||||
|
print(skynet.call(".simpledb", "lua", "GET", "b"))
|
||||||
cluster.open "db"
|
cluster.open "db"
|
||||||
|
cluster.open "db2"
|
||||||
|
-- unique snax service
|
||||||
|
snax.uniqueservice "pingserver"
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -5,4 +5,9 @@ skynet.start(function()
|
|||||||
local proxy = cluster.proxy("db", ".simpledb")
|
local proxy = cluster.proxy("db", ".simpledb")
|
||||||
print(skynet.call(proxy, "lua", "GET", "a"))
|
print(skynet.call(proxy, "lua", "GET", "a"))
|
||||||
print(cluster.call("db", ".simpledb", "GET", "a"))
|
print(cluster.call("db", ".simpledb", "GET", "a"))
|
||||||
|
print(cluster.call("db2", ".simpledb", "GET", "b"))
|
||||||
|
|
||||||
|
-- test snax service
|
||||||
|
local pingserver = cluster.snax("db", "pingserver")
|
||||||
|
print(pingserver.req.ping "hello")
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
db = "127.0.0.1:2528"
|
db = "127.0.0.1:2528"
|
||||||
|
db2 = "127.0.0.1:2529"
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ bootstrap = "snlua bootstrap" -- The service for bootstrap
|
|||||||
luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua"
|
luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua"
|
||||||
lualoader = "lualib/loader.lua"
|
lualoader = "lualib/loader.lua"
|
||||||
cpath = "./cservice/?.so"
|
cpath = "./cservice/?.so"
|
||||||
cluster = "./examples/clustername.lua"
|
cluster = "./examples/clustername.lua"
|
||||||
|
snax = "./test/?.lua"
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ bootstrap = "snlua bootstrap" -- The service for bootstrap
|
|||||||
luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua"
|
luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua"
|
||||||
lualoader = "lualib/loader.lua"
|
lualoader = "lualib/loader.lua"
|
||||||
cpath = "./cservice/?.so"
|
cpath = "./cservice/?.so"
|
||||||
cluster = "./examples/clustername.lua"
|
cluster = "./examples/clustername.lua"
|
||||||
|
snax = "./test/?.lua"
|
||||||
|
|||||||
18
examples/config.userlog
Normal file
18
examples/config.userlog
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
root = "./"
|
||||||
|
thread = 8
|
||||||
|
logger = "userlog"
|
||||||
|
logservice = "snlua"
|
||||||
|
logpath = "."
|
||||||
|
harbor = 1
|
||||||
|
address = "127.0.0.1:2526"
|
||||||
|
master = "127.0.0.1:2013"
|
||||||
|
start = "main" -- main script
|
||||||
|
bootstrap = "snlua bootstrap" -- The service for bootstrap
|
||||||
|
standalone = "0.0.0.0:2013"
|
||||||
|
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
|
||||||
|
lualoader = "lualib/loader.lua"
|
||||||
|
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
|
||||||
|
snax = root.."examples/?.lua;"..root.."test/?.lua"
|
||||||
|
-- snax_interface_g = "snax_g"
|
||||||
|
cpath = root.."cservice/?.so"
|
||||||
|
-- daemon = "./skynet.pid"
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager" -- import skynet.register
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
skynet.dispatch("lua", function(session, address, ...)
|
skynet.dispatch("lua", function(session, address, ...)
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ local text = "echo"
|
|||||||
local index = 1
|
local index = 1
|
||||||
|
|
||||||
print("connect")
|
print("connect")
|
||||||
local fd = assert(socket.connect("127.0.0.1", 8888))
|
fd = assert(socket.connect("127.0.0.1", 8888))
|
||||||
last = ""
|
last = ""
|
||||||
|
|
||||||
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
||||||
@@ -151,7 +151,7 @@ socket.close(fd)
|
|||||||
index = index + 1
|
index = index + 1
|
||||||
|
|
||||||
print("connect again")
|
print("connect again")
|
||||||
local fd = assert(socket.connect("127.0.0.1", 8888))
|
fd = assert(socket.connect("127.0.0.1", 8888))
|
||||||
last = ""
|
last = ""
|
||||||
|
|
||||||
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ function server.login_handler(uid, secret)
|
|||||||
end
|
end
|
||||||
|
|
||||||
internal_id = internal_id + 1
|
internal_id = internal_id + 1
|
||||||
local username = msgserver.username(uid, internal_id, servername)
|
local id = internal_id -- don't use internal_id directly
|
||||||
|
local username = msgserver.username(uid, id, servername)
|
||||||
|
|
||||||
-- you can use a pool to alloc new agent
|
-- you can use a pool to alloc new agent
|
||||||
local agent = skynet.newservice "msgagent"
|
local agent = skynet.newservice "msgagent"
|
||||||
@@ -25,11 +26,11 @@ function server.login_handler(uid, secret)
|
|||||||
username = username,
|
username = username,
|
||||||
agent = agent,
|
agent = agent,
|
||||||
uid = uid,
|
uid = uid,
|
||||||
subid = internal_id,
|
subid = id,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- trash subid (no used)
|
-- trash subid (no used)
|
||||||
skynet.call(agent, "lua", "login", uid, internal_id, secret)
|
skynet.call(agent, "lua", "login", uid, id, secret)
|
||||||
|
|
||||||
users[uid] = u
|
users[uid] = u
|
||||||
username_map[username] = u
|
username_map[username] = u
|
||||||
@@ -37,7 +38,7 @@ function server.login_handler(uid, secret)
|
|||||||
msgserver.login(username, secret)
|
msgserver.login(username, secret)
|
||||||
|
|
||||||
-- you should return unique subid
|
-- you should return unique subid
|
||||||
return internal_id
|
return id
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call by agent
|
-- call by agent
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
local harbor = require "skynet.harbor"
|
local harbor = require "skynet.harbor"
|
||||||
|
require "skynet.manager" -- import skynet.monitor
|
||||||
|
|
||||||
local function monitor_master()
|
local function monitor_master()
|
||||||
harbor.linkmaster()
|
harbor.linkmaster()
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ set 3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quit 4 {}
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
proto.s2c = sprotoparser.parse [[
|
proto.s2c = sprotoparser.parse [[
|
||||||
|
|||||||
@@ -37,6 +37,16 @@ skynet.start(function()
|
|||||||
skynet.error(string.format("b[%d]=%s", k,v))
|
skynet.error(string.format("b[%d]=%s", k,v))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- test lua serialization
|
||||||
|
local s = skynet.packstring(obj)
|
||||||
|
local nobj = skynet.unpack(s)
|
||||||
|
for k,v in pairs(nobj) do
|
||||||
|
skynet.error(string.format("nobj[%s]=%s", k,v))
|
||||||
|
end
|
||||||
|
for k,v in ipairs(nobj.b) do
|
||||||
|
skynet.error(string.format("nobj.b[%d]=%s", k,v))
|
||||||
|
end
|
||||||
|
|
||||||
for i = 1, 5 do
|
for i = 1, 5 do
|
||||||
skynet.sleep(100)
|
skynet.sleep(100)
|
||||||
skynet.error("second " ..i)
|
skynet.error("second " ..i)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager" -- import skynet.register
|
||||||
local db = {}
|
local db = {}
|
||||||
|
|
||||||
local command = {}
|
local command = {}
|
||||||
|
|||||||
15
examples/userlog.lua
Normal file
15
examples/userlog.lua
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager"
|
||||||
|
|
||||||
|
skynet.register_protocol {
|
||||||
|
name = "text",
|
||||||
|
id = skynet.PTYPE_TEXT,
|
||||||
|
unpack = skynet.tostring,
|
||||||
|
dispatch = function(_, address, msg)
|
||||||
|
print(string.format("%x(%.2f): %s", address, skynet.time(), msg))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
skynet.start(function()
|
||||||
|
skynet.register ".logger"
|
||||||
|
end)
|
||||||
@@ -9,14 +9,16 @@ local agent = {}
|
|||||||
function SOCKET.open(fd, addr)
|
function SOCKET.open(fd, addr)
|
||||||
skynet.error("New client from : " .. addr)
|
skynet.error("New client from : " .. addr)
|
||||||
agent[fd] = skynet.newservice("agent")
|
agent[fd] = skynet.newservice("agent")
|
||||||
skynet.call(agent[fd], "lua", "start", gate, fd)
|
skynet.call(agent[fd], "lua", "start", { gate = gate, client = fd, watchdog = skynet.self() })
|
||||||
end
|
end
|
||||||
|
|
||||||
local function close_agent(fd)
|
local function close_agent(fd)
|
||||||
local a = agent[fd]
|
local a = agent[fd]
|
||||||
|
agent[fd] = nil
|
||||||
if a then
|
if a then
|
||||||
skynet.kill(a)
|
skynet.call(gate, "lua", "kick", fd)
|
||||||
agent[fd] = nil
|
-- disconnect never return
|
||||||
|
skynet.send(a, "lua", "disconnect")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -37,6 +39,10 @@ function CMD.start(conf)
|
|||||||
skynet.call(gate, "lua", "open" , conf)
|
skynet.call(gate, "lua", "open" , conf)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function CMD.close(fd)
|
||||||
|
close_agent(fd)
|
||||||
|
end
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
|
skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
|
||||||
if cmd == "socket" then
|
if cmd == "socket" then
|
||||||
|
|||||||
@@ -243,12 +243,16 @@ append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
|||||||
write_string(bs, key, sz);
|
write_string(bs, key, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_32bit(int64_t v) {
|
||||||
|
return v >= INT32_MIN && v <= INT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||||
if (lua_isinteger(L, -1)) {
|
if (lua_isinteger(L, -1)) {
|
||||||
int64_t i = lua_tointeger(L, -1);
|
int64_t i = lua_tointeger(L, -1);
|
||||||
int si = i >> 31;
|
if (is_32bit(i)) {
|
||||||
if (si == 0 || si == -1) {
|
|
||||||
append_key(bs, BSON_INT32, key, sz);
|
append_key(bs, BSON_INT32, key, sz);
|
||||||
write_int32(bs, i);
|
write_int32(bs, i);
|
||||||
} else {
|
} else {
|
||||||
@@ -1135,15 +1139,17 @@ lobjectid(lua_State *L) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
time_t ti = time(NULL);
|
time_t ti = time(NULL);
|
||||||
|
// old_counter is a static var, use atom inc.
|
||||||
|
uint32_t id = __sync_fetch_and_add(&oid_counter,1);
|
||||||
|
|
||||||
oid[2] = (ti>>24) & 0xff;
|
oid[2] = (ti>>24) & 0xff;
|
||||||
oid[3] = (ti>>16) & 0xff;
|
oid[3] = (ti>>16) & 0xff;
|
||||||
oid[4] = (ti>>8) & 0xff;
|
oid[4] = (ti>>8) & 0xff;
|
||||||
oid[5] = ti & 0xff;
|
oid[5] = ti & 0xff;
|
||||||
memcpy(oid+6 , oid_header, 5);
|
memcpy(oid+6 , oid_header, 5);
|
||||||
oid[11] = (oid_counter>>16) & 0xff;
|
oid[11] = (id>>16) & 0xff;
|
||||||
oid[12] = (oid_counter>>8) & 0xff;
|
oid[12] = (id>>8) & 0xff;
|
||||||
oid[13] = oid_counter & 0xff;
|
oid[13] = id & 0xff;
|
||||||
++oid_counter;
|
|
||||||
}
|
}
|
||||||
lua_pushlstring( L, (const char *)oid, 14);
|
lua_pushlstring( L, (const char *)oid, 14);
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ lpackrequest(lua_State *L) {
|
|||||||
size_t sz = (size_t)luaL_checkinteger(L,4);
|
size_t sz = (size_t)luaL_checkinteger(L,4);
|
||||||
int session = luaL_checkinteger(L,2);
|
int session = luaL_checkinteger(L,2);
|
||||||
if (session <= 0) {
|
if (session <= 0) {
|
||||||
|
skynet_free(msg);
|
||||||
return luaL_error(L, "Invalid request session %d", session);
|
return luaL_error(L, "Invalid request session %d", session);
|
||||||
}
|
}
|
||||||
int addr_type = lua_type(L,1);
|
int addr_type = lua_type(L,1);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
/* the eight DES S-boxes */
|
/* the eight DES S-boxes */
|
||||||
|
|
||||||
uint32_t SB1[64] = {
|
static uint32_t SB1[64] = {
|
||||||
0x01010400, 0x00000000, 0x00010000, 0x01010404,
|
0x01010400, 0x00000000, 0x00010000, 0x01010404,
|
||||||
0x01010004, 0x00010404, 0x00000004, 0x00010000,
|
0x01010004, 0x00010404, 0x00000004, 0x00010000,
|
||||||
0x00000400, 0x01010400, 0x01010404, 0x00000400,
|
0x00000400, 0x01010400, 0x01010404, 0x00000400,
|
||||||
@@ -602,11 +602,7 @@ read64(lua_State *L, uint32_t xx[2], uint32_t yy[2]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lhmac64(lua_State *L) {
|
pushqword(lua_State *L, uint32_t result[2]) {
|
||||||
uint32_t x[2], y[2];
|
|
||||||
read64(L, x, y);
|
|
||||||
uint32_t result[2];
|
|
||||||
hmac(x,y,result);
|
|
||||||
uint8_t tmp[8];
|
uint8_t tmp[8];
|
||||||
tmp[0] = result[0] & 0xff;
|
tmp[0] = result[0] & 0xff;
|
||||||
tmp[1] = (result[0] >> 8 )& 0xff;
|
tmp[1] = (result[0] >> 8 )& 0xff;
|
||||||
@@ -621,6 +617,40 @@ lhmac64(lua_State *L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lhmac64(lua_State *L) {
|
||||||
|
uint32_t x[2], y[2];
|
||||||
|
read64(L, x, y);
|
||||||
|
uint32_t result[2];
|
||||||
|
hmac(x,y,result);
|
||||||
|
return pushqword(L, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
8bytes key
|
||||||
|
string text
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lhmac_hash(lua_State *L) {
|
||||||
|
uint32_t key[2];
|
||||||
|
size_t sz = 0;
|
||||||
|
const uint8_t *x = (const uint8_t *)luaL_checklstring(L, 1, &sz);
|
||||||
|
if (sz != 8) {
|
||||||
|
luaL_error(L, "Invalid uint64 key");
|
||||||
|
}
|
||||||
|
key[0] = x[0] | x[1]<<8 | x[2]<<16 | x[3]<<24;
|
||||||
|
key[1] = x[4] | x[5]<<8 | x[6]<<16 | x[7]<<24;
|
||||||
|
const char * text = luaL_checklstring(L, 2, &sz);
|
||||||
|
uint8_t h[8];
|
||||||
|
Hash(text,(int)sz,h);
|
||||||
|
uint32_t htext[2];
|
||||||
|
htext[0] = h[0] | h[1]<<8 | h[2]<<16 | h[3]<<24;
|
||||||
|
htext[1] = h[4] | h[5]<<8 | h[6]<<16 | h[7]<<24;
|
||||||
|
uint32_t result[2];
|
||||||
|
hmac(htext,key,result);
|
||||||
|
return pushqword(L, result);
|
||||||
|
}
|
||||||
|
|
||||||
// powmodp64 for DH-key exchange
|
// powmodp64 for DH-key exchange
|
||||||
|
|
||||||
// The biggest 64bit prime
|
// The biggest 64bit prime
|
||||||
@@ -858,6 +888,7 @@ luaopen_crypt(lua_State *L) {
|
|||||||
{ "base64decode", lb64decode },
|
{ "base64decode", lb64decode },
|
||||||
{ "sha1", lsha1 },
|
{ "sha1", lsha1 },
|
||||||
{ "hmac_sha1", lhmac_sha1 },
|
{ "hmac_sha1", lhmac_sha1 },
|
||||||
|
{ "hmac_hash", lhmac_hash },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
luaL_newlib(L,l);
|
luaL_newlib(L,l);
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ channel_release(struct channel *c) {
|
|||||||
free(p);
|
free(p);
|
||||||
p = next;
|
p = next;
|
||||||
}
|
}
|
||||||
|
free(c);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ luaopen_memory(lua_State *L) {
|
|||||||
{ "block", lblock },
|
{ "block", lblock },
|
||||||
{ "dumpinfo", ldumpinfo },
|
{ "dumpinfo", ldumpinfo },
|
||||||
{ "dump", ldump },
|
{ "dump", ldump },
|
||||||
|
{ "info", dump_mem_lua },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,16 @@ push_more(lua_State *L, int fd, uint8_t *buffer, int size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_uncomplete(lua_State *L, int fd) {
|
||||||
|
struct queue *q = lua_touserdata(L,1);
|
||||||
|
struct uncomplete * uc = find_uncomplete(q, fd);
|
||||||
|
if (uc) {
|
||||||
|
skynet_free(uc->pack.buffer);
|
||||||
|
skynet_free(uc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
filter_data_(lua_State *L, int fd, uint8_t * buffer, int size) {
|
filter_data_(lua_State *L, int fd, uint8_t * buffer, int size) {
|
||||||
struct queue *q = lua_touserdata(L,1);
|
struct queue *q = lua_touserdata(L,1);
|
||||||
@@ -343,6 +353,8 @@ lfilter(lua_State *L) {
|
|||||||
// ignore listen fd connect
|
// ignore listen fd connect
|
||||||
return 1;
|
return 1;
|
||||||
case SKYNET_SOCKET_TYPE_CLOSE:
|
case SKYNET_SOCKET_TYPE_CLOSE:
|
||||||
|
// no more data in fd (message->id)
|
||||||
|
close_uncomplete(L, message->id);
|
||||||
lua_pushvalue(L, lua_upvalueindex(TYPE_CLOSE));
|
lua_pushvalue(L, lua_upvalueindex(TYPE_CLOSE));
|
||||||
lua_pushinteger(L, message->id);
|
lua_pushinteger(L, message->id);
|
||||||
return 3;
|
return 3;
|
||||||
@@ -353,6 +365,8 @@ lfilter(lua_State *L) {
|
|||||||
pushstring(L, buffer, size);
|
pushstring(L, buffer, size);
|
||||||
return 4;
|
return 4;
|
||||||
case SKYNET_SOCKET_TYPE_ERROR:
|
case SKYNET_SOCKET_TYPE_ERROR:
|
||||||
|
// no more data in fd (message->id)
|
||||||
|
close_uncomplete(L, message->id);
|
||||||
lua_pushvalue(L, lua_upvalueindex(TYPE_ERROR));
|
lua_pushvalue(L, lua_upvalueindex(TYPE_ERROR));
|
||||||
lua_pushinteger(L, message->id);
|
lua_pushinteger(L, message->id);
|
||||||
pushstring(L, buffer, size);
|
pushstring(L, buffer, size);
|
||||||
|
|||||||
@@ -254,13 +254,41 @@ wb_table_hash(lua_State *L, struct write_block * wb, int index, int depth, int a
|
|||||||
wb_nil(wb);
|
wb_nil(wb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wb_table_metapairs(lua_State *L, struct write_block *wb, int index, int depth) {
|
||||||
|
uint8_t n = COMBINE_TYPE(TYPE_TABLE, 0);
|
||||||
|
wb_push(wb, &n, 1);
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
lua_call(L, 1, 3);
|
||||||
|
for(;;) {
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_copy(L, -5, -3);
|
||||||
|
lua_call(L, 2, 2);
|
||||||
|
int type = lua_type(L, -2);
|
||||||
|
if (type == LUA_TNIL) {
|
||||||
|
lua_pop(L, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pack_one(L, wb, -2, depth);
|
||||||
|
pack_one(L, wb, -1, depth);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
wb_nil(wb);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wb_table(lua_State *L, struct write_block *wb, int index, int depth) {
|
wb_table(lua_State *L, struct write_block *wb, int index, int depth) {
|
||||||
|
luaL_checkstack(L, LUA_MINSTACK, NULL);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = lua_gettop(L) + index + 1;
|
index = lua_gettop(L) + index + 1;
|
||||||
}
|
}
|
||||||
int array_size = wb_table_array(L, wb, index, depth);
|
if (luaL_getmetafield(L, index, "__pairs") != LUA_TNIL) {
|
||||||
wb_table_hash(L, wb, index, depth, array_size);
|
wb_table_metapairs(L, wb, index, depth);
|
||||||
|
} else {
|
||||||
|
int array_size = wb_table_array(L, wb, index, depth);
|
||||||
|
wb_table_hash(L, wb, index, depth, array_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -416,6 +444,7 @@ unpack_table(lua_State *L, struct read_block *rb, int array_size) {
|
|||||||
}
|
}
|
||||||
array_size = get_integer(L,rb,cookie);
|
array_size = get_integer(L,rb,cookie);
|
||||||
}
|
}
|
||||||
|
luaL_checkstack(L,LUA_MINSTACK,NULL);
|
||||||
lua_createtable(L,array_size,0);
|
lua_createtable(L,array_size,0);
|
||||||
int i;
|
int i;
|
||||||
for (i=1;i<=array_size;i++) {
|
for (i=1;i<=array_size;i++) {
|
||||||
@@ -549,8 +578,8 @@ _luaseri_unpack(lua_State *L) {
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i=0;;i++) {
|
for (i=0;;i++) {
|
||||||
if (i%16==15) {
|
if (i%8==7) {
|
||||||
lua_checkstack(L,i);
|
luaL_checkstack(L,LUA_MINSTACK,NULL);
|
||||||
}
|
}
|
||||||
uint8_t type = 0;
|
uint8_t type = 0;
|
||||||
uint8_t *t = rb_read(&rb, sizeof(type));
|
uint8_t *t = rb_read(&rb, sizeof(type));
|
||||||
|
|||||||
@@ -376,6 +376,7 @@ pconv(lua_State *L) {
|
|||||||
static void
|
static void
|
||||||
convert_stringmap(struct context *ctx, struct table *tbl) {
|
convert_stringmap(struct context *ctx, struct table *tbl) {
|
||||||
lua_State *L = ctx->L;
|
lua_State *L = ctx->L;
|
||||||
|
lua_checkstack(L, ctx->string_index + LUA_MINSTACK);
|
||||||
lua_settop(L, ctx->string_index + 1);
|
lua_settop(L, ctx->string_index + 1);
|
||||||
lua_pushvalue(L, 1);
|
lua_pushvalue(L, 1);
|
||||||
struct state * s = lua_newuserdata(L, sizeof(*s));
|
struct state * s = lua_newuserdata(L, sizeof(*s));
|
||||||
|
|||||||
@@ -190,7 +190,10 @@ pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
luaL_addlstring(&b, current->msg + sb->offset, (sz - skip < bytes) ? sz - skip : bytes);
|
int real_sz = sz - skip;
|
||||||
|
if (real_sz > 0) {
|
||||||
|
luaL_addlstring(&b, current->msg + sb->offset, (real_sz < bytes) ? real_sz : bytes);
|
||||||
|
}
|
||||||
return_free_node(L,2,sb);
|
return_free_node(L,2,sb);
|
||||||
sz-=bytes;
|
sz-=bytes;
|
||||||
if (sz==0)
|
if (sz==0)
|
||||||
@@ -534,12 +537,6 @@ lnodelay(lua_State *L) {
|
|||||||
skynet_socket_nodelay(ctx,id);
|
skynet_socket_nodelay(ctx,id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
int skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port);
|
|
||||||
int skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port);
|
|
||||||
int skynet_socket_udp_send(struct skynet_context *ctx, int id, const char * address, const void *buffer, int sz);
|
|
||||||
const char * skynet_socket_udp_address(struct skynet_context *ctx, struct skynet_socket_message *, int *addrsz);
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ludp(lua_State *L) {
|
ludp(lua_State *L) {
|
||||||
@@ -599,7 +596,9 @@ static int
|
|||||||
ludp_address(lua_State *L) {
|
ludp_address(lua_State *L) {
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
const uint8_t * addr = (const uint8_t *)luaL_checklstring(L, 1, &sz);
|
const uint8_t * addr = (const uint8_t *)luaL_checklstring(L, 1, &sz);
|
||||||
int port = addr[1] * 256 + addr[2];
|
uint16_t port = 0;
|
||||||
|
memcpy(&port, addr+1, sizeof(uint16_t));
|
||||||
|
port = ntohs(port);
|
||||||
const void * src = addr+3;
|
const void * src = addr+3;
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
int family;
|
int family;
|
||||||
|
|||||||
@@ -39,17 +39,22 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
|
|||||||
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LUA_VERSION_NUM < 503
|
||||||
|
|
||||||
|
// lua_isinteger is lua 5.3 api
|
||||||
|
#define lua_isinteger lua_isnumber
|
||||||
|
|
||||||
|
// work around , use push & lua_gettable may be better
|
||||||
|
#define lua_geti lua_rawgeti
|
||||||
|
#define lua_seti lua_rawseti
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lnewproto(lua_State *L) {
|
lnewproto(lua_State *L) {
|
||||||
size_t sz = 0;
|
|
||||||
void * buffer;
|
|
||||||
struct sproto * sp;
|
struct sproto * sp;
|
||||||
if (lua_isuserdata(L,1)) {
|
size_t sz;
|
||||||
buffer = lua_touserdata(L,1);
|
void * buffer = (void *)luaL_checklstring(L,1,&sz);
|
||||||
sz = luaL_checkinteger(L,2);
|
|
||||||
} else {
|
|
||||||
buffer = (void *)luaL_checklstring(L,1,&sz);
|
|
||||||
}
|
|
||||||
sp = sproto_create(buffer, sz);
|
sp = sproto_create(buffer, sz);
|
||||||
if (sp) {
|
if (sp) {
|
||||||
lua_pushlightuserdata(L, sp);
|
lua_pushlightuserdata(L, sp);
|
||||||
@@ -104,6 +109,7 @@ encode(const struct sproto_arg *args) {
|
|||||||
return luaL_error(L, "The table is too deep");
|
return luaL_error(L, "The table is too deep");
|
||||||
if (args->index > 0) {
|
if (args->index > 0) {
|
||||||
if (args->tagname != self->array_tag) {
|
if (args->tagname != self->array_tag) {
|
||||||
|
// a new array
|
||||||
self->array_tag = args->tagname;
|
self->array_tag = args->tagname;
|
||||||
lua_getfield(L, self->tbl_index, args->tagname);
|
lua_getfield(L, self->tbl_index, args->tagname);
|
||||||
if (lua_isnil(L, -1)) {
|
if (lua_isnil(L, -1)) {
|
||||||
@@ -113,6 +119,10 @@ encode(const struct sproto_arg *args) {
|
|||||||
self->array_index = 0;
|
self->array_index = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!lua_istable(L, -1)) {
|
||||||
|
return luaL_error(L, ".*%s(%d) should be a table (Is a %s)",
|
||||||
|
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
|
||||||
|
}
|
||||||
if (self->array_index) {
|
if (self->array_index) {
|
||||||
lua_replace(L, self->array_index);
|
lua_replace(L, self->array_index);
|
||||||
} else {
|
} else {
|
||||||
@@ -133,7 +143,7 @@ encode(const struct sproto_arg *args) {
|
|||||||
lua_insert(L, -2);
|
lua_insert(L, -2);
|
||||||
lua_replace(L, self->iter_index);
|
lua_replace(L, self->iter_index);
|
||||||
} else {
|
} else {
|
||||||
lua_rawgeti(L, self->array_index, args->index);
|
lua_geti(L, self->array_index, args->index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lua_getfield(L, self->tbl_index, args->tagname);
|
lua_getfield(L, self->tbl_index, args->tagname);
|
||||||
@@ -144,8 +154,14 @@ encode(const struct sproto_arg *args) {
|
|||||||
}
|
}
|
||||||
switch (args->type) {
|
switch (args->type) {
|
||||||
case SPROTO_TINTEGER: {
|
case SPROTO_TINTEGER: {
|
||||||
lua_Integer v = luaL_checkinteger(L, -1);
|
lua_Integer v;
|
||||||
lua_Integer vh;
|
lua_Integer vh;
|
||||||
|
if (!lua_isinteger(L, -1)) {
|
||||||
|
return luaL_error(L, ".%s[%d] is not an integer (Is a %s)",
|
||||||
|
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
|
||||||
|
} else {
|
||||||
|
v = lua_tointeger(L, -1);
|
||||||
|
}
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
// notice: in lua 5.2, lua_Integer maybe 52bit
|
// notice: in lua 5.2, lua_Integer maybe 52bit
|
||||||
vh = v >> 31;
|
vh = v >> 31;
|
||||||
@@ -160,32 +176,47 @@ encode(const struct sproto_arg *args) {
|
|||||||
}
|
}
|
||||||
case SPROTO_TBOOLEAN: {
|
case SPROTO_TBOOLEAN: {
|
||||||
int v = lua_toboolean(L, -1);
|
int v = lua_toboolean(L, -1);
|
||||||
|
if (!lua_isboolean(L,-1)) {
|
||||||
|
return luaL_error(L, ".%s[%d] is not a boolean (Is a %s)",
|
||||||
|
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
|
||||||
|
}
|
||||||
*(int *)args->value = v;
|
*(int *)args->value = v;
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
case SPROTO_TSTRING: {
|
case SPROTO_TSTRING: {
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
const char * str = luaL_checklstring(L, -1, &sz);
|
const char * str;
|
||||||
|
if (!lua_isstring(L, -1)) {
|
||||||
|
return luaL_error(L, ".%s[%d] is not a string (Is a %s)",
|
||||||
|
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
|
||||||
|
} else {
|
||||||
|
str = lua_tolstring(L, -1, &sz);
|
||||||
|
}
|
||||||
if (sz > args->length)
|
if (sz > args->length)
|
||||||
return -1;
|
return -1;
|
||||||
memcpy(args->value, str, sz);
|
memcpy(args->value, str, sz);
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
return sz;
|
return sz + 1; // The length of empty string is 1.
|
||||||
}
|
}
|
||||||
case SPROTO_TSTRUCT: {
|
case SPROTO_TSTRUCT: {
|
||||||
struct encode_ud sub;
|
struct encode_ud sub;
|
||||||
int r;
|
int r;
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
if (!lua_istable(L, top)) {
|
||||||
|
return luaL_error(L, ".%s[%d] is not a table (Is a %s)",
|
||||||
|
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
|
||||||
|
}
|
||||||
sub.L = L;
|
sub.L = L;
|
||||||
sub.st = args->subtype;
|
sub.st = args->subtype;
|
||||||
sub.tbl_index = lua_gettop(L);
|
sub.tbl_index = top;
|
||||||
sub.array_tag = NULL;
|
sub.array_tag = NULL;
|
||||||
sub.array_index = 0;
|
sub.array_index = 0;
|
||||||
sub.deep = self->deep + 1;
|
sub.deep = self->deep + 1;
|
||||||
lua_pushnil(L); // prepare an iterator slot
|
lua_pushnil(L); // prepare an iterator slot
|
||||||
sub.iter_index = sub.tbl_index + 1;
|
sub.iter_index = sub.tbl_index + 1;
|
||||||
r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
|
r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
|
||||||
lua_pop(L,2); // pop the value and the iterator slot
|
lua_settop(L, top-1); // pop the value
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -222,29 +253,30 @@ lencode(lua_State *L) {
|
|||||||
struct encode_ud self;
|
struct encode_ud self;
|
||||||
void * buffer = lua_touserdata(L, lua_upvalueindex(1));
|
void * buffer = lua_touserdata(L, lua_upvalueindex(1));
|
||||||
int sz = lua_tointeger(L, lua_upvalueindex(2));
|
int sz = lua_tointeger(L, lua_upvalueindex(2));
|
||||||
|
int tbl_index = 2;
|
||||||
struct sproto_type * st = lua_touserdata(L, 1);
|
struct sproto_type * st = lua_touserdata(L, 1);
|
||||||
if (st == NULL) {
|
if (st == NULL) {
|
||||||
return luaL_argerror(L, 1, "Need a sproto_type object");
|
return luaL_argerror(L, 1, "Need a sproto_type object");
|
||||||
}
|
}
|
||||||
luaL_checktype(L, 2, LUA_TTABLE);
|
luaL_checktype(L, tbl_index, LUA_TTABLE);
|
||||||
luaL_checkstack(L, ENCODE_DEEPLEVEL*2 + 8, NULL);
|
luaL_checkstack(L, ENCODE_DEEPLEVEL*2 + 8, NULL);
|
||||||
self.L = L;
|
self.L = L;
|
||||||
self.st = st;
|
self.st = st;
|
||||||
self.tbl_index = 2;
|
self.tbl_index = tbl_index;
|
||||||
self.array_tag = NULL;
|
|
||||||
self.array_index = 0;
|
|
||||||
self.deep = 0;
|
|
||||||
lua_pushnil(L); // for iterator (stack 3)
|
|
||||||
self.iter_index = 3;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int r = sproto_encode(st, buffer, sz, encode, &self);
|
int r;
|
||||||
|
self.array_tag = NULL;
|
||||||
|
self.array_index = 0;
|
||||||
|
self.deep = 0;
|
||||||
|
|
||||||
|
lua_settop(L, tbl_index);
|
||||||
|
lua_pushnil(L); // for iterator (stack slot 3)
|
||||||
|
self.iter_index = tbl_index+1;
|
||||||
|
|
||||||
|
r = sproto_encode(st, buffer, sz, encode, &self);
|
||||||
if (r<0) {
|
if (r<0) {
|
||||||
buffer = expand_buffer(L, sz, sz*2);
|
buffer = expand_buffer(L, sz, sz*2);
|
||||||
sz *= 2;
|
sz *= 2;
|
||||||
// reset iterator slot
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_replace(L, 3);
|
|
||||||
} else {
|
} else {
|
||||||
lua_pushlstring(L, buffer, r);
|
lua_pushlstring(L, buffer, r);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -322,7 +354,7 @@ decode(const struct sproto_arg *args) {
|
|||||||
luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
|
luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
|
||||||
}
|
}
|
||||||
lua_pushvalue(L, sub.result_index);
|
lua_pushvalue(L, sub.result_index);
|
||||||
lua_rawset(L, self->array_index);
|
lua_settable(L, self->array_index);
|
||||||
lua_settop(L, sub.result_index-1);
|
lua_settop(L, sub.result_index-1);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -339,7 +371,7 @@ decode(const struct sproto_arg *args) {
|
|||||||
luaL_error(L, "Invalid type");
|
luaL_error(L, "Invalid type");
|
||||||
}
|
}
|
||||||
if (args->index > 0) {
|
if (args->index > 0) {
|
||||||
lua_rawseti(L, self->array_index, args->index);
|
lua_seti(L, self->array_index, args->index);
|
||||||
} else {
|
} else {
|
||||||
if (self->mainindex_tag == args->tagid) {
|
if (self->mainindex_tag == args->tagid) {
|
||||||
// This tag is marked, save the value to key_index
|
// This tag is marked, save the value to key_index
|
||||||
@@ -455,10 +487,10 @@ lunpack(lua_State *L) {
|
|||||||
return luaL_error(L, "Invalid unpack stream");
|
return luaL_error(L, "Invalid unpack stream");
|
||||||
if (r > osz) {
|
if (r > osz) {
|
||||||
output = expand_buffer(L, osz, r);
|
output = expand_buffer(L, osz, r);
|
||||||
|
r = sproto_unpack(buffer, sz, output, r);
|
||||||
|
if (r < 0)
|
||||||
|
return luaL_error(L, "Invalid unpack stream");
|
||||||
}
|
}
|
||||||
r = sproto_unpack(buffer, sz, output, r);
|
|
||||||
if (r < 0)
|
|
||||||
return luaL_error(L, "Invalid unpack stream");
|
|
||||||
lua_pushlstring(L, output, r);
|
lua_pushlstring(L, output, r);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -511,48 +543,98 @@ lprotocol(lua_State *L) {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* global sproto pointer for multi states */
|
/* global sproto pointer for multi states
|
||||||
struct sproto_bin {
|
NOTICE : It is not thread safe
|
||||||
void *ptr;
|
*/
|
||||||
size_t sz;
|
static struct sproto * G_sproto[MAX_GLOBALSPROTO];
|
||||||
};
|
|
||||||
|
|
||||||
static struct sproto_bin G_sproto[MAX_GLOBALSPROTO];
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lsaveproto(lua_State *L) {
|
lsaveproto(lua_State *L) {
|
||||||
size_t sz;
|
struct sproto * sp = lua_touserdata(L, 1);
|
||||||
void * buffer = (void *)luaL_checklstring(L,1,&sz);
|
|
||||||
int index = luaL_optinteger(L, 2, 0);
|
int index = luaL_optinteger(L, 2, 0);
|
||||||
void * tmp;
|
|
||||||
struct sproto_bin * sbin = &G_sproto[index];
|
|
||||||
if (index < 0 || index >= MAX_GLOBALSPROTO) {
|
if (index < 0 || index >= MAX_GLOBALSPROTO) {
|
||||||
return luaL_error(L, "Invalid global slot index %d", index);
|
return luaL_error(L, "Invalid global slot index %d", index);
|
||||||
}
|
}
|
||||||
tmp = malloc(sz);
|
/* TODO : release old object (memory leak now, but thread safe)*/
|
||||||
memcpy(tmp, buffer, sz);
|
G_sproto[index] = sp;
|
||||||
if (sbin->ptr) {
|
|
||||||
free(sbin->ptr);
|
|
||||||
}
|
|
||||||
sbin->ptr = tmp;
|
|
||||||
sbin->sz = sz;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lloadproto(lua_State *L) {
|
lloadproto(lua_State *L) {
|
||||||
int index = luaL_optinteger(L, 1, 0);
|
int index = luaL_optinteger(L, 1, 0);
|
||||||
struct sproto_bin * sbin = &G_sproto[index];
|
struct sproto * sp;
|
||||||
if (index < 0 || index >= MAX_GLOBALSPROTO) {
|
if (index < 0 || index >= MAX_GLOBALSPROTO) {
|
||||||
return luaL_error(L, "Invalid global slot index %d", index);
|
return luaL_error(L, "Invalid global slot index %d", index);
|
||||||
}
|
}
|
||||||
if (sbin->ptr == NULL) {
|
sp = G_sproto[index];
|
||||||
|
if (sp == NULL) {
|
||||||
return luaL_error(L, "nil sproto at index %d", index);
|
return luaL_error(L, "nil sproto at index %d", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushlightuserdata(L, sbin->ptr);
|
lua_pushlightuserdata(L, sp);
|
||||||
lua_pushinteger(L, sbin->sz);
|
|
||||||
return 2;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
encode_default(const struct sproto_arg *args) {
|
||||||
|
lua_State *L = args->ud;
|
||||||
|
lua_pushstring(L, args->tagname);
|
||||||
|
if (args->index > 0) {
|
||||||
|
lua_newtable(L);
|
||||||
|
} else {
|
||||||
|
switch(args->type) {
|
||||||
|
case SPROTO_TINTEGER:
|
||||||
|
lua_pushinteger(L, 0);
|
||||||
|
break;
|
||||||
|
case SPROTO_TBOOLEAN:
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
break;
|
||||||
|
case SPROTO_TSTRING:
|
||||||
|
lua_pushliteral(L, "");
|
||||||
|
break;
|
||||||
|
case SPROTO_TSTRUCT:
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
lua_pushstring(L, sproto_name(args->subtype));
|
||||||
|
lua_setfield(L, -2, "__type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_rawset(L, -3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
lightuserdata sproto_type
|
||||||
|
return default table
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ldefault(lua_State *L) {
|
||||||
|
int ret;
|
||||||
|
// 64 is always enough for dummy buffer, except the type has many fields ( > 27).
|
||||||
|
char dummy[64];
|
||||||
|
struct sproto_type * st = lua_touserdata(L, 1);
|
||||||
|
if (st == NULL) {
|
||||||
|
return luaL_argerror(L, 1, "Need a sproto_type object");
|
||||||
|
}
|
||||||
|
lua_newtable(L);
|
||||||
|
ret = sproto_encode(st, dummy, sizeof(dummy), encode_default, L);
|
||||||
|
if (ret<0) {
|
||||||
|
// try again
|
||||||
|
int sz = sizeof(dummy) * 2;
|
||||||
|
void * tmp = lua_newuserdata(L, sz);
|
||||||
|
lua_insert(L, -2);
|
||||||
|
for (;;) {
|
||||||
|
ret = sproto_encode(st, tmp, sz, encode_default, L);
|
||||||
|
if (ret >= 0)
|
||||||
|
break;
|
||||||
|
sz *= 2;
|
||||||
|
tmp = lua_newuserdata(L, sz);
|
||||||
|
lua_replace(L, -3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -569,6 +651,7 @@ luaopen_sproto_core(lua_State *L) {
|
|||||||
{ "protocol", lprotocol },
|
{ "protocol", lprotocol },
|
||||||
{ "loadproto", lloadproto },
|
{ "loadproto", lloadproto },
|
||||||
{ "saveproto", lsaveproto },
|
{ "saveproto", lsaveproto },
|
||||||
|
{ "default", ldefault },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
luaL_newlib(L,l);
|
luaL_newlib(L,l);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static void *
|
|||||||
pool_alloc(struct pool *p, size_t sz) {
|
pool_alloc(struct pool *p, size_t sz) {
|
||||||
// align by 8
|
// align by 8
|
||||||
sz = (sz + 7) & ~7;
|
sz = (sz + 7) & ~7;
|
||||||
if (sz > CHUNK_SIZE) {
|
if (sz >= CHUNK_SIZE) {
|
||||||
return pool_newchunk(p, sz);
|
return pool_newchunk(p, sz);
|
||||||
}
|
}
|
||||||
if (p->current == NULL) {
|
if (p->current == NULL) {
|
||||||
@@ -97,7 +97,7 @@ pool_alloc(struct pool *p, size_t sz) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sz > p->current_used) {
|
if (sz >= p->current_used) {
|
||||||
return pool_newchunk(p, sz);
|
return pool_newchunk(p, sz);
|
||||||
} else {
|
} else {
|
||||||
void * ret = pool_newchunk(p, CHUNK_SIZE);
|
void * ret = pool_newchunk(p, CHUNK_SIZE);
|
||||||
@@ -152,7 +152,7 @@ struct_field(const uint8_t * stream, size_t sz) {
|
|||||||
sz -= header;
|
sz -= header;
|
||||||
stream += header;
|
stream += header;
|
||||||
for (i=0;i<fn;i++) {
|
for (i=0;i<fn;i++) {
|
||||||
int value= toword(field + i * SIZEOF_FIELD + SIZEOF_HEADER);
|
int value= toword(field + i * SIZEOF_FIELD);
|
||||||
uint32_t dsz;
|
uint32_t dsz;
|
||||||
if (value != 0)
|
if (value != 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -305,7 +305,7 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
|
|||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
tag = f->tag;
|
tag = f->tag;
|
||||||
if (tag < last)
|
if (tag <= last)
|
||||||
return NULL; // tag must in ascending order
|
return NULL; // tag must in ascending order
|
||||||
if (tag > last+1) {
|
if (tag > last+1) {
|
||||||
++maxn;
|
++maxn;
|
||||||
@@ -394,7 +394,7 @@ create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
|
|||||||
const uint8_t * protocoldata = NULL;
|
const uint8_t * protocoldata = NULL;
|
||||||
int fn = struct_field(stream, sz);
|
int fn = struct_field(stream, sz);
|
||||||
int i;
|
int i;
|
||||||
if (fn < 0)
|
if (fn < 0 || fn > 2)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
stream += SIZEOF_HEADER;
|
stream += SIZEOF_HEADER;
|
||||||
@@ -500,7 +500,11 @@ sproto_dump(struct sproto *s) {
|
|||||||
printf("=== %d protocol ===\n", s->protocol_n);
|
printf("=== %d protocol ===\n", s->protocol_n);
|
||||||
for (i=0;i<s->protocol_n;i++) {
|
for (i=0;i<s->protocol_n;i++) {
|
||||||
struct protocol *p = &s->proto[i];
|
struct protocol *p = &s->proto[i];
|
||||||
printf("\t%s (%d) request:%s", p->name, p->tag, p->p[SPROTO_REQUEST]->name);
|
if (p->p[SPROTO_REQUEST]) {
|
||||||
|
printf("\t%s (%d) request:%s", p->name, p->tag, p->p[SPROTO_REQUEST]->name);
|
||||||
|
} else {
|
||||||
|
printf("\t%s (%d) request:(null)", p->name, p->tag);
|
||||||
|
}
|
||||||
if (p->p[SPROTO_RESPONSE]) {
|
if (p->p[SPROTO_RESPONSE]) {
|
||||||
printf(" response:%s", p->p[SPROTO_RESPONSE]->name);
|
printf(" response:%s", p->p[SPROTO_RESPONSE]->name);
|
||||||
}
|
}
|
||||||
@@ -510,7 +514,7 @@ sproto_dump(struct sproto *s) {
|
|||||||
|
|
||||||
// query
|
// query
|
||||||
int
|
int
|
||||||
sproto_prototag(struct sproto *sp, const char * name) {
|
sproto_prototag(const struct sproto *sp, const char * name) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<sp->protocol_n;i++) {
|
for (i=0;i<sp->protocol_n;i++) {
|
||||||
if (strcmp(name, sp->proto[i].name) == 0) {
|
if (strcmp(name, sp->proto[i].name) == 0) {
|
||||||
@@ -521,7 +525,7 @@ sproto_prototag(struct sproto *sp, const char * name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct protocol *
|
static struct protocol *
|
||||||
query_proto(struct sproto *sp, int tag) {
|
query_proto(const struct sproto *sp, int tag) {
|
||||||
int begin = 0, end = sp->protocol_n;
|
int begin = 0, end = sp->protocol_n;
|
||||||
while(begin<end) {
|
while(begin<end) {
|
||||||
int mid = (begin+end)/2;
|
int mid = (begin+end)/2;
|
||||||
@@ -539,7 +543,7 @@ query_proto(struct sproto *sp, int tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct sproto_type *
|
struct sproto_type *
|
||||||
sproto_protoquery(struct sproto *sp, int proto, int what) {
|
sproto_protoquery(const struct sproto *sp, int proto, int what) {
|
||||||
struct protocol * p;
|
struct protocol * p;
|
||||||
if (what <0 || what >1) {
|
if (what <0 || what >1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -552,7 +556,7 @@ sproto_protoquery(struct sproto *sp, int proto, int what) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
sproto_protoname(struct sproto *sp, int proto) {
|
sproto_protoname(const struct sproto *sp, int proto) {
|
||||||
struct protocol * p = query_proto(sp, proto);
|
struct protocol * p = query_proto(sp, proto);
|
||||||
if (p) {
|
if (p) {
|
||||||
return p->name;
|
return p->name;
|
||||||
@@ -561,7 +565,7 @@ sproto_protoname(struct sproto *sp, int proto) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct sproto_type *
|
struct sproto_type *
|
||||||
sproto_type(struct sproto *sp, const char * type_name) {
|
sproto_type(const struct sproto *sp, const char * type_name) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<sp->type_n;i++) {
|
for (i=0;i<sp->type_n;i++) {
|
||||||
if (strcmp(type_name, sp->type[i].name) == 0) {
|
if (strcmp(type_name, sp->type[i].name) == 0) {
|
||||||
@@ -577,7 +581,7 @@ sproto_name(struct sproto_type * st) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct field *
|
static struct field *
|
||||||
findtag(struct sproto_type *st, int tag) {
|
findtag(const struct sproto_type *st, int tag) {
|
||||||
int begin, end;
|
int begin, end;
|
||||||
if (st->base >=0 ) {
|
if (st->base >=0 ) {
|
||||||
tag -= st->base;
|
tag -= st->base;
|
||||||
@@ -609,10 +613,6 @@ findtag(struct sproto_type *st, int tag) {
|
|||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
fill_size(uint8_t * data, int sz) {
|
fill_size(uint8_t * data, int sz) {
|
||||||
if (sz < 0)
|
|
||||||
return -1;
|
|
||||||
if (sz == 0)
|
|
||||||
return 0;
|
|
||||||
data[0] = sz & 0xff;
|
data[0] = sz & 0xff;
|
||||||
data[1] = (sz >> 8) & 0xff;
|
data[1] = (sz >> 8) & 0xff;
|
||||||
data[2] = (sz >> 16) & 0xff;
|
data[2] = (sz >> 16) & 0xff;
|
||||||
@@ -677,6 +677,11 @@ encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int si
|
|||||||
args->value = data+SIZEOF_LENGTH;
|
args->value = data+SIZEOF_LENGTH;
|
||||||
args->length = size-SIZEOF_LENGTH;
|
args->length = size-SIZEOF_LENGTH;
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
|
if (sz <= 0)
|
||||||
|
return sz;
|
||||||
|
if (args->type == SPROTO_TSTRING) {
|
||||||
|
--sz; // the length of null string is 1
|
||||||
|
}
|
||||||
return fill_size(data, sz);
|
return fill_size(data, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,7 +723,7 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
|
|||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (sz == 0)
|
if (sz == 0) // nil object, end of array
|
||||||
break;
|
break;
|
||||||
if (size < sizeof(uint64_t))
|
if (size < sizeof(uint64_t))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -798,7 +803,7 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (sz == 0)
|
if (sz == 0) // nil object , end of array
|
||||||
break;
|
break;
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -817,10 +822,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
args->value = buffer+SIZEOF_LENGTH;
|
args->value = buffer+SIZEOF_LENGTH;
|
||||||
args->length = size;
|
args->length = size;
|
||||||
sz = cb(args);
|
sz = cb(args);
|
||||||
if (sz < 0)
|
|
||||||
return -1;
|
|
||||||
if (sz == 0)
|
if (sz == 0)
|
||||||
break;
|
break;
|
||||||
|
if (sz < 0)
|
||||||
|
return -1;
|
||||||
|
if (args->type == SPROTO_TSTRING) {
|
||||||
|
--sz;
|
||||||
|
}
|
||||||
fill_size(buffer, sz);
|
fill_size(buffer, sz);
|
||||||
buffer += SIZEOF_LENGTH+sz;
|
buffer += SIZEOF_LENGTH+sz;
|
||||||
size -=sz;
|
size -=sz;
|
||||||
@@ -829,13 +837,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sz = buffer - (data + SIZEOF_LENGTH);
|
sz = buffer - (data + SIZEOF_LENGTH);
|
||||||
if (sz == 0)
|
if (sz == 0) // empty array
|
||||||
return 0;
|
return 0;
|
||||||
return fill_size(data, sz);
|
return fill_size(data, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback cb, void *ud) {
|
sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_callback cb, void *ud) {
|
||||||
struct sproto_arg args;
|
struct sproto_arg args;
|
||||||
uint8_t * header = buffer;
|
uint8_t * header = buffer;
|
||||||
uint8_t * data;
|
uint8_t * data;
|
||||||
@@ -878,7 +886,7 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
|
|||||||
sz = cb(&args);
|
sz = cb(&args);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (sz == 0)
|
if (sz == 0) // nil object
|
||||||
continue;
|
continue;
|
||||||
if (sz == sizeof(uint32_t)) {
|
if (sz == sizeof(uint32_t)) {
|
||||||
if (u.u32 < 0x7fff) {
|
if (u.u32 < 0x7fff) {
|
||||||
@@ -895,11 +903,10 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPROTO_TSTRUCT:
|
case SPROTO_TSTRUCT:
|
||||||
case SPROTO_TSTRING: {
|
case SPROTO_TSTRING:
|
||||||
sz = encode_object(cb, &args, data, size);
|
sz = encode_object(cb, &args, data, size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1032,7 +1039,7 @@ decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sproto_decode(struct sproto_type *st, const void * data, int size, sproto_callback cb, void *ud) {
|
sproto_decode(const struct sproto_type *st, const void * data, int size, sproto_callback cb, void *ud) {
|
||||||
struct sproto_arg args;
|
struct sproto_arg args;
|
||||||
int total = size;
|
int total = size;
|
||||||
uint8_t * stream;
|
uint8_t * stream;
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ struct sproto_type;
|
|||||||
struct sproto * sproto_create(const void * proto, size_t sz);
|
struct sproto * sproto_create(const void * proto, size_t sz);
|
||||||
void sproto_release(struct sproto *);
|
void sproto_release(struct sproto *);
|
||||||
|
|
||||||
int sproto_prototag(struct sproto *, const char * name);
|
int sproto_prototag(const struct sproto *, const char * name);
|
||||||
const char * sproto_protoname(struct sproto *, int proto);
|
const char * sproto_protoname(const struct sproto *, int proto);
|
||||||
// SPROTO_REQUEST(0) : request, SPROTO_RESPONSE(1): response
|
// SPROTO_REQUEST(0) : request, SPROTO_RESPONSE(1): response
|
||||||
struct sproto_type * sproto_protoquery(struct sproto *, int proto, int what);
|
struct sproto_type * sproto_protoquery(const struct sproto *, int proto, int what);
|
||||||
|
|
||||||
struct sproto_type * sproto_type(struct sproto *, const char * type_name);
|
struct sproto_type * sproto_type(const struct sproto *, const char * type_name);
|
||||||
|
|
||||||
int sproto_pack(const void * src, int srcsz, void * buffer, int bufsz);
|
int sproto_pack(const void * src, int srcsz, void * buffer, int bufsz);
|
||||||
int sproto_unpack(const void * src, int srcsz, void * buffer, int bufsz);
|
int sproto_unpack(const void * src, int srcsz, void * buffer, int bufsz);
|
||||||
@@ -41,8 +41,8 @@ struct sproto_arg {
|
|||||||
|
|
||||||
typedef int (*sproto_callback)(const struct sproto_arg *args);
|
typedef int (*sproto_callback)(const struct sproto_arg *args);
|
||||||
|
|
||||||
int sproto_decode(struct sproto_type *, const void * data, int size, sproto_callback cb, void *ud);
|
int sproto_decode(const struct sproto_type *, const void * data, int size, sproto_callback cb, void *ud);
|
||||||
int sproto_encode(struct sproto_type *, void * buffer, int size, sproto_callback cb, void *ud);
|
int sproto_encode(const struct sproto_type *, void * buffer, int size, sproto_callback cb, void *ud);
|
||||||
|
|
||||||
// for debug use
|
// for debug use
|
||||||
void sproto_dump(struct sproto *);
|
void sproto_dump(struct sproto *);
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ function cluster.proxy(node, name)
|
|||||||
return skynet.call(clusterd, "lua", "proxy", node, name)
|
return skynet.call(clusterd, "lua", "proxy", node, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cluster.snax(node, name, address)
|
||||||
|
local snax = require "snax"
|
||||||
|
if not address then
|
||||||
|
address = cluster.call(node, ".service", "QUERY", "snaxd" , name)
|
||||||
|
end
|
||||||
|
local handle = skynet.call(clusterd, "lua", "proxy", node, address)
|
||||||
|
return snax.bind(handle, name)
|
||||||
|
end
|
||||||
|
|
||||||
skynet.init(function()
|
skynet.init(function()
|
||||||
clusterd = skynet.uniqueservice("clusterd")
|
clusterd = skynet.uniqueservice("clusterd")
|
||||||
end)
|
end)
|
||||||
|
|||||||
290
lualib/dns.lua
Normal file
290
lualib/dns.lua
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
--[[
|
||||||
|
lua dns resolver library
|
||||||
|
See https://github.com/xjdrew/levent/blob/master/levent/dns.lua for more detail
|
||||||
|
|
||||||
|
-- resource record type:
|
||||||
|
-- TYPE value and meaning
|
||||||
|
-- A 1 a host address
|
||||||
|
-- NS 2 an authoritative name server
|
||||||
|
-- MD 3 a mail destination (Obsolete - use MX)
|
||||||
|
-- MF 4 a mail forwarder (Obsolete - use MX)
|
||||||
|
-- CNAME 5 the canonical name for an alias
|
||||||
|
-- SOA 6 marks the start of a zone of authority
|
||||||
|
-- MB 7 a mailbox domain name (EXPERIMENTAL)
|
||||||
|
-- MG 8 a mail group member (EXPERIMENTAL)
|
||||||
|
-- MR 9 a mail rename domain name (EXPERIMENTAL)
|
||||||
|
-- NULL 10 a null RR (EXPERIMENTAL)
|
||||||
|
-- WKS 11 a well known service description
|
||||||
|
-- PTR 12 a domain name pointer
|
||||||
|
-- HINFO 13 host information
|
||||||
|
-- MINFO 14 mailbox or mail list information
|
||||||
|
-- MX 15 mail exchange
|
||||||
|
-- TXT 16 text strings
|
||||||
|
-- AAAA 28 a ipv6 host address
|
||||||
|
-- only appear in the question section:
|
||||||
|
-- AXFR 252 A request for a transfer of an entire zone
|
||||||
|
-- MAILB 253 A request for mailbox-related records (MB, MG or MR)
|
||||||
|
-- MAILA 254 A request for mail agent RRs (Obsolete - see MX)
|
||||||
|
-- * 255 A request for all records
|
||||||
|
--
|
||||||
|
-- resource recode class:
|
||||||
|
-- IN 1 the Internet
|
||||||
|
-- CS 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs)
|
||||||
|
-- CH 3 the CHAOS class
|
||||||
|
-- HS 4 Hesiod [Dyer 87]
|
||||||
|
-- only appear in the question section:
|
||||||
|
-- * 255 any class
|
||||||
|
-- ]]
|
||||||
|
|
||||||
|
--[[
|
||||||
|
-- struct header {
|
||||||
|
-- uint16_t tid # identifier assigned by the program that generates any kind of query.
|
||||||
|
-- uint16_t flags # flags
|
||||||
|
-- uint16_t qdcount # the number of entries in the question section.
|
||||||
|
-- uint16_t ancount # the number of resource records in the answer section.
|
||||||
|
-- uint16_t nscount # the number of name server resource records in the authority records section.
|
||||||
|
-- uint16_t arcount # the number of resource records in the additional records section.
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
-- request body:
|
||||||
|
-- struct request {
|
||||||
|
-- string name
|
||||||
|
-- uint16_t atype
|
||||||
|
-- uint16_t class
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
-- response body:
|
||||||
|
-- struct response {
|
||||||
|
-- string name
|
||||||
|
-- uint16_t atype
|
||||||
|
-- uint16_t class
|
||||||
|
-- uint16_t ttl
|
||||||
|
-- uint16_t rdlength
|
||||||
|
-- string rdata
|
||||||
|
-- }
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local skynet = require "skynet"
|
||||||
|
local socket = require "socket"
|
||||||
|
|
||||||
|
local MAX_DOMAIN_LEN = 1024
|
||||||
|
local MAX_LABEL_LEN = 63
|
||||||
|
local MAX_PACKET_LEN = 2048
|
||||||
|
local DNS_HEADER_LEN = 12
|
||||||
|
|
||||||
|
local QTYPE = {
|
||||||
|
A = 1,
|
||||||
|
CNAME = 5,
|
||||||
|
AAAA = 28,
|
||||||
|
}
|
||||||
|
|
||||||
|
local QCLASS = {
|
||||||
|
IN = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
local dns = {}
|
||||||
|
|
||||||
|
local function verify_domain_name(name)
|
||||||
|
if #name > MAX_DOMAIN_LEN then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not name:match("^[_%l%d%-%.]+$") then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for w in name:gmatch("([_%w%-]+)%.?") do
|
||||||
|
if #w > MAX_LABEL_LEN then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local next_tid = 1
|
||||||
|
local function gen_tid()
|
||||||
|
local tid = next_tid
|
||||||
|
next_tid = next_tid + 1
|
||||||
|
return tid
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pack_header(t)
|
||||||
|
return string.pack(">HHHHHH",
|
||||||
|
t.tid, t.flags, t.qdcount, t.ancount or 0, t.nscount or 0, t.arcount or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pack_question(name, qtype, qclass)
|
||||||
|
local labels = {}
|
||||||
|
for w in name:gmatch("([_%w%-]+)%.?") do
|
||||||
|
table.insert(labels, string.pack("s1",w))
|
||||||
|
end
|
||||||
|
table.insert(labels, '\0')
|
||||||
|
table.insert(labels, string.pack(">HH", qtype, qclass))
|
||||||
|
return table.concat(labels)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unpack_header(chunk)
|
||||||
|
local tid, flags, qdcount, ancount, nscount, arcount, left = string.unpack(">HHHHHH", chunk)
|
||||||
|
return {
|
||||||
|
tid = tid,
|
||||||
|
flags = flags,
|
||||||
|
qdcount = qdcount,
|
||||||
|
ancount = ancount,
|
||||||
|
nscount = nscount,
|
||||||
|
arcount = arcount
|
||||||
|
}, left
|
||||||
|
end
|
||||||
|
|
||||||
|
-- unpack a resource name
|
||||||
|
local function unpack_name(chunk, left)
|
||||||
|
local t = {}
|
||||||
|
local jump_pointer
|
||||||
|
local tag, offset, label
|
||||||
|
while true do
|
||||||
|
tag, left = string.unpack("B", chunk, left)
|
||||||
|
if tag & 0xc0 == 0xc0 then
|
||||||
|
-- pointer
|
||||||
|
offset,left = string.unpack(">H", chunk, left - 1)
|
||||||
|
offset = offset & 0x3fff
|
||||||
|
if not jump_pointer then
|
||||||
|
jump_pointer = left
|
||||||
|
end
|
||||||
|
-- offset is base 0, need to plus 1
|
||||||
|
left = offset + 1
|
||||||
|
elseif tag == 0 then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
label, left = string.unpack("s1", chunk, left - 1)
|
||||||
|
t[#t+1] = label
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(t, "."), jump_pointer or left
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unpack_question(chunk, left)
|
||||||
|
local name, left = unpack_name(chunk, left)
|
||||||
|
local atype, class, left = string.unpack(">HH", chunk, left)
|
||||||
|
return {
|
||||||
|
name = name,
|
||||||
|
atype = atype,
|
||||||
|
class = class
|
||||||
|
}, left
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unpack_answer(chunk, left)
|
||||||
|
local name, left = unpack_name(chunk, left)
|
||||||
|
local atype, class, ttl, rdata, left = string.unpack(">HHI4s2", chunk, left)
|
||||||
|
return {
|
||||||
|
name = name,
|
||||||
|
atype = atype,
|
||||||
|
class = class,
|
||||||
|
ttl = ttl,
|
||||||
|
rdata = rdata
|
||||||
|
},left
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unpack_rdata(qtype, chunk)
|
||||||
|
if qtype == QTYPE.A then
|
||||||
|
local a,b,c,d = string.unpack("BBBB", chunk)
|
||||||
|
return string.format("%d.%d.%d.%d", a,b,c,d)
|
||||||
|
elseif qtype == QTYPE.AAAA then
|
||||||
|
local a,b,c,d,e,f,g,h = string.unpack(">HHHHHHHH", chunk)
|
||||||
|
return string.format("%x:%x:%x:%x:%x:%x:%x:%x", a, b, c, d, e, f, g, h)
|
||||||
|
else
|
||||||
|
error("Error qtype " .. qtype)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dns_server
|
||||||
|
local request_pool = {}
|
||||||
|
|
||||||
|
local function resolve(content)
|
||||||
|
if #content < DNS_HEADER_LEN then
|
||||||
|
-- drop
|
||||||
|
skynet.error("Recv an invalid package when dns query")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local answer_header,left = unpack_header(content)
|
||||||
|
-- verify answer
|
||||||
|
assert(answer_header.qdcount == 1, "malformed packet")
|
||||||
|
|
||||||
|
local resp = request_pool[answer_header.tid]
|
||||||
|
if not resp then
|
||||||
|
skynet.error("Recv an invalid tid when dns query")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local question,left = unpack_question(content, left)
|
||||||
|
if question.name ~= resp.name then
|
||||||
|
skynet.error("Recv an invalid name when dns query")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local ttl
|
||||||
|
local answer
|
||||||
|
local answers = {}
|
||||||
|
for i=1, answer_header.ancount do
|
||||||
|
answer, left = unpack_answer(content, left)
|
||||||
|
-- only extract qtype address
|
||||||
|
if answer.atype == resp.qtype then
|
||||||
|
local ip = unpack_rdata(resp.qtype, answer.rdata)
|
||||||
|
ttl = ttl and math.min(ttl, answer.ttl) or answer.ttl
|
||||||
|
answers[#answers+1] = ip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #answers > 0 then
|
||||||
|
resp.answers = answers
|
||||||
|
end
|
||||||
|
|
||||||
|
skynet.wakeup(resp.co)
|
||||||
|
end
|
||||||
|
|
||||||
|
function dns.server(server, port)
|
||||||
|
if not server then
|
||||||
|
local f = assert(io.open "/etc/resolv.conf")
|
||||||
|
for line in f:lines() do
|
||||||
|
server = line:match("%s*nameserver%s+([^%s]+)")
|
||||||
|
if server then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(server, "Can't get nameserver")
|
||||||
|
end
|
||||||
|
dns_server = socket.udp(function(str, from)
|
||||||
|
resolve(str)
|
||||||
|
end)
|
||||||
|
socket.udp_connect(dns_server, server, port or 53)
|
||||||
|
return server
|
||||||
|
end
|
||||||
|
|
||||||
|
local function suspend(tid, name, qtype)
|
||||||
|
local req = {
|
||||||
|
name = name,
|
||||||
|
tid = tid,
|
||||||
|
qtype = qtype,
|
||||||
|
time = skynet.now(), -- for timeout
|
||||||
|
co = coroutine.running(),
|
||||||
|
}
|
||||||
|
request_pool[tid] = req
|
||||||
|
skynet.wait()
|
||||||
|
local answers = request_pool[tid].answers
|
||||||
|
request_pool[tid] = nil
|
||||||
|
assert(answers, "no ip")
|
||||||
|
return answers[1], answers
|
||||||
|
end
|
||||||
|
|
||||||
|
function dns.resolve(name, ipv6)
|
||||||
|
local qtype = ipv6 and QTYPE.AAAA or QTYPE.A
|
||||||
|
local name = name:lower()
|
||||||
|
assert(verify_domain_name(name) , "illegal name")
|
||||||
|
local question_header = {
|
||||||
|
tid = gen_tid(),
|
||||||
|
flags = 0x100, -- flags: 00000001 00000000, set RD
|
||||||
|
qdcount = 1,
|
||||||
|
}
|
||||||
|
local req = pack_header(question_header) .. pack_question(name, qtype, QCLASS.IN)
|
||||||
|
assert(dns_server, "Call dns.server first")
|
||||||
|
socket.write(dns_server, req)
|
||||||
|
return suspend(question_header.tid, name, qtype)
|
||||||
|
end
|
||||||
|
|
||||||
|
return dns
|
||||||
@@ -11,16 +11,21 @@ local function request(fd, method, host, url, recvheader, header, content)
|
|||||||
local write = socket.writefunc(fd)
|
local write = socket.writefunc(fd)
|
||||||
local header_content = ""
|
local header_content = ""
|
||||||
if header then
|
if header then
|
||||||
|
if not header.host then
|
||||||
|
header.host = host
|
||||||
|
end
|
||||||
for k,v in pairs(header) do
|
for k,v in pairs(header) do
|
||||||
header_content = string.format("%s%s:%s\r\n", header_content, k, v)
|
header_content = string.format("%s%s:%s\r\n", header_content, k, v)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
header_content = string.format("host:%s\r\n",host)
|
||||||
end
|
end
|
||||||
|
|
||||||
if content then
|
if content then
|
||||||
local data = string.format("%s %s HTTP/1.1\r\nhost:%s\r\ncontent-length:%d\r\n%s\r\n%s", method, url, host, #content, header_content, content)
|
local data = string.format("%s %s HTTP/1.1\r\n%scontent-length:%d\r\n\r\n%s", method, url, header_content, #content, content)
|
||||||
write(data)
|
write(data)
|
||||||
else
|
else
|
||||||
local request_header = string.format("%s %s HTTP/1.1\r\nhost:%s\r\ncontent-length:0\r\n%s\r\n", method, url, host, header_content)
|
local request_header = string.format("%s %s HTTP/1.1\r\n%scontent-length:0\r\n\r\n", method, url, header_content)
|
||||||
write(request_header)
|
write(request_header)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ local internal = require "http.internal"
|
|||||||
|
|
||||||
local table = table
|
local table = table
|
||||||
local string = string
|
local string = string
|
||||||
|
local type = type
|
||||||
|
|
||||||
local httpd = {}
|
local httpd = {}
|
||||||
|
|
||||||
@@ -113,7 +114,13 @@ local function writeall(writefunc, statuscode, bodyfunc, header)
|
|||||||
writefunc(statusline)
|
writefunc(statusline)
|
||||||
if header then
|
if header then
|
||||||
for k,v in pairs(header) do
|
for k,v in pairs(header) do
|
||||||
writefunc(string.format("%s: %s\r\n", k,v))
|
if type(v) == "table" then
|
||||||
|
for _,v in ipairs(v) do
|
||||||
|
writefunc(string.format("%s: %s\r\n", k,v))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
writefunc(string.format("%s: %s\r\n", k,v))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local t = type(bodyfunc)
|
local t = type(bodyfunc)
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
local table = table
|
||||||
|
local type = type
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local LIMIT = 8192
|
local LIMIT = 8192
|
||||||
@@ -83,7 +86,12 @@ function M.parseheader(lines, from, header)
|
|||||||
end
|
end
|
||||||
name = name:lower()
|
name = name:lower()
|
||||||
if header[name] then
|
if header[name] then
|
||||||
header[name] = header[name] .. ", " .. value
|
local v = header[name]
|
||||||
|
if type(v) == "table" then
|
||||||
|
table.insert(v, value)
|
||||||
|
else
|
||||||
|
header[name] = { v , value }
|
||||||
|
end
|
||||||
else
|
else
|
||||||
header[name] = value
|
header[name] = value
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ local dispatch = setmetatable({} , {__mode = "kv" })
|
|||||||
local chan = {}
|
local chan = {}
|
||||||
local chan_meta = {
|
local chan_meta = {
|
||||||
__index = chan,
|
__index = chan,
|
||||||
__gc = unsubscribe,
|
__gc = function(self)
|
||||||
|
self:unsubscribe()
|
||||||
|
end,
|
||||||
__tostring = function (self)
|
__tostring = function (self)
|
||||||
return string.format("[Multicast:%x]",self.channel)
|
return string.format("[Multicast:%x]",self.channel)
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -30,12 +30,14 @@ function sharemap.writer(typename, obj)
|
|||||||
local sp = loadsp()
|
local sp = loadsp()
|
||||||
obj = obj or {}
|
obj = obj or {}
|
||||||
local stmobj = stm.new(sp:encode(typename,obj))
|
local stmobj = stm.new(sp:encode(typename,obj))
|
||||||
obj.__typename = typename
|
local ret = {
|
||||||
obj.__obj = stmobj
|
__typename = typename,
|
||||||
obj.__data = obj
|
__obj = stmobj,
|
||||||
obj.commit = sharemap.commit
|
__data = obj,
|
||||||
obj.copy = sharemap.copy
|
commit = sharemap.commit,
|
||||||
return setmetatable(obj, { __index = obj.__data, __newindex = obj.__data })
|
copy = sharemap.copy,
|
||||||
|
}
|
||||||
|
return setmetatable(ret, { __index = obj, __newindex = obj })
|
||||||
end
|
end
|
||||||
|
|
||||||
local function decode(msg, sz, self)
|
local function decode(msg, sz, self)
|
||||||
@@ -63,7 +65,7 @@ function sharemap.reader(typename, stmcpy)
|
|||||||
__data = data,
|
__data = data,
|
||||||
update = sharemap.update,
|
update = sharemap.update,
|
||||||
}
|
}
|
||||||
return setmetatable(obj, { __index = obj.__data, __newindex = error })
|
return setmetatable(obj, { __index = data, __newindex = error })
|
||||||
end
|
end
|
||||||
|
|
||||||
return sharemap
|
return sharemap
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ local session_id_coroutine = {}
|
|||||||
local session_coroutine_id = {}
|
local session_coroutine_id = {}
|
||||||
local session_coroutine_address = {}
|
local session_coroutine_address = {}
|
||||||
local session_response = {}
|
local session_response = {}
|
||||||
|
local unresponse = {}
|
||||||
|
|
||||||
local wakeup_session = {}
|
local wakeup_session = {}
|
||||||
local sleep_session = {}
|
local sleep_session = {}
|
||||||
@@ -96,7 +97,6 @@ end
|
|||||||
|
|
||||||
local coroutine_pool = {}
|
local coroutine_pool = {}
|
||||||
local coroutine_yield = coroutine.yield
|
local coroutine_yield = coroutine.yield
|
||||||
local coroutine_count = 0
|
|
||||||
|
|
||||||
local function co_create(f)
|
local function co_create(f)
|
||||||
local co = table.remove(coroutine_pool)
|
local co = table.remove(coroutine_pool)
|
||||||
@@ -110,11 +110,6 @@ local function co_create(f)
|
|||||||
f(coroutine_yield())
|
f(coroutine_yield())
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
coroutine_count = coroutine_count + 1
|
|
||||||
if coroutine_count > 1024 then
|
|
||||||
skynet.error("May overload, create 1024 task")
|
|
||||||
coroutine_count = 0
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
coroutine.resume(co, f)
|
coroutine.resume(co, f)
|
||||||
end
|
end
|
||||||
@@ -128,7 +123,7 @@ local function dispatch_wakeup()
|
|||||||
local session = sleep_session[co]
|
local session = sleep_session[co]
|
||||||
if session then
|
if session then
|
||||||
session_id_coroutine[session] = "BREAK"
|
session_id_coroutine[session] = "BREAK"
|
||||||
return suspend(co, coroutine.resume(co, true, "BREAK"))
|
return suspend(co, coroutine.resume(co, false, "BREAK"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -175,7 +170,11 @@ function suspend(co, result, command, param, size)
|
|||||||
local ret
|
local ret
|
||||||
if not dead_service[co_address] then
|
if not dead_service[co_address] then
|
||||||
ret = c.send(co_address, skynet.PTYPE_RESPONSE, co_session, param, size) ~= nil
|
ret = c.send(co_address, skynet.PTYPE_RESPONSE, co_session, param, size) ~= nil
|
||||||
elseif size == nil then
|
if not ret then
|
||||||
|
-- If the package is too large, returns nil. so we should report error back
|
||||||
|
c.send(co_address, skynet.PTYPE_ERROR, co_session, "")
|
||||||
|
end
|
||||||
|
elseif size ~= nil then
|
||||||
c.trash(param, size)
|
c.trash(param, size)
|
||||||
ret = false
|
ret = false
|
||||||
end
|
end
|
||||||
@@ -209,6 +208,10 @@ function suspend(co, result, command, param, size)
|
|||||||
if not dead_service[co_address] then
|
if not dead_service[co_address] then
|
||||||
if ok then
|
if ok then
|
||||||
ret = c.send(co_address, skynet.PTYPE_RESPONSE, co_session, f(...)) ~= nil
|
ret = c.send(co_address, skynet.PTYPE_RESPONSE, co_session, f(...)) ~= nil
|
||||||
|
if not ret then
|
||||||
|
-- If the package is too large, returns false. so we should report error back
|
||||||
|
c.send(co_address, skynet.PTYPE_ERROR, co_session, "")
|
||||||
|
end
|
||||||
else
|
else
|
||||||
ret = c.send(co_address, skynet.PTYPE_ERROR, co_session, "") ~= nil
|
ret = c.send(co_address, skynet.PTYPE_ERROR, co_session, "") ~= nil
|
||||||
end
|
end
|
||||||
@@ -216,11 +219,13 @@ function suspend(co, result, command, param, size)
|
|||||||
ret = false
|
ret = false
|
||||||
end
|
end
|
||||||
release_watching(co_address)
|
release_watching(co_address)
|
||||||
|
unresponse[response] = nil
|
||||||
f = nil
|
f = nil
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
watching_service[co_address] = watching_service[co_address] + 1
|
watching_service[co_address] = watching_service[co_address] + 1
|
||||||
session_response[co] = response
|
session_response[co] = response
|
||||||
|
unresponse[response] = true
|
||||||
return suspend(co, coroutine.resume(co, response))
|
return suspend(co, coroutine.resume(co, response))
|
||||||
elseif command == "EXIT" then
|
elseif command == "EXIT" then
|
||||||
-- coroutine exit
|
-- coroutine exit
|
||||||
@@ -257,9 +262,13 @@ function skynet.sleep(ti)
|
|||||||
session = tonumber(session)
|
session = tonumber(session)
|
||||||
local succ, ret = coroutine_yield("SLEEP", session)
|
local succ, ret = coroutine_yield("SLEEP", session)
|
||||||
sleep_session[coroutine.running()] = nil
|
sleep_session[coroutine.running()] = nil
|
||||||
assert(succ, ret)
|
if succ then
|
||||||
|
return
|
||||||
|
end
|
||||||
if ret == "BREAK" then
|
if ret == "BREAK" then
|
||||||
return "BREAK"
|
return "BREAK"
|
||||||
|
else
|
||||||
|
error(ret)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -269,41 +278,12 @@ end
|
|||||||
|
|
||||||
function skynet.wait()
|
function skynet.wait()
|
||||||
local session = c.genid()
|
local session = c.genid()
|
||||||
coroutine_yield("SLEEP", session)
|
local ret, msg = coroutine_yield("SLEEP", session)
|
||||||
local co = coroutine.running()
|
local co = coroutine.running()
|
||||||
sleep_session[co] = nil
|
sleep_session[co] = nil
|
||||||
session_id_coroutine[session] = nil
|
session_id_coroutine[session] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local function globalname(name, handle)
|
|
||||||
local c = string.sub(name,1,1)
|
|
||||||
assert(c ~= ':')
|
|
||||||
if c == '.' then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
assert(#name <= 16) -- GLOBALNAME_LENGTH is 16, defined in skynet_harbor.h
|
|
||||||
assert(tonumber(name) == nil) -- global name can't be number
|
|
||||||
|
|
||||||
local harbor = require "skynet.harbor"
|
|
||||||
|
|
||||||
harbor.globalname(name, handle)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.register(name)
|
|
||||||
if not globalname(name) then
|
|
||||||
c.command("REG", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.name(name, handle)
|
|
||||||
if not globalname(name, handle) then
|
|
||||||
c.command("NAME", name .. " " .. skynet.address(handle))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local self_handle
|
local self_handle
|
||||||
function skynet.self()
|
function skynet.self()
|
||||||
if self_handle then
|
if self_handle then
|
||||||
@@ -320,13 +300,6 @@ function skynet.localname(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.launch(...)
|
|
||||||
local addr = c.command("LAUNCH", table.concat({...}," "))
|
|
||||||
if addr then
|
|
||||||
return string_to_handle(addr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.now()
|
function skynet.now()
|
||||||
return tonumber(c.command("NOW"))
|
return tonumber(c.command("NOW"))
|
||||||
end
|
end
|
||||||
@@ -349,6 +322,9 @@ function skynet.exit()
|
|||||||
c.redirect(address, 0, skynet.PTYPE_ERROR, session, "")
|
c.redirect(address, 0, skynet.PTYPE_ERROR, session, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for resp in pairs(unresponse) do
|
||||||
|
resp(false)
|
||||||
|
end
|
||||||
-- report the sources I call but haven't return
|
-- report the sources I call but haven't return
|
||||||
local tmp = {}
|
local tmp = {}
|
||||||
for session, address in pairs(watching_session) do
|
for session, address in pairs(watching_session) do
|
||||||
@@ -362,14 +338,6 @@ function skynet.exit()
|
|||||||
coroutine_yield "QUIT"
|
coroutine_yield "QUIT"
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.kill(name)
|
|
||||||
if type(name) == "number" then
|
|
||||||
skynet.send(".launcher","lua","REMOVE",name, true)
|
|
||||||
name = skynet.address(name)
|
|
||||||
end
|
|
||||||
c.command("KILL",name)
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.getenv(key)
|
function skynet.getenv(key)
|
||||||
local ret = c.command("GETENV",key)
|
local ret = c.command("GETENV",key)
|
||||||
if ret == "" then
|
if ret == "" then
|
||||||
@@ -398,13 +366,14 @@ skynet.pack = assert(c.pack)
|
|||||||
skynet.packstring = assert(c.packstring)
|
skynet.packstring = assert(c.packstring)
|
||||||
skynet.unpack = assert(c.unpack)
|
skynet.unpack = assert(c.unpack)
|
||||||
skynet.tostring = assert(c.tostring)
|
skynet.tostring = assert(c.tostring)
|
||||||
|
skynet.trash = assert(c.trash)
|
||||||
|
|
||||||
local function yield_call(service, session)
|
local function yield_call(service, session)
|
||||||
watching_session[session] = service
|
watching_session[session] = service
|
||||||
local succ, msg, sz = coroutine_yield("CALL", session)
|
local succ, msg, sz = coroutine_yield("CALL", session)
|
||||||
watching_session[session] = nil
|
watching_session[session] = nil
|
||||||
if not succ then
|
if not succ then
|
||||||
error(debug.traceback())
|
error "call failed"
|
||||||
end
|
end
|
||||||
return msg,sz
|
return msg,sz
|
||||||
end
|
end
|
||||||
@@ -446,9 +415,14 @@ function skynet.wakeup(co)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.dispatch(typename, func)
|
function skynet.dispatch(typename, func)
|
||||||
local p = assert(proto[typename],tostring(typename))
|
local p = proto[typename]
|
||||||
assert(p.dispatch == nil, tostring(typename))
|
if func then
|
||||||
p.dispatch = func
|
local ret = p.dispatch
|
||||||
|
p.dispatch = func
|
||||||
|
return ret
|
||||||
|
else
|
||||||
|
return p and p.dispatch
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function unknown_request(session, address, msg, sz, prototype)
|
local function unknown_request(session, address, msg, sz, prototype)
|
||||||
@@ -463,7 +437,7 @@ function skynet.dispatch_unknown_request(unknown)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function unknown_response(session, address, msg, sz)
|
local function unknown_response(session, address, msg, sz)
|
||||||
skynet.error(string.format("Response message :" , c.tostring(msg,sz)))
|
skynet.error(string.format("Response message : %s" , c.tostring(msg,sz)))
|
||||||
error(string.format("Unknown session : %d from %x", session, address))
|
error(string.format("Unknown session : %d from %x", session, address))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -481,6 +455,7 @@ function skynet.fork(func,...)
|
|||||||
func(tunpack(args))
|
func(tunpack(args))
|
||||||
end)
|
end)
|
||||||
table.insert(fork_queue, co)
|
table.insert(fork_queue, co)
|
||||||
|
return co
|
||||||
end
|
end
|
||||||
|
|
||||||
local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
|
local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
|
||||||
@@ -496,7 +471,15 @@ local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
|
|||||||
suspend(co, coroutine.resume(co, true, msg, sz))
|
suspend(co, coroutine.resume(co, true, msg, sz))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local p = assert(proto[prototype], prototype)
|
local p = proto[prototype]
|
||||||
|
if p == nil then
|
||||||
|
if session ~= 0 then
|
||||||
|
c.send(source, skynet.PTYPE_ERROR, session, "")
|
||||||
|
else
|
||||||
|
unknown_request(session, source, msg, sz, prototype)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
local f = p.dispatch
|
local f = p.dispatch
|
||||||
if f then
|
if f then
|
||||||
local ref = watching_service[source]
|
local ref = watching_service[source]
|
||||||
@@ -510,12 +493,12 @@ local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
|
|||||||
session_coroutine_address[co] = source
|
session_coroutine_address[co] = source
|
||||||
suspend(co, coroutine.resume(co, session,source, p.unpack(msg,sz, ...)))
|
suspend(co, coroutine.resume(co, session,source, p.unpack(msg,sz, ...)))
|
||||||
else
|
else
|
||||||
unknown_request(session, source, msg, sz, proto[prototype])
|
unknown_request(session, source, msg, sz, proto[prototype].name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dispatch_message(...)
|
function skynet.dispatch_message(...)
|
||||||
local succ, err = pcall(raw_dispatch_message,...)
|
local succ, err = pcall(raw_dispatch_message,...)
|
||||||
while true do
|
while true do
|
||||||
local key,co = next(fork_queue)
|
local key,co = next(fork_queue)
|
||||||
@@ -619,8 +602,10 @@ end
|
|||||||
local function init_all()
|
local function init_all()
|
||||||
local funcs = init_func
|
local funcs = init_func
|
||||||
init_func = nil
|
init_func = nil
|
||||||
for k,v in pairs(funcs) do
|
if funcs then
|
||||||
v()
|
for k,v in pairs(funcs) do
|
||||||
|
v()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -631,8 +616,12 @@ local function init_template(start)
|
|||||||
init_all()
|
init_all()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function init_service(start)
|
function skynet.pcall(start)
|
||||||
local ok, err = xpcall(init_template, debug.traceback, start)
|
return xpcall(init_template, debug.traceback, start)
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.init_service(start)
|
||||||
|
local ok, err = skynet.pcall(start)
|
||||||
if not ok then
|
if not ok then
|
||||||
skynet.error("init service failed: " .. tostring(err))
|
skynet.error("init service failed: " .. tostring(err))
|
||||||
skynet.send(".launcher","lua", "ERROR")
|
skynet.send(".launcher","lua", "ERROR")
|
||||||
@@ -643,33 +632,9 @@ local function init_service(start)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function skynet.start(start_func)
|
function skynet.start(start_func)
|
||||||
c.callback(dispatch_message)
|
c.callback(skynet.dispatch_message)
|
||||||
skynet.timeout(0, function()
|
skynet.timeout(0, function()
|
||||||
init_service(start_func)
|
skynet.init_service(start_func)
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.filter(f ,start_func)
|
|
||||||
c.callback(function(...)
|
|
||||||
dispatch_message(f(...))
|
|
||||||
end)
|
|
||||||
skynet.timeout(0, function()
|
|
||||||
init_service(start_func)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.forward_type(map, start_func)
|
|
||||||
c.callback(function(ptype, msg, sz, ...)
|
|
||||||
local prototype = map[ptype]
|
|
||||||
if prototype then
|
|
||||||
dispatch_message(prototype, msg, sz, ...)
|
|
||||||
else
|
|
||||||
dispatch_message(ptype, msg, sz, ...)
|
|
||||||
c.trash(msg, sz)
|
|
||||||
end
|
|
||||||
end, true)
|
|
||||||
skynet.timeout(0, function()
|
|
||||||
init_service(start_func)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -677,22 +642,6 @@ function skynet.endless()
|
|||||||
return c.command("ENDLESS")~=nil
|
return c.command("ENDLESS")~=nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function skynet.abort()
|
|
||||||
c.command("ABORT")
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.monitor(service, query)
|
|
||||||
local monitor
|
|
||||||
if query then
|
|
||||||
monitor = skynet.queryservice(true, service)
|
|
||||||
else
|
|
||||||
monitor = skynet.uniqueservice(true, service)
|
|
||||||
end
|
|
||||||
assert(monitor, "Monitor launch failed")
|
|
||||||
c.command("MONITOR", string.format(":%08x", monitor))
|
|
||||||
return monitor
|
|
||||||
end
|
|
||||||
|
|
||||||
function skynet.mqlen()
|
function skynet.mqlen()
|
||||||
return tonumber(c.command "MQLEN")
|
return tonumber(c.command "MQLEN")
|
||||||
end
|
end
|
||||||
@@ -719,7 +668,7 @@ end
|
|||||||
-- Inject internal debug framework
|
-- Inject internal debug framework
|
||||||
local debug = require "skynet.debug"
|
local debug = require "skynet.debug"
|
||||||
debug(skynet, {
|
debug(skynet, {
|
||||||
dispatch = dispatch_message,
|
dispatch = skynet.dispatch_message,
|
||||||
clear = clear_pool,
|
clear = clear_pool,
|
||||||
suspend = suspend,
|
suspend = suspend,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ function skynet.info_func(func)
|
|||||||
internal_info_func = func
|
internal_info_func = func
|
||||||
end
|
end
|
||||||
|
|
||||||
local dbgcmd = {}
|
local dbgcmd
|
||||||
|
|
||||||
|
local function init_dbgcmd()
|
||||||
|
dbgcmd = {}
|
||||||
|
|
||||||
function dbgcmd.MEM()
|
function dbgcmd.MEM()
|
||||||
local kb, bytes = collectgarbage "count"
|
local kb, bytes = collectgarbage "count"
|
||||||
@@ -49,7 +52,7 @@ end
|
|||||||
|
|
||||||
function dbgcmd.RUN(source, filename)
|
function dbgcmd.RUN(source, filename)
|
||||||
local inject = require "skynet.inject"
|
local inject = require "skynet.inject"
|
||||||
local output = inject(source, filename , export.dispatch, skynet.register_protocol)
|
local output = inject(skynet, source, filename , export.dispatch, skynet.register_protocol)
|
||||||
collectgarbage "collect"
|
collectgarbage "collect"
|
||||||
skynet.ret(skynet.pack(table.concat(output, "\n")))
|
skynet.ret(skynet.pack(table.concat(output, "\n")))
|
||||||
end
|
end
|
||||||
@@ -63,8 +66,15 @@ function dbgcmd.REMOTEDEBUG(...)
|
|||||||
remotedebug.start(export, ...)
|
remotedebug.start(export, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dbgcmd.SUPPORT(pname)
|
||||||
|
return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
|
||||||
|
end
|
||||||
|
|
||||||
|
return dbgcmd
|
||||||
|
end -- function init_dbgcmd
|
||||||
|
|
||||||
local function _debug_dispatch(session, address, cmd, ...)
|
local function _debug_dispatch(session, address, cmd, ...)
|
||||||
local f = dbgcmd[cmd]
|
local f = (dbgcmd or init_dbgcmd())[cmd] -- lazy init dbgcmd
|
||||||
assert(f, cmd)
|
assert(f, cmd)
|
||||||
f(...)
|
f(...)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local function getupvaluetable(u, func, unique)
|
local function getupvaluetable(u, func, unique)
|
||||||
i = 1
|
local i = 1
|
||||||
while true do
|
while true do
|
||||||
local name, value = debug.getupvalue(func, i)
|
local name, value = debug.getupvalue(func, i)
|
||||||
if name == nil then
|
if name == nil then
|
||||||
@@ -18,7 +18,7 @@ local function getupvaluetable(u, func, unique)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return function(source, filename , ...)
|
return function(skynet, source, filename , ...)
|
||||||
if filename then
|
if filename then
|
||||||
filename = "@" .. filename
|
filename = "@" .. filename
|
||||||
else
|
else
|
||||||
@@ -44,7 +44,7 @@ return function(source, filename , ...)
|
|||||||
if proto then
|
if proto then
|
||||||
for k,v in pairs(proto) do
|
for k,v in pairs(proto) do
|
||||||
local name, dispatch = v.name, v.dispatch
|
local name, dispatch = v.name, v.dispatch
|
||||||
if name and dispatch then
|
if name and dispatch and not p[name] then
|
||||||
local pp = {}
|
local pp = {}
|
||||||
p[name] = pp
|
p[name] = pp
|
||||||
getupvaluetable(pp, dispatch, unique)
|
getupvaluetable(pp, dispatch, unique)
|
||||||
@@ -56,7 +56,7 @@ return function(source, filename , ...)
|
|||||||
if not func then
|
if not func then
|
||||||
return { err }
|
return { err }
|
||||||
end
|
end
|
||||||
local ok, err = xpcall(func, debug.traceback)
|
local ok, err = skynet.pcall(func)
|
||||||
if not ok then
|
if not ok then
|
||||||
table.insert(output, err)
|
table.insert(output, err)
|
||||||
end
|
end
|
||||||
|
|||||||
90
lualib/skynet/manager.lua
Normal file
90
lualib/skynet/manager.lua
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
local c = require "skynet.core"
|
||||||
|
|
||||||
|
function skynet.launch(...)
|
||||||
|
local addr = c.command("LAUNCH", table.concat({...}," "))
|
||||||
|
if addr then
|
||||||
|
return tonumber("0x" .. string.sub(addr , 2))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.kill(name)
|
||||||
|
if type(name) == "number" then
|
||||||
|
skynet.send(".launcher","lua","REMOVE",name, true)
|
||||||
|
name = skynet.address(name)
|
||||||
|
end
|
||||||
|
c.command("KILL",name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.abort()
|
||||||
|
c.command("ABORT")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function globalname(name, handle)
|
||||||
|
local c = string.sub(name,1,1)
|
||||||
|
assert(c ~= ':')
|
||||||
|
if c == '.' then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(#name <= 16) -- GLOBALNAME_LENGTH is 16, defined in skynet_harbor.h
|
||||||
|
assert(tonumber(name) == nil) -- global name can't be number
|
||||||
|
|
||||||
|
local harbor = require "skynet.harbor"
|
||||||
|
|
||||||
|
harbor.globalname(name, handle)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.register(name)
|
||||||
|
if not globalname(name) then
|
||||||
|
c.command("REG", name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.name(name, handle)
|
||||||
|
if not globalname(name, handle) then
|
||||||
|
c.command("NAME", name .. " " .. skynet.address(handle))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dispatch_message = skynet.dispatch_message
|
||||||
|
|
||||||
|
function skynet.forward_type(map, start_func)
|
||||||
|
c.callback(function(ptype, msg, sz, ...)
|
||||||
|
local prototype = map[ptype]
|
||||||
|
if prototype then
|
||||||
|
dispatch_message(prototype, msg, sz, ...)
|
||||||
|
else
|
||||||
|
dispatch_message(ptype, msg, sz, ...)
|
||||||
|
c.trash(msg, sz)
|
||||||
|
end
|
||||||
|
end, true)
|
||||||
|
skynet.timeout(0, function()
|
||||||
|
skynet.init_service(start_func)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.filter(f ,start_func)
|
||||||
|
c.callback(function(...)
|
||||||
|
dispatch_message(f(...))
|
||||||
|
end)
|
||||||
|
skynet.timeout(0, function()
|
||||||
|
skynet.init_service(start_func)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function skynet.monitor(service, query)
|
||||||
|
local monitor
|
||||||
|
if query then
|
||||||
|
monitor = skynet.queryservice(true, service)
|
||||||
|
else
|
||||||
|
monitor = skynet.uniqueservice(true, service)
|
||||||
|
end
|
||||||
|
assert(monitor, "Monitor launch failed")
|
||||||
|
c.command("MONITOR", string.format(":%08x", monitor))
|
||||||
|
return monitor
|
||||||
|
end
|
||||||
|
|
||||||
|
return skynet
|
||||||
@@ -162,4 +162,8 @@ function snax.hotfix(obj, source, ...)
|
|||||||
return test_result(skynet_call(obj.handle, "snax", t.system.hotfix, source, ...))
|
return test_result(skynet_call(obj.handle, "snax", t.system.hotfix, source, ...))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function snax.printf(fmt, ...)
|
||||||
|
skynet.error(string.format(fmt, ...))
|
||||||
|
end
|
||||||
|
|
||||||
return snax
|
return snax
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ local function collect_all_uv(funcs)
|
|||||||
collect_uv(v[4], global, envid(v[4]))
|
collect_uv(v[4], global, envid(v[4]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not global["_ENV"] then
|
||||||
|
global["_ENV"] = {func = collect_uv, index = 1}
|
||||||
|
end
|
||||||
return global
|
return global
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ return function (name , G, loader)
|
|||||||
local pattern
|
local pattern
|
||||||
|
|
||||||
do
|
do
|
||||||
local path = skynet.getenv "snax"
|
local path = assert(skynet.getenv "snax" , "please set snax in config file")
|
||||||
|
|
||||||
local errlist = {}
|
local errlist = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager"
|
||||||
local socket = require "socket"
|
local socket = require "socket"
|
||||||
local crypt = require "crypt"
|
local crypt = require "crypt"
|
||||||
local table = table
|
local table = table
|
||||||
@@ -33,17 +34,17 @@ Success:
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local socket_error = {}
|
local socket_error = {}
|
||||||
local function assert_socket(v, fd)
|
local function assert_socket(service, v, fd)
|
||||||
if v then
|
if v then
|
||||||
return v
|
return v
|
||||||
else
|
else
|
||||||
skynet.error(string.format("auth failed: socket (fd = %d) closed", fd))
|
skynet.error(string.format("%s failed: socket (fd = %d) closed", service, fd))
|
||||||
error(socket_error)
|
error(socket_error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function write(fd, text)
|
local function write(service, fd, text)
|
||||||
assert_socket(socket.write(fd, text), fd)
|
assert_socket(service, socket.write(fd, text), fd)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function launch_slave(auth_handler)
|
local function launch_slave(auth_handler)
|
||||||
@@ -57,27 +58,27 @@ local function launch_slave(auth_handler)
|
|||||||
socket.limit(fd, 8192)
|
socket.limit(fd, 8192)
|
||||||
|
|
||||||
local challenge = crypt.randomkey()
|
local challenge = crypt.randomkey()
|
||||||
write(fd, crypt.base64encode(challenge).."\n")
|
write("auth", fd, crypt.base64encode(challenge).."\n")
|
||||||
|
|
||||||
local handshake = assert_socket(socket.readline(fd), fd)
|
local handshake = assert_socket("auth", socket.readline(fd), fd)
|
||||||
local clientkey = crypt.base64decode(handshake)
|
local clientkey = crypt.base64decode(handshake)
|
||||||
if #clientkey ~= 8 then
|
if #clientkey ~= 8 then
|
||||||
error "Invalid client key"
|
error "Invalid client key"
|
||||||
end
|
end
|
||||||
local serverkey = crypt.randomkey()
|
local serverkey = crypt.randomkey()
|
||||||
write(fd, crypt.base64encode(crypt.dhexchange(serverkey)).."\n")
|
write("auth", fd, crypt.base64encode(crypt.dhexchange(serverkey)).."\n")
|
||||||
|
|
||||||
local secret = crypt.dhsecret(clientkey, serverkey)
|
local secret = crypt.dhsecret(clientkey, serverkey)
|
||||||
|
|
||||||
local response = assert_socket(socket.readline(fd), fd)
|
local response = assert_socket("auth", socket.readline(fd), fd)
|
||||||
local hmac = crypt.hmac64(challenge, secret)
|
local hmac = crypt.hmac64(challenge, secret)
|
||||||
|
|
||||||
if hmac ~= crypt.base64decode(response) then
|
if hmac ~= crypt.base64decode(response) then
|
||||||
write(fd, "400 Bad Request\n")
|
write("auth", fd, "400 Bad Request\n")
|
||||||
error "challenge failed"
|
error "challenge failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
local etoken = assert_socket(socket.readline(fd),fd)
|
local etoken = assert_socket("auth", socket.readline(fd),fd)
|
||||||
|
|
||||||
local token = crypt.desdecode(secret, crypt.base64decode(etoken))
|
local token = crypt.desdecode(secret, crypt.base64decode(etoken))
|
||||||
|
|
||||||
@@ -91,7 +92,11 @@ local function launch_slave(auth_handler)
|
|||||||
if ok then
|
if ok then
|
||||||
skynet.ret(skynet.pack(err, ...))
|
skynet.ret(skynet.pack(err, ...))
|
||||||
else
|
else
|
||||||
error(err)
|
if err == socket_error then
|
||||||
|
skynet.ret(skynet.pack(nil, "socket error"))
|
||||||
|
else
|
||||||
|
skynet.ret(skynet.pack(false, err))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -108,13 +113,15 @@ local function accept(conf, s, fd, addr)
|
|||||||
socket.start(fd)
|
socket.start(fd)
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
write(fd, "401 Unauthorized\n")
|
if ok ~= nil then
|
||||||
|
write("response 401", fd, "401 Unauthorized\n")
|
||||||
|
end
|
||||||
error(server)
|
error(server)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not conf.multilogin then
|
if not conf.multilogin then
|
||||||
if user_login[uid] then
|
if user_login[uid] then
|
||||||
write(fd, "406 Not Acceptable\n")
|
write("response 406", fd, "406 Not Acceptable\n")
|
||||||
error(string.format("User %s is already login", uid))
|
error(string.format("User %s is already login", uid))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,9 +134,9 @@ local function accept(conf, s, fd, addr)
|
|||||||
|
|
||||||
if ok then
|
if ok then
|
||||||
err = err or ""
|
err = err or ""
|
||||||
write(fd, "200 "..crypt.base64encode(err).."\n")
|
write("response 200",fd, "200 "..crypt.base64encode(err).."\n")
|
||||||
else
|
else
|
||||||
write(fd, "403 Forbidden\n")
|
write("response 403",fd, "403 Forbidden\n")
|
||||||
error(err)
|
error(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ function server.start(conf)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local text = string.format("%s:%s", username, index)
|
local text = string.format("%s:%s", username, index)
|
||||||
local v = crypt.hmac64(crypt.hashkey(text), u.secret)
|
local v = crypt.hmac_hash(u.secret, text) -- equivalent to crypt.hmac64(crypt.hashkey(text), u.secret)
|
||||||
if v ~= hmac then
|
if v ~= hmac then
|
||||||
return "401 Unauthorized"
|
return "401 Unauthorized"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local driver = require "socketdriver"
|
local driver = require "socketdriver"
|
||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
local skynet_core = require "skynet.core"
|
||||||
local assert = assert
|
local assert = assert
|
||||||
|
|
||||||
local socket = {} -- api
|
local socket = {} -- api
|
||||||
@@ -127,7 +128,9 @@ socket_message[6] = function(id, size, data, address)
|
|||||||
driver.drop(data, size)
|
driver.drop(data, size)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
s.callback(data, size, address)
|
local str = skynet.tostring(data, size)
|
||||||
|
skynet_core.trash(data, size)
|
||||||
|
s.callback(str, address)
|
||||||
end
|
end
|
||||||
|
|
||||||
skynet.register_protocol {
|
skynet.register_protocol {
|
||||||
|
|||||||
@@ -303,7 +303,11 @@ local function wait_for_response(self, response)
|
|||||||
self.__result_data[co] = nil
|
self.__result_data[co] = nil
|
||||||
|
|
||||||
if result == socket_error then
|
if result == socket_error then
|
||||||
error(socket_error)
|
if result_data then
|
||||||
|
error(result_data)
|
||||||
|
else
|
||||||
|
error(socket_error)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
assert(result, result_data)
|
assert(result, result_data)
|
||||||
return result_data
|
return result_data
|
||||||
|
|||||||
@@ -13,14 +13,23 @@ function sproto_mt:__gc()
|
|||||||
core.deleteproto(self.__cobj)
|
core.deleteproto(self.__cobj)
|
||||||
end
|
end
|
||||||
|
|
||||||
function sproto.new(bin,sz,nogc)
|
function sproto.new(bin)
|
||||||
local cobj = assert(core.newproto(bin,sz))
|
local cobj = assert(core.newproto(bin))
|
||||||
local self = {
|
local self = {
|
||||||
__cobj = cobj,
|
__cobj = cobj,
|
||||||
__tcache = setmetatable( {} , weak_mt ),
|
__tcache = setmetatable( {} , weak_mt ),
|
||||||
__pcache = setmetatable( {} , weak_mt ),
|
__pcache = setmetatable( {} , weak_mt ),
|
||||||
}
|
}
|
||||||
return setmetatable(self, nogc and sproto_nogc or sproto_mt)
|
return setmetatable(self, sproto_mt)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sproto.sharenew(cobj)
|
||||||
|
local self = {
|
||||||
|
__cobj = cobj,
|
||||||
|
__tcache = setmetatable( {} , weak_mt ),
|
||||||
|
__pcache = setmetatable( {} , weak_mt ),
|
||||||
|
}
|
||||||
|
return setmetatable(self, sproto_nogc)
|
||||||
end
|
end
|
||||||
|
|
||||||
function sproto.parse(ptext)
|
function sproto.parse(ptext)
|
||||||
@@ -90,6 +99,66 @@ local function queryproto(self, pname)
|
|||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function sproto:request_encode(protoname, tbl)
|
||||||
|
local p = queryproto(self, protoname)
|
||||||
|
local request = p.request
|
||||||
|
if request then
|
||||||
|
return core.encode(request,tbl) , p.tag
|
||||||
|
else
|
||||||
|
return "" , p.tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sproto:response_encode(protoname, tbl)
|
||||||
|
local p = queryproto(self, protoname)
|
||||||
|
local response = p.response
|
||||||
|
if response then
|
||||||
|
return core.encode(response,tbl)
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sproto:request_decode(protoname, ...)
|
||||||
|
local p = queryproto(self, protoname)
|
||||||
|
local request = p.request
|
||||||
|
if request then
|
||||||
|
return core.decode(request,...) , p.name
|
||||||
|
else
|
||||||
|
return nil, p.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sproto:response_decode(protoname, ...)
|
||||||
|
local p = queryproto(self, protoname)
|
||||||
|
local response = p.response
|
||||||
|
if response then
|
||||||
|
return core.decode(response,...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sproto.pack = core.pack
|
||||||
|
sproto.unpack = core.unpack
|
||||||
|
|
||||||
|
function sproto:default(typename, type)
|
||||||
|
if type == nil then
|
||||||
|
return core.default(querytype(self, typename))
|
||||||
|
else
|
||||||
|
local p = queryproto(self, typename)
|
||||||
|
if type == "REQUEST" then
|
||||||
|
if p.request then
|
||||||
|
return core.default(p.request)
|
||||||
|
end
|
||||||
|
elseif type == "RESPONSE" then
|
||||||
|
if p.response then
|
||||||
|
return core.default(p.response)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error "Invalid type"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local header_tmp = {}
|
local header_tmp = {}
|
||||||
|
|
||||||
local function gen_response(self, response, session)
|
local function gen_response(self, response, session)
|
||||||
|
|||||||
@@ -8,16 +8,19 @@ function loader.register(filename, index)
|
|||||||
local f = assert(io.open(filename), "Can't open sproto file")
|
local f = assert(io.open(filename), "Can't open sproto file")
|
||||||
local data = f:read "a"
|
local data = f:read "a"
|
||||||
f:close()
|
f:close()
|
||||||
local bin = parser.parse(data)
|
local sp = core.newproto(parser.parse(data))
|
||||||
core.saveproto(bin, index)
|
core.saveproto(sp, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
loader.save = core.saveproto
|
function loader.save(bin, index)
|
||||||
|
local sp = core.newproto(bin)
|
||||||
|
core.saveproto(sp, index)
|
||||||
|
end
|
||||||
|
|
||||||
function loader.load(index)
|
function loader.load(index)
|
||||||
local bin, sz = core.loadproto(index)
|
local sp = core.loadproto(index)
|
||||||
-- no __gc in metatable
|
-- no __gc in metatable
|
||||||
return sproto.new(bin,sz, true)
|
return sproto.sharenew(sp)
|
||||||
end
|
end
|
||||||
|
|
||||||
return loader
|
return loader
|
||||||
|
|||||||
@@ -81,10 +81,10 @@ end
|
|||||||
|
|
||||||
local typedef = P {
|
local typedef = P {
|
||||||
"ALL",
|
"ALL",
|
||||||
FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^0 * typename * mainkey^0)),
|
FIELD = namedpat("field", (name * blanks * tag * blank0 * ":" * blank0 * (C"*")^-1 * typename * mainkey^0)),
|
||||||
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
|
STRUCT = P"{" * multipat(V"FIELD" + V"TYPE") * P"}",
|
||||||
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
|
TYPE = namedpat("type", P"." * name * blank0 * V"STRUCT" ),
|
||||||
SUBPROTO = Ct((C"request" + C"response") * blanks * (name + V"STRUCT")),
|
SUBPROTO = Ct((C"request" + C"response") * blanks * (typename + V"STRUCT")),
|
||||||
PROTOCOL = namedpat("protocol", name * blanks * tag * blank0 * P"{" * multipat(V"SUBPROTO") * P"}"),
|
PROTOCOL = namedpat("protocol", name * blanks * tag * blank0 * P"{" * multipat(V"SUBPROTO") * P"}"),
|
||||||
ALL = multipat(V"TYPE" + V"PROTOCOL"),
|
ALL = multipat(V"TYPE" + V"PROTOCOL"),
|
||||||
}
|
}
|
||||||
@@ -186,6 +186,32 @@ local function checktype(types, ptype, t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function check_protocol(r)
|
||||||
|
local map = {}
|
||||||
|
local type = r.type
|
||||||
|
for name, v in pairs(r.protocol) do
|
||||||
|
local tag = v.tag
|
||||||
|
local request = v.request
|
||||||
|
local response = v.response
|
||||||
|
local p = map[tag]
|
||||||
|
|
||||||
|
if p then
|
||||||
|
error(string.format("redefined protocol tag %d at %s", tag, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
if request and not type[request] then
|
||||||
|
error(string.format("Undefined request type %s in protocol %s", request, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
if response and not type[response] then
|
||||||
|
error(string.format("Undefined response type %s in protocol %s", response, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
map[tag] = v
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
|
||||||
local function flattypename(r)
|
local function flattypename(r)
|
||||||
for typename, t in pairs(r.type) do
|
for typename, t in pairs(r.type) do
|
||||||
for _, f in pairs(t) do
|
for _, f in pairs(t) do
|
||||||
@@ -204,7 +230,7 @@ end
|
|||||||
local function parser(text,filename)
|
local function parser(text,filename)
|
||||||
local state = { file = filename, pos = 0, line = 1 }
|
local state = { file = filename, pos = 0, line = 1 }
|
||||||
local r = lpeg.match(proto * -1 + exception , text , 1, state )
|
local r = lpeg.match(proto * -1 + exception , text , 1, state )
|
||||||
return flattypename(adjust(r))
|
return flattypename(check_protocol(adjust(r)))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -314,9 +340,6 @@ local function packtype(name, t, alltypes)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function packproto(name, p, alltypes)
|
local function packproto(name, p, alltypes)
|
||||||
-- if p.request == nil then
|
|
||||||
-- error(string.format("Protocol %s need request", name))
|
|
||||||
-- end
|
|
||||||
if p.request then
|
if p.request then
|
||||||
local request = alltypes[p.request]
|
local request = alltypes[p.request]
|
||||||
if request == nil then
|
if request == nil then
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ _ctrl(struct gate * g, const void * msg, int sz) {
|
|||||||
skynet_socket_start(ctx, g->listen_id);
|
skynet_socket_start(ctx, g->listen_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (memcmp(command, "close", i) == 0) {
|
if (memcmp(command, "close", i) == 0) {
|
||||||
if (g->listen_id >= 0) {
|
if (g->listen_id >= 0) {
|
||||||
skynet_socket_close(ctx, g->listen_id);
|
skynet_socket_close(ctx, g->listen_id);
|
||||||
g->listen_id = -1;
|
g->listen_id = -1;
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ dispatch_name_queue(struct harbor *h, struct keyvalue * node) {
|
|||||||
while ((m = pop_queue(queue)) != NULL) {
|
while ((m = pop_queue(queue)) != NULL) {
|
||||||
m->header.destination |= (handle & HANDLE_MASK);
|
m->header.destination |= (handle & HANDLE_MASK);
|
||||||
send_remote(context, fd, m->buffer, m->size, &m->header);
|
send_remote(context, fd, m->buffer, m->size, &m->header);
|
||||||
|
skynet_free(m->buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,6 +382,7 @@ dispatch_queue(struct harbor *h, int id) {
|
|||||||
struct harbor_msg * m;
|
struct harbor_msg * m;
|
||||||
while ((m = pop_queue(queue)) != NULL) {
|
while ((m = pop_queue(queue)) != NULL) {
|
||||||
send_remote(h->ctx, fd, m->buffer, m->size, &m->header);
|
send_remote(h->ctx, fd, m->buffer, m->size, &m->header);
|
||||||
|
skynet_free(m->buffer);
|
||||||
}
|
}
|
||||||
release_queue(queue);
|
release_queue(queue);
|
||||||
s->queue = NULL;
|
s->queue = NULL;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
local harbor = require "skynet.harbor"
|
local harbor = require "skynet.harbor"
|
||||||
|
require "skynet.manager" -- import skynet.launch, ...
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
local standalone = skynet.getenv "standalone"
|
local standalone = skynet.getenv "standalone"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
local skynet = require "skynet"
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager" -- import skynet.launch, ...
|
||||||
|
|
||||||
local globalname = {}
|
local globalname = {}
|
||||||
local queryname = {}
|
local queryname = {}
|
||||||
local harbor = {}
|
local harbor = {}
|
||||||
|
local harbor_service
|
||||||
|
|
||||||
skynet.register_protocol {
|
skynet.register_protocol {
|
||||||
name = "harbor",
|
name = "harbor",
|
||||||
|
|||||||
@@ -5,14 +5,6 @@ local cluster = require "cluster.core"
|
|||||||
|
|
||||||
local config_name = skynet.getenv "cluster"
|
local config_name = skynet.getenv "cluster"
|
||||||
local node_address = {}
|
local node_address = {}
|
||||||
|
|
||||||
local function loadconfig()
|
|
||||||
local f = assert(io.open(config_name))
|
|
||||||
local source = f:read "*a"
|
|
||||||
f:close()
|
|
||||||
assert(load(source, "@"..config_name, "t", node_address))()
|
|
||||||
end
|
|
||||||
|
|
||||||
local node_session = {}
|
local node_session = {}
|
||||||
local command = {}
|
local command = {}
|
||||||
|
|
||||||
@@ -28,15 +20,33 @@ local function open_channel(t, key)
|
|||||||
host = host,
|
host = host,
|
||||||
port = tonumber(port),
|
port = tonumber(port),
|
||||||
response = read_response,
|
response = read_response,
|
||||||
|
nodelay = true,
|
||||||
}
|
}
|
||||||
assert(c:connect(true))
|
assert(c:connect(true))
|
||||||
t[key] = c
|
t[key] = c
|
||||||
node_session[key] = 1
|
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
local node_channel = setmetatable({}, { __index = open_channel })
|
local node_channel = setmetatable({}, { __index = open_channel })
|
||||||
|
|
||||||
|
local function loadconfig()
|
||||||
|
local f = assert(io.open(config_name))
|
||||||
|
local source = f:read "*a"
|
||||||
|
f:close()
|
||||||
|
local tmp = {}
|
||||||
|
assert(load(source, "@"..config_name, "t", tmp))()
|
||||||
|
for name,address in pairs(tmp) do
|
||||||
|
assert(type(address) == "string")
|
||||||
|
if node_address[name] ~= address then
|
||||||
|
-- address changed
|
||||||
|
if rawget(node_channel, name) then
|
||||||
|
node_channel[name] = nil -- reset connection
|
||||||
|
end
|
||||||
|
node_address[name] = address
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function command.reload()
|
function command.reload()
|
||||||
loadconfig()
|
loadconfig()
|
||||||
skynet.ret(skynet.pack(nil))
|
skynet.ret(skynet.pack(nil))
|
||||||
@@ -52,11 +62,13 @@ function command.listen(source, addr, port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function send_request(source, node, addr, msg, sz)
|
local function send_request(source, node, addr, msg, sz)
|
||||||
local request
|
local session = node_session[node] or 1
|
||||||
local c = node_channel[node]
|
|
||||||
local session = node_session[node]
|
|
||||||
-- msg is a local pointer, cluster.packrequest will free it
|
-- msg is a local pointer, cluster.packrequest will free it
|
||||||
request, node_session[node] = cluster.packrequest(addr, session , msg, sz)
|
local request, new_session = cluster.packrequest(addr, session, msg, sz)
|
||||||
|
node_session[node] = new_session
|
||||||
|
|
||||||
|
-- node_channel[node] may yield or throw error
|
||||||
|
local c = node_channel[node]
|
||||||
|
|
||||||
return c:request(request, session)
|
return c:request(request, session)
|
||||||
end
|
end
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user