diff --git a/Makefile b/Makefile index 45b4254c..d67e9852 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ .PHONY : all clean -CFLAGS = -g -Wall +CFLAGS = -g -Wall SHARED = -fPIC --shared +LUALIB = -llua all : \ skynet \ @@ -31,8 +32,9 @@ skynet : \ skynet-src/skynet_harbor.c \ skynet-src/skynet_multicast.c \ skynet-src/skynet_group.c \ - skynet-src/skynet_env.c - gcc $(CFLAGS) -Wl,-E -o $@ $^ -Iskynet-src -lpthread -ldl -lrt -Wl,-E -llua -lm + skynet-src/skynet_env.c \ + luacompat/compat52.c + gcc $(CFLAGS) -Iluacompat -Wl,-E -o $@ $^ -Iskynet-src -lpthread -ldl -lrt -Wl,-E $(LUALIB) -lm luaclib: mkdir luaclib @@ -53,13 +55,13 @@ service/logger.so : skynet-src/skynet_logger.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src service/snlua.so : service-src/service_lua.c - gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src + gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src service/gate.so : gate/mread.c gate/ringbuffer.c gate/main.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Igate -Iskynet-src luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/lua-remoteobj.c | luaclib - gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src + gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src service/client.so : service-src/service_client.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src @@ -68,10 +70,10 @@ service/connection.so : connection/connection.c connection/main.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iconnection luaclib/socket.so : connection/lua-socket.c | luaclib - gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iconnection + gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iconnection luaclib/int64.so : lua-int64/int64.c | luaclib - gcc $(CFLAGS) $(SHARED) -O2 $^ -o $@ + gcc $(CFLAGS) $(SHARED) -Iluacompat -O2 $^ -o $@ client : client-src/client.c gcc $(CFLAGS) $^ -o $@ -lpthread diff --git a/connection/lua-socket.c b/connection/lua-socket.c index 1b8895cc..bdad5f61 100644 --- a/connection/lua-socket.c +++ b/connection/lua-socket.c @@ -1,5 +1,7 @@ #include "skynet.h" +#include "luacompat52.h" + #include #include #include diff --git a/lua-int64/int64.c b/lua-int64/int64.c index 6d72c1bc..e1a07e15 100644 --- a/lua-int64/int64.c +++ b/lua-int64/int64.c @@ -1,3 +1,4 @@ +#include "luacompat52.h" #include #include #include @@ -198,7 +199,7 @@ tostring(lua_State *L) { uintptr_t n = (uintptr_t)lua_touserdata(L,1); if (lua_gettop(L) == 1) { luaL_Buffer b; - luaL_buffinitsize(L , &b , 28); + luaL_buffinit(L , &b); luaL_addstring(&b, "int64: 0x"); int i; bool strip = true; @@ -230,7 +231,7 @@ tostring(lua_State *L) { case 10: { int64_t dec = (int64_t)n; luaL_Buffer b; - luaL_buffinitsize(L , &b , 28); + luaL_buffinit(L , &b); if (dec<0) { luaL_addchar(&b, '-'); dec = -dec; diff --git a/luacompat/compat52.c b/luacompat/compat52.c new file mode 100644 index 00000000..d59d247c --- /dev/null +++ b/luacompat/compat52.c @@ -0,0 +1,371 @@ +#include "luacompat52.h" +#include + +#if (LUA_VERSION_NUM == 501) + +LUALIB_API void +luaL_init(lua_State *L) { + lua_pushglobaltable(L); + lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); + int mt = lua_pushthread(L); + if (mt == 0) { + luaL_error(L, "luaL_init must be call in mainthread"); + } + lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); +} + +LUA_API int +lua_absindex(lua_State *L, int idx) { + if (idx > 0 || idx <= LUA_REGISTRYINDEX) + return idx; + else { + return lua_gettop(L) + idx + 1; + } +} + +LUA_API int +lua_compare(lua_State *L, int idx1, int idx2, int op) { + switch(op) { + case LUA_OPEQ: + return lua_equal(L,idx1,idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + return !lua_lessthan(L, idx2, idx1); + } + assert(0); + return 0; +} + +LUA_API void +lua_copy(lua_State *L, int fromidx, int toidx) { + lua_pushvalue(L, fromidx); + lua_replace(L, toidx); +} + +LUA_API void +lua_getuservalue(lua_State *L, int idx) { + lua_getfenv(L, idx); +} + +LUA_API void +lua_setuservalue(lua_State *L, int idx) { + lua_setfenv(L, idx); +} + +LUA_API void +lua_len(lua_State *L, int idx) { + int hasmeta = luaL_callmeta (L, idx, "__len"); + if (hasmeta == 0) { + size_t sz = lua_objlen(L, idx); + lua_pushnumber(L, sz); + } +} + +LUA_API void +lua_rawgetp(lua_State *L, int idx, const void *p) { + idx = lua_absindex(L, idx); + lua_pushlightuserdata(L, (void *)p); + lua_rawget(L, idx); +} + +LUA_API void +lua_rawsetp(lua_State *L, int idx, const void *p) { + idx = lua_absindex(L, idx); + lua_pushlightuserdata(L, (void *)p); + lua_insert(L, -2); + lua_rawset(L, idx); +} + +LUA_API lua_Number +lua_tonumberx(lua_State *L, int index, int *isnum) { + lua_Number n = lua_tonumber(L, index); + if (isnum) { + if (n != 0) { + *isnum = 1; + } else { + switch (lua_type(L, index)) { + case LUA_TNUMBER: + *isnum = 1; + break; + case LUA_TSTRING: { + size_t sz = 0; + const char * number = lua_tolstring(L, index, &sz); + if ((sz == 1 && number[0] == '0') || + (sz == 3 && number[0] == '0' && (number[1] == 'x' || number[1] == 'X') && number[2] == '0')) { + *isnum = 1; + } else { + *isnum = 0; + } + break; + } + default: + *isnum = 0; + break; + } + } + } + return n; +} + +LUA_API lua_Unsigned +lua_tounsignedx(lua_State *L, int idx, int *isnum) { + lua_Number n = lua_tonumberx(L, idx, isnum); + return (lua_Unsigned)n; +} + +LUA_API lua_Integer +lua_tointegerx(lua_State *L, int idx, int *isnum) { + lua_Number n = lua_tonumberx(L, idx, isnum); + return (lua_Integer)n; +} + +LUA_API const lua_Number * +lua_version(lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + return &version; +} + +LUALIB_API void +luaL_checkversion_ (lua_State *L, lua_Number ver) { + const lua_Number *v = lua_version(L); + if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + +LUALIB_API int +luaL_len (lua_State *L, int idx) { + int l; + int isnum; + lua_len(L, idx); + l = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not a number"); + lua_pop(L, 1); /* remove object */ + return l; +} + +LUALIB_API int +luaL_getsubtable (lua_State *L, int idx, const char *fname) { + lua_getfield(L, idx, fname); + if (lua_istable(L, -1)) return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + +LUALIB_API lua_Unsigned +luaL_checkunsigned (lua_State *L, int narg) { + int isnum; + lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); + if (!isnum) { + return luaL_error(L, "arg %d is not a unsigned", narg); + } + return d; +} + +LUALIB_API lua_Unsigned +luaL_optunsigned (lua_State *L, int narg, lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, narg, def); +} + +LUALIB_API void +luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + +LUALIB_API void +luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* open module */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_pushvalue(L, -2); /* make copy of module (call result) */ + lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ + lua_pop(L, 1); /* remove _LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of 'mod' */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + +LUALIB_API void +luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkversion(L); + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + +LUALIB_API void +luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +LUALIB_API const char * +luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ + switch (lua_type(L, idx)) { + case LUA_TNUMBER: + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushglobaltable(L); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushfstring(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + + +static int countlevels (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ + +#else + +LUALIB_API void +luaL_init(lua_State *L) { +} + +#endif diff --git a/luacompat/luacompat52.h b/luacompat/luacompat52.h new file mode 100644 index 00000000..9bc9b4ff --- /dev/null +++ b/luacompat/luacompat52.h @@ -0,0 +1,88 @@ +#ifndef LUA_COMPAT_52_H +#define LUA_COMPAT_52_H + +#include "lua.h" +#include "lauxlib.h" + +LUALIB_API void (luaL_init)(lua_State *L); + +#if (LUA_VERSION_NUM == 501) + +#include + +#define LUA_OK 0 +#define LUA_ERRGCMM 6 + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + +#define LUA_UNSIGNED unsigned int +typedef LUA_UNSIGNED lua_Unsigned; + +LUA_API int (lua_absindex) (lua_State *L, int idx); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); + +LUA_API void (lua_getuservalue) (lua_State *L, int idx); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + +LUA_API void (lua_len) (lua_State *L, int idx); + +#define lua_rawlen(L,idx) lua_objlen(L,idx) + +LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); + +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) +LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); + +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int index, int *isnum); + +LUA_API const lua_Number *(lua_version) (lua_State *L); + +#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) + +LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); +LUALIB_API int (luaL_len) (lua_State *L, int idx); + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, + lua_Unsigned def); + +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); + +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +#endif + +#endif diff --git a/lualib-src/lua-remoteobj.c b/lualib-src/lua-remoteobj.c index 5a551173..21610734 100644 --- a/lualib-src/lua-remoteobj.c +++ b/lualib-src/lua-remoteobj.c @@ -1,5 +1,6 @@ #include #include +#include "luacompat52.h" #include #include diff --git a/lualib-src/lua-seri.c b/lualib-src/lua-seri.c index 86924ba8..236d7930 100644 --- a/lualib-src/lua-seri.c +++ b/lualib-src/lua-seri.c @@ -2,6 +2,7 @@ https://github.com/cloudwu/lua-serialize */ +#include "luacompat52.h" #include #include #include diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c index 61e3b5c6..6c42c98f 100644 --- a/lualib-src/lua-skynet.c +++ b/lualib-src/lua-skynet.c @@ -1,6 +1,8 @@ #include "skynet.h" #include "lua-seri.h" +#include "luacompat52.h" + #include #include #include diff --git a/service-src/service_lua.c b/service-src/service_lua.c index e3b3f8de..000a08d3 100644 --- a/service-src/service_lua.c +++ b/service-src/service_lua.c @@ -3,6 +3,7 @@ #include #include #include +#include "luacompat52.h" #include #include @@ -90,6 +91,7 @@ traceback (lua_State *L) { int snlua_init(lua_State *L, struct skynet_context *ctx, const char * args) { + luaL_init(L); lua_gc(L, LUA_GCSTOP, 0); luaL_openlibs(L); lua_pushlightuserdata(L, ctx); diff --git a/skynet-src/skynet_main.c b/skynet-src/skynet_main.c index 294bca3f..37272de1 100644 --- a/skynet-src/skynet_main.c +++ b/skynet-src/skynet_main.c @@ -1,5 +1,6 @@ #include "skynet_imp.h" #include "skynet_env.h" +#include "luacompat52.h" #include #include @@ -45,7 +46,7 @@ optstring(const char *key,const char * opt) { static void _init_env(lua_State *L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); + lua_pushglobaltable(L); lua_pushnil(L); /* first key */ while (lua_next(L, -2) != 0) { int keyt = lua_type(L, -2); @@ -85,6 +86,7 @@ main(int argc, char *argv[]) { lua_close(L); L = luaL_newstate(); + luaL_init(L); int err = luaL_dofile(L, config_file); if (err) {