// 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 NV_LUA_VERSION == NV_LUA_5C 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; #endif #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 # 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 #endif #endif #if NV_LUA_VERSION == NV_LUA_5C int LUA_UPVALUEINDEX = 0; int LUA_REGISTRYINDEX = 0; int LUA_VERSION_NUM = 0; # 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 #if defined( NV_LUA_DYNAMIC ) 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; } #else bool nv::load_lua_library( const char* path ) { 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; return true; } #endif