// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #include "nv/lib/lua.hh" #if defined( NV_LUA_DYNAMIC ) #include "nv/core/library.hh" #if NV_LUA_VERSION == NV_LUA_52 # undef luaL_loadfile # undef luaL_loadbuffer # undef luaL_prepbuffer # undef lua_tonumber # undef lua_tointeger # undef lua_tounsigned # undef lua_call # undef lua_pcall # undef lua_yield #endif #define NV_LUA_FUN( rtype, fname, fparams ) rtype (*fname) fparams = nullptr; #if NV_LUA_VERSION == NV_LUA_52 # define NV_LUA_FUN_51( rtype, fname, fparams ) # define NV_LUA_FUN_52 NV_LUA_FUN #elif NV_LUA_VERSION == NV_LUA_51 # define NV_LUA_FUN_51 NV_LUA_FUN # define NV_LUA_FUN_52( rtype, fname, fparams ) #else # define NV_LUA_FUN_51( rtype, fname, fparams ) # define NV_LUA_FUN_52( rtype, fname, fparams ) #endif #include #undef NV_LUA_FUN #undef NV_LUA_FUN_51 #undef NV_LUA_FUN_52 #if NV_LUA_VERSION == NV_LUA_5C # define NV_LUA_COMPAT_FUN( rt, fn, fp,u1,u2,u3,u4,u5 ) rt (*fn) fp = nullptr; # include # undef NV_LUA_COMPAT_FUN int LUA_UPVALUEINDEX = 0; int LUA_REGISTRYINDEX = 0; int LUA_VERSION_NUM = 0; size_t (*lua_rawlen) (lua_State *L, int idx) = nullptr; int (*lua_absindex) (lua_State *L, int idx) = nullptr; void (*lua_getglobal) (lua_State *L, const char *var) = nullptr; void (*lua_setglobal) (lua_State *L, const char *var) = nullptr; void (*luaL_requiref) (lua_State *L, const char *modname, lua_CFunction openf, int glb) = nullptr; void (*luaL_setmetatable) (lua_State *L, const char *tname) = nullptr; void* (*luaL_testudata) (lua_State *L, int ud, const char *tname) = nullptr; void (*lua_copy) (lua_State *L, int fromidx, int toidx) = nullptr; int (*lua_compare) (lua_State *L, int idx1, int idx2, int op) = nullptr; void (*lua_rawgetp) (lua_State *L, int idx, const void *p) = nullptr; void (*lua_rawsetp) (lua_State *L, int idx, const void *p) = nullptr; void (*lua_pushglobaltable)(lua_State* L) = nullptr; void (*luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup) = nullptr; int (*luaL_getsubtable) (lua_State *L, int idx, const char *fname) = nullptr; const lua_Number* (*lua_version) (lua_State *L) = nullptr; // only loaded in 5.1 mode to implement lua_compare static int (*lua_equal) (lua_State *L, int idx1, int idx2) = nullptr; static int (*lua_lessthan) (lua_State *L, int idx1, int idx2) = nullptr; # define NV_LUA_COMPAT_FUN( u1,u2,u3,rt2,fn2,fp2,u4,u5 ) static rt2 (*fn2##_compat) fp2 = nullptr; # include # undef NV_LUA_COMPAT_FUN # define NV_LUA_COMPAT_FUN( rt, fn, fp, rt2, fn2, fp2,arg,ret ) \ static rt call_##fn2##_compat fp { ret fn2##_compat arg; } # include # undef NV_LUA_COMPAT_FUN # define LUAI_MAXSTACK_52 1000000 # define LUAI_FIRSTPSEUDOIDX_52 (-LUAI_MAXSTACK_52 - 1000) # define LUA_REGISTRYINDEX_52 LUAI_FIRSTPSEUDOIDX_52 # define LUA_GLOBALSINDEX_51 (-10002) # define LUA_GLOBALSINDEX_52 2 # define LUA_REGISTRYINDEX_51 (-10000) static int lua_absindex_51 (lua_State *L, int idx) { return (idx > 0 ? idx : idx + lua_gettop(L) + 1); }; static void lua_getglobal_51 (lua_State *L, const char *var) { lua_getfield(L, LUA_GLOBALSINDEX_51, var ); }; static void lua_setglobal_51 (lua_State *L, const char *var) { lua_setfield(L, LUA_GLOBALSINDEX_51, var ); }; static void luaL_requiref_51 (lua_State *L, const char *modname, lua_CFunction openf, int glb) { lua_pushcfunction(L, openf); lua_pushstring(L, modname); lua_call(L, 1, 1); if (glb != 0) { lua_pushvalue( L, LUA_GLOBALSINDEX_51 ); lua_pushvalue(L, -2); lua_setfield(L, -2, modname); lua_pop(L, 1); } } static void luaL_setmetatable_51 (lua_State *L, const char *tname) { luaL_getmetatable(L, tname); lua_setmetatable(L, -2); } static void *luaL_testudata_51 (lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { if (lua_getmetatable(L, ud)) { luaL_getmetatable(L, tname); if ( !lua_rawequal(L, -1, -2)) p = NULL; lua_pop(L, 2); return p; } } return NULL; } static const lua_Number *lua_version_51 (lua_State*) { static const lua_Number version = lua_Number( LUA_VERSION_NUM ); return &version; } static void lua_copy_51 (lua_State *L, int fromidx, int toidx) { toidx = lua_absindex( L, toidx ); lua_pushvalue( L, fromidx ); lua_replace( L, toidx ); } static int lua_compare_51(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, idx1, idx2 ) || lua_equal( L, idx1, idx2 ); default: return 0; } } static void lua_rawgetp_51(lua_State *L, int idx, const void *p) { idx = lua_absindex( L, idx ); void* pp = const_cast(p); // EVIL lua_pushlightuserdata( L, pp ); lua_rawget( L, idx ); } static void lua_rawsetp_51(lua_State *L, int idx, const void *p) { idx = lua_absindex( L, idx ); void* pp = const_cast(p); // EVIL lua_pushlightuserdata( L, pp ); lua_insert( L, -1 ); lua_rawset( L, idx ); } static int luaL_getsubtable_51(lua_State *L, int idx, const char *fname) { lua_getfield(L, idx, fname); if ( lua_istable(L, -1) ) return 1; else { idx = lua_absindex(L, idx); lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); lua_setfield(L, idx, fname); return 0; } } static void luaL_setfuncs_51(lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup, "too many upvalues"); for (; l->name != NULL; l++) { for (int i = 0; i < nup; i++) { lua_pushvalue(L, -nup); } lua_pushcclosure(L, l->func, nup); lua_setfield(L, -(nup + 2), l->name); } lua_pop(L, nup); } static void lua_pushglobaltable_51(lua_State* L) { lua_pushvalue( L, LUA_GLOBALSINDEX_51 ); } static void lua_pushglobaltable_52(lua_State* L) { lua_rawgeti( L, LUA_REGISTRYINDEX_52, LUA_GLOBALSINDEX_52 ); } #endif bool nv::load_lua_library( const char* path ) { static nv::library lua_library; if ( lua_library.is_open() ) return true; #if NV_LUA_VERSION == NV_LUA_5C if ( path == nullptr ) { if (!lua_library.try_open( NV_LUA_PATH_JIT ) && !lua_library.try_open( NV_LUA_PATH_52 ) ) { lua_library.open( NV_LUA_PATH_51 ); } } else #else lua_library.open( path ); #endif # define NV_LUA_FUN( rtype, fname, fparams ) void_assign( fname, lua_library.get(#fname) ); # if NV_LUA_VERSION == NV_LUA_52 # define NV_LUA_FUN_51( rtype, fname, fparams ) # define NV_LUA_FUN_52 NV_LUA_FUN # elif NV_LUA_VERSION == NV_LUA_51 # define NV_LUA_FUN_51 NV_LUA_FUN # define NV_LUA_FUN_52( rtype, fname, fparams ) # else # define NV_LUA_FUN_51( rtype, fname, fparams ) # define NV_LUA_FUN_52( rtype, fname, fparams ) # endif # include # undef NV_LUA_FUN # undef NV_LUA_FUN_51 # undef NV_LUA_FUN_52 #if NV_LUA_VERSION == NV_LUA_5C # define NV_LUA_LOAD( fname ) void_assign( fname, lua_library.get(#fname) ); # define NV_LUA_LOAD_AS( fname,fname2 ) void_assign( fname, lua_library.get(#fname2) ); bool version_52 = lua_library.try_get("luaL_checkversion_") != nullptr; if (version_52) { # define NV_LUA_COMPAT_FUN( u1, fn, u2, u3, fn2, u5, u6, u7 ) \ void_assign( fn2##_compat, lua_library.get(#fn2) ); \ fn = call_##fn2##_compat; # include # undef NV_LUA_COMPAT_FUN NV_LUA_LOAD( lua_rawlen ); NV_LUA_LOAD( lua_absindex ); NV_LUA_LOAD( lua_getglobal ); NV_LUA_LOAD( lua_setglobal ); NV_LUA_LOAD( luaL_setmetatable ); NV_LUA_LOAD( luaL_testudata ); NV_LUA_LOAD( lua_version ); NV_LUA_LOAD( lua_copy ); NV_LUA_LOAD( lua_compare ); NV_LUA_LOAD( lua_rawgetp ); NV_LUA_LOAD( lua_rawsetp ); NV_LUA_LOAD( luaL_setfuncs ); NV_LUA_LOAD( luaL_getsubtable ); NV_LUA_LOAD( luaL_requiref ); lua_pushglobaltable = lua_pushglobaltable_52; LUA_UPVALUEINDEX = LUA_REGISTRYINDEX_52; LUA_REGISTRYINDEX = LUA_REGISTRYINDEX_52; LUA_VERSION_NUM = 502; } else { # define NV_LUA_COMPAT_FUN( u1, fn, u2, u3, u4, u5, u6, u7 ) \ void_assign(fn, lua_library.get(#fn) ); # include # undef NV_LUA_COMPAT_FUN NV_LUA_LOAD_AS( lua_rawlen, lua_objlen ) lua_absindex = lua_absindex_51; lua_getglobal = lua_getglobal_51; lua_setglobal = lua_setglobal_51; luaL_setmetatable = luaL_setmetatable_51; luaL_testudata = luaL_testudata_51; lua_version = lua_version_51; lua_copy = lua_copy_51; lua_rawgetp = lua_rawgetp_51; lua_rawsetp = lua_rawsetp_51; lua_pushglobaltable = lua_pushglobaltable_51; luaL_setfuncs = luaL_setfuncs_51; luaL_getsubtable = luaL_getsubtable_51; luaL_requiref = luaL_requiref_51; NV_LUA_LOAD( lua_lessthan ); NV_LUA_LOAD( lua_equal ); lua_compare = lua_compare_51; LUA_UPVALUEINDEX = LUA_GLOBALSINDEX_51; LUA_REGISTRYINDEX = LUA_REGISTRYINDEX_51; LUA_VERSION_NUM = 501; } # undef NV_LUA_LOAD #endif return true; } #endif