diff options
-rw-r--r-- | src/tools.c | 84 |
1 files changed, 41 insertions, 43 deletions
diff --git a/src/tools.c b/src/tools.c index 2fc7b58..e89b340 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -202,19 +202,19 @@ static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out) | |||
202 | 202 | ||
203 | 203 | ||
204 | // inspired from tconcat() in ltablib.c | 204 | // inspired from tconcat() in ltablib.c |
205 | static char const * luaG_pushFQN(lua_State *L, int t, int last) | 205 | static char const* luaG_pushFQN(lua_State *L, int t, int last) |
206 | { | 206 | { |
207 | int i = 1; | 207 | int i = 1; |
208 | luaL_Buffer b; | 208 | luaL_Buffer b; |
209 | STACK_CHECK( L) | 209 | STACK_CHECK( L) |
210 | luaL_buffinit(L, &b); | 210 | luaL_buffinit(L, &b); |
211 | for( ; i < last; i++) | 211 | for( ; i < last; ++ i) |
212 | { | 212 | { |
213 | lua_rawgeti( L, t, i); | 213 | lua_rawgeti( L, t, i); |
214 | luaL_addvalue( &b); | 214 | luaL_addvalue( &b); |
215 | luaL_addlstring(&b, ".", 1); | 215 | luaL_addlstring(&b, ".", 1); |
216 | } | 216 | } |
217 | if (i == last) /* add last value (if interval was not empty) */ | 217 | if( i == last) // add last value (if interval was not empty) |
218 | { | 218 | { |
219 | lua_rawgeti( L, t, i); | 219 | lua_rawgeti( L, t, i); |
220 | luaL_addvalue( &b); | 220 | luaL_addvalue( &b); |
@@ -225,7 +225,7 @@ static char const * luaG_pushFQN(lua_State *L, int t, int last) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | 227 | ||
228 | static void populate_func_lookup_table_recur( lua_State *L, int _ctx_base, int _i, int _depth) | 228 | static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _i, int _depth) |
229 | { | 229 | { |
230 | lua_Integer visit_count; | 230 | lua_Integer visit_count; |
231 | // slot 1 in the stack contains the table that receives everything we found | 231 | // slot 1 in the stack contains the table that receives everything we found |
@@ -282,49 +282,47 @@ static void populate_func_lookup_table_recur( lua_State *L, int _ctx_base, int _ | |||
282 | lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k | 282 | lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k |
283 | lua_insert( L, -2); // ... {_i} {bfc} k k {} | 283 | lua_insert( L, -2); // ... {_i} {bfc} k k {} |
284 | lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k | 284 | lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k |
285 | STACK_MID( L, 2) | ||
286 | } | 285 | } |
287 | else if( lua_isfunction( L, -1)) // ... {_i} {bfc} k func | 286 | else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func |
288 | { | 287 | { |
289 | if( luaG_getfuncsubtype( L, -1) != FST_Bytecode) | 288 | char const* prevName, * newName; |
289 | // first, raise an error if the function is already known | ||
290 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func func | ||
291 | lua_rawget( L, dest); // ... {_i} {bfc} k func name? | ||
292 | prevName = lua_tostring( L, -1); // NULL if we got nil (first encounter of this function) | ||
293 | // push function name in fqn stack (note that concatenation will crash if name is a not string or a number) | ||
294 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func name? k | ||
295 | ++ _depth; | ||
296 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func name? | ||
297 | // generate name | ||
298 | newName = luaG_pushFQN( L, fqn, _depth); // ... {_i} {bfc} k func name? "f.q.n" | ||
299 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order | ||
300 | // on different VMs even when the tables are populated the exact same way. | ||
301 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), | ||
302 | // this causes several base libraries to register functions under multiple names. | ||
303 | // This, with the randomizer, can cause the first name of a function to be different on different VMs, | ||
304 | // which breaks function transfer. | ||
305 | // This means that Lua 5.2 must be built with compatibility off to be able to use Lanes. | ||
306 | // Even under Lua 5.1, this may cause trouble (even if this would be much less frequent) | ||
307 | // Unfortunately, this fails with string.gfind/string.gmatch when Lua 5.1 is built with LUA_COMPAT_GFIND (which is the case of LuaBinaries), | ||
308 | // so for the time being, fail only for Lua 5.2 as the randomizer is the real show breaker here. | ||
309 | if( (LUA_VERSION_NUM > 501) && (prevName != NULL)) | ||
290 | { | 310 | { |
291 | //char const *fqnString; for debugging | 311 | (void) luaL_error( L, "multiple names detected (%s and %s)", prevName, newName); |
292 | bool_t not_registered; | 312 | return; |
293 | // first, skip everything if the function is already known | ||
294 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func func | ||
295 | lua_rawget( L, dest); // ... {_i} {bfc} k func name? | ||
296 | not_registered = lua_isnil( L, -1); | ||
297 | lua_pop( L, 1); // ... {_i} {bfc} k func | ||
298 | if( not_registered) | ||
299 | { | ||
300 | ++ _depth; | ||
301 | // push function name in fqn stack (note that concatenation will crash if name is a not string!) | ||
302 | lua_pushvalue( L, -2); // ... {_i} {bfc} k func k | ||
303 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func | ||
304 | // generate name | ||
305 | /*fqnString =*/ (void) luaG_pushFQN( L, fqn, _depth); // ... {_i} {bfc} k func "f.q.n" | ||
306 | //puts( fqnString); | ||
307 | // prepare the stack for database feed | ||
308 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n" | ||
309 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func | ||
310 | // t["f.q.n"] = func | ||
311 | lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n" | ||
312 | // t[func] = "f.q.n" | ||
313 | lua_rawset( L, dest); // ... {_i} {bfc} k | ||
314 | // remove table name from fqn stack | ||
315 | lua_pushnil( L); // ... {_i} {bfc} k nil | ||
316 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k | ||
317 | -- _depth; | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | lua_pop( L, 1); // ... {_i} {bfc} k | ||
322 | } | ||
323 | } | ||
324 | else | ||
325 | { | ||
326 | lua_pop( L, 1); // ... {_i} {bfc} k | ||
327 | } | 313 | } |
314 | // prepare the stack for database feed | ||
315 | lua_remove( L, -2); // ... {_i} {bfc} k func "f.q.n" | ||
316 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n" | ||
317 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func | ||
318 | // t["f.q.n"] = func | ||
319 | lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n" | ||
320 | // t[func] = "f.q.n" | ||
321 | lua_rawset( L, dest); // ... {_i} {bfc} k | ||
322 | // remove table name from fqn stack | ||
323 | lua_pushnil( L); // ... {_i} {bfc} k nil | ||
324 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k | ||
325 | -- _depth; | ||
328 | } | 326 | } |
329 | else | 327 | else |
330 | { | 328 | { |