Compare commits

...

45 Commits

Author SHA1 Message Date
Cloud Wu
ed1a8313f4 1.0.0 rc3 2016-05-09 10:06:32 +08:00
Cloud Wu
c450b7b5d7 update jemaloc to 4.1.1 2016-05-09 09:56:30 +08:00
Cloud Wu
56846b7dda new script to check deadloop service 2016-05-09 09:47:01 +08:00
Cloud Wu
fb232cc43e update lua to 5.3.3 rc1 2016-05-09 09:45:40 +08:00
Cloud Wu
a5c79cc4bd move skynet.memlimit from skynet.manager to skynet 2016-05-07 09:23:01 +08:00
Cloud Wu
4b96ade660 support sandbox memory limit 2016-05-06 23:40:44 +08:00
Cloud Wu
76d1e6fa1f memory warning 2016-05-06 20:37:51 +08:00
Cloud Wu
a6299a0748 optimize skynet.error 2016-05-06 20:10:11 +08:00
Cloud Wu
6cc558bb82 output Exit when new service exit 2016-05-06 19:45:50 +08:00
Cloud Wu
84b08bf286 detect console fd closed 2016-05-06 19:37:16 +08:00
Cloud Wu
4ada09b93c add pcall in launcher 2016-05-06 14:06:38 +08:00
Cloud Wu
2862568eca typo in history 2016-04-29 16:25:12 +08:00
cloudwu
ed2e16a346 Merge pull request #491 from asanosoyokaze/patch-go
skynet.pcall support vararg; sharedata loader can use custom args
2016-04-27 21:44:59 +08:00
David Feng
45d46b9072 skynet.pcall support vararg; sharedata loader can use custom args 2016-04-27 20:53:05 +08:00
Cloud Wu
4924c6d30b Merge branch 'master' of github.com:cloudwu/skynet 2016-04-20 22:35:29 +08:00
Cloud Wu
6b2eb80188 fix #487 2016-04-20 22:35:01 +08:00
cloudwu
298e4baf0e Merge pull request #485 from dpull/patch-1
给dbgcmd增加扩展性
2016-04-20 10:24:54 +08:00
Cloud Wu
c5fb93823a update sproto, fix bug in sproto.default 2016-04-20 10:11:55 +08:00
Acai
f238113677 给dbgcmd增加扩展性
我们项目增加了一个dbgcmd的指令,主要用于热更新,但在升级skynet版本时,需要记得合并这个差异,感觉挺挫的。

但现有的debug.lua并不利于扩展,于是呢,我想通过给debug.lua增加一个upvalue来解决这个问题。

其实也是解决的挺挫的 :)
2016-04-19 21:11:31 +08:00
Cloud Wu
f56d777cc2 for compatible 2016-04-18 12:05:46 +08:00
Cloud Wu
b124d4c1b8 skynet.getenv can return empty string 2016-04-18 11:55:39 +08:00
cloudwu
4fe098713f Merge pull request #483 from t0350/master
bugfix, error when use lua apicheck
2016-04-08 10:34:45 +08:00
caijietao
146f8ea09d bugfix, error when use lua apicheck 2016-04-08 10:29:34 +08:00
Cloud Wu
69b5bd8c13 update sproto. support encode empty table 2016-04-07 10:12:30 +08:00
cloudwu
dd7e962c94 Merge pull request #480 from rickone/master
Update redis.lua
2016-04-01 14:33:10 +08:00
rickone
5332021086 Update redis.lua
exec执行时其中一条出错,看不到错误信息
2016-04-01 12:39:09 +08:00
Cloud Wu
8de3149485 request global name from master, see issue #476 2016-04-01 10:22:57 +08:00
cloudwu
e3fee604e1 Merge pull request #478 from xjdrew/skynet_init
skynet.init按照顺序初始化
2016-03-31 17:51:29 +08:00
xjdrew
dd152fc910 skynet.init按照顺序初始化 2016-03-31 17:33:47 +08:00
Cloud Wu
c4b45acae3 sproto: check args 2016-03-29 12:34:55 +08:00
cloudwu
cf50a582f2 Merge pull request #474 from felixonmars/patch-1
Improve some English in README
2016-03-24 17:53:00 +08:00
Felix Yan
ca5e855c34 Improve some English in README 2016-03-24 17:48:43 +08:00
Cloud Wu
13d1d9fc9d update jemalloc to 4.1.0 2016-03-24 16:29:00 +08:00
Cloud Wu
242ff32bca lua 5.3.2 bugfix 2/3 2016-03-24 16:19:06 +08:00
cloudwu
ba451c1cd2 Merge pull request #465 from mrvon/master
skynet.coroutine
2016-03-11 15:28:56 +08:00
dennis
e5490522ce this line is useless 2016-03-09 17:50:33 +08:00
dennis
ae717c3e7d Merge remote-tracking branch 'upstream/master' 2016-03-09 17:48:16 +08:00
cloudwu
1a7df9108a Merge pull request #463 from great90/master
delete unused local variable
2016-03-08 11:34:25 +08:00
great90
7771e180ec delete unused local variable
delete unused local variable table "udp_socket"
2016-03-08 11:25:59 +08:00
great90
82bbb1c944 Merge pull request #3 from cloudwu/master
release rc2
2016-03-08 11:21:18 +08:00
great90
bacaf10f1b Merge pull request #2 from cloudwu/master
update from cloudwu
2016-03-02 09:08:40 +08:00
dennis
6303886b8c Merge remote-tracking branch 'upstream/master' 2016-02-15 10:12:09 +08:00
dennis
30cbcfd013 Merge remote-tracking branch 'upstream/master' 2016-01-06 15:57:42 +08:00
Dennis
a39e822184 Merge pull request #1 from cloudwu/master
update from origin
2015-12-30 09:51:58 +08:00
great90
716ecccaed Merge pull request #1 from cloudwu/master
update skynet
2015-10-23 14:33:54 +08:00
57 changed files with 1291 additions and 743 deletions

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $ ** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -379,9 +379,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
return NULL; return NULL;
} }
lua_lock(L); /* 'luaO_tostring' may create a new string */ lua_lock(L); /* 'luaO_tostring' may create a new string */
luaO_tostring(L, o);
luaC_checkGC(L); luaC_checkGC(L);
o = index2addr(L, idx); /* previous call may reallocate the stack */ o = index2addr(L, idx); /* previous call may reallocate the stack */
luaO_tostring(L, o);
lua_unlock(L); lua_unlock(L);
} }
if (len != NULL) if (len != NULL)
@@ -480,10 +480,10 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
TString *ts; TString *ts;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
setsvalue2s(L, L->top, ts); setsvalue2s(L, L->top, ts);
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return getstr(ts); return getstr(ts);
} }
@@ -495,12 +495,12 @@ LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
setnilvalue(L->top); setnilvalue(L->top);
else { else {
TString *ts; TString *ts;
luaC_checkGC(L);
ts = luaS_new(L, s); ts = luaS_new(L, s);
setsvalue2s(L, L->top, ts); setsvalue2s(L, L->top, ts);
s = getstr(ts); /* internal copy's address */ s = getstr(ts); /* internal copy's address */
} }
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return s; return s;
} }
@@ -510,8 +510,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp) { va_list argp) {
const char *ret; const char *ret;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, argp); ret = luaO_pushvfstring(L, fmt, argp);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return ret; return ret;
} }
@@ -521,10 +521,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret; const char *ret;
va_list argp; va_list argp;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
va_start(argp, fmt); va_start(argp, fmt);
ret = luaO_pushvfstring(L, fmt, argp); ret = luaO_pushvfstring(L, fmt, argp);
va_end(argp); va_end(argp);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return ret; return ret;
} }
@@ -539,7 +539,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
CClosure *cl; CClosure *cl;
api_checknelems(L, n); api_checknelems(L, n);
api_check(L, n <= MAXUPVAL, "upvalue index too large"); api_check(L, n <= MAXUPVAL, "upvalue index too large");
luaC_checkGC(L);
cl = luaF_newCclosure(L, n); cl = luaF_newCclosure(L, n);
cl->f = fn; cl->f = fn;
L->top -= n; L->top -= n;
@@ -550,6 +549,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
setclCvalue(L, L->top, cl); setclCvalue(L, L->top, cl);
} }
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@@ -586,16 +586,16 @@ LUA_API int lua_pushthread (lua_State *L) {
static int auxgetstr (lua_State *L, const TValue *t, const char *k) { static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux; const TValue *slot;
TString *str = luaS_new(L, k); TString *str = luaS_new(L, k);
if (luaV_fastget(L, t, str, aux, luaH_getstr)) { if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
setobj2s(L, L->top, aux); setobj2s(L, L->top, slot);
api_incr_top(L); api_incr_top(L);
} }
else { else {
setsvalue2s(L, L->top, str); setsvalue2s(L, L->top, str);
api_incr_top(L); api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux); luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
} }
lua_unlock(L); lua_unlock(L);
return ttnov(L->top - 1); return ttnov(L->top - 1);
@@ -627,17 +627,17 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
StkId t; StkId t;
const TValue *aux; const TValue *slot;
lua_lock(L); lua_lock(L);
t = index2addr(L, idx); t = index2addr(L, idx);
if (luaV_fastget(L, t, n, aux, luaH_getint)) { if (luaV_fastget(L, t, n, slot, luaH_getint)) {
setobj2s(L, L->top, aux); setobj2s(L, L->top, slot);
api_incr_top(L); api_incr_top(L);
} }
else { else {
setivalue(L->top, n); setivalue(L->top, n);
api_incr_top(L); api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux); luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
} }
lua_unlock(L); lua_unlock(L);
return ttnov(L->top - 1); return ttnov(L->top - 1);
@@ -684,12 +684,12 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
Table *t; Table *t;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
t = luaH_new(L); t = luaH_new(L);
sethvalue(L, L->top, t); sethvalue(L, L->top, t);
api_incr_top(L); api_incr_top(L);
if (narray > 0 || nrec > 0) if (narray > 0 || nrec > 0)
luaH_resize(L, t, narray, nrec); luaH_resize(L, t, narray, nrec);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@@ -741,15 +741,15 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
** t[k] = value at the top of the stack (where 'k' is a string) ** t[k] = value at the top of the stack (where 'k' is a string)
*/ */
static void auxsetstr (lua_State *L, const TValue *t, const char *k) { static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux; const TValue *slot;
TString *str = luaS_new(L, k); TString *str = luaS_new(L, k);
api_checknelems(L, 1); api_checknelems(L, 1);
if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1)) if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
L->top--; /* pop value */ L->top--; /* pop value */
else { else {
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
api_incr_top(L); api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux); luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */ L->top -= 2; /* pop value and key */
} }
lua_unlock(L); /* lock done by caller */ lua_unlock(L); /* lock done by caller */
@@ -782,16 +782,16 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
StkId t; StkId t;
const TValue *aux; const TValue *slot;
lua_lock(L); lua_lock(L);
api_checknelems(L, 1); api_checknelems(L, 1);
t = index2addr(L, idx); t = index2addr(L, idx);
if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
L->top--; /* pop value */ L->top--; /* pop value */
else { else {
setivalue(L->top, n); setivalue(L->top, n);
api_incr_top(L); api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux); luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */ L->top -= 2; /* pop value and key */
} }
lua_unlock(L); lua_unlock(L);
@@ -1193,7 +1193,6 @@ LUA_API void lua_concat (lua_State *L, int n) {
lua_lock(L); lua_lock(L);
api_checknelems(L, n); api_checknelems(L, n);
if (n >= 2) { if (n >= 2) {
luaC_checkGC(L);
luaV_concat(L, n); luaV_concat(L, n);
} }
else if (n == 0) { /* push empty string */ else if (n == 0) { /* push empty string */
@@ -1201,6 +1200,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
api_incr_top(L); api_incr_top(L);
} }
/* else n == 1; nothing to do */ /* else n == 1; nothing to do */
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@@ -1236,10 +1236,10 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
LUA_API void *lua_newuserdata (lua_State *L, size_t size) { LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u; Udata *u;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, size); u = luaS_newudata(L, size);
setuvalue(L, L->top, u); setuvalue(L, L->top, u);
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return getudatamem(u); return getudatamem(u);
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $ ** $Id: lauxlib.c,v 1.286 2016/01/08 15:33:09 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
*/ */
@@ -17,7 +17,8 @@
#include <string.h> #include <string.h>
/* This file uses only the official API of Lua. /*
** This file uses only the official API of Lua.
** Any function declared here could be written as an application function. ** Any function declared here could be written as an application function.
*/ */
@@ -198,6 +199,10 @@ static void tag_error (lua_State *L, int arg, int tag) {
} }
/*
** The use of 'lua_pushfstring' ensures this function does not
** need reserved stack space when called.
*/
LUALIB_API void luaL_where (lua_State *L, int level) { LUALIB_API void luaL_where (lua_State *L, int level) {
lua_Debug ar; lua_Debug ar;
if (lua_getstack(L, level, &ar)) { /* check function at level */ if (lua_getstack(L, level, &ar)) { /* check function at level */
@@ -207,10 +212,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) {
return; return;
} }
} }
lua_pushliteral(L, ""); /* else, no information available... */ lua_pushfstring(L, ""); /* else, no information available... */
} }
/*
** Again, the use of 'lua_pushvfstring' ensures this function does
** not need reserved stack space when called. (At worst, it generates
** an error with "stack overflow" instead of the given message.)
*/
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
@@ -349,10 +359,15 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
} }
/*
** Ensures the stack has at least 'space' extra slots, raising an error
** if it cannot fulfill the request. (The error handling needs a few
** extra slots to format the error message. In case of an error without
** this extra space, Lua will generate the same 'stack overflow' error,
** but without 'msg'.)
*/
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
/* keep some extra space to run error routines, if needed */ if (!lua_checkstack(L, space)) {
const int extra = LUA_MINSTACK;
if (!lua_checkstack(L, space + extra)) {
if (msg) if (msg)
luaL_error(L, "stack overflow (%s)", msg); luaL_error(L, "stack overflow (%s)", msg);
else else
@@ -678,7 +693,7 @@ static int skipcomment (LoadF *lf, int *cp) {
if (c == '#') { /* first line is a comment (Unix exec. file)? */ if (c == '#') { /* first line is a comment (Unix exec. file)? */
do { /* skip first line */ do { /* skip first line */
c = getc(lf->f); c = getc(lf->f);
} while (c != EOF && c != '\n') ; } while (c != EOF && c != '\n');
*cp = getc(lf->f); /* skip end-of-line, if present */ *cp = getc(lf->f); /* skip end-of-line, if present */
return 1; /* there was a comment */ return 1; /* there was a comment */
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $ ** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -102,8 +102,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) { static int luaB_error (lua_State *L) {
int level = (int)luaL_optinteger(L, 2, 1); int level = (int)luaL_optinteger(L, 2, 1);
lua_settop(L, 1); lua_settop(L, 1);
if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
luaL_where(L, level); luaL_where(L, level); /* add extra information */
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
lua_concat(L, 2); lua_concat(L, 2);
} }
@@ -251,9 +251,8 @@ static int ipairsaux (lua_State *L) {
/* /*
** This function will use either 'ipairsaux' or 'ipairsaux_raw' to ** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** traverse a table, depending on whether the table has metamethods ** (The given "table" may not be a table.)
** that can affect the traversal.
*/ */
static int luaB_ipairs (lua_State *L) { static int luaB_ipairs (lua_State *L) {
#if defined(LUA_COMPAT_IPAIRS) #if defined(LUA_COMPAT_IPAIRS)

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $ ** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -40,7 +40,8 @@ typedef enum BinOpr {
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define getcode(fs,e) ((fs)->f->sp->code[(e)->u.info]) /* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->sp->code[(e)->u.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $ ** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $
** Coroutine Library ** Coroutine Library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -75,7 +75,7 @@ static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1)); lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L)); int r = auxresume(L, co, lua_gettop(L));
if (r < 0) { if (r < 0) {
if (lua_isstring(L, -1)) { /* error object is a string? */ if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */ luaL_where(L, 1); /* add extra info */
lua_insert(L, -2); lua_insert(L, -2);
lua_concat(L, 2); lua_concat(L, 2);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $ ** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -69,7 +69,13 @@ static void swapextra (lua_State *L) {
/* /*
** this function can be called asynchronous (e.g. during a signal) ** This function can be called asynchronously (e.g. during a signal).
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
** 'resethookcount') are for debug only, and it is no problem if they
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
** is an atomic value. We assume that pointers are atomic too (e.g., gcc
** ensures that for all platforms where it runs). Moreover, 'hook' is
** always checked before being called (see 'luaD_hook').
*/ */
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
if (func == NULL || mask == 0) { /* turn off hooks? */ if (func == NULL || mask == 0) { /* turn off hooks? */
@@ -118,7 +124,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
static const char *upvalname (Proto *p, int uv) { static const char *upvalname (Proto *p, int uv) {
TString *s = check_exp(uv < p->sizeupvalues, p->sp->upvalues[uv].name); TString *s = check_exp(uv < p->sp->sizeupvalues, p->sp->upvalues[uv].name);
if (s == NULL) return "?"; if (s == NULL) return "?";
else return getstr(s); else return getstr(s);
} }
@@ -558,7 +564,7 @@ static const char *varinfo (lua_State *L, const TValue *o) {
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *t = objtypename(o); const char *t = luaT_objtypename(L, o);
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
} }
@@ -590,9 +596,9 @@ l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = objtypename(p1); const char *t1 = luaT_objtypename(L, p1);
const char *t2 = objtypename(p2); const char *t2 = luaT_objtypename(L, p2);
if (t1 == t2) if (strcmp(t1, t2) == 0)
luaG_runerror(L, "attempt to compare two %s values", t1); luaG_runerror(L, "attempt to compare two %s values", t1);
else else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2); luaG_runerror(L, "attempt to compare %s with %s", t1, t2);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $ ** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 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
*/ */
@@ -242,9 +242,14 @@ void luaD_inctop (lua_State *L) {
/* }================================================================== */ /* }================================================================== */
/*
** Call a hook for the given event. Make sure there is a hook to be
** called. (Both 'L->hook' and 'L->hookmask', which triggers this
** function, can be changed asynchronously by signals.)
*/
void luaD_hook (lua_State *L, int event, int line) { void luaD_hook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook; lua_Hook hook = L->hook;
if (hook && L->allowhook) { if (hook && L->allowhook) { /* make sure there is a hook */
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
ptrdiff_t top = savestack(L, L->top); ptrdiff_t top = savestack(L, L->top);
ptrdiff_t ci_top = savestack(L, ci->top); ptrdiff_t ci_top = savestack(L, ci->top);
@@ -768,7 +773,7 @@ static void f_parser (lua_State *L, void *ud) {
checkmode(L, p->mode, "text"); checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
} }
lua_assert(cl->nupvalues == cl->p->sizeupvalues); lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues);
luaF_initupvals(L, cl); luaF_initupvals(L, cl);
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp $ ** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 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
*/ */
@@ -25,7 +25,7 @@
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
/* In general, 'pre'/'pos' are empty (nothing to save) */ /* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,,) #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.210 2015/11/03 18:10:44 roberto Exp $ ** $Id: lgc.c,v 2.212 2016/03/31 19:02:03 roberto Exp $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -761,14 +761,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
/* /*
** sweep a list until a live object (or end of list) ** sweep a list until a live object (or end of list)
*/ */
static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { static GCObject **sweeptolive (lua_State *L, GCObject **p) {
GCObject **old = p; GCObject **old = p;
int i = 0;
do { do {
i++;
p = sweeplist(L, p, 1); p = sweeplist(L, p, 1);
} while (p == old); } while (p == old);
if (n) *n += i;
return p; return p;
} }
@@ -863,10 +860,10 @@ static int runafewfinalizers (lua_State *L) {
/* /*
** call all pending finalizers ** call all pending finalizers
*/ */
static void callallpendingfinalizers (lua_State *L, int propagateerrors) { static void callallpendingfinalizers (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
while (g->tobefnz) while (g->tobefnz)
GCTM(L, propagateerrors); GCTM(L, 0);
} }
@@ -916,7 +913,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
if (issweepphase(g)) { if (issweepphase(g)) {
makewhite(g, o); /* "sweep" object 'o' */ makewhite(g, o); /* "sweep" object 'o' */
if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */
g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
} }
/* search for pointer pointing to 'o' */ /* search for pointer pointing to 'o' */
for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
@@ -958,19 +955,16 @@ static void setpause (global_State *g) {
/* /*
** Enter first sweep phase. ** Enter first sweep phase.
** The call to 'sweeptolive' makes pointer point to an object inside ** The call to 'sweeplist' tries to make pointer point to an object
** the list (instead of to the header), so that the real sweep do not ** inside the list (instead of to the header), so that the real sweep do
** need to skip objects created between "now" and the start of the real ** not need to skip objects created between "now" and the start of the
** sweep. ** real sweep.
** Returns how many objects it swept.
*/ */
static int entersweep (lua_State *L) { static void entersweep (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
int n = 0;
g->gcstate = GCSswpallgc; g->gcstate = GCSswpallgc;
lua_assert(g->sweepgc == NULL); lua_assert(g->sweepgc == NULL);
g->sweepgc = sweeptolive(L, &g->allgc, &n); g->sweepgc = sweeplist(L, &g->allgc, 1);
return n;
} }
@@ -978,7 +972,7 @@ void luaC_freeallobjects (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
separatetobefnz(g, 1); /* separate all objects with finalizers */ separatetobefnz(g, 1); /* separate all objects with finalizers */
lua_assert(g->finobj == NULL); lua_assert(g->finobj == NULL);
callallpendingfinalizers(L, 0); callallpendingfinalizers(L);
lua_assert(g->tobefnz == NULL); lua_assert(g->tobefnz == NULL);
g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
g->gckind = KGC_NORMAL; g->gckind = KGC_NORMAL;
@@ -1071,12 +1065,11 @@ static lu_mem singlestep (lua_State *L) {
} }
case GCSatomic: { case GCSatomic: {
lu_mem work; lu_mem work;
int sw;
propagateall(g); /* make sure gray list is empty */ propagateall(g); /* make sure gray list is empty */
work = atomic(L); /* work is what was traversed by 'atomic' */ work = atomic(L); /* work is what was traversed by 'atomic' */
sw = entersweep(L); entersweep(L);
g->GCestimate = gettotalbytes(g); /* first estimate */; g->GCestimate = gettotalbytes(g); /* first estimate */;
return work + sw * GCSWEEPCOST; return work;
} }
case GCSswpallgc: { /* sweep "regular" objects */ case GCSswpallgc: { /* sweep "regular" objects */
return sweepstep(L, g, GCSswpfinobj, &g->finobj); return sweepstep(L, g, GCSswpfinobj, &g->finobj);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp $ ** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -112,7 +112,7 @@
condchangemem(L,pre,pos); } condchangemem(L,pre,pos); }
/* more often than not, 'pre'/'pos' are empty */ /* more often than not, 'pre'/'pos' are empty */
#define luaC_checkGC(L) luaC_condGC(L,,) #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
#define luaC_barrier(L,p,v) ( \ #define luaC_barrier(L,p,v) ( \

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: liolib.c,v 2.148 2015/11/23 11:36:11 roberto Exp $ ** $Id: liolib.c,v 2.149 2016/05/02 14:03:19 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
*/ */
@@ -375,14 +375,17 @@ static int io_lines (lua_State *L) {
/* maximum length of a numeral */ /* maximum length of a numeral */
#define MAXRN 200 #if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
/* auxiliary structure used by 'read_number' */ /* auxiliary structure used by 'read_number' */
typedef struct { typedef struct {
FILE *f; /* file being read */ FILE *f; /* file being read */
int c; /* current character (look ahead) */ int c; /* current character (look ahead) */
int n; /* number of elements in buffer 'buff' */ int n; /* number of elements in buffer 'buff' */
char buff[MAXRN + 1]; /* +1 for ending '\0' */ char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
} RN; } RN;
@@ -390,7 +393,7 @@ typedef struct {
** Add current char to buffer (if not out of space) and read next one ** Add current char to buffer (if not out of space) and read next one
*/ */
static int nextc (RN *rn) { static int nextc (RN *rn) {
if (rn->n >= MAXRN) { /* buffer overflow? */ if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
rn->buff[0] = '\0'; /* invalidate result */ rn->buff[0] = '\0'; /* invalidate result */
return 0; /* fail */ return 0; /* fail */
} }
@@ -403,10 +406,10 @@ static int nextc (RN *rn) {
/* /*
** Accept current char if it is in 'set' (of size 1 or 2) ** Accept current char if it is in 'set' (of size 2)
*/ */
static int test2 (RN *rn, const char *set) { static int test2 (RN *rn, const char *set) {
if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0')) if (rn->c == set[0] || rn->c == set[1])
return nextc(rn); return nextc(rn);
else return 0; else return 0;
} }
@@ -435,11 +438,11 @@ static int read_number (lua_State *L, FILE *f) {
char decp[2]; char decp[2];
rn.f = f; rn.n = 0; rn.f = f; rn.n = 0;
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
decp[1] = '\0'; decp[1] = '.'; /* always accept a dot */
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 */
if (test2(&rn, "0")) { if (test2(&rn, "00")) {
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
else count = 1; /* count initial '0' as a valid digit */ else count = 1; /* count initial '0' as a valid digit */
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp $ ** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -162,7 +162,6 @@ static void inclinenumber (LexState *ls) {
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
int firstchar) { int firstchar) {
ls->t.token = 0; ls->t.token = 0;
ls->decpoint = '.';
ls->L = L; ls->L = L;
ls->current = firstchar; ls->current = firstchar;
ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->lookahead.token = TK_EOS; /* no look-ahead token */
@@ -207,35 +206,6 @@ static int check_next2 (LexState *ls, const char *set) {
} }
/*
** change all characters 'from' in buffer to 'to'
*/
static void buffreplace (LexState *ls, char from, char to) {
if (from != to) {
size_t n = luaZ_bufflen(ls->buff);
char *p = luaZ_buffer(ls->buff);
while (n--)
if (p[n] == from) p[n] = to;
}
}
/*
** in case of format error, try to change decimal point separator to
** the one defined in the current locale and check again
*/
static void trydecpoint (LexState *ls, TValue *o) {
char old = ls->decpoint;
ls->decpoint = lua_getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
lexerror(ls, "malformed number", TK_FLT);
}
}
/* LUA_NUMBER */ /* LUA_NUMBER */
/* /*
** this function is quite liberal in what it accepts, as 'luaO_str2num' ** this function is quite liberal in what it accepts, as 'luaO_str2num'
@@ -259,9 +229,8 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
else break; else break;
} }
save(ls, '\0'); save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
trydecpoint(ls, &obj); /* try to update decimal point separator */ lexerror(ls, "malformed number", TK_FLT);
if (ttisinteger(&obj)) { if (ttisinteger(&obj)) {
seminfo->i = ivalue(&obj); seminfo->i = ivalue(&obj);
return TK_INT; return TK_INT;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp $ ** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -69,7 +69,6 @@ typedef struct LexState {
struct Dyndata *dyd; /* dynamic structures used by the parser */ struct Dyndata *dyd; /* dynamic structures used by the parser */
TString *source; /* current source name */ TString *source; /* current source name */
TString *envn; /* environment variable name */ TString *envn; /* environment variable name */
char decpoint; /* locale decimal point */
} LexState; } LexState;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp $ ** $Id: lobject.c,v 2.110 2016/05/02 14:00:32 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
*/ */
@@ -243,17 +243,53 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
/* }====================================================== */ /* }====================================================== */
static const char *l_str2d (const char *s, lua_Number *result) { /* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
char *endptr; char *endptr;
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */
: lua_str2number(s, &endptr);
if (endptr == s) return NULL; /* nothing recognized? */
while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */
return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */
}
/*
** Convert string 's' to a Lua number (put in 'result'). Return NULL
** on fail or the address of the ending '\0' on success.
** 'pmode' points to (and 'mode' contains) special things in the string:
** - 'x'/'X' means an hexadecimal numeral
** - 'n'/'N' means 'inf' or 'nan' (which should be rejected)
** - '.' just optimizes the search for the common case (nothing special)
** This function accepts both the current locale or a dot as the radix
** mark. If the convertion fails, it may mean number has a dot but
** locale accepts something else. In that case, the code copies 's'
** to a buffer (because 's' is read-only), changes the dot to the
** current locale radix mark, and tries to convert again.
*/
static const char *l_str2d (const char *s, lua_Number *result) {
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN");
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
if (mode == 'n') /* reject 'inf' and 'nan' */
return NULL; return NULL;
else if (strpbrk(s, "xX")) /* hex? */ endptr = l_str2dloc(s, result, mode); /* try to convert */
*result = lua_strx2number(s, &endptr); if (endptr == NULL) { /* failed? may be a different locale */
else char buff[L_MAXLENNUM + 1];
*result = lua_str2number(s, &endptr); char *pdot = strchr(s, '.');
if (endptr == s) return NULL; /* nothing recognized */ if (strlen(s) > L_MAXLENNUM || pdot == NULL)
while (lisspace(cast_uchar(*endptr))) endptr++; return NULL; /* string too long or no dot; fail */
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */ strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
endptr = l_str2dloc(buff, result, mode); /* try again */
if (endptr != NULL)
endptr = s + (endptr - buff); /* make relative to 's' */
}
return endptr;
} }
@@ -351,8 +387,10 @@ static void pushstr (lua_State *L, const char *str, size_t l) {
} }
/* this function handles only '%d', '%c', '%f', '%p', and '%s' /*
conventional formats, plus Lua-specific '%I' and '%U' */ ** this function handles only '%d', '%c', '%f', '%p', and '%s'
conventional formats, plus Lua-specific '%I' and '%U'
*/
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 0; int n = 0;
for (;;) { for (;;) {
@@ -360,13 +398,13 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
if (e == NULL) break; if (e == NULL) break;
pushstr(L, fmt, e - fmt); pushstr(L, fmt, e - fmt);
switch (*(e+1)) { switch (*(e+1)) {
case 's': { case 's': { /* zero-terminated string */
const char *s = va_arg(argp, char *); const char *s = va_arg(argp, char *);
if (s == NULL) s = "(null)"; if (s == NULL) s = "(null)";
pushstr(L, s, strlen(s)); pushstr(L, s, strlen(s));
break; break;
} }
case 'c': { case 'c': { /* an 'int' as a character */
char buff = cast(char, va_arg(argp, int)); char buff = cast(char, va_arg(argp, int));
if (lisprint(cast_uchar(buff))) if (lisprint(cast_uchar(buff)))
pushstr(L, &buff, 1); pushstr(L, &buff, 1);
@@ -374,28 +412,28 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
break; break;
} }
case 'd': { case 'd': { /* an 'int' */
setivalue(L->top, va_arg(argp, int)); setivalue(L->top, va_arg(argp, int));
goto top2str; goto top2str;
} }
case 'I': { case 'I': { /* a 'lua_Integer' */
setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
goto top2str; goto top2str;
} }
case 'f': { case 'f': { /* a 'lua_Number' */
setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
top2str: top2str: /* convert the top element to a string */
luaD_inctop(L); luaD_inctop(L);
luaO_tostring(L, L->top - 1); luaO_tostring(L, L->top - 1);
break; break;
} }
case 'p': { case 'p': { /* a pointer */
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff, l); pushstr(L, buff, l);
break; break;
} }
case 'U': { case 'U': { /* an 'int' as a UTF-8 sequence */
char buff[UTF8BUFFSZ]; char buff[UTF8BUFFSZ];
int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
pushstr(L, buff + UTF8BUFFSZ - l, l); pushstr(L, buff + UTF8BUFFSZ - l, l);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: loslib.c,v 1.60 2015/11/19 19:16:22 roberto Exp $ ** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $
** Standard Operating System library ** Standard Operating System library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -24,18 +24,29 @@
/* /*
** {================================================================== ** {==================================================================
** list of valid conversion specifiers for the 'strftime' function ** List of valid conversion specifiers for the 'strftime' function;
** options are grouped by length; group of length 2 start with '||'.
** =================================================================== ** ===================================================================
*/ */
#if !defined(LUA_STRFTIMEOPTIONS) /* { */ #if !defined(LUA_STRFTIMEOPTIONS) /* { */
#if defined(LUA_USE_C89) /* options for ANSI C 89 */
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } #define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy"
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#else /* C99 specification */ #else /* C99 specification */
#define LUA_STRFTIMEOPTIONS \ #define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
"E", "cCxXyY", \
"O", "deHImMSuUVwWy" }
#endif #endif
#endif /* } */ #endif /* } */
@@ -195,6 +206,23 @@ static void setboolfield (lua_State *L, const char *key, int value) {
lua_setfield(L, -2, key); lua_setfield(L, -2, key);
} }
/*
** Set all fields from structure 'tm' in the table on top of the stack
*/
static void setallfields (lua_State *L, struct tm *stm) {
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon + 1);
setfield(L, "year", stm->tm_year + 1900);
setfield(L, "wday", stm->tm_wday + 1);
setfield(L, "yday", stm->tm_yday + 1);
setboolfield(L, "isdst", stm->tm_isdst);
}
static int getboolfield (lua_State *L, const char *key) { static int getboolfield (lua_State *L, const char *key) {
int res; int res;
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
@@ -210,18 +238,18 @@ static int getboolfield (lua_State *L, const char *key) {
static int getfield (lua_State *L, const char *key, int d, int delta) { static int getfield (lua_State *L, const char *key, int d, int delta) {
int isnum; int isnum;
int t = lua_getfield(L, -1, key); int t = lua_getfield(L, -1, key); /* get field and its type */
lua_Integer res = lua_tointegerx(L, -1, &isnum); lua_Integer res = lua_tointegerx(L, -1, &isnum);
if (!isnum) { /* field is not a number? */ if (!isnum) { /* field is not an integer? */
if (t != LUA_TNIL) /* some other value? */ if (t != LUA_TNIL) /* some other value? */
return luaL_error(L, "field '%s' not an integer", key); return luaL_error(L, "field '%s' is not an integer", key);
else if (d < 0) /* absent field; no default? */ else if (d < 0) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key); return luaL_error(L, "field '%s' missing in date table", key);
res = d; res = d;
} }
else { else {
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
return luaL_error(L, "field '%s' out-of-bounds", key); return luaL_error(L, "field '%s' is out-of-bound", key);
res -= delta; res -= delta;
} }
lua_pop(L, 1); lua_pop(L, 1);
@@ -230,21 +258,15 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
static const char *checkoption (lua_State *L, const char *conv, char *buff) { static const char *checkoption (lua_State *L, const char *conv, char *buff) {
static const char *const options[] = LUA_STRFTIMEOPTIONS; const char *option;
unsigned int i; int oplen = 1;
for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) {
if (*conv != '\0' && strchr(options[i], *conv) != NULL) { if (*option == '|') /* next block? */
buff[1] = *conv; oplen++; /* next length */
if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ else if (memcmp(conv, option, oplen) == 0) { /* match? */
buff[2] = '\0'; /* end buffer */ memcpy(buff, conv, oplen); /* copy valid option to buffer */
return conv + 1; buff[oplen] = '\0';
} return conv + oplen; /* return next item */
else if (*(conv + 1) != '\0' &&
strchr(options[i + 1], *(conv + 1)) != NULL) {
buff[2] = *(conv + 1); /* valid two-char conversion specifier */
buff[3] = '\0'; /* end buffer */
return conv + 2;
}
} }
} }
luaL_argerror(L, 1, luaL_argerror(L, 1,
@@ -271,18 +293,10 @@ static int os_date (lua_State *L) {
luaL_error(L, "time result cannot be represented in this installation"); luaL_error(L, "time result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) { if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */ lua_createtable(L, 0, 9); /* 9 = number of fields */
setfield(L, "sec", stm->tm_sec); setallfields(L, stm);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon+1);
setfield(L, "year", stm->tm_year+1900);
setfield(L, "wday", stm->tm_wday+1);
setfield(L, "yday", stm->tm_yday+1);
setboolfield(L, "isdst", stm->tm_isdst);
} }
else { else {
char cc[4]; char cc[4]; /* buffer for individual conversion specifiers */
luaL_Buffer b; luaL_Buffer b;
cc[0] = '%'; cc[0] = '%';
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
@@ -292,7 +306,7 @@ static int os_date (lua_State *L) {
else { else {
size_t reslen; size_t reslen;
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s = checkoption(L, s + 1, cc); s = checkoption(L, s + 1, cc + 1); /* copy specifier to 'cc' */
reslen = strftime(buff, SIZETIMEFMT, cc, stm); reslen = strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen); luaL_addsize(&b, reslen);
} }
@@ -319,6 +333,7 @@ static int os_time (lua_State *L) {
ts.tm_year = getfield(L, "year", -1, 1900); ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_isdst = getboolfield(L, "isdst"); ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts); t = mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
} }
if (t != (time_t)(l_timet)t || t == (time_t)(-1)) if (t != (time_t)(l_timet)t || t == (time_t)(-1))
luaL_error(L, "time result cannot be represented in this installation"); luaL_error(L, "time result cannot be represented in this installation");

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 2.149 2015/11/02 16:09:30 roberto Exp $ ** $Id: lparser.c,v 2.152 2016/03/07 19:25:39 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -165,7 +165,8 @@ static int registerlocalvar (LexState *ls, TString *varname) {
int oldsize = f->sizelocvars; int oldsize = f->sizelocvars;
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
LocVar, SHRT_MAX, "local variables"); LocVar, SHRT_MAX, "local variables");
while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; while (oldsize < f->sizelocvars)
f->locvars[oldsize++].varname = NULL;
f->locvars[fs->nlocvars].varname = varname; f->locvars[fs->nlocvars].varname = varname;
luaC_objbarrier(ls->L, fp, varname); luaC_objbarrier(ls->L, fp, varname);
return fs->nlocvars++; return fs->nlocvars++;
@@ -232,7 +233,8 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
Upvaldesc, MAXUPVAL, "upvalues"); Upvaldesc, MAXUPVAL, "upvalues");
while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; while (oldsize < f->sizeupvalues)
f->upvalues[oldsize++].name = NULL;
f->upvalues[fs->nups].instack = (v->k == VLOCAL); f->upvalues[fs->nups].instack = (v->k == VLOCAL);
f->upvalues[fs->nups].idx = cast_byte(v->u.info); f->upvalues[fs->nups].idx = cast_byte(v->u.info);
f->upvalues[fs->nups].name = name; f->upvalues[fs->nups].name = name;
@@ -257,7 +259,8 @@ static int searchvar (FuncState *fs, TString *n) {
*/ */
static void markupval (FuncState *fs, int level) { static void markupval (FuncState *fs, int level) {
BlockCnt *bl = fs->bl; BlockCnt *bl = fs->bl;
while (bl->nactvar > level) bl = bl->previous; while (bl->nactvar > level)
bl = bl->previous;
bl->upval = 1; bl->upval = 1;
} }
@@ -501,7 +504,8 @@ static Proto *addprototype (LexState *ls) {
if (fs->np >= f->sp->sizep) { if (fs->np >= f->sp->sizep) {
int oldsize = f->sp->sizep; int oldsize = f->sp->sizep;
luaM_growvector(L, f->p, fs->np, f->sp->sizep, Proto *, MAXARG_Bx, "functions"); luaM_growvector(L, f->p, fs->np, f->sp->sizep, Proto *, MAXARG_Bx, "functions");
while (oldsize < f->sp->sizep) f->p[oldsize++] = NULL; while (oldsize < f->sp->sizep)
f->p[oldsize++] = NULL;
} }
f->p[fs->np++] = clp = luaF_newproto(L, NULL); f->p[fs->np++] = clp = luaF_newproto(L, NULL);
luaC_objbarrier(L, f, clp); luaC_objbarrier(L, f, clp);
@@ -1229,7 +1233,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
checkrepeated(fs, ll, label); /* check for repeated labels */ checkrepeated(fs, ll, label); /* check for repeated labels */
checknext(ls, TK_DBCOLON); /* skip double colon */ checknext(ls, TK_DBCOLON); /* skip double colon */
/* create new entry for this label */ /* create new entry for this label */
l = newlabelentry(ls, ll, label, line, fs->pc); l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
skipnoopstat(ls); /* skip other no-op statements */ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */ /* assume that locals are already out of scope */
@@ -1497,7 +1501,7 @@ static void exprstat (LexState *ls) {
} }
else { /* stat -> func */ else { /* stat -> func */
check_condition(ls, v.v.k == VCALL, "syntax error"); check_condition(ls, v.v.k == VCALL, "syntax error");
SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */
} }
} }
@@ -1514,8 +1518,8 @@ static void retstat (LexState *ls) {
if (hasmultret(e.k)) { if (hasmultret(e.k)) {
luaK_setmultret(fs, &e); luaK_setmultret(fs, &e);
if (e.k == VCALL && nret == 1) { /* tail call? */ if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(getcode(fs,&e), OP_TAILCALL); SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
} }
first = fs->nactvar; first = fs->nactvar;
nret = LUA_MULTRET; /* return all values */ nret = LUA_MULTRET; /* return all values */
@@ -1597,7 +1601,7 @@ static void statement (LexState *ls) {
break; break;
} }
} }
lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && lua_assert(ls->fs->f->sp->maxstacksize >= ls->fs->freereg &&
ls->fs->freereg >= ls->fs->nactvar); ls->fs->freereg >= ls->fs->nactvar);
ls->fs->freereg = ls->fs->nactvar; /* free registers */ ls->fs->freereg = ls->fs->nactvar; /* free registers */
leavelevel(ls); leavelevel(ls);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.74 2014/10/25 11:50:46 roberto Exp $ ** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -13,25 +13,38 @@
/* /*
** Expression descriptor ** Expression and variable descriptor.
** Code generation for variables and expressions can be delayed to allow
** optimizations; An 'expdesc' structure describes a potentially-delayed
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
*/ */
/* kinds of variables/expressions */
typedef enum { typedef enum {
VVOID, /* no value */ VVOID, /* when 'expdesc' describes the last expression a list,
VNIL, this kind means an empty list (so, no expression) */
VTRUE, VNIL, /* constant nil */
VFALSE, VTRUE, /* constant true */
VK, /* info = index of constant in 'k' */ VFALSE, /* constant false */
VKFLT, /* nval = numerical float value */ VK, /* constant in 'k'; info = index of constant in 'k' */
VKINT, /* nval = numerical integer value */ VKFLT, /* floating constant; nval = numerical float value */
VNONRELOC, /* info = result register */ VKINT, /* integer constant; nval = numerical integer value */
VLOCAL, /* info = local register */ VNONRELOC, /* expression has its value in a fixed register;
VUPVAL, /* info = index of upvalue in 'upvalues' */ info = result register */
VINDEXED, /* t = table register/upvalue; idx = index R/K */ VLOCAL, /* local variable; info = local register */
VJMP, /* info = instruction pc */ VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VRELOCABLE, /* info = instruction pc */ VINDEXED, /* indexed variable;
VCALL, /* info = instruction pc */ ind.vt = whether 't' is register or upvalue;
VVARARG /* info = instruction pc */ ind.t = table register or upvalue;
ind.idx = key's R/K index */
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction */
VRELOCABLE, /* expression can put result in any register;
info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc */
VVARARG /* vararg expression; info = instruction pc */
} expkind; } expkind;
@@ -41,14 +54,14 @@ typedef enum {
typedef struct expdesc { typedef struct expdesc {
expkind k; expkind k;
union { union {
lua_Integer ival; /* for VKINT */
lua_Number nval; /* for VKFLT */
int info; /* for generic use */
struct { /* for indexed variables (VINDEXED) */ struct { /* for indexed variables (VINDEXED) */
short idx; /* index (R/K) */ short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */ lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind; } ind;
int info; /* for generic use */
lua_Number nval; /* for VKFLT */
lua_Integer ival; /* for VKINT */
} u; } u;
int t; /* patch list of 'exit when true' */ int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */ int f; /* patch list of 'exit when false' */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $ ** $Id: lstate.h,v 2.130 2015/12/16 16:39:38 roberto Exp $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -33,6 +33,15 @@
struct lua_longjmp; /* defined in ldo.c */ struct lua_longjmp; /* defined in ldo.c */
/*
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
** is thread safe
*/
#if !defined(l_signalT)
#include <signal.h>
#define l_signalT sig_atomic_t
#endif
/* extra stack space to handle TM calls and some other extras */ /* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5 #define EXTRA_STACK 5
@@ -162,14 +171,14 @@ struct lua_State {
struct lua_State *twups; /* list of threads with open upvalues */ struct lua_State *twups; /* list of threads with open upvalues */
struct lua_longjmp *errorJmp; /* current error recover point */ struct lua_longjmp *errorJmp; /* current error recover point */
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
lua_Hook hook; volatile lua_Hook hook;
ptrdiff_t errfunc; /* current error handling function (stack index) */ ptrdiff_t errfunc; /* current error handling function (stack index) */
int stacksize; int stacksize;
int basehookcount; int basehookcount;
int hookcount; int hookcount;
unsigned short nny; /* number of non-yieldable calls in stack */ unsigned short nny; /* number of non-yieldable calls in stack */
unsigned short nCcalls; /* number of nested C calls */ unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask; l_signalT hookmask;
lu_byte allowhook; lu_byte allowhook;
}; };

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $ ** $Id: lstrlib.c,v 1.248 2016/05/02 13:58:01 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
*/ */
@@ -13,6 +13,7 @@
#include <ctype.h> #include <ctype.h>
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
#include <locale.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -26,7 +27,8 @@
/* /*
** maximum number of captures that a pattern can do during ** maximum number of captures that a pattern can do during
** pattern-matching. This limit is arbitrary. ** pattern-matching. This limit is arbitrary, but must fit in
** an unsigned char.
*/ */
#if !defined(LUA_MAXCAPTURES) #if !defined(LUA_MAXCAPTURES)
#define LUA_MAXCAPTURES 32 #define LUA_MAXCAPTURES 32
@@ -214,9 +216,8 @@ typedef struct MatchState {
const char *src_end; /* end ('\0') of source string */ const char *src_end; /* end ('\0') of source string */
const char *p_end; /* end ('\0') of pattern */ const char *p_end; /* end ('\0') of pattern */
lua_State *L; lua_State *L;
size_t nrep; /* limit to avoid non-linear complexity */
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
int level; /* total number of captures (finished or unfinished) */ unsigned char level; /* total number of captures (finished or unfinished) */
struct { struct {
const char *init; const char *init;
ptrdiff_t len; ptrdiff_t len;
@@ -234,17 +235,6 @@ static const char *match (MatchState *ms, const char *s, const char *p);
#endif #endif
/*
** parameters to control the maximum number of operators handled in
** a match (to avoid non-linear complexity). The maximum will be:
** (subject length) * A_REPS + B_REPS
*/
#if !defined(A_REPS)
#define A_REPS 4
#define B_REPS 100000
#endif
#define L_ESC '%' #define L_ESC '%'
#define SPECIALS "^$*+?.([%-" #define SPECIALS "^$*+?.([%-"
@@ -502,8 +492,6 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
s = NULL; /* fail */ s = NULL; /* fail */
} }
else { /* matched once */ else { /* matched once */
if (ms->nrep-- == 0)
luaL_error(ms->L, "pattern too complex");
switch (*ep) { /* handle optional suffix */ switch (*ep) { /* handle optional suffix */
case '?': { /* optional */ case '?': { /* optional */
const char *res; const char *res;
@@ -607,10 +595,6 @@ static void prepstate (MatchState *ms, lua_State *L,
ms->src_init = s; ms->src_init = s;
ms->src_end = s + ls; ms->src_end = s + ls;
ms->p_end = p + lp; ms->p_end = p + lp;
if (ls < (MAX_SIZET - B_REPS) / A_REPS)
ms->nrep = A_REPS * ls + B_REPS;
else /* overflow (very long subject) */
ms->nrep = MAX_SIZET; /* no limit */
} }
@@ -681,6 +665,7 @@ static int str_match (lua_State *L) {
typedef struct GMatchState { typedef struct GMatchState {
const char *src; /* current position */ const char *src; /* current position */
const char *p; /* pattern */ const char *p; /* pattern */
const char *lastmatch; /* end of last match */
MatchState ms; /* match state */ MatchState ms; /* match state */
} GMatchState; } GMatchState;
@@ -688,14 +673,12 @@ typedef struct GMatchState {
static int gmatch_aux (lua_State *L) { static int gmatch_aux (lua_State *L) {
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
const char *src; const char *src;
gm->ms.L = L;
for (src = gm->src; src <= gm->ms.src_end; src++) { for (src = gm->src; src <= gm->ms.src_end; src++) {
const char *e; const char *e;
reprepstate(&gm->ms); reprepstate(&gm->ms);
if ((e = match(&gm->ms, src, gm->p)) != NULL) { if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
if (e == src) /* empty match? */ gm->src = gm->lastmatch = e;
gm->src =src + 1; /* go at least one position */
else
gm->src = e;
return push_captures(&gm->ms, src, e); return push_captures(&gm->ms, src, e);
} }
} }
@@ -711,7 +694,7 @@ static int gmatch (lua_State *L) {
lua_settop(L, 2); /* keep them on closure to avoid being collected */ lua_settop(L, 2); /* keep them on closure to avoid being collected */
gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
prepstate(&gm->ms, L, s, ls, p, lp); prepstate(&gm->ms, L, s, ls, p, lp);
gm->src = s; gm->p = p; gm->src = s; gm->p = p; gm->lastmatch = NULL;
lua_pushcclosure(L, gmatch_aux, 3); lua_pushcclosure(L, gmatch_aux, 3);
return 1; return 1;
} }
@@ -778,12 +761,13 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
static int str_gsub (lua_State *L) { static int str_gsub (lua_State *L) {
size_t srcl, lp; size_t srcl, lp;
const char *src = luaL_checklstring(L, 1, &srcl); const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
const char *p = luaL_checklstring(L, 2, &lp); const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
int tr = lua_type(L, 3); const char *lastmatch = NULL; /* end of last match */
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); int tr = lua_type(L, 3); /* replacement type */
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
int anchor = (*p == '^'); int anchor = (*p == '^');
lua_Integer n = 0; lua_Integer n = 0; /* replacement count */
MatchState ms; MatchState ms;
luaL_Buffer b; luaL_Buffer b;
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
@@ -796,16 +780,15 @@ static int str_gsub (lua_State *L) {
prepstate(&ms, L, src, srcl, p, lp); prepstate(&ms, L, src, srcl, p, lp);
while (n < max_s) { while (n < max_s) {
const char *e; const char *e;
reprepstate(&ms); reprepstate(&ms); /* (re)prepare state for new match */
if ((e = match(&ms, src, p)) != NULL) { if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
n++; n++;
add_value(&ms, &b, src, e, tr); add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
src = lastmatch = e;
} }
if (e && e>src) /* non empty match? */ else if (src < ms.src_end) /* otherwise, skip one character */
src = e; /* skip it */
else if (src < ms.src_end)
luaL_addchar(&b, *src++); luaL_addchar(&b, *src++);
else break; else break; /* end of subject */
if (anchor) break; if (anchor) break;
} }
luaL_addlstring(&b, src, ms.src_end-src); luaL_addlstring(&b, src, ms.src_end-src);
@@ -830,7 +813,6 @@ static int str_gsub (lua_State *L) {
** Hexadecimal floating-point formatter ** Hexadecimal floating-point formatter
*/ */
#include <locale.h>
#include <math.h> #include <math.h>
#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
@@ -922,16 +904,14 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
#define MAX_FORMAT 32 #define MAX_FORMAT 32
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
luaL_addchar(b, '"'); luaL_addchar(b, '"');
while (l--) { while (len--) {
if (*s == '"' || *s == '\\' || *s == '\n') { if (*s == '"' || *s == '\\' || *s == '\n') {
luaL_addchar(b, '\\'); luaL_addchar(b, '\\');
luaL_addchar(b, *s); luaL_addchar(b, *s);
} }
else if (*s == '\0' || iscntrl(uchar(*s))) { else if (iscntrl(uchar(*s))) {
char buff[10]; char buff[10];
if (!isdigit(uchar(*(s+1)))) if (!isdigit(uchar(*(s+1))))
l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
@@ -946,6 +926,52 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
luaL_addchar(b, '"'); luaL_addchar(b, '"');
} }
/*
** Convert a Lua number to a string in floating-point hexadecimal
** format. Ensures the resulting string uses a dot as the radix
** character.
*/
static void addliteralnum (lua_State *L, luaL_Buffer *b, lua_Number n) {
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb = lua_number2strx(L, buff, MAX_ITEM,
"%" LUA_NUMBER_FRMLEN "a", n);
if (memchr(buff, '.', nb) == NULL) { /* no dot? */
char point = lua_getlocaledecpoint(); /* try locale point */
char *ppoint = memchr(buff, point, nb);
if (ppoint) *ppoint = '.'; /* change it to a dot */
}
luaL_addsize(b, nb);
}
static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
switch (lua_type(L, arg)) {
case LUA_TSTRING: {
size_t len;
const char *s = lua_tolstring(L, arg, &len);
addquoted(b, s, len);
break;
}
case LUA_TNUMBER: {
if (!lua_isinteger(L, arg)) { /* write floats as hexa ('%a') */
addliteralnum(L, b, lua_tonumber(L, arg));
break;
}
/* else integers; write in "native" format *//* FALLTHROUGH */
}
case LUA_TNIL: case LUA_TBOOLEAN: {
luaL_tolstring(L, arg, NULL);
luaL_addvalue(b);
break;
}
default: {
luaL_argerror(L, arg, "value has no literal form");
}
}
}
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
const char *p = strfrmt; const char *p = strfrmt;
while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
@@ -1025,7 +1051,7 @@ static int str_format (lua_State *L) {
break; break;
} }
case 'q': { case 'q': {
addquoted(L, &b, arg); addliteral(L, &b, arg);
break; break;
} }
case 's': { case 's': {
@@ -1070,8 +1096,8 @@ static int str_format (lua_State *L) {
/* value used for padding */ /* value used for padding */
#if !defined(LUA_PACKPADBYTE) #if !defined(LUAL_PACKPADBYTE)
#define LUA_PACKPADBYTE 0x00 #define LUAL_PACKPADBYTE 0x00
#endif #endif
/* maximum size for the binary representation of an integer */ /* maximum size for the binary representation of an integer */
@@ -1308,7 +1334,7 @@ static int str_pack (lua_State *L) {
KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
totalsize += ntoalign + size; totalsize += ntoalign + size;
while (ntoalign-- > 0) while (ntoalign-- > 0)
luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
arg++; arg++;
switch (opt) { switch (opt) {
case Kint: { /* signed integers */ case Kint: { /* signed integers */
@@ -1348,7 +1374,7 @@ static int str_pack (lua_State *L) {
else { /* string smaller than needed */ else { /* string smaller than needed */
luaL_addlstring(&b, s, len); /* add it all */ luaL_addlstring(&b, s, len); /* add it all */
while (len++ < (size_t)size) /* pad extra space */ while (len++ < (size_t)size) /* pad extra space */
luaL_addchar(&b, LUA_PACKPADBYTE); luaL_addchar(&b, LUAL_PACKPADBYTE);
} }
break; break;
} }
@@ -1372,7 +1398,7 @@ static int str_pack (lua_State *L) {
totalsize += len + 1; totalsize += len + 1;
break; break;
} }
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */ case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
case Kpaddalign: case Knop: case Kpaddalign: case Knop:
arg--; /* undo increment */ arg--; /* undo increment */
break; break;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $ ** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $
** Library for Table Manipulation ** Library for Table Manipulation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -53,7 +53,7 @@ static void checktab (lua_State *L, int arg, int what) {
lua_pop(L, n); /* pop metatable and tested metamethods */ lua_pop(L, n); /* pop metatable and tested metamethods */
} }
else else
luaL_argerror(L, arg, "table expected"); /* force an error */ luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
} }
} }
@@ -139,7 +139,7 @@ static int tmove (lua_State *L) {
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, luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
"destination wrap around"); "destination wrap around");
if (t > e || t <= f || tt != 1) { if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
lua_geti(L, 1, f + i); lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i); lua_seti(L, tt, t + i);
@@ -152,7 +152,7 @@ static int tmove (lua_State *L) {
} }
} }
} }
lua_pushvalue(L, tt); /* return "to table" */ lua_pushvalue(L, tt); /* return destination table */
return 1; return 1;
} }
@@ -172,7 +172,7 @@ static int tconcat (lua_State *L) {
size_t lsep; size_t lsep;
const char *sep = luaL_optlstring(L, 2, "", &lsep); const char *sep = luaL_optlstring(L, 2, "", &lsep);
lua_Integer i = luaL_optinteger(L, 3, 1); lua_Integer i = luaL_optinteger(L, 3, 1);
last = luaL_opt(L, luaL_checkinteger, 4, last); last = luaL_optinteger(L, 4, last);
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (; i < last; i++) { for (; i < last; i++) {
addfield(L, &b, i); addfield(L, &b, i);
@@ -232,6 +232,10 @@ static int unpack (lua_State *L) {
*/ */
/* type for array indices */
typedef unsigned int IdxT;
/* /*
** Produce a "random" 'unsigned int' to randomize pivot choice. This ** Produce a "random" 'unsigned int' to randomize pivot choice. This
** macro is used only when 'sort' detects a big imbalance in the result ** macro is used only when 'sort' detects a big imbalance in the result
@@ -270,7 +274,7 @@ static unsigned int l_randomizePivot (void) {
#define RANLIMIT 100u #define RANLIMIT 100u
static void set2 (lua_State *L, unsigned int i, unsigned int j) { static void set2 (lua_State *L, IdxT i, IdxT j) {
lua_seti(L, 1, i); lua_seti(L, 1, i);
lua_seti(L, 1, j); lua_seti(L, 1, j);
} }
@@ -303,10 +307,9 @@ static int sort_comp (lua_State *L, int a, int b) {
** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
** returns 'i'. ** returns 'i'.
*/ */
static unsigned int partition (lua_State *L, unsigned int lo, static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
unsigned int up) { IdxT i = lo; /* will be incremented before first use */
unsigned int i = lo; /* will be incremented before first use */ IdxT j = up - 1; /* will be decremented before first use */
unsigned int j = up - 1; /* will be decremented before first use */
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */ /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
for (;;) { for (;;) {
/* next loop: repeat ++i while a[i] < P */ /* next loop: repeat ++i while a[i] < P */
@@ -340,10 +343,9 @@ static unsigned int partition (lua_State *L, unsigned int lo,
** Choose an element in the middle (2nd-3th quarters) of [lo,up] ** Choose an element in the middle (2nd-3th quarters) of [lo,up]
** "randomized" by 'rnd' ** "randomized" by 'rnd'
*/ */
static unsigned int choosePivot (unsigned int lo, unsigned int up, static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
unsigned int rnd) { IdxT r4 = (up - lo) / 4; /* range/4 */
unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ IdxT p = rnd % (r4 * 2) + (lo + r4);
unsigned int p = rnd % (r4 * 2) + (lo + r4);
lua_assert(lo + r4 <= p && p <= up - r4); lua_assert(lo + r4 <= p && p <= up - r4);
return p; return p;
} }
@@ -352,11 +354,11 @@ static unsigned int choosePivot (unsigned int lo, unsigned int up,
/* /*
** QuickSort algorithm (recursive function) ** QuickSort algorithm (recursive function)
*/ */
static void auxsort (lua_State *L, unsigned int lo, unsigned int up, static void auxsort (lua_State *L, IdxT lo, IdxT up,
unsigned int rnd) { unsigned int rnd) {
while (lo < up) { /* loop for tail recursion */ while (lo < up) { /* loop for tail recursion */
unsigned int p; /* Pivot index */ IdxT p; /* Pivot index */
unsigned int n; /* to be used later */ IdxT n; /* to be used later */
/* sort elements 'lo', 'p', and 'up' */ /* sort elements 'lo', 'p', and 'up' */
lua_geti(L, 1, lo); lua_geti(L, 1, lo);
lua_geti(L, 1, up); lua_geti(L, 1, up);
@@ -400,7 +402,7 @@ static void auxsort (lua_State *L, unsigned int lo, unsigned int up,
n = up - p; /* size of smaller interval */ n = up - p; /* size of smaller interval */
up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
} }
if ((up - lo) / 128u > n) /* partition too imbalanced? */ if ((up - lo) / 128 > n) /* partition too imbalanced? */
rnd = l_randomizePivot(); /* try a new randomization */ rnd = l_randomizePivot(); /* try a new randomization */
} /* tail call auxsort(L, lo, up, rnd) */ } /* tail call auxsort(L, lo, up, rnd) */
} }
@@ -410,11 +412,10 @@ static int sort (lua_State *L) {
lua_Integer n = aux_getn(L, 1, TAB_RW); lua_Integer n = aux_getn(L, 1, TAB_RW);
if (n > 1) { /* non-trivial interval? */ if (n > 1) { /* non-trivial interval? */
luaL_argcheck(L, n < INT_MAX, 1, "array too big"); luaL_argcheck(L, n < INT_MAX, 1, "array too big");
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
lua_settop(L, 2); /* make sure there are two arguments */ lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, 1, (unsigned int)n, 0u); auxsort(L, 1, (IdxT)n, 0);
} }
return 0; return 0;
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltm.c,v 2.36 2015/11/03 15:47:30 roberto Exp $ ** $Id: ltm.c,v 2.37 2016/02/26 19:20:15 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -83,6 +83,22 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
} }
/*
** Return the name of the type of an object. For tables and userdata
** with metatable, use their '__name' metafield, if present.
*/
const char *luaT_objtypename (lua_State *L, const TValue *o) {
Table *mt;
if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
(ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
if (ttisstring(name)) /* is '__name' a string? */
return getstr(tsvalue(name)); /* use it as type name */
}
return ttypename(ttnov(o)); /* else use standard type name */
}
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, TValue *p3, int hasres) { const TValue *p2, TValue *p3, int hasres) {
ptrdiff_t result = savestack(L, p3); ptrdiff_t result = savestack(L, p3);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltm.h,v 2.21 2014/10/25 11:50:46 roberto Exp $ ** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -51,11 +51,12 @@ typedef enum {
#define fasttm(l,et,e) gfasttm(G(l), et, e) #define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1] #define ttypename(x) luaT_typenames_[(x) + 1]
#define objtypename(x) ttypename(ttnov(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event); TMS event);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $ ** $Id: lua.h,v 1.330 2016/01/13 17:55:19 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,11 +19,11 @@
#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 "2" #define LUA_VERSION_RELEASE "3"
#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
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio" #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2016 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
@@ -467,7 +467,7 @@ 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); }
/****************************************************************************** /******************************************************************************
* Copyright (C) 1994-2015 Lua.org, PUC-Rio. * Copyright (C) 1994-2016 Lua.org, PUC-Rio.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: luaconf.h,v 1.254 2015/10/21 18:17:40 roberto Exp $ ** $Id: luaconf.h,v 1.255 2016/05/01 20:06:09 roberto Exp $
** Configuration file for Lua ** Configuration file for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -612,7 +612,7 @@
** provide its own implementation. ** provide its own implementation.
*/ */
#if !defined(LUA_USE_C89) #if !defined(LUA_USE_C89)
#define lua_number2strx(L,b,sz,f,n) l_sprintf(b,sz,f,n) #define lua_number2strx(L,b,sz,f,n) ((void)L, l_sprintf(b,sz,f,n))
#endif #endif

View File

@@ -273,7 +273,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
luaD_inctop(L); luaD_inctop(L);
cl->p = luaF_newproto(L, NULL); cl->p = luaF_newproto(L, NULL);
LoadFunction(&S, cl->p, NULL); LoadFunction(&S, cl->p, NULL);
lua_assert(cl->nupvalues == cl->p->sizeupvalues); lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues);
luai_verifycode(L, buff, cl->p); luai_verifycode(L, buff, cl->p);
return cl; return cl;
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $ ** $Id: lvm.c,v 2.268 2016/02/05 19:59:14 roberto Exp $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -163,54 +163,67 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
/* /*
** Complete a table access: if 't' is a table, 'tm' has its metamethod; ** Finish the table access 'val = t[key]'.
** otherwise, 'tm' is NULL. ** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
** t[k] entry (which must be nil).
*/ */
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
const TValue *tm) { const TValue *slot) {
int loop; /* counter to avoid infinite loops */ int loop; /* counter to avoid infinite loops */
lua_assert(tm != NULL || !ttistable(t)); const TValue *tm; /* metamethod */
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
if (tm == NULL) { /* no metamethod (from a table)? */ if (slot == NULL) { /* 't' is not a table? */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) lua_assert(!ttistable(t));
tm = luaT_gettmbyobj(L, t, TM_INDEX);
if (ttisnil(tm))
luaG_typeerror(L, t, "index"); /* no metamethod */ luaG_typeerror(L, t, "index"); /* no metamethod */
/* else will try the metamethod */
} }
if (ttisfunction(tm)) { /* metamethod is a function */ else { /* 't' is a table */
lua_assert(ttisnil(slot));
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
if (tm == NULL) { /* no metamethod? */
setnilvalue(val); /* result is nil */
return;
}
/* else will try the metamethod */
}
if (ttisfunction(tm)) { /* is metamethod a function? */
luaT_callTM(L, tm, t, key, val, 1); /* call it */ luaT_callTM(L, tm, t, key, val, 1); /* call it */
return; return;
} }
t = tm; /* else repeat access over 'tm' */ t = tm; /* else try to access 'tm[key]' */
if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */
setobj2s(L, val, tm); /* done */ setobj2s(L, val, slot); /* done */
return; return;
} }
/* else repeat */ /* else repeat (tail call 'luaV_finishget') */
} }
luaG_runerror(L, "gettable chain too long; possible loop"); luaG_runerror(L, "'__index' chain too long; possible loop");
} }
/* /*
** Main function for table assignment (invoking metamethods if needed). ** Finish a table assignment 't[key] = val'.
** Compute 't[key] = val' ** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset'
** would have done the job.)
*/ */
void luaV_finishset (lua_State *L, const TValue *t, TValue *key, void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval) { StkId val, const TValue *slot) {
int loop; /* counter to avoid infinite loops */ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm; /* '__newindex' metamethod */
if (oldval != NULL) { if (slot != NULL) { /* is 't' a table? */
Table *h = hvalue(t); Table *h = hvalue(t); /* save 't' table */
lua_assert(ttisnil(oldval)); lua_assert(ttisnil(slot)); /* old value must be nil */
/* must check the metamethod */ tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
if ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && if (tm == NULL) { /* no metamethod? */
/* no metamethod; is there a previous entry in the table? */ if (slot == luaO_nilobject) /* no previous entry? */
(oldval != luaO_nilobject || slot = luaH_newkey(L, h, key); /* create one */
/* no previous entry; must create one. (The next test is
always true; we only need the assignment.) */
(oldval = luaH_newkey(L, h, key), 1))) {
/* no metamethod and (now) there is an entry with given key */ /* no metamethod and (now) there is an entry with given key */
setobj2t(L, cast(TValue *, oldval), val); setobj2t(L, cast(TValue *, slot), val); /* set its new value */
invalidateTMcache(h); invalidateTMcache(h);
luaC_barrierback(L, h, val); luaC_barrierback(L, h, val);
return; return;
@@ -227,11 +240,11 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
return; return;
} }
t = tm; /* else repeat assignment over 'tm' */ t = tm; /* else repeat assignment over 'tm' */
if (luaV_fastset(L, t, key, oldval, luaH_get, val)) if (luaV_fastset(L, t, key, slot, luaH_get, val))
return; /* done */ return; /* done */
/* else loop */ /* else loop */
} }
luaG_runerror(L, "settable chain too long; possible loop"); luaG_runerror(L, "'__newindex' chain too long; possible loop");
} }
@@ -749,18 +762,28 @@ void luaV_finishOp (lua_State *L) {
luai_threadyield(L); } luai_threadyield(L); }
/* fetch an instruction and prepare its execution */
#define vmfetch() { \
i = *(ci->u.l.savedpc++); \
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \
Protect(luaG_traceexec(L)); \
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
lua_assert(base == ci->u.l.base); \
lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \
}
#define vmdispatch(o) switch(o) #define vmdispatch(o) switch(o)
#define vmcase(l) case l: #define vmcase(l) case l:
#define vmbreak break #define vmbreak break
/* /*
** copy of 'luaV_gettable', but protecting call to potential metamethod ** copy of 'luaV_gettable', but protecting the call to potential
** (which can reallocate the stack) ** metamethod (which can reallocate the stack)
*/ */
#define gettableProtected(L,t,k,v) { const TValue *aux; \ #define gettableProtected(L,t,k,v) { const TValue *slot; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
else Protect(luaV_finishget(L,t,k,v,aux)); } else Protect(luaV_finishget(L,t,k,v,slot)); }
/* same for 'luaV_settable' */ /* same for 'luaV_settable' */
@@ -783,14 +806,9 @@ void luaV_execute (lua_State *L) {
base = ci->u.l.base; /* local copy of function's base */ base = ci->u.l.base; /* local copy of function's base */
/* main loop of interpreter */ /* main loop of interpreter */
for (;;) { for (;;) {
Instruction i = *(ci->u.l.savedpc++); Instruction i;
StkId ra; StkId ra;
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) vmfetch();
Protect(luaG_traceexec(L));
/* WARNING: several calls may realloc the stack and invalidate 'ra' */
ra = RA(i);
lua_assert(base == ci->u.l.base);
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
vmdispatch (GET_OPCODE(i)) { vmdispatch (GET_OPCODE(i)) {
vmcase(OP_MOVE) { vmcase(OP_MOVE) {
setobjs2s(L, ra, RB(i)); setobjs2s(L, ra, RB(i));
@@ -1163,7 +1181,7 @@ void luaV_execute (lua_State *L) {
oci->u.l.savedpc = nci->u.l.savedpc; oci->u.l.savedpc = nci->u.l.savedpc;
oci->callstatus |= CIST_TAIL; /* function was tail called */ oci->callstatus |= CIST_TAIL; /* function was tail called */
ci = L->ci = oci; /* remove new frame */ ci = L->ci = oci; /* remove new frame */
lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); lua_assert(L->top == oci->u.l.base + getproto(ofunc)->sp->maxstacksize);
goto newframe; /* restart luaV_execute over new Lua function */ goto newframe; /* restart luaV_execute over new Lua function */
} }
vmbreak; vmbreak;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $ ** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -49,25 +49,24 @@
/* /*
** fast track for 'gettable': 1 means 'aux' points to resulted value; ** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is ** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise,
** the raw get function to use. ** return 0 (meaning it will have to check metamethod) with 'slot'
** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
** 'f' is the raw get function to use.
*/ */
#define luaV_fastget(L,t,k,aux,f) \ #define luaV_fastget(L,t,k,slot,f) \
(!ttistable(t) \ (!ttistable(t) \
? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
: (aux = f(hvalue(t), k), /* else, do raw access */ \ : (slot = f(hvalue(t), k), /* else, do raw access */ \
!ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ !ttisnil(slot))) /* result not nil? */
: (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\
aux != NULL ? 0 /* has metamethod? must call it */ \
: (aux = luaO_nilobject, 1)))) /* else, final result is nil */
/* /*
** standard implementation for 'gettable' ** standard implementation for 'gettable'
*/ */
#define luaV_gettable(L,t,k,v) { const TValue *aux; \ #define luaV_gettable(L,t,k,v) { const TValue *slot; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
else luaV_finishget(L,t,k,v,aux); } else luaV_finishget(L,t,k,v,slot); }
/* /*
@@ -100,9 +99,9 @@ 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, int mode); LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *tm); StkId val, const TValue *slot);
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval); StkId val, const TValue *slot);
LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total); LUAI_FUNC void luaV_concat (lua_State *L, int total);

View File

@@ -1,4 +1,17 @@
v1.0.0-rc2 (2015-3-7) v1.0.0-rc3 (2016-5-9)
-----------
* Update jemalloc 4.1.1
* Update lua 5.3.3 rc1
* Update sproto to support encoding empty table
* Make skynet.init stable (keep order)
* skynet.getenv can return empty string
* Add lua VM memory warning
* lua VM support memory limit
* skynet.pcall suport varargs
* Bugfix : Global name query
* Bugfix : snax.queryglobal
v1.0.0-rc2 (2016-3-7)
----------- -----------
* Fix a bug in lua 5.3.2 * Fix a bug in lua 5.3.2
* Update sproto (fix bugs and add ud for package) * Update sproto (fix bugs and add ud for package)

View File

@@ -1,6 +1,6 @@
## Build ## Build
For linux, install autoconf first for jemalloc For Linux, install autoconf first for jemalloc:
``` ```
git clone https://github.com/cloudwu/skynet.git git clone https://github.com/cloudwu/skynet.git
@@ -8,18 +8,18 @@ cd skynet
make 'PLATFORM' # PLATFORM can be linux, macosx, freebsd now make 'PLATFORM' # PLATFORM can be linux, macosx, freebsd now
``` ```
Or you can : Or you can:
``` ```
export PLAT=linux export PLAT=linux
make make
``` ```
For freeBSD , use gmake instead of make . For FreeBSD , use gmake instead of make.
## Test ## Test
Run these in different console Run these in different consoles:
``` ```
./skynet examples/config # Launch first skynet node (Gate server) and a skynet-master (see config for standalone option) ./skynet examples/config # Launch first skynet node (Gate server) and a skynet-master (see config for standalone option)
@@ -28,11 +28,11 @@ Run these in different console
## About Lua ## About Lua
Skynet now use a modify version of lua 5.3.2 ( http://www.lua.org/ftp/lua-5.3.2.tar.gz ) . Skynet now uses a modified version of lua 5.3.2 ( http://www.lua.org/ftp/lua-5.3.2.tar.gz ) .
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html For details: 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 other official Lua versions, just edit the Makefile by yourself.
## How To Use (Sorry, Only in Chinese now) ## How To Use (Sorry, Only in Chinese now)

View File

@@ -0,0 +1,30 @@
local skynet = require "skynet"
local list = {}
local function timeout_check(ti)
if not next(list) then
return
end
skynet.sleep(ti) -- sleep 10 sec
for k,v in pairs(list) do
skynet.error("timout",ti,k,v)
end
end
skynet.start(function()
skynet.error("ping all")
local list_ret = skynet.call(".launcher", "lua", "LIST")
for addr, desc in pairs(list_ret) do
list[addr] = desc
skynet.fork(function()
skynet.call(addr,"debug","INFO")
list[addr] = nil
end)
end
skynet.sleep(0)
timeout_check(100)
timeout_check(400)
timeout_check(500)
skynet.exit()
end)

View File

@@ -4,7 +4,7 @@ local sprotoloader = require "sprotoloader"
local max_client = 64 local max_client = 64
skynet.start(function() skynet.start(function()
print("Server start") skynet.error("Server start")
skynet.uniqueservice("protoloader") skynet.uniqueservice("protoloader")
local console = skynet.newservice("console") local console = skynet.newservice("console")
skynet.newservice("debug_console",8000) skynet.newservice("debug_console",8000)
@@ -15,7 +15,6 @@ skynet.start(function()
maxclient = max_client, maxclient = max_client,
nodelay = true, nodelay = true,
}) })
print("Watchdog listen on ", 8888) skynet.error("Watchdog listen on", 8888)
skynet.exit() skynet.exit()
end) end)

View File

@@ -551,7 +551,7 @@ seri(lua_State *L, struct block *b, int len) {
} }
int int
_luaseri_unpack(lua_State *L) { luaseri_unpack(lua_State *L) {
if (lua_isnoneornil(L,1)) { if (lua_isnoneornil(L,1)) {
return 0; return 0;
} }
@@ -595,7 +595,7 @@ _luaseri_unpack(lua_State *L) {
} }
int int
_luaseri_pack(lua_State *L) { luaseri_pack(lua_State *L) {
struct block temp; struct block temp;
temp.next = NULL; temp.next = NULL;
struct write_block wb; struct write_block wb;

View File

@@ -3,7 +3,7 @@
#include <lua.h> #include <lua.h>
int _luaseri_pack(lua_State *L); int luaseri_pack(lua_State *L);
int _luaseri_unpack(lua_State *L); int luaseri_unpack(lua_State *L);
#endif #endif

View File

@@ -81,7 +81,7 @@ forward_cb(struct skynet_context * context, void * ud, int type, int session, ui
} }
static int static int
_callback(lua_State *L) { lcallback(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
int forward = lua_toboolean(L, 2); int forward = lua_toboolean(L, 2);
luaL_checktype(L,1,LUA_TFUNCTION); luaL_checktype(L,1,LUA_TFUNCTION);
@@ -101,7 +101,7 @@ _callback(lua_State *L) {
} }
static int static int
_command(lua_State *L) { lcommand(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
const char * cmd = luaL_checkstring(L,1); const char * cmd = luaL_checkstring(L,1);
const char * result; const char * result;
@@ -119,7 +119,7 @@ _command(lua_State *L) {
} }
static int static int
_intcommand(lua_State *L) { lintcommand(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
const char * cmd = luaL_checkstring(L,1); const char * cmd = luaL_checkstring(L,1);
const char * result; const char * result;
@@ -141,7 +141,7 @@ _intcommand(lua_State *L) {
} }
static int static int
_genid(lua_State *L) { lgenid(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
int session = skynet_send(context, 0, 0, PTYPE_TAG_ALLOCSESSION , 0 , NULL, 0); int session = skynet_send(context, 0, 0, PTYPE_TAG_ALLOCSESSION , 0 , NULL, 0);
lua_pushinteger(L, session); lua_pushinteger(L, session);
@@ -167,7 +167,7 @@ get_dest_string(lua_State *L, int index) {
integer len integer len
*/ */
static int static int
_send(lua_State *L) { lsend(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
uint32_t dest = (uint32_t)lua_tointeger(L, 1); uint32_t dest = (uint32_t)lua_tointeger(L, 1);
const char * dest_string = NULL; const char * dest_string = NULL;
@@ -224,7 +224,7 @@ _send(lua_State *L) {
} }
static int static int
_redirect(lua_State *L) { lredirect(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
uint32_t dest = (uint32_t)lua_tointeger(L,1); uint32_t dest = (uint32_t)lua_tointeger(L,1);
const char * dest_string = NULL; const char * dest_string = NULL;
@@ -267,14 +267,32 @@ _redirect(lua_State *L) {
} }
static int static int
_error(lua_State *L) { lerror(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
skynet_error(context, "%s", luaL_checkstring(L,1)); int n = lua_gettop(L);
if (n <= 1) {
lua_settop(L, 1);
const char * s = luaL_tolstring(L, 1, NULL);
skynet_error(context, "%s", s);
return 0;
}
luaL_Buffer b;
luaL_buffinit(L, &b);
int i;
for (i=1; i<=n; i++) {
luaL_tolstring(L, i, NULL);
luaL_addvalue(&b);
if (i<n) {
luaL_addchar(&b, ' ');
}
}
luaL_pushresult(&b);
skynet_error(context, "%s", lua_tostring(L, -1));
return 0; return 0;
} }
static int static int
_tostring(lua_State *L) { ltostring(lua_State *L) {
if (lua_isnoneornil(L,1)) { if (lua_isnoneornil(L,1)) {
return 0; return 0;
} }
@@ -285,7 +303,7 @@ _tostring(lua_State *L) {
} }
static int static int
_harbor(lua_State *L) { lharbor(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
uint32_t handle = (uint32_t)luaL_checkinteger(L,1); uint32_t handle = (uint32_t)luaL_checkinteger(L,1);
int harbor = 0; int harbor = 0;
@@ -298,7 +316,7 @@ _harbor(lua_State *L) {
static int static int
lpackstring(lua_State *L) { lpackstring(lua_State *L) {
_luaseri_pack(L); luaseri_pack(L);
char * str = (char *)lua_touserdata(L, -2); char * str = (char *)lua_touserdata(L, -2);
int sz = lua_tointeger(L, -1); int sz = lua_tointeger(L, -1);
lua_pushlstring(L, str, sz); lua_pushlstring(L, str, sz);
@@ -338,19 +356,19 @@ luaopen_skynet_core(lua_State *L) {
luaL_checkversion(L); luaL_checkversion(L);
luaL_Reg l[] = { luaL_Reg l[] = {
{ "send" , _send }, { "send" , lsend },
{ "genid", _genid }, { "genid", lgenid },
{ "redirect", _redirect }, { "redirect", lredirect },
{ "command" , _command }, { "command" , lcommand },
{ "intcommand", _intcommand }, { "intcommand", lintcommand },
{ "error", _error }, { "error", lerror },
{ "tostring", _tostring }, { "tostring", ltostring },
{ "harbor", _harbor }, { "harbor", lharbor },
{ "pack", _luaseri_pack }, { "pack", luaseri_pack },
{ "unpack", _luaseri_unpack }, { "unpack", luaseri_unpack },
{ "packstring", lpackstring }, { "packstring", lpackstring },
{ "trash" , ltrash }, { "trash" , ltrash },
{ "callback", _callback }, { "callback", lcallback },
{ "now", lnow }, { "now", lnow },
{ NULL, NULL }, { NULL, NULL },
}; };

View File

@@ -210,13 +210,13 @@ Each integer number must be serialized in little-endian format.
The sproto message must be a user defined type struct, and a struct is encoded in three parts. The header, the field part, and the data part. The sproto message must be a user defined type struct, and a struct is encoded in three parts. The header, the field part, and the data part.
The tag and small integer or boolean will be encoded in field part, and others are in data part. The tag and small integer or boolean will be encoded in field part, and others are in data part.
All the fields must be encoded in ascending order (by tag). The tags of fields can be discontinuous, if a field is nil. (default value in lua), don't encode it in message. All the fields must be encoded in ascending order (by tag, base 0). The tags of fields can be discontinuous, if a field is nil. (default value in lua), don't encode it in message.
The header is a 16bit integer. It is the number of fields. The header is a 16bit integer. It is the number of fields.
Each field in field part is a 16bit integer (n). If n is zero, that means the field data is encoded in data part ; Each field in field part is a 16bit integer (n). If n is zero, that means the field data is encoded in data part ;
If n is even (and not zero), the value of this field is n/2-1 ; If n is even (and not zero), the value of this field is n/2-1 , and the tag increases 1;
If n is odd, that means the tags is not continuous, and we should add current tag by (n+1)/2 . If n is odd, that means the tags is not continuous, and we should add current tag by (n+1)/2 .

View File

@@ -126,7 +126,7 @@ encode(const struct sproto_arg *args) {
lua_replace(L, self->array_index); lua_replace(L, self->array_index);
} }
self->array_index = 0; self->array_index = 0;
return 0; return SPROTO_CB_NOARRAY;
} }
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
return luaL_error(L, ".*%s(%d) should be a table (Is a %s)", return luaL_error(L, ".*%s(%d) should be a table (Is a %s)",
@@ -147,7 +147,7 @@ encode(const struct sproto_arg *args) {
// iterate end // iterate end
lua_pushnil(L); lua_pushnil(L);
lua_replace(L, self->iter_index); lua_replace(L, self->iter_index);
return 0; return SPROTO_CB_NIL;
} }
lua_insert(L, -2); lua_insert(L, -2);
lua_replace(L, self->iter_index); lua_replace(L, self->iter_index);
@@ -159,7 +159,7 @@ encode(const struct sproto_arg *args) {
} }
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
lua_pop(L,1); lua_pop(L,1);
return 0; return SPROTO_CB_NIL;
} }
switch (args->type) { switch (args->type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
@@ -203,10 +203,10 @@ encode(const struct sproto_arg *args) {
str = lua_tolstring(L, -1, &sz); str = lua_tolstring(L, -1, &sz);
} }
if (sz > args->length) if (sz > args->length)
return -1; return SPROTO_CB_ERROR;
memcpy(args->value, str, sz); memcpy(args->value, str, sz);
lua_pop(L,1); lua_pop(L,1);
return sz + 1; // The length of empty string is 1. return sz;
} }
case SPROTO_TSTRUCT: { case SPROTO_TSTRUCT: {
struct encode_ud sub; struct encode_ud sub;
@@ -226,6 +226,8 @@ encode(const struct sproto_arg *args) {
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_settop(L, top-1); // pop the value lua_settop(L, top-1); // pop the value
if (r < 0)
return SPROTO_CB_ERROR;
return r; return r;
} }
default: default:
@@ -309,7 +311,7 @@ decode(const struct sproto_arg *args) {
lua_State *L = self->L; lua_State *L = self->L;
if (self->deep >= ENCODE_DEEPLEVEL) if (self->deep >= ENCODE_DEEPLEVEL)
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) {
// It's array // It's array
if (args->tagname != self->array_tag) { if (args->tagname != self->array_tag) {
self->array_tag = args->tagname; self->array_tag = args->tagname;
@@ -321,6 +323,10 @@ decode(const struct sproto_arg *args) {
} else { } else {
self->array_index = lua_gettop(L); self->array_index = lua_gettop(L);
} }
if (args->index < 0) {
// It's a empty array, return now.
return 0;
}
} }
} }
switch (args->type) { switch (args->type) {
@@ -355,9 +361,10 @@ decode(const struct sproto_arg *args) {
sub.key_index = lua_gettop(L); sub.key_index = lua_gettop(L);
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub); r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
if (r < 0 || r != args->length) if (r < 0)
return SPROTO_CB_ERROR;
if (r != args->length)
return r; return r;
// assert(args->index > 0);
lua_pushvalue(L, sub.key_index); lua_pushvalue(L, sub.key_index);
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
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);
@@ -370,7 +377,9 @@ decode(const struct sproto_arg *args) {
sub.mainindex_tag = -1; sub.mainindex_tag = -1;
sub.key_index = 0; sub.key_index = 0;
r = sproto_decode(args->subtype, args->value, args->length, decode, &sub); r = sproto_decode(args->subtype, args->value, args->length, decode, &sub);
if (r < 0 || r != args->length) if (r < 0)
return SPROTO_CB_ERROR;
if (r != args->length)
return r; return r;
lua_settop(L, sub.result_index); lua_settop(L, sub.result_index);
break; break;
@@ -532,6 +541,9 @@ lprotocol(lua_State *L) {
lua_pushstring(L, name); lua_pushstring(L, name);
} else { } else {
const char * name = lua_tostring(L, 2); const char * name = lua_tostring(L, 2);
if (name == NULL) {
return luaL_argerror(L, 2, "Should be number or string");
}
tag = sproto_prototag(sp, name); tag = sproto_prototag(sp, name);
if (tag < 0) if (tag < 0)
return 0; return 0;
@@ -592,6 +604,8 @@ encode_default(const struct sproto_arg *args) {
lua_pushstring(L, args->tagname); lua_pushstring(L, args->tagname);
if (args->index > 0) { if (args->index > 0) {
lua_newtable(L); lua_newtable(L);
lua_rawset(L, -3);
return SPROTO_CB_NOARRAY;
} else { } else {
switch(args->type) { switch(args->type) {
case SPROTO_TINTEGER: case SPROTO_TINTEGER:
@@ -609,9 +623,9 @@ encode_default(const struct sproto_arg *args) {
lua_setfield(L, -2, "__type"); lua_setfield(L, -2, "__type");
break; break;
} }
lua_rawset(L, -3);
return SPROTO_CB_NIL;
} }
lua_rawset(L, -3);
return 0;
} }
/* /*

View File

@@ -677,10 +677,10 @@ 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) if (sz < 0) {
return sz; if (sz == SPROTO_CB_NIL)
if (args->type == SPROTO_TSTRING) { return 0;
--sz; // the length of null string is 1 return -1; // sz == SPROTO_CB_ERROR
} }
assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
return fill_size(data, sz); return fill_size(data, sz);
@@ -702,7 +702,7 @@ uint32_to_uint64(int negative, uint8_t *buffer) {
} }
static uint8_t * static uint8_t *
encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size) { encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size, int *noarray) {
uint8_t * header = buffer; uint8_t * header = buffer;
int intlen; int intlen;
int index; int index;
@@ -712,6 +712,8 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
size--; size--;
intlen = sizeof(uint32_t); intlen = sizeof(uint32_t);
index = 1; index = 1;
*noarray = 0;
for (;;) { for (;;) {
int sz; int sz;
union { union {
@@ -722,10 +724,15 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
args->length = sizeof(u); args->length = sizeof(u);
args->index = index; args->index = index;
sz = cb(args); sz = cb(args);
if (sz < 0) if (sz <= 0) {
return NULL; if (sz == SPROTO_CB_NIL) // nil object, end of array
if (sz == 0) // nil object, end of array break;
break; if (sz == SPROTO_CB_NOARRAY) { // no array, don't encode it
*noarray = 1;
break;
}
return NULL; // sz == SPROTO_CB_ERROR
}
if (size < sizeof(uint64_t)) if (size < sizeof(uint64_t))
return NULL; return NULL;
if (sz == sizeof(uint32_t)) { if (sz == sizeof(uint32_t)) {
@@ -790,11 +797,17 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
size -= SIZEOF_LENGTH; size -= SIZEOF_LENGTH;
buffer = data + SIZEOF_LENGTH; buffer = data + SIZEOF_LENGTH;
switch (args->type) { switch (args->type) {
case SPROTO_TINTEGER: case SPROTO_TINTEGER: {
buffer = encode_integer_array(cb,args,buffer,size); int noarray;
buffer = encode_integer_array(cb,args,buffer,size, &noarray);
if (buffer == NULL) if (buffer == NULL)
return -1; return -1;
if (noarray) {
return 0;
}
break; break;
}
case SPROTO_TBOOLEAN: case SPROTO_TBOOLEAN:
args->index = 1; args->index = 1;
for (;;) { for (;;) {
@@ -802,10 +815,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
args->value = &v; args->value = &v;
args->length = sizeof(v); args->length = sizeof(v);
sz = cb(args); sz = cb(args);
if (sz < 0) if (sz < 0) {
return -1; if (sz == SPROTO_CB_NIL) // nil object , end of array
if (sz == 0) // nil object , end of array break;
break; if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
return 0;
return -1; // sz == SPROTO_CB_ERROR
}
if (size < 1) if (size < 1)
return -1; return -1;
buffer[0] = v ? 1: 0; buffer[0] = v ? 1: 0;
@@ -823,12 +839,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) if (sz < 0) {
break; if (sz == SPROTO_CB_NIL) {
if (sz < 0) break;
return -1; }
if (args->type == SPROTO_TSTRING) { if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
--sz; return 0;
return -1; // sz == SPROTO_CB_ERROR
} }
fill_size(buffer, sz); fill_size(buffer, sz);
buffer += SIZEOF_LENGTH+sz; buffer += SIZEOF_LENGTH+sz;
@@ -838,8 +855,6 @@ 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) // empty array
return 0;
return fill_size(data, sz); return fill_size(data, sz);
} }
@@ -885,10 +900,13 @@ sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_call
args.value = &u; args.value = &u;
args.length = sizeof(u); args.length = sizeof(u);
sz = cb(&args); sz = cb(&args);
if (sz < 0) if (sz < 0) {
return -1; if (sz == SPROTO_CB_NIL)
if (sz == 0) // nil object continue;
continue; if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
return 0;
return -1; // sz == SPROTO_CB_ERROR
}
if (sz == sizeof(uint32_t)) { if (sz == sizeof(uint32_t)) {
if (u.u32 < 0x7fff) { if (u.u32 < 0x7fff) {
value = (u.u32+1) * 2; value = (u.u32+1) * 2;
@@ -985,13 +1003,18 @@ decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
uint32_t sz = todword(stream); uint32_t sz = todword(stream);
int type = args->type; int type = args->type;
int i; int i;
if (sz == 0) {
// It's empty array, call cb with index == -1 to create the empty array.
args->index = -1;
args->value = NULL;
args->length = 0;
cb(args);
return 0;
}
stream += SIZEOF_LENGTH; stream += SIZEOF_LENGTH;
switch (type) { switch (type) {
case SPROTO_TINTEGER: { case SPROTO_TINTEGER: {
int len; int len = *stream;
if (sz < 1)
return -1;
len = *stream;
++stream; ++stream;
--sz; --sz;
if (len == sizeof(uint32_t)) { if (len == sizeof(uint32_t)) {

View File

@@ -14,6 +14,10 @@ struct sproto_type;
#define SPROTO_TSTRING 2 #define SPROTO_TSTRING 2
#define SPROTO_TSTRUCT 3 #define SPROTO_TSTRUCT 3
#define SPROTO_CB_ERROR -1
#define SPROTO_CB_NIL -2
#define SPROTO_CB_NOARRAY -3
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 *);

View File

@@ -54,11 +54,10 @@ redcmd[42] = function(fd, data) -- '*'
local noerr = true local noerr = true
for i = 1,n do for i = 1,n do
local ok, v = read_response(fd) local ok, v = read_response(fd)
if ok then if not ok then
bulk[i] = v
else
noerr = false noerr = false
end end
bulk[i] = v
end end
return noerr, bulk return noerr, bulk
end end

View File

@@ -28,12 +28,12 @@ function sharedata.query(name)
return r return r
end end
function sharedata.new(name, v) function sharedata.new(name, v, ...)
skynet.call(service, "lua", "new", name, v) skynet.call(service, "lua", "new", name, v, ...)
end end
function sharedata.update(name, v) function sharedata.update(name, v, ...)
skynet.call(service, "lua", "update", name, v) skynet.call(service, "lua", "update", name, v, ...)
end end
function sharedata.delete(name) function sharedata.delete(name)

View File

@@ -343,12 +343,7 @@ function skynet.exit()
end end
function skynet.getenv(key) function skynet.getenv(key)
local ret = c.command("GETENV",key) return (c.command("GETENV",key))
if ret == "" then
return
else
return ret
end
end end
function skynet.setenv(key, value) function skynet.setenv(key, value)
@@ -553,13 +548,7 @@ function skynet.harbor(addr)
return c.harbor(addr) return c.harbor(addr)
end end
function skynet.error(...) skynet.error = c.error
local t = {...}
for i=1,#t do
t[i] = tostring(t[i])
end
return c.error(table.concat(t, " "))
end
----- register protocol ----- register protocol
do do
@@ -592,9 +581,9 @@ function skynet.init(f, name)
if init_func == nil then if init_func == nil then
f() f()
else else
if name == nil then table.insert(init_func, f)
table.insert(init_func, f) if name then
else assert(type(name) == "string")
assert(init_func[name] == nil) assert(init_func[name] == nil)
init_func[name] = f init_func[name] = f
end end
@@ -605,8 +594,8 @@ local function init_all()
local funcs = init_func local funcs = init_func
init_func = nil init_func = nil
if funcs then if funcs then
for k,v in pairs(funcs) do for _,f in ipairs(funcs) do
v() f()
end end
end end
end end
@@ -616,14 +605,14 @@ local function ret(f, ...)
return ... return ...
end end
local function init_template(start) local function init_template(start, ...)
init_all() init_all()
init_func = {} init_func = {}
return ret(init_all, start()) return ret(init_all, start(...))
end end
function skynet.pcall(start) function skynet.pcall(start, ...)
return xpcall(init_template, debug.traceback, start) return xpcall(init_template, debug.traceback, start, ...)
end end
function skynet.init_service(start) function skynet.init_service(start)
@@ -667,6 +656,11 @@ function skynet.term(service)
return _error_dispatch(0, service) return _error_dispatch(0, service)
end end
function skynet.memlimit(bytes)
debug.getregistry().memlimit = bytes
skynet.memlimit = nil -- set only once
end
local function clear_pool() local function clear_pool()
coroutine_pool = {} coroutine_pool = {}
end end

View File

@@ -10,7 +10,6 @@ local coroutine_running = coroutine.running
local select = select local select = select
local skynetco = {} local skynetco = {}
skynetco.create = coroutine.create
skynetco.isyieldable = coroutine.isyieldable skynetco.isyieldable = coroutine.isyieldable
skynetco.running = coroutine.running skynetco.running = coroutine.running
skynetco.status = coroutine.status skynetco.status = coroutine.status

View File

@@ -1,4 +1,5 @@
local table = table local table = table
local extern_dbgcmd = {};
return function (skynet, export) return function (skynet, export)
@@ -11,7 +12,7 @@ end
local dbgcmd local dbgcmd
local function init_dbgcmd() local function init_dbgcmd()
dbgcmd = {} dbgcmd = extern_dbgcmd
function dbgcmd.MEM() function dbgcmd.MEM()
local kb, bytes = collectgarbage "count" local kb, bytes = collectgarbage "count"

View File

@@ -407,8 +407,6 @@ end
---------------------- UDP ---------------------- UDP
local udp_socket = {}
local function create_udp_object(id, cb) local function create_udp_object(id, cb)
assert(not socket_pool[id], "socket is not closed") assert(not socket_pool[id], "socket is not closed")
socket_pool[id] = { socket_pool[id] = {

View File

@@ -9,9 +9,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#define MEMORY_WARNING_REPORT (1024 * 1024 * 32)
struct snlua { struct snlua {
lua_State * L; lua_State * L;
struct skynet_context * ctx; struct skynet_context * ctx;
size_t mem;
size_t mem_report;
size_t mem_limit;
}; };
// LUA_CACHELIB may defined in patched lua for shared proto // LUA_CACHELIB may defined in patched lua for shared proto
@@ -53,7 +58,7 @@ traceback (lua_State *L) {
} }
static void static void
_report_launcher_error(struct skynet_context *ctx) { report_launcher_error(struct skynet_context *ctx) {
// sizeof "ERROR" == 5 // sizeof "ERROR" == 5
skynet_sendname(ctx, 0, ".launcher", PTYPE_TEXT, 0, "ERROR", 5); skynet_sendname(ctx, 0, ".launcher", PTYPE_TEXT, 0, "ERROR", 5);
} }
@@ -68,7 +73,7 @@ optstring(struct skynet_context *ctx, const char *key, const char * str) {
} }
static int static int
_init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz) { init_cb(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz) {
lua_State *L = l->L; lua_State *L = l->L;
l->ctx = ctx; l->ctx = ctx;
lua_gc(L, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
@@ -101,17 +106,25 @@ _init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz)
int r = luaL_loadfile(L,loader); int r = luaL_loadfile(L,loader);
if (r != LUA_OK) { if (r != LUA_OK) {
skynet_error(ctx, "Can't load %s : %s", loader, lua_tostring(L, -1)); skynet_error(ctx, "Can't load %s : %s", loader, lua_tostring(L, -1));
_report_launcher_error(ctx); report_launcher_error(ctx);
return 1; return 1;
} }
lua_pushlstring(L, args, sz); lua_pushlstring(L, args, sz);
r = lua_pcall(L,1,0,1); r = lua_pcall(L,1,0,1);
if (r != LUA_OK) { if (r != LUA_OK) {
skynet_error(ctx, "lua loader error : %s", lua_tostring(L, -1)); skynet_error(ctx, "lua loader error : %s", lua_tostring(L, -1));
_report_launcher_error(ctx); report_launcher_error(ctx);
return 1; return 1;
} }
lua_settop(L,0); lua_settop(L,0);
if (lua_getfield(L, LUA_REGISTRYINDEX, "memlimit") == LUA_TNUMBER) {
size_t limit = lua_tointeger(L, -1);
l->mem_limit = limit;
skynet_error(ctx, "Set memory limit to %.2f M", (float)limit / (1024 * 1024));
lua_pushnil(L);
lua_setfield(L, LUA_REGISTRYINDEX, "memlimit");
}
lua_pop(L, 1);
lua_gc(L, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
@@ -119,11 +132,11 @@ _init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz)
} }
static int static int
_launch(struct skynet_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz) { launch_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz) {
assert(type == 0 && session == 0); assert(type == 0 && session == 0);
struct snlua *l = ud; struct snlua *l = ud;
skynet_callback(context, NULL, NULL); skynet_callback(context, NULL, NULL);
int err = _init(l, context, msg, sz); int err = init_cb(l, context, msg, sz);
if (err) { if (err) {
skynet_command(context, "EXIT", NULL); skynet_command(context, "EXIT", NULL);
} }
@@ -136,7 +149,7 @@ snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
int sz = strlen(args); int sz = strlen(args);
char * tmp = skynet_malloc(sz); char * tmp = skynet_malloc(sz);
memcpy(tmp, args, sz); memcpy(tmp, args, sz);
skynet_callback(ctx, l , _launch); skynet_callback(ctx, l , launch_cb);
const char * self = skynet_command(ctx, "REG", NULL); const char * self = skynet_command(ctx, "REG", NULL);
uint32_t handle_id = strtoul(self+1, NULL, 16); uint32_t handle_id = strtoul(self+1, NULL, 16);
// it must be first message // it must be first message
@@ -144,11 +157,33 @@ snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
return 0; return 0;
} }
static void *
lalloc(void * ud, void *ptr, size_t osize, size_t nsize) {
struct snlua *l = ud;
size_t mem = l->mem;
l->mem += nsize;
if (ptr)
l->mem -= osize;
if (l->mem_limit != 0 && l->mem > l->mem_limit) {
if (ptr == NULL || nsize > osize) {
l->mem = mem;
return NULL;
}
}
if (l->mem > l->mem_report) {
l->mem_report *= 2;
skynet_error(l->ctx, "Memory warning %.2f M", (float)l->mem / (1024 * 1024));
}
return skynet_lalloc(ptr, osize, nsize);
}
struct snlua * struct snlua *
snlua_create(void) { snlua_create(void) {
struct snlua * l = skynet_malloc(sizeof(*l)); struct snlua * l = skynet_malloc(sizeof(*l));
memset(l,0,sizeof(*l)); memset(l,0,sizeof(*l));
l->L = lua_newstate(skynet_lalloc, NULL); l->mem_report = MEMORY_WARNING_REPORT;
l->mem_limit = 0;
l->L = lua_newstate(lalloc, l);
return l; return l;
} }
@@ -161,8 +196,12 @@ snlua_release(struct snlua *l) {
void void
snlua_signal(struct snlua *l, int signal) { snlua_signal(struct snlua *l, int signal) {
skynet_error(l->ctx, "recv a signal %d", signal); skynet_error(l->ctx, "recv a signal %d", signal);
if (signal == 0) {
#ifdef lua_checksig #ifdef lua_checksig
// If our lua support signal (modified lua version by skynet), trigger it. // If our lua support signal (modified lua version by skynet), trigger it.
skynet_sig_L = l->L; skynet_sig_L = l->L;
#endif #endif
} else if (signal == 1) {
skynet_error(l->ctx, "Current Memory %.3fK", (float)l->mem / 1024);
}
} }

View File

@@ -4,15 +4,15 @@ require "skynet.manager" -- import skynet.launch, ...
local memory = require "memory" local memory = require "memory"
skynet.start(function() skynet.start(function()
local sharestring = tonumber(skynet.getenv "sharestring") local sharestring = tonumber(skynet.getenv "sharestring" or 4096)
memory.ssexpand(sharestring or 4096) memory.ssexpand(sharestring)
local standalone = skynet.getenv "standalone" local standalone = skynet.getenv "standalone"
local launcher = assert(skynet.launch("snlua","launcher")) local launcher = assert(skynet.launch("snlua","launcher"))
skynet.name(".launcher", launcher) skynet.name(".launcher", launcher)
local harbor_id = tonumber(skynet.getenv "harbor") local harbor_id = tonumber(skynet.getenv "harbor" or 0)
if harbor_id == 0 then if harbor_id == 0 then
assert(standalone == nil) assert(standalone == nil)
standalone = true standalone = true

View File

@@ -215,6 +215,7 @@ function harbor.QUERYNAME(fd, name)
end end
local queue = queryname[name] local queue = queryname[name]
if queue == nil then if queue == nil then
socket.write(fd, pack_package("Q", name))
queue = { skynet.response() } queue = { skynet.response() }
queryname[name] = queue queryname[name] = queue
else else

View File

@@ -52,13 +52,10 @@ end
local function docmd(cmdline, print, fd) local function docmd(cmdline, print, fd)
local split = split_cmdline(cmdline) local split = split_cmdline(cmdline)
local command = split[1] local command = split[1]
if command == "debug" then
table.insert(split, fd)
end
local cmd = COMMAND[command] local cmd = COMMAND[command]
local ok, list local ok, list
if cmd then if cmd then
ok, list = pcall(cmd, select(2,table.unpack(split))) ok, list = pcall(cmd, fd, select(2,table.unpack(split)))
else else
print("Invalid command, type help for command list") print("Invalid command, type help for command list")
end end
@@ -79,18 +76,21 @@ local function docmd(cmdline, print, fd)
end end
local function console_main_loop(stdin, print) local function console_main_loop(stdin, print)
socket.lock(stdin)
print("Welcome to skynet console") print("Welcome to skynet console")
while true do skynet.error(stdin, "connected")
local cmdline = socket.readline(stdin, "\n") pcall(function()
if not cmdline then while true do
break local cmdline = socket.readline(stdin, "\n")
if not cmdline then
break
end
if cmdline ~= "" then
docmd(cmdline, print, stdin)
end
end end
if cmdline ~= "" then end)
docmd(cmdline, print, stdin) skynet.error(stdin, "disconnected")
end socket.close(stdin)
end
socket.unlock(stdin)
end end
skynet.start(function() skynet.start(function()
@@ -140,25 +140,33 @@ function COMMAND.clearcache()
codecache.clear() codecache.clear()
end end
function COMMAND.start(...) function COMMAND.start(fd, ...)
local ok, addr = pcall(skynet.newservice, ...) local ok, addr = pcall(skynet.newservice, ...)
if ok then if ok then
return { [skynet.address(addr)] = ... } if addr then
return { [skynet.address(addr)] = ... }
else
return "Exit"
end
else else
return "Failed" return "Failed"
end end
end end
function COMMAND.log(...) function COMMAND.log(fd, ...)
local ok, addr = pcall(skynet.call, ".launcher", "lua", "LOGLAUNCH", "snlua", ...) local ok, addr = pcall(skynet.call, ".launcher", "lua", "LOGLAUNCH", "snlua", ...)
if ok then if ok then
return { [skynet.address(addr)] = ... } if addr then
return { [skynet.address(addr)] = ... }
else
return "Failed"
end
else else
return "Failed" return "Failed"
end end
end end
function COMMAND.snax(...) function COMMAND.snax(fd, ...)
local ok, s = pcall(snax.newservice, ...) local ok, s = pcall(snax.newservice, ...)
if ok then if ok then
local addr = s.handle local addr = s.handle
@@ -191,7 +199,7 @@ function COMMAND.mem()
return skynet.call(".launcher", "lua", "MEM") return skynet.call(".launcher", "lua", "MEM")
end end
function COMMAND.kill(address) function COMMAND.kill(fd, address)
return skynet.call(".launcher", "lua", "KILL", address) return skynet.call(".launcher", "lua", "KILL", address)
end end
@@ -199,11 +207,11 @@ function COMMAND.gc()
return skynet.call(".launcher", "lua", "GC") return skynet.call(".launcher", "lua", "GC")
end end
function COMMAND.exit(address) function COMMAND.exit(fd, address)
skynet.send(adjust_address(address), "debug", "EXIT") skynet.send(adjust_address(address), "debug", "EXIT")
end end
function COMMAND.inject(address, filename) function COMMAND.inject(fd, address, filename)
address = adjust_address(address) address = adjust_address(address)
local f = io.open(filename, "rb") local f = io.open(filename, "rb")
if not f then if not f then
@@ -214,17 +222,17 @@ function COMMAND.inject(address, filename)
return skynet.call(address, "debug", "RUN", source, filename) return skynet.call(address, "debug", "RUN", source, filename)
end end
function COMMAND.task(address) function COMMAND.task(fd, address)
address = adjust_address(address) address = adjust_address(address)
return skynet.call(address,"debug","TASK") return skynet.call(address,"debug","TASK")
end end
function COMMAND.info(address) function COMMAND.info(fd, address)
address = adjust_address(address) address = adjust_address(address)
return skynet.call(address,"debug","INFO") return skynet.call(address,"debug","INFO")
end end
function COMMAND.debug(address, fd) function COMMAND.debug(fd, address)
address = adjust_address(address) address = adjust_address(address)
local agent = skynet.newservice "debug_agent" local agent = skynet.newservice "debug_agent"
local stop local stop
@@ -243,17 +251,17 @@ function COMMAND.debug(address, fd)
stop = true stop = true
end end
function COMMAND.logon(address) function COMMAND.logon(fd, address)
address = adjust_address(address) address = adjust_address(address)
core.command("LOGON", skynet.address(address)) core.command("LOGON", skynet.address(address))
end end
function COMMAND.logoff(address) function COMMAND.logoff(fd, address)
address = adjust_address(address) address = adjust_address(address)
core.command("LOGOFF", skynet.address(address)) core.command("LOGOFF", skynet.address(address))
end end
function COMMAND.signal(address, sig) function COMMAND.signal(fd, address, sig)
address = skynet.address(adjust_address(address)) address = skynet.address(adjust_address(address))
if sig then if sig then
core.command("SIGNAL", string.format("%s %d",address,sig)) core.command("SIGNAL", string.format("%s %d",address,sig))

View File

@@ -24,7 +24,10 @@ end
function command.STAT() function command.STAT()
local list = {} local list = {}
for k,v in pairs(services) do for k,v in pairs(services) do
local stat = skynet.call(k,"debug","STAT") local ok, stat = pcall(skynet.call,k,"debug","STAT")
if not ok then
stat = string.format("ERROR (%s)",v)
end
list[skynet.address(k)] = stat list[skynet.address(k)] = stat
end end
return list return list
@@ -41,8 +44,12 @@ end
function command.MEM() function command.MEM()
local list = {} local list = {}
for k,v in pairs(services) do for k,v in pairs(services) do
local kb, bytes = skynet.call(k,"debug","MEM") local ok, kb, bytes = pcall(skynet.call,k,"debug","MEM")
list[skynet.address(k)] = string.format("%.2f Kb (%s)",kb,v) if not ok then
list[skynet.address(k)] = string.format("ERROR (%s)",v)
else
list[skynet.address(k)] = string.format("%.2f Kb (%s)",kb,v)
end
end end
return list return list
end end

View File

@@ -142,14 +142,23 @@ local function register_global()
end end
local function register_local() local function register_local()
function cmd.GLAUNCH(name, ...) local function waitfor_remote(cmd, name, ...)
local global_name = "@" .. name local global_name = "@" .. name
return waitfor(global_name, skynet.call, "SERVICE", "lua", "LAUNCH", global_name, ...) local local_name
if name == "snaxd" then
local_name = global_name .. "." .. (...)
else
local_name = global_name
end
return waitfor(local_name, skynet.call, "SERVICE", "lua", cmd, global_name, ...)
end end
function cmd.GQUERY(name, ...) function cmd.GLAUNCH(...)
local global_name = "@" .. name return waitfor_remote("LAUNCH", ...)
return waitfor(global_name, skynet.call, "SERVICE", "lua", "QUERY", global_name, ...) end
function cmd.GQUERY(...)
return waitfor_remote("QUERY", ...)
end end
function cmd.LIST() function cmd.LIST()

View File

@@ -38,7 +38,7 @@ local CMD = {}
local env_mt = { __index = _ENV } local env_mt = { __index = _ENV }
function CMD.new(name, t) function CMD.new(name, t, ...)
local dt = type(t) local dt = type(t)
local value local value
if dt == "table" then if dt == "table" then
@@ -51,7 +51,7 @@ function CMD.new(name, t)
else else
f = assert(load(t, "=" .. name, "bt", value)) f = assert(load(t, "=" .. name, "bt", value))
end end
local _, ret = assert(skynet.pcall(f)) local _, ret = assert(skynet.pcall(f, ...))
setmetatable(value, nil) setmetatable(value, nil)
if type(ret) == "table" then if type(ret) == "table" then
value = ret value = ret
@@ -90,7 +90,7 @@ function CMD.confirm(cobj)
return NORET return NORET
end end
function CMD.update(name, t) function CMD.update(name, t, ...)
local v = pool[name] local v = pool[name]
local watch, oldcobj local watch, oldcobj
if v then if v then
@@ -101,7 +101,7 @@ function CMD.update(name, t)
pool[name] = nil pool[name] = nil
pool_count[name] = nil pool_count[name] = nil
end end
CMD.new(name, t) CMD.new(name, t, ...)
local newobj = pool[name].obj local newobj = pool[name].obj
if watch then if watch then
sharedata.host.markdirty(oldcobj) sharedata.host.markdirty(oldcobj)

View File

@@ -227,7 +227,7 @@ skynet_strdup(const char *str) {
} }
void * void *
skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) { skynet_lalloc(void *ptr, size_t osize, size_t nsize) {
if (nsize == 0) { if (nsize == 0) {
raw_free(ptr); raw_free(ptr);
return NULL; return NULL;

View File

@@ -115,7 +115,7 @@ main(int argc, char *argv[]) {
struct skynet_config config; struct skynet_config config;
struct lua_State *L = lua_newstate(skynet_lalloc, NULL); struct lua_State *L = luaL_newstate();
luaL_openlibs(L); // link lua lib luaL_openlibs(L); // link lua lib
int err = luaL_loadstring(L, load_config); int err = luaL_loadstring(L, load_config);

View File

@@ -13,6 +13,6 @@ void * skynet_calloc(size_t nmemb,size_t size);
void * skynet_realloc(void *ptr, size_t size); void * skynet_realloc(void *ptr, size_t size);
void skynet_free(void *ptr); void skynet_free(void *ptr);
char * skynet_strdup(const char *str); char * skynet_strdup(const char *str);
void * skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize); // use for lua void * skynet_lalloc(void *ptr, size_t osize, size_t nsize); // use for lua
#endif #endif

17
test/testmemlimit.lua Normal file
View File

@@ -0,0 +1,17 @@
local skynet = require "skynet"
-- set sandbox memory limit to 1M, must set here (at start, out of skynet.start)
skynet.memlimit(1 * 1024 * 1024)
skynet.start(function()
local a = {}
local limit
local ok, err = pcall(function()
for i=1, 1000000 do
limit = i
table.insert(a, {})
end
end)
skynet.error(limit, err)
skynet.exit()
end)