source: trunk/src/lib/lua.cc @ 489

Last change on this file since 489 was 489, checked in by epyon, 9 years ago
File size: 10.4 KB
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[5]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[5]6
7#include "nv/lib/lua.hh"
8
[489]9#if NV_LUA_VERSION == NV_LUA_5C
10size_t( *lua_rawlen )        ( lua_State *L, int idx ) = nullptr;
11int( *lua_absindex )      ( lua_State *L, int idx ) = nullptr;
12void( *lua_getglobal )     ( lua_State *L, const char *var ) = nullptr;
13void( *lua_setglobal )     ( lua_State *L, const char *var ) = nullptr;
14void( *luaL_requiref )     ( lua_State *L, const char *modname, lua_CFunction openf, int glb ) = nullptr;
15void( *luaL_setmetatable ) ( lua_State *L, const char *tname ) = nullptr;
16void*  ( *luaL_testudata )    ( lua_State *L, int ud, const char *tname ) = nullptr;
17void( *lua_copy )          ( lua_State *L, int fromidx, int toidx ) = nullptr;
18int( *lua_compare )       ( lua_State *L, int idx1, int idx2, int op ) = nullptr;
19void( *lua_rawgetp )       ( lua_State *L, int idx, const void *p ) = nullptr;
20void( *lua_rawsetp )       ( lua_State *L, int idx, const void *p ) = nullptr;
21void( *lua_pushglobaltable )( lua_State* L ) = nullptr;
22void( *luaL_setfuncs )     ( lua_State *L, const luaL_Reg *l, int nup ) = nullptr;
23int( *luaL_getsubtable )  ( lua_State *L, int idx, const char *fname ) = nullptr;
24
25const lua_Number* ( *lua_version ) ( lua_State *L ) = nullptr;
26
27// only loaded in 5.1 mode to implement lua_compare
28static int( *lua_equal )        ( lua_State *L, int idx1, int idx2 ) = nullptr;
29static int( *lua_lessthan )     ( lua_State *L, int idx1, int idx2 ) = nullptr;
30#endif
31
32
[5]33#if defined( NV_LUA_DYNAMIC )
34
[319]35#include "nv/core/library.hh"
[5]36
[164]37#if NV_LUA_VERSION == NV_LUA_52
38#       undef luaL_loadfile
39#       undef luaL_loadbuffer
40#       undef luaL_prepbuffer
41#       undef lua_tonumber
42#       undef lua_tointeger
43#       undef lua_tounsigned
44#       undef lua_call
45#       undef lua_pcall
46#       undef lua_yield
47#endif
[5]48
[164]49#define NV_LUA_FUN( rtype, fname, fparams ) rtype (*fname) fparams = nullptr;
50#if NV_LUA_VERSION == NV_LUA_52
51#       define NV_LUA_FUN_51( rtype, fname, fparams )
52#       define NV_LUA_FUN_52 NV_LUA_FUN
[165]53#elif NV_LUA_VERSION == NV_LUA_51
54#       define NV_LUA_FUN_51 NV_LUA_FUN
55#       define NV_LUA_FUN_52( rtype, fname, fparams )
[164]56#else
[165]57#       define NV_LUA_FUN_51( rtype, fname, fparams )
58#       define NV_LUA_FUN_52( rtype, fname, fparams )
[164]59#endif
[5]60
[164]61#include <nv/lib/detail/lua_functions.inc>
[5]62
[164]63#undef NV_LUA_FUN
64#undef NV_LUA_FUN_51
65#undef NV_LUA_FUN_52
[5]66
[166]67#if NV_LUA_VERSION == NV_LUA_5C
68#       define NV_LUA_COMPAT_FUN( rt, fn, fp,u1,u2,u3,u4,u5 ) rt (*fn) fp = nullptr;
69#       include <nv/lib/detail/lua_functions_compat.inc>
70#       undef NV_LUA_COMPAT_FUN
71
72#       define NV_LUA_COMPAT_FUN( u1,u2,u3,rt2,fn2,fp2,u4,u5 ) static rt2 (*fn2##_compat) fp2 = nullptr;
73#       include <nv/lib/detail/lua_functions_compat.inc>
74#       undef NV_LUA_COMPAT_FUN
75
76#       define NV_LUA_COMPAT_FUN( rt, fn, fp, rt2, fn2, fp2,arg,ret ) \
[198]77                static rt call_##fn2##_compat fp { ret fn2##_compat arg; }
[166]78#       include <nv/lib/detail/lua_functions_compat.inc>
79#       undef NV_LUA_COMPAT_FUN
80
[489]81#endif
82
83#endif
84
85#if NV_LUA_VERSION == NV_LUA_5C
86int LUA_UPVALUEINDEX = 0;
87int LUA_REGISTRYINDEX = 0;
88int LUA_VERSION_NUM = 0;
[166]89#       define LUAI_MAXSTACK_52             1000000
90#       define LUAI_FIRSTPSEUDOIDX_52   (-LUAI_MAXSTACK_52 - 1000)
91#       define LUA_REGISTRYINDEX_52         LUAI_FIRSTPSEUDOIDX_52
92#       define LUA_GLOBALSINDEX_51      (-10002)
[173]93#       define LUA_GLOBALSINDEX_52      2
[166]94#       define LUA_REGISTRYINDEX_51     (-10000)
95
[489]96static int lua_absindex_51( lua_State *L, int idx )
[166]97{
[489]98        return ( idx > 0 ? idx : idx + lua_gettop( L ) + 1 );
99};
100
101static void lua_getglobal_51( lua_State *L, const char *var )
102{
103        lua_getfield( L, LUA_GLOBALSINDEX_51, var );
104};
105
106static void lua_setglobal_51( lua_State *L, const char *var )
107{
108        lua_setfield( L, LUA_GLOBALSINDEX_51, var );
109};
110
111static void luaL_requiref_51( lua_State *L, const char *modname, lua_CFunction openf, int glb )
112{
113        lua_pushcfunction( L, openf );
114        lua_pushstring( L, modname );
115        lua_call( L, 1, 1 );
116        if ( glb != 0 )
[166]117        {
118                lua_pushvalue( L, LUA_GLOBALSINDEX_51 );
[489]119                lua_pushvalue( L, -2 );
120                lua_setfield( L, -2, modname );
121                lua_pop( L, 1 );
[166]122        }
123}
124
[489]125static void luaL_setmetatable_51( lua_State *L, const char *tname )
[166]126{
[489]127        luaL_getmetatable( L, tname );
128        lua_setmetatable( L, -2 );
[166]129}
130
[489]131static void *luaL_testudata_51( lua_State *L, int ud, const char *tname )
[166]132{
[489]133        void *p = lua_touserdata( L, ud );
134        if ( p != NULL )
135        {
136                if ( lua_getmetatable( L, ud ) )
[166]137                {
[489]138                        luaL_getmetatable( L, tname );
139                        if ( !lua_rawequal( L, -1, -2 ) )
140                                p = NULL;
141                        lua_pop( L, 2 );
[166]142                        return p;
143                }
144        }
145        return NULL;
146}
147
[489]148static const lua_Number *lua_version_51( lua_State* )
[166]149{
[406]150        static const lua_Number version = lua_Number( LUA_VERSION_NUM );
[166]151        return &version;
152}
153
[489]154static void lua_copy_51( lua_State *L, int fromidx, int toidx )
[166]155{
156        toidx = lua_absindex( L, toidx );
157        lua_pushvalue( L, fromidx );
158        lua_replace( L, toidx );
159}
160
[489]161static int lua_compare_51( lua_State *L, int idx1, int idx2, int op )
[166]162{
[489]163        switch ( op )
[166]164        {
[489]165        case LUA_OPEQ: return lua_equal( L, idx1, idx2 );
166        case LUA_OPLT: return lua_lessthan( L, idx1, idx2 );
167        case LUA_OPLE: return lua_lessthan( L, idx1, idx2 ) || lua_equal( L, idx1, idx2 );
[172]168        default:
[166]169                return 0;
170        }
171}
172
[489]173static void lua_rawgetp_51( lua_State *L, int idx, const void *p )
[166]174{
175        idx = lua_absindex( L, idx );
[489]176        void* pp = const_cast<void *>( p ); // EVIL
[166]177        lua_pushlightuserdata( L, pp );
178        lua_rawget( L, idx );
179}
180
[489]181static void lua_rawsetp_51( lua_State *L, int idx, const void *p )
[166]182{
183        idx = lua_absindex( L, idx );
[489]184        void* pp = const_cast<void *>( p ); // EVIL
[166]185        lua_pushlightuserdata( L, pp );
186        lua_insert( L, -1 );
187        lua_rawset( L, idx );
188}
189
[489]190static int luaL_getsubtable_51( lua_State *L, int idx, const char *fname )
[166]191{
[489]192        lua_getfield( L, idx, fname );
193        if ( lua_istable( L, -1 ) ) return 1;
194        else
195        {
196                idx = lua_absindex( L, idx );
197                lua_pop( L, 1 );
198                lua_newtable( L );
199                lua_pushvalue( L, -1 );
200                lua_setfield( L, idx, fname );
201                return 0;
[166]202        }
203}
204
[489]205static void luaL_setfuncs_51( lua_State *L, const luaL_Reg *l, int nup )
[166]206{
[489]207        luaL_checkstack( L, nup, "too many upvalues" );
208        for ( ; l->name != NULL; l++ )
[166]209        {
[489]210                for ( int i = 0; i < nup; i++ )
[166]211                {
[489]212                        lua_pushvalue( L, -nup );
[166]213                }
[489]214                lua_pushcclosure( L, l->func, nup );
215                lua_setfield( L, -( nup + 2 ), l->name );
[166]216        }
[489]217        lua_pop( L, nup );
[166]218}
219
[489]220static void lua_pushglobaltable_51( lua_State* L )
[166]221{
222        lua_pushvalue( L, LUA_GLOBALSINDEX_51 );
223}
224
[489]225static void lua_pushglobaltable_52( lua_State* L )
[173]226{
227        lua_rawgeti( L, LUA_REGISTRYINDEX_52, LUA_GLOBALSINDEX_52 );
228}
229
[489]230
[166]231#endif
232
[489]233#if defined( NV_LUA_DYNAMIC )
234
[5]235bool nv::load_lua_library( const char* path )
236{
[109]237        static nv::library lua_library;
238        if ( lua_library.is_open() ) return true;
[166]239#if NV_LUA_VERSION == NV_LUA_5C
240        if ( path == nullptr )
241        {
242                if (!lua_library.try_open( NV_LUA_PATH_JIT ) &&
243                        !lua_library.try_open( NV_LUA_PATH_52 ) )
244                {
245                        lua_library.open( NV_LUA_PATH_51 );
246                }
247        }
248        else
249#else
250                lua_library.open( path );
251#endif
[5]252
[406]253#       define NV_LUA_FUN( rtype, fname, fparams ) void_assign( fname, lua_library.get(#fname) );
[164]254#       if NV_LUA_VERSION == NV_LUA_52
255#               define NV_LUA_FUN_51( rtype, fname, fparams )
256#               define NV_LUA_FUN_52 NV_LUA_FUN
[165]257#       elif NV_LUA_VERSION == NV_LUA_51
[164]258#               define NV_LUA_FUN_51 NV_LUA_FUN
259#               define NV_LUA_FUN_52( rtype, fname, fparams )
[165]260#       else
261#               define NV_LUA_FUN_51( rtype, fname, fparams )
262#               define NV_LUA_FUN_52( rtype, fname, fparams )
[164]263#       endif
[109]264
[165]265#       include <nv/lib/detail/lua_functions.inc>
[5]266
[165]267#       undef NV_LUA_FUN
268#       undef NV_LUA_FUN_51
269#       undef NV_LUA_FUN_52
[166]270
271#if NV_LUA_VERSION == NV_LUA_5C
[406]272#       define NV_LUA_LOAD( fname ) void_assign( fname, lua_library.get(#fname) );
273#       define NV_LUA_LOAD_AS( fname,fname2 ) void_assign( fname, lua_library.get(#fname2) );
[166]274        bool version_52 = lua_library.try_get("luaL_checkversion_") != nullptr;
275        if (version_52)
276        {
277#       define NV_LUA_COMPAT_FUN( u1, fn, u2, u3, fn2, u5, u6, u7 ) \
[406]278        void_assign( fn2##_compat, lua_library.get(#fn2) ); \
[166]279        fn = call_##fn2##_compat;
280#       include <nv/lib/detail/lua_functions_compat.inc>
281#       undef NV_LUA_COMPAT_FUN
282                NV_LUA_LOAD( lua_rawlen );
283                NV_LUA_LOAD( lua_absindex );
284                NV_LUA_LOAD( lua_getglobal );
285                NV_LUA_LOAD( lua_setglobal );
286                NV_LUA_LOAD( luaL_setmetatable );
287                NV_LUA_LOAD( luaL_testudata );
288                NV_LUA_LOAD( lua_version );
289                NV_LUA_LOAD( lua_copy );
290                NV_LUA_LOAD( lua_compare );
291                NV_LUA_LOAD( lua_rawgetp );
292                NV_LUA_LOAD( lua_rawsetp );
293                NV_LUA_LOAD( luaL_setfuncs );
294                NV_LUA_LOAD( luaL_getsubtable );
[173]295                NV_LUA_LOAD( luaL_requiref );
[166]296
[173]297                lua_pushglobaltable = lua_pushglobaltable_52;
298
[172]299                LUA_UPVALUEINDEX  = LUA_REGISTRYINDEX_52;
[166]300                LUA_REGISTRYINDEX = LUA_REGISTRYINDEX_52;
301                LUA_VERSION_NUM   = 502;
302        }
303        else
304        {
305#       define NV_LUA_COMPAT_FUN( u1, fn, u2, u3, u4, u5, u6, u7 ) \
[406]306                void_assign(fn, lua_library.get(#fn) );
[166]307#       include <nv/lib/detail/lua_functions_compat.inc>
308#       undef NV_LUA_COMPAT_FUN
309                NV_LUA_LOAD_AS( lua_rawlen, lua_objlen )
310                lua_absindex        = lua_absindex_51;
311                lua_getglobal       = lua_getglobal_51;
312                lua_setglobal       = lua_setglobal_51;
313                luaL_setmetatable   = luaL_setmetatable_51;
314                luaL_testudata      = luaL_testudata_51;
315                lua_version         = lua_version_51;
316                lua_copy            = lua_copy_51;
317                lua_rawgetp         = lua_rawgetp_51;
318                lua_rawsetp         = lua_rawsetp_51;
319                lua_pushglobaltable = lua_pushglobaltable_51;
320                luaL_setfuncs       = luaL_setfuncs_51;
321                luaL_getsubtable    = luaL_getsubtable_51;
[173]322                luaL_requiref       = luaL_requiref_51;
[166]323
324                NV_LUA_LOAD( lua_lessthan );
325                NV_LUA_LOAD( lua_equal );
326                lua_compare       = lua_compare_51;
[172]327                LUA_UPVALUEINDEX  = LUA_GLOBALSINDEX_51;
[166]328                LUA_REGISTRYINDEX = LUA_REGISTRYINDEX_51;
329                LUA_VERSION_NUM   = 501;
330        }
331#       undef NV_LUA_LOAD
332#endif
333
[5]334        return true;
335}
336
[489]337#else
338
339bool nv::load_lua_library( const char* path )
340{
341        lua_rawlen = lua_objlen;
342        lua_absindex = lua_absindex_51;
343        lua_getglobal = lua_getglobal_51;
344        lua_setglobal = lua_setglobal_51;
345        luaL_setmetatable = luaL_setmetatable_51;
346        luaL_testudata = luaL_testudata_51;
347        lua_version = lua_version_51;
348        lua_copy = lua_copy_51;
349        lua_rawgetp = lua_rawgetp_51;
350        lua_rawsetp = lua_rawsetp_51;
351        lua_pushglobaltable = lua_pushglobaltable_51;
352        luaL_setfuncs = luaL_setfuncs_51;
353        luaL_getsubtable = luaL_getsubtable_51;
354        luaL_requiref = luaL_requiref_51;
355
356        NV_LUA_LOAD( lua_lessthan );
357        NV_LUA_LOAD( lua_equal );
358        lua_compare = lua_compare_51;
359        LUA_UPVALUEINDEX = LUA_GLOBALSINDEX_51;
360        LUA_REGISTRYINDEX = LUA_REGISTRYINDEX_51;
361        LUA_VERSION_NUM = 501;
362        return true;
363}
364
[5]365#endif
Note: See TracBrowser for help on using the repository browser.