aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2013-04-05 18:31:36 +0300
committerBenoit Germain <bnt.germain@gmail.com>2013-04-05 18:31:36 +0300
commitbfd0254b339c57f78c3844daefb7166f5a818b54 (patch)
tree616f6313b3660537e7b3b510f8c4454a511b11a3 /src
parent2ed40018fa50e4aaa9aff44560bc3af86633feac (diff)
downloadlanes-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.c98
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
268static char const* luaG_pushFQN(lua_State *L, int t, int last) 268static 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 */
1321int discover_object_name_recur( lua_State* L, int _shortest, int _length) 1337static 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/*