aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Janda <siffiejoe@gmx.net>2015-04-11 17:09:37 +0200
committerPhilipp Janda <siffiejoe@gmx.net>2015-04-11 17:09:37 +0200
commitddeb3f7a1e25667694eaf3c8bf639b66d6809cb4 (patch)
treea02b62ce9ad9135dd8dc6aab13940e96ea87dcfe
parentba8686d6af119fc7ecf734a2d2b6e319c8d74df5 (diff)
downloadlua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.tar.gz
lua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.tar.bz2
lua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.zip
split compat53 Lua module into separate modules that do/don't modify the global env
-rw-r--r--compat53/base.lua (renamed from compat53.lua)305
-rw-r--r--compat53/init.lua103
-rw-r--r--compat53/module.lua37
-rwxr-xr-xtests/test.lua2
4 files changed, 282 insertions, 165 deletions
diff --git a/compat53.lua b/compat53/base.lua
index 84ef101..370909a 100644
--- a/compat53.lua
+++ b/compat53/base.lua
@@ -1,8 +1,28 @@
1local _G, _VERSION, setmetatable = _G, _VERSION, setmetatable
1local lua_version = _VERSION:sub(-3) 2local lua_version = _VERSION:sub(-3)
2 3
4
5local M = {}
6local M_meta = {
7 __index = _G
8}
9setmetatable(M, M_meta)
10
11
3if lua_version < "5.3" then 12if lua_version < "5.3" then
4 -- local aliases for commonly used functions 13
5 local type, select, error = type, select, error 14 -- cache globals in upvalues
15 local error, getmetatable, ipairs, pairs, pcall, require, select, type =
16 error, getmetatable, ipairs, pairs, pcall, require, select, type
17 local debug, math, package, string, table =
18 debug, math, package, string, table
19
20 -- create subtables
21 M.math = setmetatable({}, { __index = math })
22 M.string = setmetatable({}, { __index = string })
23 M.table = setmetatable({}, { __index = table })
24 M.utf8 = {}
25
6 26
7 -- select the most powerful getmetatable function available 27 -- select the most powerful getmetatable function available
8 local gmt = type(debug) == "table" and debug.getmetatable or 28 local gmt = type(debug) == "table" and debug.getmetatable or
@@ -29,11 +49,13 @@ if lua_version < "5.3" then
29 -- load utf8 library 49 -- load utf8 library
30 local utf8_ok, utf8lib = pcall(require, "compat53.utf8") 50 local utf8_ok, utf8lib = pcall(require, "compat53.utf8")
31 if utf8_ok then 51 if utf8_ok then
32 utf8 = utf8lib
33 package.loaded["utf8"] = utf8lib
34 if lua_version == "5.1" then 52 if lua_version == "5.1" then
35 utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" 53 utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*"
36 end 54 end
55 for k,v in pairs(utf8lib) do
56 M.utf8[k] = v
57 end
58 package.loaded["utf8"] = M.utf8
37 end 59 end
38 60
39 61
@@ -41,7 +63,7 @@ if lua_version < "5.3" then
41 local table_ok, tablib = pcall(require, "compat53.table") 63 local table_ok, tablib = pcall(require, "compat53.table")
42 if table_ok then 64 if table_ok then
43 for k,v in pairs(tablib) do 65 for k,v in pairs(tablib) do
44 table[k] = v 66 M.table[k] = v
45 end 67 end
46 end 68 end
47 69
@@ -50,7 +72,7 @@ if lua_version < "5.3" then
50 local str_ok, strlib = pcall(require, "compat53.string") 72 local str_ok, strlib = pcall(require, "compat53.string")
51 if str_ok then 73 if str_ok then
52 for k,v in pairs(strlib) do 74 for k,v in pairs(strlib) do
53 string[k] = v 75 M.string[k] = v
54 end 76 end
55 end 77 end
56 78
@@ -60,9 +82,9 @@ if lua_version < "5.3" then
60 if not str_ok then 82 if not str_ok then
61 local struct_ok, struct = pcall(require, "struct") 83 local struct_ok, struct = pcall(require, "struct")
62 if struct_ok then 84 if struct_ok then
63 string.pack = struct.pack 85 M.string.pack = struct.pack
64 string.packsize = struct.size 86 M.string.packsize = struct.size
65 string.unpack = struct.unpack 87 M.string.unpack = struct.unpack
66 end 88 end
67 end 89 end
68 90
@@ -81,17 +103,17 @@ if lua_version < "5.3" then
81 maxint = maxint 103 maxint = maxint
82 minint = -maxint 104 minint = -maxint
83 end 105 end
84 math.maxinteger = maxint 106 M.math.maxinteger = maxint
85 math.mininteger = minint 107 M.math.mininteger = minint
86 108
87 function math.tointeger(n) 109 function M.math.tointeger(n)
88 if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then 110 if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then
89 return n 111 return n
90 end 112 end
91 return nil 113 return nil
92 end 114 end
93 115
94 function math.type(n) 116 function M.math.type(n)
95 if type(n) == "number" then 117 if type(n) == "number" then
96 if n <= maxint and n >= minint and n % 1 == 0 then 118 if n <= maxint and n >= minint and n % 1 == 0 then
97 return "integer" 119 return "integer"
@@ -116,7 +138,7 @@ if lua_version < "5.3" then
116 end 138 end
117 end 139 end
118 140
119 function math.ult(m, n) 141 function M.math.ult(m, n)
120 m = checkinteger(m, "1", "math.ult") 142 m = checkinteger(m, "1", "math.ult")
121 n = checkinteger(n, "2", "math.ult") 143 n = checkinteger(n, "2", "math.ult")
122 if m >= 0 and n < 0 then 144 if m >= 0 and n < 0 then
@@ -132,7 +154,6 @@ if lua_version < "5.3" then
132 154
133 -- ipairs should respect __index metamethod 155 -- ipairs should respect __index metamethod
134 do 156 do
135 local _ipairs = ipairs
136 local function ipairs_iterator(st, var) 157 local function ipairs_iterator(st, var)
137 var = var + 1 158 var = var + 1
138 local val = st[var] 159 local val = st[var]
@@ -140,11 +161,11 @@ if lua_version < "5.3" then
140 return var, st[var] 161 return var, st[var]
141 end 162 end
142 end 163 end
143 function ipairs(t) 164 function M.ipairs(t)
144 if gmt(t) ~= nil then -- t has metatable 165 if gmt(t) ~= nil then -- t has metatable
145 return ipairs_iterator, t, 0 166 return ipairs_iterator, t, 0
146 else 167 else
147 return _ipairs(t) 168 return ipairs(t)
148 end 169 end
149 end 170 end
150 end 171 end
@@ -153,7 +174,12 @@ if lua_version < "5.3" then
153 -- update table library (if C module not available) 174 -- update table library (if C module not available)
154 if not table_ok then 175 if not table_ok then
155 local table_concat = table.concat 176 local table_concat = table.concat
156 function table.concat(list, sep, i, j) 177 local table_insert = table.insert
178 local table_remove = table.remove
179 local table_sort = table.sort
180 local table_unpack = lua_version == "5.1" and unpack or table.unpack
181
182 function M.table.concat(list, sep, i, j)
157 local mt = gmt(list) 183 local mt = gmt(list)
158 if type(mt) == "table" and type(mt.__len) == "function" then 184 if type(mt) == "table" and type(mt.__len) == "function" then
159 local src = list 185 local src = list
@@ -165,8 +191,7 @@ if lua_version < "5.3" then
165 return table_concat(list, sep, i, j) 191 return table_concat(list, sep, i, j)
166 end 192 end
167 193
168 local table_insert = table.insert 194 function M.table.insert(list, ...)
169 function table.insert(list, ...)
170 local mt = gmt(list) 195 local mt = gmt(list)
171 local has_mt = type(mt) == "table" 196 local has_mt = type(mt) == "table"
172 local has_len = has_mt and type(mt.__len) == "function" 197 local has_len = has_mt and type(mt.__len) == "function"
@@ -191,7 +216,7 @@ if lua_version < "5.3" then
191 end 216 end
192 end 217 end
193 218
194 function table.move(a1, f, e, t, a2) 219 function M.table.move(a1, f, e, t, a2)
195 a2 = a2 or a1 220 a2 = a2 or a1
196 f = checkinteger(f, "2", "table.move") 221 f = checkinteger(f, "2", "table.move")
197 argcheck(f > 0, "2", "table.move", 222 argcheck(f > 0, "2", "table.move",
@@ -208,8 +233,7 @@ if lua_version < "5.3" then
208 return a2 233 return a2
209 end 234 end
210 235
211 local table_remove = table.remove 236 function M.table.remove(list, pos)
212 function table.remove(list, pos)
213 local mt = gmt(list) 237 local mt = gmt(list)
214 local has_mt = type(mt) == "table" 238 local has_mt = type(mt) == "table"
215 local has_len = has_mt and type(mt.__len) == "function" 239 local has_len = has_mt and type(mt.__len) == "function"
@@ -282,8 +306,7 @@ if lua_version < "5.3" then
282 end 306 end
283 end 307 end
284 308
285 local table_sort = table.sort 309 function M.table.sort(list, cmp)
286 function table.sort(list, cmp)
287 local mt = gmt(list) 310 local mt = gmt(list)
288 local has_mt = type(mt) == "table" 311 local has_mt = type(mt) == "table"
289 local has_len = has_mt and type(mt.__len) == "function" 312 local has_len = has_mt and type(mt.__len) == "function"
@@ -297,7 +320,6 @@ if lua_version < "5.3" then
297 end 320 end
298 end 321 end
299 322
300 local table_unpack = lua_version == "5.1" and unpack or table.unpack
301 local function unpack_helper(list, i, j, ...) 323 local function unpack_helper(list, i, j, ...)
302 if j < i then 324 if j < i then
303 return ... 325 return ...
@@ -305,7 +327,7 @@ if lua_version < "5.3" then
305 return unpack_helper(list, i, j-1, list[j], ...) 327 return unpack_helper(list, i, j-1, list[j], ...)
306 end 328 end
307 end 329 end
308 function table.unpack(list, i, j) 330 function M.table.unpack(list, i, j)
309 local mt = gmt(list) 331 local mt = gmt(list)
310 local has_mt = type(mt) == "table" 332 local has_mt = type(mt) == "table"
311 local has_len = has_mt and type(mt.__len) == "function" 333 local has_len = has_mt and type(mt.__len) == "function"
@@ -319,7 +341,6 @@ if lua_version < "5.3" then
319 end -- update table library 341 end -- update table library
320 342
321 343
322
323 -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 344 -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2
324 if lua_version == "5.1" then 345 if lua_version == "5.1" then
325 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) 346 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
@@ -327,6 +348,35 @@ if lua_version < "5.3" then
327 local is_luajit52 = is_luajit and 348 local is_luajit52 = is_luajit and
328 #setmetatable({}, { __len = function() return 1 end }) == 1 349 #setmetatable({}, { __len = function() return 1 end }) == 1
329 350
351 -- cache globals in upvalues
352 local load, loadfile, loadstring, setfenv, tostring, unpack, xpcall =
353 load, loadfile, loadstring, setfenv, tostring, unpack, xpcall
354 local coroutine, io, os = coroutine, io, os
355 local coroutine_create = coroutine.create
356 local coroutine_resume = coroutine.resume
357 local coroutine_running = coroutine.running
358 local coroutine_status = coroutine.status
359 local coroutine_yield = coroutine.yield
360 local io_input = io.input
361 local io_open = io.open
362 local io_output = io.output
363 local io_write = io.write
364 local math_log = math.log
365 local os_execute = os.execute
366 local string_find = string.find
367 local string_format = string.format
368 local string_gmatch = string.gmatch
369 local string_gsub = string.gsub
370 local string_match = string.match
371 local string_rep = string.rep
372 local table_concat = table.concat
373
374 -- create subtables
375 M.coroutine = setmetatable({}, { __index = coroutine })
376 M.io = setmetatable({}, { __index = io })
377 M.os = setmetatable({}, { __index = os })
378 M.package = setmetatable({}, { __index = package })
379
330 380
331 -- table that maps each running coroutine to the coroutine that resumed it 381 -- table that maps each running coroutine to the coroutine that resumed it
332 -- this is used to build complete tracebacks when "coroutine-friendly" pcall 382 -- this is used to build complete tracebacks when "coroutine-friendly" pcall
@@ -334,15 +384,19 @@ if lua_version < "5.3" then
334 local pcall_previous = {} 384 local pcall_previous = {}
335 local pcall_callOf = {} 385 local pcall_callOf = {}
336 local xpcall_running = {} 386 local xpcall_running = {}
337 local coroutine_running = coroutine.running
338 387
339 -- handle debug functions 388 -- handle debug functions
340 if type(debug) == "table" then 389 if type(debug) == "table" then
390 local debug_setfenv = debug.setfenv
391 local debug_getfenv = debug.getfenv
392 local debug_setmetatable = debug.setmetatable
393 local debug_getinfo = debug.getinfo
394 local debug_traceback = debug.traceback
395
396 M.debug = setmetatable({}, { __index = debug })
341 397
342 if not is_luajit52 then 398 if not is_luajit52 then
343 local _G, package = _G, package 399 function M.debug.setuservalue(obj, value)
344 local debug_setfenv = debug.setfenv
345 function debug.setuservalue(obj, value)
346 if type(obj) ~= "userdata" then 400 if type(obj) ~= "userdata" then
347 error("bad argument #1 to 'setuservalue' (userdata expected, got ".. 401 error("bad argument #1 to 'setuservalue' (userdata expected, got "..
348 type(obj)..")", 2) 402 type(obj)..")", 2)
@@ -355,8 +409,7 @@ if lua_version < "5.3" then
355 return debug_setfenv(obj, value) 409 return debug_setfenv(obj, value)
356 end 410 end
357 411
358 local debug_getfenv = debug.getfenv 412 function M.debug.getuservalue(obj)
359 function debug.getuservalue(obj)
360 if type(obj) ~= "userdata" then 413 if type(obj) ~= "userdata" then
361 return nil 414 return nil
362 else 415 else
@@ -368,15 +421,13 @@ if lua_version < "5.3" then
368 end 421 end
369 end 422 end
370 423
371 local debug_setmetatable = debug.setmetatable 424 function M.debug.setmetatable(value, tab)
372 function debug.setmetatable(value, tab)
373 debug_setmetatable(value, tab) 425 debug_setmetatable(value, tab)
374 return value 426 return value
375 end 427 end
376 end -- not luajit with compat52 enabled 428 end -- not luajit with compat52 enabled
377 429
378 if not is_luajit then 430 if not is_luajit then
379 local debug_getinfo = debug.getinfo
380 local function calculate_trace_level(co, level) 431 local function calculate_trace_level(co, level)
381 if level ~= nil then 432 if level ~= nil then
382 for out = 1, 1/0 do 433 for out = 1, 1/0 do
@@ -395,8 +446,7 @@ if lua_version < "5.3" then
395 446
396 local stack_pattern = "\nstack traceback:" 447 local stack_pattern = "\nstack traceback:"
397 local stack_replace = "" 448 local stack_replace = ""
398 local debug_traceback = debug.traceback 449 function M.debug.traceback(co, msg, level)
399 function debug.traceback(co, msg, level)
400 local lvl 450 local lvl
401 local nilmsg 451 local nilmsg
402 if type(co) ~= "thread" then 452 if type(co) ~= "thread" then
@@ -471,13 +521,12 @@ if lua_version < "5.3" then
471 521
472 522
473 if not is_luajit52 then 523 if not is_luajit52 then
474 local _pairs = pairs 524 function M.pairs(t)
475 function pairs(t)
476 local mt = gmt(t) 525 local mt = gmt(t)
477 if type(mt) == "table" and type(mt.__pairs) == "function" then 526 if type(mt) == "table" and type(mt.__pairs) == "function" then
478 return mt.__pairs(t) 527 return mt.__pairs(t)
479 else 528 else
480 return _pairs(t) 529 return pairs(t)
481 end 530 end
482 end 531 end
483 end 532 end
@@ -497,9 +546,7 @@ if lua_version < "5.3" then
497 end 546 end
498 end 547 end
499 548
500 local setfenv = setfenv 549 function M.load(ld, source, mode, env)
501 local _load, _loadstring = load, loadstring
502 function load(ld, source, mode, env)
503 mode = mode or "bt" 550 mode = mode or "bt"
504 local chunk, msg 551 local chunk, msg
505 if type( ld ) == "string" then 552 if type( ld ) == "string" then
@@ -507,7 +554,7 @@ if lua_version < "5.3" then
507 local merr = check_mode(mode, ld) 554 local merr = check_mode(mode, ld)
508 if merr then return nil, merr end 555 if merr then return nil, merr end
509 end 556 end
510 chunk, msg = _loadstring(ld, source) 557 chunk, msg = loadstring(ld, source)
511 else 558 else
512 local ld_type = type(ld) 559 local ld_type = type(ld)
513 if ld_type ~= "function" then 560 if ld_type ~= "function" then
@@ -527,10 +574,10 @@ if lua_version < "5.3" then
527 return v 574 return v
528 end 575 end
529 end 576 end
530 chunk, msg = _load(checked_ld, source) 577 chunk, msg = load(checked_ld, source)
531 if merr then return nil, merr end 578 if merr then return nil, merr end
532 else 579 else
533 chunk, msg = _load(ld, source) 580 chunk, msg = load(ld, source)
534 end 581 end
535 end 582 end
536 if not chunk then 583 if not chunk then
@@ -542,11 +589,9 @@ if lua_version < "5.3" then
542 return chunk 589 return chunk
543 end 590 end
544 591
545 loadstring = load 592 M.loadstring = load
546 593
547 local _loadfile = loadfile 594 function M.loadfile(file, mode, env)
548 local io_open = io.open
549 function loadfile(file, mode, env)
550 mode = mode or "bt" 595 mode = mode or "bt"
551 if mode ~= "bt" then 596 if mode ~= "bt" then
552 local f = io_open(file, "rb") 597 local f = io_open(file, "rb")
@@ -559,7 +604,7 @@ if lua_version < "5.3" then
559 end 604 end
560 end 605 end
561 end 606 end
562 local chunk, msg = _loadfile(file) 607 local chunk, msg = loadfile(file)
563 if not chunk then 608 if not chunk then
564 return chunk, msg 609 return chunk, msg
565 end 610 end
@@ -572,7 +617,7 @@ if lua_version < "5.3" then
572 617
573 618
574 if not is_luajit52 then 619 if not is_luajit52 then
575 function rawlen(v) 620 function M.rawlen(v)
576 local t = type(v) 621 local t = type(v)
577 if t ~= "string" and t ~= "table" then 622 if t ~= "string" and t ~= "table" then
578 error("bad argument #1 to 'rawlen' (table or string expected)", 2) 623 error("bad argument #1 to 'rawlen' (table or string expected)", 2)
@@ -583,32 +628,29 @@ if lua_version < "5.3" then
583 628
584 629
585 if not is_luajit52 then 630 if not is_luajit52 then
586 local os_execute = os.execute 631 function M.os.execute(cmd)
587 function os.execute(cmd)
588 local code = os_execute(cmd) 632 local code = os_execute(cmd)
589 -- Lua 5.1 does not report exit by signal. 633 -- Lua 5.1 does not report exit by signal.
590 if code == 0 then 634 if code == 0 then
591 return true, "exit", code 635 return true, "exit", code
592 else 636 else
593 return nil, "exit", code/256 -- only correct on POSIX! 637 return nil, "exit", code/256 -- only correct on Linux!
594 end 638 end
595 end 639 end
596 end 640 end
597 641
598 642
599 if not table_ok and not is_luajit52 then 643 if not table_ok and not is_luajit52 then
600 table.pack = function(...) 644 M.table.pack = function(...)
601 return { n = select('#', ...), ... } 645 return { n = select('#', ...), ... }
602 end 646 end
603 end 647 end
604 648
605 649
606 local main_coroutine = coroutine.create(function() end) 650 local main_coroutine = coroutine_create(function() end)
607 651
608 local _pcall = pcall 652 function M.coroutine.create(func)
609 local coroutine_create = coroutine.create 653 local success, result = pcall(coroutine_create, func)
610 function coroutine.create(func)
611 local success, result = _pcall(coroutine_create, func)
612 if not success then 654 if not success then
613 if type(func) ~= "function" then 655 if type(func) ~= "function" then
614 error("bad argument #1 (function expected)", 0) 656 error("bad argument #1 (function expected)", 0)
@@ -621,7 +663,7 @@ if lua_version < "5.3" then
621 local pcall_mainOf = {} 663 local pcall_mainOf = {}
622 664
623 if not is_luajit52 then 665 if not is_luajit52 then
624 function coroutine.running() 666 function M.coroutine.running()
625 local co = coroutine_running() 667 local co = coroutine_running()
626 if co then 668 if co then
627 return pcall_mainOf[co] or co, false 669 return pcall_mainOf[co] or co, false
@@ -631,8 +673,7 @@ if lua_version < "5.3" then
631 end 673 end
632 end 674 end
633 675
634 local coroutine_yield = coroutine.yield 676 function M.coroutine.yield(...)
635 function coroutine.yield(...)
636 local co, flag = coroutine_running() 677 local co, flag = coroutine_running()
637 if co and not flag then 678 if co and not flag then
638 return coroutine_yield(...) 679 return coroutine_yield(...)
@@ -642,8 +683,7 @@ if lua_version < "5.3" then
642 end 683 end
643 684
644 if not is_luajit then 685 if not is_luajit then
645 local coroutine_resume = coroutine.resume 686 function M.coroutine.resume(co, ...)
646 function coroutine.resume(co, ...)
647 if co == main_coroutine then 687 if co == main_coroutine then
648 return false, "cannot resume non-suspended coroutine" 688 return false, "cannot resume non-suspended coroutine"
649 else 689 else
@@ -651,8 +691,7 @@ if lua_version < "5.3" then
651 end 691 end
652 end 692 end
653 693
654 local coroutine_status = coroutine.status 694 function M.coroutine.status(co)
655 function coroutine.status(co)
656 local notmain = coroutine_running() 695 local notmain = coroutine_running()
657 if co == main_coroutine then 696 if co == main_coroutine then
658 return notmain and "normal" or "running" 697 return notmain and "normal" or "running"
@@ -683,7 +722,7 @@ if lua_version < "5.3" then
683 end 722 end
684 return pcall_results(current, call, coroutine_resume(call, ...)) 723 return pcall_results(current, call, coroutine_resume(call, ...))
685 end 724 end
686 local coroutine_create52 = coroutine.create 725 local coroutine_create52 = M.coroutine.create
687 local function pcall_coroutine(func) 726 local function pcall_coroutine(func)
688 if type(func) ~= "function" then 727 if type(func) ~= "function" then
689 local callable = func 728 local callable = func
@@ -691,32 +730,29 @@ if lua_version < "5.3" then
691 end 730 end
692 return coroutine_create52(func) 731 return coroutine_create52(func)
693 end 732 end
694 function pcall(func, ...) 733 function M.pcall(func, ...)
695 local current = coroutine_running() 734 local current = coroutine_running()
696 if not current then return _pcall(func, ...) end 735 if not current then return pcall(func, ...) end
697 return pcall_exec(current, pcall_coroutine(func), ...) 736 return pcall_exec(current, pcall_coroutine(func), ...)
698 end 737 end
699 738
700 local _tostring = tostring
701 local function xpcall_catch(current, call, msgh, success, ...) 739 local function xpcall_catch(current, call, msgh, success, ...)
702 if not success then 740 if not success then
703 xpcall_running[current] = call 741 xpcall_running[current] = call
704 local ok, result = _pcall(msgh, ...) 742 local ok, result = pcall(msgh, ...)
705 xpcall_running[current] = nil 743 xpcall_running[current] = nil
706 if not ok then 744 if not ok then
707 return false, "error in error handling (".._tostring(result)..")" 745 return false, "error in error handling ("..tostring(result)..")"
708 end 746 end
709 return false, result 747 return false, result
710 end 748 end
711 return true, ... 749 return true, ...
712 end 750 end
713 local _xpcall = xpcall 751 function M.xpcall(f, msgh, ...)
714 local _unpack = unpack
715 function xpcall(f, msgh, ...)
716 local current = coroutine_running() 752 local current = coroutine_running()
717 if not current then 753 if not current then
718 local args, n = { ... }, select('#', ...) 754 local args, n = { ... }, select('#', ...)
719 return _xpcall(function() return f(_unpack(args, 1, n)) end, msgh) 755 return xpcall(function() return f(unpack(args, 1, n)) end, msgh)
720 end 756 end
721 local call = pcall_coroutine(f) 757 local call = pcall_coroutine(f)
722 return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) 758 return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...))
@@ -725,8 +761,7 @@ if lua_version < "5.3" then
725 761
726 762
727 if not is_luajit then 763 if not is_luajit then
728 local math_log = math.log 764 M.math.log = function(x, base)
729 math.log = function(x, base)
730 if base ~= nil then 765 if base ~= nil then
731 return math_log(x)/math_log(base) 766 return math_log(x)/math_log(base)
732 else 767 else
@@ -736,11 +771,8 @@ if lua_version < "5.3" then
736 end 771 end
737 772
738 773
739 local package = package
740 if not is_luajit then 774 if not is_luajit then
741 local io_open = io.open 775 function M.package.searchpath(name, path, sep, rep)
742 local table_concat = table.concat
743 function package.searchpath(name, path, sep, rep)
744 sep = (sep or "."):gsub("(%p)", "%%%1") 776 sep = (sep or "."):gsub("(%p)", "%%%1")
745 rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") 777 rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1")
746 local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") 778 local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1")
@@ -758,48 +790,29 @@ if lua_version < "5.3" then
758 end 790 end
759 end 791 end
760 792
761 local p_index = { searchers = package.loaders }
762 local rawset = rawset
763 setmetatable(package, {
764 __index = p_index,
765 __newindex = function(p, k, v)
766 if k == "searchers" then
767 rawset(p, "loaders", v)
768 p_index.searchers = v
769 else
770 rawset(p, k, v)
771 end
772 end
773 })
774
775 793
776 local string_gsub = string.gsub
777 local function fix_pattern(pattern) 794 local function fix_pattern(pattern)
778 return (string_gsub(pattern, "%z", "%%z")) 795 return (string_gsub(pattern, "%z", "%%z"))
779 end 796 end
780 797
781 local string_find = string.find 798 function M.string.find(s, pattern, ...)
782 function string.find(s, pattern, ...)
783 return string_find(s, fix_pattern(pattern), ...) 799 return string_find(s, fix_pattern(pattern), ...)
784 end 800 end
785 801
786 local string_gmatch = string.gmatch 802 function M.string.gmatch(s, pattern)
787 function string.gmatch(s, pattern)
788 return string_gmatch(s, fix_pattern(pattern)) 803 return string_gmatch(s, fix_pattern(pattern))
789 end 804 end
790 805
791 function string.gsub(s, pattern, ...) 806 function M.string.gsub(s, pattern, ...)
792 return string_gsub(s, fix_pattern(pattern), ...) 807 return string_gsub(s, fix_pattern(pattern), ...)
793 end 808 end
794 809
795 local string_match = string.match 810 function M.string.match(s, pattern, ...)
796 function string.match(s, pattern, ...)
797 return string_match(s, fix_pattern(pattern), ...) 811 return string_match(s, fix_pattern(pattern), ...)
798 end 812 end
799 813
800 if not is_luajit then 814 if not is_luajit then
801 local string_rep = string.rep 815 function M.string.rep(s, n, sep)
802 function string.rep(s, n, sep)
803 if sep ~= nil and sep ~= "" and n >= 2 then 816 if sep ~= nil and sep ~= "" and n >= 2 then
804 return s .. string_rep(sep..s, n-1) 817 return s .. string_rep(sep..s, n-1)
805 else 818 else
@@ -809,7 +822,6 @@ if lua_version < "5.3" then
809 end 822 end
810 823
811 if not is_luajit then 824 if not is_luajit then
812 local string_format = string.format
813 do 825 do
814 local addqt = { 826 local addqt = {
815 ["\n"] = "\\\n", 827 ["\n"] = "\\\n",
@@ -821,15 +833,14 @@ if lua_version < "5.3" then
821 return addqt[c] or string_format("\\%03d", c:byte()) 833 return addqt[c] or string_format("\\%03d", c:byte())
822 end 834 end
823 835
824 local _unpack = unpack 836 function M.string.format(fmt, ...)
825 function string.format(fmt, ...)
826 local args, n = { ... }, select('#', ...) 837 local args, n = { ... }, select('#', ...)
827 local i = 0 838 local i = 0
828 local function adjust_fmt(lead, mods, kind) 839 local function adjust_fmt(lead, mods, kind)
829 if #lead % 2 == 0 then 840 if #lead % 2 == 0 then
830 i = i + 1 841 i = i + 1
831 if kind == "s" then 842 if kind == "s" then
832 args[i] = tostring(args[i]) 843 args[i] = _G.tostring(args[i])
833 elseif kind == "q" then 844 elseif kind == "q" then
834 args[i] = '"'..string_gsub(args[i], "[%z%c\\\"\n]", addquoted)..'"' 845 args[i] = '"'..string_gsub(args[i], "[%z%c\\\"\n]", addquoted)..'"'
835 return lead.."%"..mods.."s" 846 return lead.."%"..mods.."s"
@@ -837,16 +848,13 @@ if lua_version < "5.3" then
837 end 848 end
838 end 849 end
839 fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) 850 fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt)
840 return string_format(fmt, _unpack(args, 1, n)) 851 return string_format(fmt, unpack(args, 1, n))
841 end 852 end
842 end 853 end
843 end 854 end
844 855
845 856
846 local io_open = io.open 857 function M.io.write(...)
847 local io_write = io.write
848 local io_output = io.output
849 function io.write(...)
850 local res, msg, errno = io_write(...) 858 local res, msg, errno = io_write(...)
851 if res then 859 if res then
852 return io_output() 860 return io_output()
@@ -856,28 +864,23 @@ if lua_version < "5.3" then
856 end 864 end
857 865
858 if not is_luajit then 866 if not is_luajit then
859 local lines_iterator 867 local function helper(st, var_1, ...)
860 do 868 if var_1 == nil then
861 local function helper( st, var_1, ... ) 869 if st.doclose then st.f:close() end
862 if var_1 == nil then 870 if (...) ~= nil then
863 if st.doclose then st.f:close() end 871 error((...), 2)
864 if (...) ~= nil then
865 error((...), 2)
866 end
867 end 872 end
868 return var_1, ...
869 end 873 end
874 return var_1, ...
875 end
870 876
871 local _unpack = unpack 877 local function lines_iterator(st)
872 function lines_iterator(st) 878 return helper(st, st.f:read(unpack(st, 1, st.n)))
873 return helper(st, st.f:read(_unpack(st, 1, st.n)))
874 end
875 end 879 end
876 880
877 local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true } 881 local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true }
878 882
879 local io_input = io.input 883 function M.io.lines(fname, ...)
880 function io.lines(fname, ...)
881 local doclose, file, msg 884 local doclose, file, msg
882 if fname ~= nil then 885 if fname ~= nil then
883 doclose, file, msg = true, io_open(fname, "r") 886 doclose, file, msg = true, io_open(fname, "r")
@@ -893,36 +896,6 @@ if lua_version < "5.3" then
893 end 896 end
894 return lines_iterator, st 897 return lines_iterator, st
895 end 898 end
896
897 do
898 local io_stdout = io.stdout
899 local io_type = io.type
900 local file_meta = gmt(io_stdout)
901 if type(file_meta) == "table" and type(file_meta.__index) == "table" then
902 local file_write = file_meta.__index.write
903 file_meta.__index.write = function(self, ...)
904 local res, msg, errno = file_write(self, ...)
905 if res then
906 return self
907 else
908 return nil, msg, errno
909 end
910 end
911
912 file_meta.__index.lines = function(self, ...)
913 if io_type(self) == "closed file" then
914 error("attempt to use a closed file", 2)
915 end
916 local st = { f=self, doclose=false, n=select('#', ...), ... }
917 for i = 1, st.n do
918 if type(st[i]) ~= "number" and not valid_format[st[i]] then
919 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
920 end
921 end
922 return lines_iterator, st
923 end
924 end
925 end
926 end -- not luajit 899 end -- not luajit
927 900
928 901
@@ -930,4 +903,8 @@ if lua_version < "5.3" then
930 903
931end -- lua < 5.3 904end -- lua < 5.3
932 905
906
907-- return module table
908return M
909
933-- vi: set expandtab softtabstop=3 shiftwidth=3 : 910-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/compat53/init.lua b/compat53/init.lua
new file mode 100644
index 0000000..cdd5f34
--- /dev/null
+++ b/compat53/init.lua
@@ -0,0 +1,103 @@
1local _G, _VERSION, type, pairs, require =
2 _G, _VERSION, type, pairs, require
3
4local M = require("compat53.base")
5local lua_version = _VERSION:sub(-3)
6
7
8-- apply other global effects
9if lua_version == "5.1" then
10
11 -- cache globals
12 local error, rawset, select, setmetatable, type, unpack =
13 error, rawset, select, setmetatable, type, unpack
14 local debug, io, package, string = debug, io, package, string
15 local io_type, io_stdout = io.type, io.stdout
16
17 -- select the most powerful getmetatable function available
18 local gmt = type(debug) == "table" and debug.getmetatable or
19 getmetatable or function() return false end
20
21 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
22 local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ"
23
24
25 -- make package.searchers available as an alias for package.loaders
26 local p_index = { searchers = package.loaders }
27 setmetatable(package, {
28 __index = p_index,
29 __newindex = function(p, k, v)
30 if k == "searchers" then
31 rawset(p, "loaders", v)
32 p_index.searchers = v
33 else
34 rawset(p, k, v)
35 end
36 end
37 })
38
39
40 if not is_luajit then
41 local function helper(st, var_1, ...)
42 if var_1 == nil then
43 if (...) ~= nil then
44 error((...), 2)
45 end
46 end
47 return var_1, ...
48 end
49
50 local function lines_iterator(st)
51 return helper(st, st.f:read(unpack(st, 1, st.n)))
52 end
53
54 local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true }
55
56 local file_meta = gmt(io_stdout)
57 if type(file_meta) == "table" and type(file_meta.__index) == "table" then
58 local file_write = file_meta.__index.write
59 file_meta.__index.write = function(self, ...)
60 local res, msg, errno = file_write(self, ...)
61 if res then
62 return self
63 else
64 return nil, msg, errno
65 end
66 end
67
68 file_meta.__index.lines = function(self, ...)
69 if io_type(self) == "closed file" then
70 error("attempt to use a closed file", 2)
71 end
72 local st = { f=self, n=select('#', ...), ... }
73 for i = 1, st.n do
74 if type(st[i]) ~= "number" and not valid_format[st[i]] then
75 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
76 end
77 end
78 return lines_iterator, st
79 end
80 end
81 end -- not luajit
82
83end -- lua == 5.1
84
85
86-- handle exporting to global scope
87local function extend_table(from, to)
88 for k,v in pairs(from) do
89 if type(v) == "table" and
90 type(to[k]) == "table" and
91 v ~= to[k] then
92 extend_table(v, to[k])
93 else
94 to[k] = v
95 end
96 end
97end
98
99extend_table(M, _G)
100
101return _G
102
103-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/compat53/module.lua b/compat53/module.lua
new file mode 100644
index 0000000..f6fd1f7
--- /dev/null
+++ b/compat53/module.lua
@@ -0,0 +1,37 @@
1local _G, _VERSION, debug, error, require, setfenv, setmetatable =
2 _G, _VERSION, debug, error, require, setfenv, setmetatable
3local lua_version = _VERSION:sub(-3)
4local M = require("compat53.base")
5
6local function findmain()
7 local i = 3
8 local info = debug.getinfo(i, "fS")
9 while info do
10 if info.what == "main" then
11 return info.func
12 end
13 i = i + 1
14 info = debug.getinfo(i, "fS")
15 end
16end
17
18local main = findmain()
19if not main then
20 error("must require 'compat53.module' from Lua")
21end
22local env = setmetatable({}, {
23 __index = M,
24 __newindex = _G,
25})
26if lua_version == "5.1" then
27 setfenv(main, env)
28elseif lua_version == "5.2" or lua_version == "5.3" then
29 debug.setupvalue(main, 1, env)
30else
31 error("unsupported Lua version")
32end
33
34-- return false to force reevaluation on next require
35return false
36
37-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/tests/test.lua b/tests/test.lua
index 83e174e..664cfa6 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -37,7 +37,7 @@ local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2")
37if jit then V = "jit" end 37if jit then V = "jit" end
38 38
39print( "testing Lua API ..." ) 39print( "testing Lua API ..." )
40package.path = "../?.lua;"..package.path 40package.path = "../?.lua;../?/init.lua;"..package.path
41package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll" 41package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll"
42require("compat53") 42require("compat53")
43 43