diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2013-04-05 18:31:36 +0300 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2013-04-05 18:31:36 +0300 |
commit | bfd0254b339c57f78c3844daefb7166f5a818b54 (patch) | |
tree | 616f6313b3660537e7b3b510f8c4454a511b11a3 /src | |
parent | 2ed40018fa50e4aaa9aff44560bc3af86633feac (diff) | |
download | lanes-bfd0254b339c57f78c3844daefb7166f5a818b54.tar.gz lanes-bfd0254b339c57f78c3844daefb7166f5a818b54.tar.bz2 lanes-bfd0254b339c57f78c3844daefb7166f5a818b54.zip |
Removed LUA_COMPAT_ALL-less Lua5.2 restriction
Diffstat (limited to 'src')
-rw-r--r-- | src/tools.c | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/src/tools.c b/src/tools.c index f72663f..773735d 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -265,7 +265,7 @@ static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out) | |||
265 | 265 | ||
266 | 266 | ||
267 | // inspired from tconcat() in ltablib.c | 267 | // inspired from tconcat() in ltablib.c |
268 | static char const* luaG_pushFQN(lua_State *L, int t, int last) | 268 | static char const* luaG_pushFQN(lua_State *L, int t, int last, int* length) |
269 | { | 269 | { |
270 | int i = 1; | 270 | int i = 1; |
271 | luaL_Buffer b; | 271 | luaL_Buffer b; |
@@ -284,7 +284,7 @@ static char const* luaG_pushFQN(lua_State *L, int t, int last) | |||
284 | } | 284 | } |
285 | luaL_pushresult( &b); | 285 | luaL_pushresult( &b); |
286 | STACK_END( L, 1); | 286 | STACK_END( L, 1); |
287 | return lua_tostring( L, -1); | 287 | return lua_tolstring( L, -1, length); |
288 | } | 288 | } |
289 | 289 | ||
290 | 290 | ||
@@ -355,44 +355,60 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
355 | } | 355 | } |
356 | else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func | 356 | else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func |
357 | { | 357 | { |
358 | char const* prevName, * newName; | 358 | int prevNameLength, newNameLength; |
359 | char const* prevName, *newName; | ||
359 | // first, raise an error if the function is already known | 360 | // first, raise an error if the function is already known |
360 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func func | 361 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func func |
361 | lua_rawget( L, dest); // ... {_i} {bfc} k func name? | 362 | lua_rawget( L, dest); // ... {_i} {bfc} k func name? |
362 | prevName = lua_tostring( L, -1); // NULL if we got nil (first encounter of this function) | 363 | prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this function) |
363 | // push function name in fqn stack (note that concatenation will crash if name is a not string or a number) | 364 | // push function name in fqn stack (note that concatenation will crash if name is a not string or a number) |
364 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func name? k | 365 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func name? k |
365 | ++ _depth; | 366 | ++ _depth; |
366 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func name? | 367 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func name? |
367 | // generate name | 368 | // generate name |
368 | newName = luaG_pushFQN( L, fqn, _depth); // ... {_i} {bfc} k func name? "f.q.n" | 369 | newName = luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {_i} {bfc} k func name? "f.q.n" |
369 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order | 370 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order |
370 | // on different VMs even when the tables are populated the exact same way. | 371 | // on different VMs even when the tables are populated the exact same way. |
371 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), | 372 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), |
372 | // this causes several base libraries to register functions under multiple names. | 373 | // this causes several base libraries to register functions under multiple names. |
373 | // This, with the randomizer, can cause the first name of a function to be different on different VMs, | 374 | // This, with the randomizer, can cause the first name of a function to be different on different VMs, |
374 | // which breaks function transfer. | 375 | // which breaks function transfer. |
375 | // This means that Lua 5.2 must be built with compatibility off to be able to use Lanes. | 376 | // Also, nothing prevents any external module from exposing a given function under several names, so... |
376 | // Even under Lua 5.1, this may cause trouble (even if this would be much less frequent) | 377 | // Therefore, when we encounter a function for which a name was previously registered, we need to select the names |
377 | // Unfortunately, this fails with string.gfind/string.gmatch when Lua 5.1 is built with LUA_COMPAT_GFIND (which is the case of LuaBinaries), | 378 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded |
378 | // so for the time being, fail only for Lua 5.2 as the randomizer is the real show breaker here. | 379 | if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1))) |
379 | if( (LUA_VERSION_NUM > 501) && (prevName != NULL)) | ||
380 | { | 380 | { |
381 | (void) luaL_error( L, "multiple names detected (%s and %s)", prevName, newName); | 381 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s' remained named '%s'\n" INDENT_END, newName, prevName)); |
382 | return; | 382 | // the previous name is 'smaller' than the one we just generated: keep it! |
383 | lua_pop( L, 3); // ... {_i} {bfc} k | ||
384 | } | ||
385 | else | ||
386 | { | ||
387 | // the name we generated is either the first one, or a better fit for our purposes | ||
388 | if( prevName) | ||
389 | { | ||
390 | // clear the previous name for the database to avoid clutter | ||
391 | lua_insert( L, -2); // ... {_i} {bfc} k func "f.q.n" prevName | ||
392 | // t[prevName] = nil | ||
393 | lua_pushnil( L); // ... {_i} {bfc} k func "f.q.n" prevName nil | ||
394 | lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n" | ||
395 | } | ||
396 | else | ||
397 | { | ||
398 | lua_remove( L, -2); // ... {_i} {bfc} k func "f.q.n" | ||
399 | } | ||
400 | // prepare the stack for database feed | ||
401 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n" | ||
402 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func | ||
403 | // t["f.q.n"] = func | ||
404 | lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n" | ||
405 | // t[func] = "f.q.n" | ||
406 | lua_rawset( L, dest); // ... {_i} {bfc} k | ||
407 | // remove table name from fqn stack | ||
408 | lua_pushnil( L); // ... {_i} {bfc} k nil | ||
409 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k | ||
410 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s'\n" INDENT_END, newName)); | ||
383 | } | 411 | } |
384 | // prepare the stack for database feed | ||
385 | lua_remove( L, -2); // ... {_i} {bfc} k func "f.q.n" | ||
386 | lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n" | ||
387 | lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func | ||
388 | // t["f.q.n"] = func | ||
389 | lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n" | ||
390 | // t[func] = "f.q.n" | ||
391 | lua_rawset( L, dest); // ... {_i} {bfc} k | ||
392 | // remove table name from fqn stack | ||
393 | lua_pushnil( L); // ... {_i} {bfc} k nil | ||
394 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k | ||
395 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s'\n" INDENT_END, newName)); | ||
396 | -- _depth; | 412 | -- _depth; |
397 | } | 413 | } |
398 | else | 414 | else |
@@ -675,7 +691,7 @@ void set_deep_lookup( lua_State *L ) { | |||
675 | lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); | 691 | lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); |
676 | lua_pushvalue(L,-2); | 692 | lua_pushvalue(L,-2); |
677 | // | 693 | // |
678 | // [-3]: {} (2nd ref) | 694 | // [-3]: {}��‚�� (2nd ref) |
679 | // [-2]: DEEP_LOOKUP_KEY | 695 | // [-2]: DEEP_LOOKUP_KEY |
680 | // [-1]: {} | 696 | // [-1]: {} |
681 | 697 | ||
@@ -1082,7 +1098,7 @@ luaG_IdFunction luaG_copydeep( lua_State *L, lua_State *L2, int index ) | |||
1082 | 1098 | ||
1083 | /* | 1099 | /* |
1084 | * 'reg[ REG_MT_KNOWN ]'= { | 1100 | * 'reg[ REG_MT_KNOWN ]'= { |
1085 | * [ table ]= id_uint, | 1101 | * [��‚�� table ]= id_uint, |
1086 | * ... | 1102 | * ... |
1087 | * [ id_uint ]= table, | 1103 | * [ id_uint ]= table, |
1088 | * ... | 1104 | * ... |
@@ -1318,16 +1334,16 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1318 | /* | 1334 | /* |
1319 | * Return some name helping to identify an object | 1335 | * Return some name helping to identify an object |
1320 | */ | 1336 | */ |
1321 | int discover_object_name_recur( lua_State* L, int _shortest, int _length) | 1337 | static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) |
1322 | { | 1338 | { |
1323 | int const what = 1; // o "r" {c} {fqn} ... {?} | 1339 | int const what = 1; // o "r" {c} {fqn} ... {?} |
1324 | int const result = 2; | 1340 | int const result = 2; |
1325 | int const cache = 3; | 1341 | int const cache = 3; |
1326 | int const fqn = 4; | 1342 | int const fqn = 4; |
1327 | // no need to scan this table if the name we will discover is longer than one we already know | 1343 | // no need to scan this table if the name we will discover is longer than one we already know |
1328 | if( _shortest <= _length + 1) | 1344 | if( shortest_ <= depth_ + 1) |
1329 | { | 1345 | { |
1330 | return _shortest; | 1346 | return shortest_; |
1331 | } | 1347 | } |
1332 | STACK_GROW( L, 3); | 1348 | STACK_GROW( L, 3); |
1333 | STACK_CHECK( L); | 1349 | STACK_CHECK( L); |
@@ -1338,7 +1354,7 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1338 | if( !lua_isnil( L, -1)) | 1354 | if( !lua_isnil( L, -1)) |
1339 | { | 1355 | { |
1340 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} | 1356 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} |
1341 | return _shortest; | 1357 | return shortest_; |
1342 | } | 1358 | } |
1343 | // examined table is not in the cache, add it now | 1359 | // examined table is not in the cache, add it now |
1344 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} | 1360 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} |
@@ -1351,16 +1367,16 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1351 | { | 1367 | { |
1352 | //char const *const key = lua_tostring( L, -2); // only for debugging (BEWARE, IT MAY CHANGE THE VALUE IF IT IS CONVERTIBLE, AND WRECK THE LOOP ITERATION PROCESS!) | 1368 | //char const *const key = lua_tostring( L, -2); // only for debugging (BEWARE, IT MAY CHANGE THE VALUE IF IT IS CONVERTIBLE, AND WRECK THE LOOP ITERATION PROCESS!) |
1353 | // append key name to fqn stack | 1369 | // append key name to fqn stack |
1354 | ++ _length; | 1370 | ++ depth_; |
1355 | lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k | 1371 | lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k |
1356 | lua_rawseti( L, fqn, _length); // o "r" {c} {fqn} ... {?} k v | 1372 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v |
1357 | if( lua_rawequal( L, -1, what)) // is it what we are looking for? | 1373 | if( lua_rawequal( L, -1, what)) // is it what we are looking for? |
1358 | { | 1374 | { |
1359 | // update shortest name | 1375 | // update shortest name |
1360 | if( _length < _shortest) | 1376 | if( depth_ < shortest_) |
1361 | { | 1377 | { |
1362 | _shortest = _length; | 1378 | shortest_ = depth_; |
1363 | luaG_pushFQN( L, fqn, _length); // o "r" {c} {fqn} ... {?} k v "fqn" | 1379 | luaG_pushFQN( L, fqn, depth_, NULL); // o "r" {c} {fqn} ... {?} k v "fqn" |
1364 | lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v | 1380 | lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v |
1365 | } | 1381 | } |
1366 | // no need to search further at this level | 1382 | // no need to search further at this level |
@@ -1369,13 +1385,13 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1369 | } | 1385 | } |
1370 | else if( lua_istable( L, -1)) | 1386 | else if( lua_istable( L, -1)) |
1371 | { | 1387 | { |
1372 | _shortest = discover_object_name_recur( L, _shortest, _length); | 1388 | shortest_ = discover_object_name_recur( L, shortest_, depth_); |
1373 | // search in the table's metatable too | 1389 | // search in the table's metatable too |
1374 | if( lua_getmetatable( L, -1)) | 1390 | if( lua_getmetatable( L, -1)) |
1375 | { | 1391 | { |
1376 | if( lua_istable( L, -1)) | 1392 | if( lua_istable( L, -1)) |
1377 | { | 1393 | { |
1378 | _shortest = discover_object_name_recur( L, _shortest, _length); | 1394 | shortest_ = discover_object_name_recur( L, shortest_, depth_); |
1379 | } | 1395 | } |
1380 | lua_pop( L, 1); | 1396 | lua_pop( L, 1); |
1381 | } | 1397 | } |
@@ -1387,7 +1403,7 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1387 | { | 1403 | { |
1388 | if( lua_istable( L, -1)) | 1404 | if( lua_istable( L, -1)) |
1389 | { | 1405 | { |
1390 | _shortest = discover_object_name_recur( L, _shortest, _length); | 1406 | shortest_ = discover_object_name_recur( L, shortest_, depth_); |
1391 | } | 1407 | } |
1392 | lua_pop( L, 1); | 1408 | lua_pop( L, 1); |
1393 | } | 1409 | } |
@@ -1396,15 +1412,15 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1396 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k | 1412 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k |
1397 | // remove name from fqn stack | 1413 | // remove name from fqn stack |
1398 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil | 1414 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil |
1399 | lua_rawseti( L, fqn, _length); // o "r" {c} {fqn} ... {?} k | 1415 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k |
1400 | -- _length; | 1416 | -- depth_; |
1401 | } // o "r" {c} {fqn} ... {?} | 1417 | } // o "r" {c} {fqn} ... {?} |
1402 | // remove the visited table from the cache, in case a shorter path to the searched object exists | 1418 | // remove the visited table from the cache, in case a shorter path to the searched object exists |
1403 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 1419 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
1404 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil | 1420 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil |
1405 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} | 1421 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} |
1406 | STACK_END( L, 0); | 1422 | STACK_END( L, 0); |
1407 | return _shortest; | 1423 | return shortest_; |
1408 | } | 1424 | } |
1409 | 1425 | ||
1410 | /* | 1426 | /* |