diff options
author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-01-06 10:40:14 +0100 |
---|---|---|
committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-01-06 10:40:14 +0100 |
commit | b335cbcc9f07dc71999b885ffa2962c0ec00f5eb (patch) | |
tree | ad6398a6f7e5ef155631b984bd41d07d535ea1f9 /src/tools.c | |
parent | 132e85cb40f3a88efdb66a6344061bade628fcda (diff) | |
download | lanes-b335cbcc9f07dc71999b885ffa2962c0ec00f5eb.tar.gz lanes-b335cbcc9f07dc71999b885ffa2962c0ec00f5eb.tar.bz2 lanes-b335cbcc9f07dc71999b885ffa2962c0ec00f5eb.zip |
fix on_state_create circular logic issue
* if config.on_state_create() is a C function, call it by direct C
closure reconstruction in newly created states
* bumped version to 3.7.6
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/src/tools.c b/src/tools.c index 60f9012..9f36858 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -8,7 +8,7 @@ | |||
8 | =============================================================================== | 8 | =============================================================================== |
9 | 9 | ||
10 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> | 10 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> |
11 | 2011-13 benoit Germain <bnt.germain@gmail.com> | 11 | 2011-14 benoit Germain <bnt.germain@gmail.com> |
12 | 12 | ||
13 | Permission is hereby granted, free of charge, to any person obtaining a copy | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy |
14 | of this software and associated documentation files (the "Software"), to deal | 14 | of this software and associated documentation files (the "Software"), to deal |
@@ -161,6 +161,39 @@ void luaG_dump( lua_State* L ) { | |||
161 | fprintf( stderr, "\n" ); | 161 | fprintf( stderr, "\n" ); |
162 | } | 162 | } |
163 | 163 | ||
164 | static lua_CFunction s_on_state_create_func = NULL; | ||
165 | int initialize_on_state_create( lua_State* L) | ||
166 | { | ||
167 | STACK_CHECK( L); | ||
168 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | ||
169 | if( !lua_isnil( L, -1)) | ||
170 | { | ||
171 | // store C function pointer in an internal variable | ||
172 | s_on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create | ||
173 | if( s_on_state_create_func != NULL) | ||
174 | { | ||
175 | // make sure the function doesn't have upvalues | ||
176 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? | ||
177 | if( upname != NULL) // should be "" for C functions with upvalues if any | ||
178 | { | ||
179 | luaL_error( L, "on_state_create shouldn't have upvalues"); | ||
180 | } | ||
181 | // remove this C function from the config table so that it doesn't cause problems | ||
182 | // when we transfer the config table in newly created Lua states | ||
183 | lua_pushnil( L); // settings on_state_create nil | ||
184 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create | ||
185 | } | ||
186 | else | ||
187 | { | ||
188 | // optim: store marker saying we have such a function in the config table | ||
189 | s_on_state_create_func = initialize_on_state_create; | ||
190 | } | ||
191 | } | ||
192 | lua_pop( L, 1); // settings | ||
193 | STACK_END( L, 0); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
164 | // just like lua_xmove, args are (from, to) | 197 | // just like lua_xmove, args are (from, to) |
165 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) | 198 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2, char const* name_) |
166 | { | 199 | { |
@@ -569,7 +602,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
569 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. | 602 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. |
570 | * | 603 | * |
571 | */ | 604 | */ |
572 | lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) | 605 | lua_State* luaG_newstate( lua_State* _from, char const* libs) |
573 | { | 606 | { |
574 | // reuse alloc function from the originating state | 607 | // reuse alloc function from the originating state |
575 | #if PROPAGATE_ALLOCF | 608 | #if PROPAGATE_ALLOCF |
@@ -587,7 +620,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
587 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); | 620 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); |
588 | 621 | ||
589 | // neither libs (not even 'base') nor special init func: we are done | 622 | // neither libs (not even 'base') nor special init func: we are done |
590 | if( libs == NULL && _on_state_create <= 0) | 623 | if( libs == NULL && s_on_state_create_func == NULL) |
591 | { | 624 | { |
592 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); | 625 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); |
593 | return L; | 626 | return L; |
@@ -655,22 +688,19 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con | |||
655 | 688 | ||
656 | STACK_CHECK( L); | 689 | STACK_CHECK( L); |
657 | // call this after the base libraries are loaded and GC is restarted | 690 | // call this after the base libraries are loaded and GC is restarted |
658 | if( _on_state_create > 0) | 691 | if( s_on_state_create_func != NULL) |
659 | { | 692 | { |
660 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 693 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
661 | if( lua_iscfunction( _from, _on_state_create)) | 694 | if( s_on_state_create_func != initialize_on_state_create) |
662 | { | 695 | { |
663 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 696 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
664 | lua_CFunction osc = lua_tocfunction( _from, _on_state_create); | 697 | lua_pushcfunction( L, s_on_state_create_func); |
665 | lua_pushcfunction( L, osc); | ||
666 | } | 698 | } |
667 | else | 699 | else // Lua function located in the config table |
668 | { | 700 | { |
669 | STACK_CHECK( _from); | 701 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); |
670 | // Lua function: transfer as usual (should work as long as it only uses base libraries) | 702 | lua_getfield( L, -1, "on_state_create"); |
671 | lua_pushvalue( _from, _on_state_create); | 703 | lua_remove( L, -2); |
672 | luaG_inter_move( _from, L, 1, eLM_LaneBody); | ||
673 | STACK_END( _from, 0); | ||
674 | } | 704 | } |
675 | // capture error and forward it to main state | 705 | // capture error and forward it to main state |
676 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 706 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |