diff options
Diffstat (limited to 'src/state.c')
-rw-r--r-- | src/state.c | 554 |
1 files changed, 277 insertions, 277 deletions
diff --git a/src/state.c b/src/state.c index 81371b7..9075c02 100644 --- a/src/state.c +++ b/src/state.c | |||
@@ -59,32 +59,32 @@ THE SOFTWARE. | |||
59 | // | 59 | // |
60 | static int luaG_new_require( lua_State* L) | 60 | static int luaG_new_require( lua_State* L) |
61 | { | 61 | { |
62 | int rc; | 62 | int rc; |
63 | int const args = lua_gettop( L); // args | 63 | int const args = lua_gettop( L); // args |
64 | Universe* U = universe_get( L); | 64 | Universe* U = universe_get( L); |
65 | //char const* modname = luaL_checkstring( L, 1); | 65 | //char const* modname = luaL_checkstring( L, 1); |
66 | 66 | ||
67 | STACK_GROW( L, 1); | 67 | STACK_GROW( L, 1); |
68 | 68 | ||
69 | lua_pushvalue( L, lua_upvalueindex( 1)); // args require | 69 | lua_pushvalue( L, lua_upvalueindex( 1)); // args require |
70 | lua_insert( L, 1); // require args | 70 | lua_insert( L, 1); // require args |
71 | 71 | ||
72 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would | 72 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would |
73 | // leave us locked, blocking any future 'require' calls from other lanes. | 73 | // leave us locked, blocking any future 'require' calls from other lanes. |
74 | 74 | ||
75 | MUTEX_LOCK( &U->require_cs); | 75 | MUTEX_LOCK( &U->require_cs); |
76 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET | 76 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET |
77 | rc = lua_pcall( L, args, LUA_MULTRET, 0 /*errfunc*/ ); // err|result(s) | 77 | rc = lua_pcall( L, args, LUA_MULTRET, 0 /*errfunc*/ ); // err|result(s) |
78 | MUTEX_UNLOCK( &U->require_cs); | 78 | MUTEX_UNLOCK( &U->require_cs); |
79 | 79 | ||
80 | // the required module (or an error message) is left on the stack as returned value by original require function | 80 | // the required module (or an error message) is left on the stack as returned value by original require function |
81 | 81 | ||
82 | if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? | 82 | if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? |
83 | { | 83 | { |
84 | return lua_error( L); | 84 | return lua_error( L); |
85 | } | 85 | } |
86 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 | 86 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 |
87 | return lua_gettop(L); // result(s) | 87 | return lua_gettop(L); // result(s) |
88 | } | 88 | } |
89 | 89 | ||
90 | /* | 90 | /* |
@@ -92,26 +92,26 @@ static int luaG_new_require( lua_State* L) | |||
92 | */ | 92 | */ |
93 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | 93 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) |
94 | { | 94 | { |
95 | STACK_GROW( L, 1); | 95 | STACK_GROW( L, 1); |
96 | STACK_CHECK( L, 0); | 96 | STACK_CHECK( L, 0); |
97 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); | 97 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); |
98 | 98 | ||
99 | // Check 'require' is there and not already wrapped; if not, do nothing | 99 | // Check 'require' is there and not already wrapped; if not, do nothing |
100 | // | 100 | // |
101 | lua_getglobal( L, "require"); | 101 | lua_getglobal( L, "require"); |
102 | if( lua_isfunction( L, -1) && lua_tocfunction( L, -1) != luaG_new_require) | 102 | if( lua_isfunction( L, -1) && lua_tocfunction( L, -1) != luaG_new_require) |
103 | { | 103 | { |
104 | // [-1]: original 'require' function | 104 | // [-1]: original 'require' function |
105 | lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/); | 105 | lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/); |
106 | lua_setglobal( L, "require"); | 106 | lua_setglobal( L, "require"); |
107 | } | 107 | } |
108 | else | 108 | else |
109 | { | 109 | { |
110 | // [-1]: nil | 110 | // [-1]: nil |
111 | lua_pop( L, 1); | 111 | lua_pop( L, 1); |
112 | } | 112 | } |
113 | 113 | ||
114 | STACK_END( L, 0); | 114 | STACK_END( L, 0); |
115 | } | 115 | } |
116 | 116 | ||
117 | // ################################################################################################ | 117 | // ################################################################################################ |
@@ -120,15 +120,15 @@ void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | |||
120 | 120 | ||
121 | static int require_lanes_core( lua_State* L) | 121 | static int require_lanes_core( lua_State* L) |
122 | { | 122 | { |
123 | // leaves a copy of 'lanes.core' module table on the stack | 123 | // leaves a copy of 'lanes.core' module table on the stack |
124 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); | 124 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); |
125 | return 1; | 125 | return 1; |
126 | } | 126 | } |
127 | 127 | ||
128 | 128 | ||
129 | static const luaL_Reg libs[] = | 129 | static const luaL_Reg libs[] = |
130 | { | 130 | { |
131 | { LUA_LOADLIBNAME, luaopen_package}, | 131 | { LUA_LOADLIBNAME, luaopen_package}, |
132 | { LUA_TABLIBNAME, luaopen_table}, | 132 | { LUA_TABLIBNAME, luaopen_table}, |
133 | { LUA_STRLIBNAME, luaopen_string}, | 133 | { LUA_STRLIBNAME, luaopen_string}, |
134 | { LUA_MATHLIBNAME, luaopen_math}, | 134 | { LUA_MATHLIBNAME, luaopen_math}, |
@@ -157,152 +157,152 @@ static const luaL_Reg libs[] = | |||
157 | 157 | ||
158 | { LUA_DBLIBNAME, luaopen_debug}, | 158 | { LUA_DBLIBNAME, luaopen_debug}, |
159 | { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) | 159 | { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) |
160 | // | 160 | // |
161 | { "base", NULL}, // ignore "base" (already acquired it) | 161 | { "base", NULL}, // ignore "base" (already acquired it) |
162 | { NULL, NULL } | 162 | { NULL, NULL } |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char const* name_, size_t len_) | 165 | static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char const* name_, size_t len_) |
166 | { | 166 | { |
167 | int i; | 167 | int i; |
168 | for( i = 0; libs[i].name; ++ i) | 168 | for( i = 0; libs[i].name; ++ i) |
169 | { | 169 | { |
170 | if( strncmp( name_, libs[i].name, len_) == 0) | 170 | if( strncmp( name_, libs[i].name, len_) == 0) |
171 | { | 171 | { |
172 | lua_CFunction libfunc = libs[i].func; | 172 | lua_CFunction libfunc = libs[i].func; |
173 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ | 173 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ |
174 | if( libfunc != NULL) | 174 | if( libfunc != NULL) |
175 | { | 175 | { |
176 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" | 176 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" |
177 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); | 177 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); |
178 | STACK_CHECK( L, 0); | 178 | STACK_CHECK( L, 0); |
179 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 179 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
180 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 180 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
181 | // lanes.core doesn't declare a global, so scan it here and now | 181 | // lanes.core doesn't declare a global, so scan it here and now |
182 | if( isLanesCore == TRUE) | 182 | if( isLanesCore == TRUE) |
183 | { | 183 | { |
184 | populate_func_lookup_table( L, -1, name_); | 184 | populate_func_lookup_table( L, -1, name_); |
185 | } | 185 | } |
186 | lua_pop( L, 1); | 186 | lua_pop( L, 1); |
187 | STACK_END( L, 0); | 187 | STACK_END( L, 0); |
188 | } | 188 | } |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
194 | 194 | ||
195 | // just like lua_xmove, args are (from, to) | 195 | // just like lua_xmove, args are (from, to) |
196 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | 196 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) |
197 | { | 197 | { |
198 | STACK_GROW( L, 2); | 198 | STACK_GROW( L, 2); |
199 | STACK_CHECK( L, 0); | 199 | STACK_CHECK( L, 0); |
200 | STACK_CHECK( L2, 0); | 200 | STACK_CHECK( L2, 0); |
201 | 201 | ||
202 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 202 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
203 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 203 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
204 | 204 | ||
205 | REGISTRY_GET( L, CONFIG_REGKEY); // config | 205 | REGISTRY_GET( L, CONFIG_REGKEY); // config |
206 | // copy settings from from source to destination registry | 206 | // copy settings from from source to destination registry |
207 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config | 207 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config |
208 | { | 208 | { |
209 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); | 209 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); |
210 | } | 210 | } |
211 | // set L2:_R[CONFIG_REGKEY] = settings | 211 | // set L2:_R[CONFIG_REGKEY] = settings |
212 | REGISTRY_SET( L2, CONFIG_REGKEY, lua_insert( L2, -2)); // | 212 | REGISTRY_SET( L2, CONFIG_REGKEY, lua_insert( L2, -2)); // |
213 | STACK_END( L2, 0); | 213 | STACK_END( L2, 0); |
214 | STACK_END( L, 0); | 214 | STACK_END( L, 0); |
215 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 215 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
216 | } | 216 | } |
217 | 217 | ||
218 | void initialize_on_state_create( Universe* U, lua_State* L) | 218 | void initialize_on_state_create( Universe* U, lua_State* L) |
219 | { | 219 | { |
220 | STACK_CHECK( L, 0); | 220 | STACK_CHECK( L, 0); |
221 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 221 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil |
222 | if( !lua_isnil( L, -1)) | 222 | if( !lua_isnil( L, -1)) |
223 | { | 223 | { |
224 | // store C function pointer in an internal variable | 224 | // store C function pointer in an internal variable |
225 | U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create | 225 | U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create |
226 | if( U->on_state_create_func != NULL) | 226 | if( U->on_state_create_func != NULL) |
227 | { | 227 | { |
228 | // make sure the function doesn't have upvalues | 228 | // make sure the function doesn't have upvalues |
229 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? | 229 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? |
230 | if( upname != NULL) // should be "" for C functions with upvalues if any | 230 | if( upname != NULL) // should be "" for C functions with upvalues if any |
231 | { | 231 | { |
232 | (void) luaL_error( L, "on_state_create shouldn't have upvalues"); | 232 | (void) luaL_error( L, "on_state_create shouldn't have upvalues"); |
233 | } | 233 | } |
234 | // remove this C function from the config table so that it doesn't cause problems | 234 | // remove this C function from the config table so that it doesn't cause problems |
235 | // when we transfer the config table in newly created Lua states | 235 | // when we transfer the config table in newly created Lua states |
236 | lua_pushnil( L); // settings on_state_create nil | 236 | lua_pushnil( L); // settings on_state_create nil |
237 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create | 237 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create |
238 | } | 238 | } |
239 | else | 239 | else |
240 | { | 240 | { |
241 | // optim: store marker saying we have such a function in the config table | 241 | // optim: store marker saying we have such a function in the config table |
242 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; | 242 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; |
243 | } | 243 | } |
244 | } | 244 | } |
245 | lua_pop( L, 1); // settings | 245 | lua_pop( L, 1); // settings |
246 | STACK_END( L, 0); | 246 | STACK_END( L, 0); |
247 | } | 247 | } |
248 | 248 | ||
249 | lua_State* create_state( Universe* U, lua_State* from_) | 249 | lua_State* create_state( Universe* U, lua_State* from_) |
250 | { | 250 | { |
251 | lua_State* L; | 251 | lua_State* L; |
252 | if( U->provide_allocator != NULL) | 252 | if( U->provide_allocator != NULL) |
253 | { | 253 | { |
254 | lua_pushcclosure( from_, U->provide_allocator, 0); | 254 | lua_pushcclosure( from_, U->provide_allocator, 0); |
255 | lua_call( from_, 0, 1); | 255 | lua_call( from_, 0, 1); |
256 | { | 256 | { |
257 | AllocatorDefinition* def = lua_touserdata( from_, -1); | 257 | AllocatorDefinition* def = lua_touserdata( from_, -1); |
258 | L = lua_newstate( def->allocF, def->allocUD); | 258 | L = lua_newstate( def->allocF, def->allocUD); |
259 | } | 259 | } |
260 | lua_pop( from_, 1); | 260 | lua_pop( from_, 1); |
261 | } | 261 | } |
262 | else | 262 | else |
263 | { | 263 | { |
264 | L = luaL_newstate(); | 264 | L = luaL_newstate(); |
265 | } | 265 | } |
266 | 266 | ||
267 | if( L == NULL) | 267 | if( L == NULL) |
268 | { | 268 | { |
269 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | 269 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); |
270 | } | 270 | } |
271 | return L; | 271 | return L; |
272 | } | 272 | } |
273 | 273 | ||
274 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) | 274 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) |
275 | { | 275 | { |
276 | if( U->on_state_create_func != NULL) | 276 | if( U->on_state_create_func != NULL) |
277 | { | 277 | { |
278 | STACK_CHECK( L, 0); | 278 | STACK_CHECK( L, 0); |
279 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 279 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
280 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) | 280 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
281 | { | 281 | { |
282 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 282 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
283 | lua_pushcfunction( L, U->on_state_create_func); // on_state_create() | 283 | lua_pushcfunction( L, U->on_state_create_func); // on_state_create() |
284 | } | 284 | } |
285 | else // Lua function located in the config table, copied when we opened "lanes.core" | 285 | else // Lua function located in the config table, copied when we opened "lanes.core" |
286 | { | 286 | { |
287 | if( mode_ != eLM_LaneBody) | 287 | if( mode_ != eLM_LaneBody) |
288 | { | 288 | { |
289 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there | 289 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there |
290 | // this doesn't count as an error though | 290 | // this doesn't count as an error though |
291 | return; | 291 | return; |
292 | } | 292 | } |
293 | REGISTRY_GET( L, CONFIG_REGKEY); // {} | 293 | REGISTRY_GET( L, CONFIG_REGKEY); // {} |
294 | STACK_MID( L, 1); | 294 | STACK_MID( L, 1); |
295 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() | 295 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() |
296 | lua_remove( L, -2); // on_state_create() | 296 | lua_remove( L, -2); // on_state_create() |
297 | } | 297 | } |
298 | STACK_MID( L, 1); | 298 | STACK_MID( L, 1); |
299 | // capture error and raise it in caller state | 299 | // capture error and raise it in caller state |
300 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 300 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |
301 | { | 301 | { |
302 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 302 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); |
303 | } | 303 | } |
304 | STACK_END( L, 0); | 304 | STACK_END( L, 0); |
305 | } | 305 | } |
306 | } | 306 | } |
307 | 307 | ||
308 | /* | 308 | /* |
@@ -320,116 +320,116 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
320 | */ | 320 | */ |
321 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | 321 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) |
322 | { | 322 | { |
323 | lua_State* L = create_state( U, from_); | 323 | lua_State* L = create_state( U, from_); |
324 | 324 | ||
325 | STACK_GROW( L, 2); | 325 | STACK_GROW( L, 2); |
326 | STACK_CHECK_ABS( L, 0); | 326 | STACK_CHECK_ABS( L, 0); |
327 | 327 | ||
328 | // copy the universe as a light userdata (only the master state holds the full userdata) | 328 | // copy the universe as a light userdata (only the master state holds the full userdata) |
329 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | 329 | // that way, if Lanes is required in this new state, we'll know we are part of this universe |
330 | universe_store( L, U); | 330 | universe_store( L, U); |
331 | STACK_MID( L, 0); | 331 | STACK_MID( L, 0); |
332 | 332 | ||
333 | // we'll need this every time we transfer some C function from/to this state | 333 | // we'll need this every time we transfer some C function from/to this state |
334 | REGISTRY_SET( L, LOOKUP_REGKEY, lua_newtable( L)); | 334 | REGISTRY_SET( L, LOOKUP_REGKEY, lua_newtable( L)); |
335 | STACK_MID( L, 0); | 335 | STACK_MID( L, 0); |
336 | 336 | ||
337 | // neither libs (not even 'base') nor special init func: we are done | 337 | // neither libs (not even 'base') nor special init func: we are done |
338 | if( libs_ == NULL && U->on_state_create_func == NULL) | 338 | if( libs_ == NULL && U->on_state_create_func == NULL) |
339 | { | 339 | { |
340 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); | 340 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); |
341 | return L; | 341 | return L; |
342 | } | 342 | } |
343 | 343 | ||
344 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 344 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
345 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 345 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
346 | 346 | ||
347 | // copy settings (for example because it may contain a Lua on_state_create function) | 347 | // copy settings (for example because it may contain a Lua on_state_create function) |
348 | copy_one_time_settings( U, from_, L); | 348 | copy_one_time_settings( U, from_, L); |
349 | 349 | ||
350 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | 350 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) |
351 | lua_gc( L, LUA_GCSTOP, 0); | 351 | lua_gc( L, LUA_GCSTOP, 0); |
352 | 352 | ||
353 | 353 | ||
354 | // Anything causes 'base' to be taken in | 354 | // Anything causes 'base' to be taken in |
355 | // | 355 | // |
356 | if( libs_ != NULL) | 356 | if( libs_ != NULL) |
357 | { | 357 | { |
358 | // special "*" case (mainly to help with LuaJIT compatibility) | 358 | // special "*" case (mainly to help with LuaJIT compatibility) |
359 | // as we are called from luaopen_lanes_core() already, and that would deadlock | 359 | // as we are called from luaopen_lanes_core() already, and that would deadlock |
360 | if( libs_[0] == '*' && libs_[1] == 0) | 360 | if( libs_[0] == '*' && libs_[1] == 0) |
361 | { | 361 | { |
362 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); | 362 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
363 | luaL_openlibs( L); | 363 | luaL_openlibs( L); |
364 | // don't forget lanes.core for regular lane states | 364 | // don't forget lanes.core for regular lane states |
365 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); | 365 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); |
366 | libs_ = NULL; // done with libs | 366 | libs_ = NULL; // done with libs |
367 | } | 367 | } |
368 | else | 368 | else |
369 | { | 369 | { |
370 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening base library\n" INDENT_END)); | 370 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening base library\n" INDENT_END)); |
371 | #if LUA_VERSION_NUM >= 502 | 371 | #if LUA_VERSION_NUM >= 502 |
372 | // open base library the same way as in luaL_openlibs() | 372 | // open base library the same way as in luaL_openlibs() |
373 | luaL_requiref( L, "_G", luaopen_base, 1); | 373 | luaL_requiref( L, "_G", luaopen_base, 1); |
374 | lua_pop( L, 1); | 374 | lua_pop( L, 1); |
375 | #else // LUA_VERSION_NUM | 375 | #else // LUA_VERSION_NUM |
376 | lua_pushcfunction( L, luaopen_base); | 376 | lua_pushcfunction( L, luaopen_base); |
377 | lua_pushstring( L, ""); | 377 | lua_pushstring( L, ""); |
378 | lua_call( L, 1, 0); | 378 | lua_call( L, 1, 0); |
379 | #endif // LUA_VERSION_NUM | 379 | #endif // LUA_VERSION_NUM |
380 | } | 380 | } |
381 | } | 381 | } |
382 | STACK_END( L, 0); | 382 | STACK_END( L, 0); |
383 | 383 | ||
384 | // scan all libraries, open them one by one | 384 | // scan all libraries, open them one by one |
385 | if( libs_) | 385 | if( libs_) |
386 | { | 386 | { |
387 | char const* p; | 387 | char const* p; |
388 | unsigned int len = 0; | 388 | unsigned int len = 0; |
389 | for( p = libs_; *p; p += len) | 389 | for( p = libs_; *p; p += len) |
390 | { | 390 | { |
391 | // skip delimiters ('.' can be part of name for "lanes.core") | 391 | // skip delimiters ('.' can be part of name for "lanes.core") |
392 | while( *p && !isalnum( *p) && *p != '.') | 392 | while( *p && !isalnum( *p) && *p != '.') |
393 | ++ p; | 393 | ++ p; |
394 | // skip name | 394 | // skip name |
395 | len = 0; | 395 | len = 0; |
396 | while( isalnum( p[len]) || p[len] == '.') | 396 | while( isalnum( p[len]) || p[len] == '.') |
397 | ++ len; | 397 | ++ len; |
398 | // open library | 398 | // open library |
399 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, p, len); | 399 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, p, len); |
400 | } | 400 | } |
401 | } | 401 | } |
402 | lua_gc( L, LUA_GCRESTART, 0); | 402 | lua_gc( L, LUA_GCRESTART, 0); |
403 | 403 | ||
404 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); | 404 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); |
405 | 405 | ||
406 | // call this after the base libraries are loaded and GC is restarted | 406 | // call this after the base libraries are loaded and GC is restarted |
407 | // will raise an error in from_ in case of problem | 407 | // will raise an error in from_ in case of problem |
408 | call_on_state_create( U, L, from_, eLM_LaneBody); | 408 | call_on_state_create( U, L, from_, eLM_LaneBody); |
409 | 409 | ||
410 | STACK_CHECK( L, 0); | 410 | STACK_CHECK( L, 0); |
411 | // after all this, register everything we find in our name<->function database | 411 | // after all this, register everything we find in our name<->function database |
412 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 412 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
413 | populate_func_lookup_table( L, -1, NULL); | 413 | populate_func_lookup_table( L, -1, NULL); |
414 | 414 | ||
415 | #if 0 && USE_DEBUG_SPEW | 415 | #if 0 && USE_DEBUG_SPEW |
416 | // dump the lookup database contents | 416 | // dump the lookup database contents |
417 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 417 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
418 | lua_pushnil( L); // {} nil | 418 | lua_pushnil( L); // {} nil |
419 | while( lua_next( L, -2)) // {} k v | 419 | while( lua_next( L, -2)) // {} k v |
420 | { | 420 | { |
421 | lua_getglobal( L, "print"); // {} k v print | 421 | lua_getglobal( L, "print"); // {} k v print |
422 | lua_pushlstring( L, debugspew_indent, U->debugspew_indent_depth); // {} k v print " " | 422 | lua_pushlstring( L, debugspew_indent, U->debugspew_indent_depth); // {} k v print " " |
423 | lua_pushvalue( L, -4); // {} k v print " " k | 423 | lua_pushvalue( L, -4); // {} k v print " " k |
424 | lua_pushvalue( L, -4); // {} k v print " " k v | 424 | lua_pushvalue( L, -4); // {} k v print " " k v |
425 | lua_call( L, 3, 0); // {} k v | 425 | lua_call( L, 3, 0); // {} k v |
426 | lua_pop( L, 1); // {} k | 426 | lua_pop( L, 1); // {} k |
427 | } | 427 | } |
428 | lua_pop( L, 1); // {} | 428 | lua_pop( L, 1); // {} |
429 | #endif // USE_DEBUG_SPEW | 429 | #endif // USE_DEBUG_SPEW |
430 | 430 | ||
431 | lua_pop( L, 1); | 431 | lua_pop( L, 1); |
432 | STACK_END( L, 0); | 432 | STACK_END( L, 0); |
433 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 433 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
434 | return L; | 434 | return L; |
435 | } | 435 | } |