aboutsummaryrefslogtreecommitdiff
path: root/src/compat53/module.lua
diff options
context:
space:
mode:
authorTobiasz Laskowski <tobil4sk@outlook.com>2025-02-24 21:20:56 +0000
committerHisham Muhammad <hisham@gobolinux.org>2025-02-24 20:11:55 -0300
commit71b7dd641892dd302cf37c270c472248b24ef8a4 (patch)
treebe59dcd6d92e0e3f8b354a17a6781ba03a295614 /src/compat53/module.lua
parentc71174f1c20c2b57265a5cedfdccda559445e55c (diff)
downloadluarocks-71b7dd641892dd302cf37c270c472248b24ef8a4.tar.gz
luarocks-71b7dd641892dd302cf37c270c472248b24ef8a4.tar.bz2
luarocks-71b7dd641892dd302cf37c270c472248b24ef8a4.zip
Add vendored lua compat53 v0.14.4
Diffstat (limited to 'src/compat53/module.lua')
-rw-r--r--src/compat53/module.lua894
1 files changed, 894 insertions, 0 deletions
diff --git a/src/compat53/module.lua b/src/compat53/module.lua
new file mode 100644
index 00000000..52b1dd63
--- /dev/null
+++ b/src/compat53/module.lua
@@ -0,0 +1,894 @@
1local _G, _VERSION = _G, _VERSION
2local lua_version = _VERSION:sub(-3)
3
4
5local M = _G
6
7if lua_version < "5.3" then
8
9 -- cache globals in upvalues
10 local error, ipairs, pairs, pcall, require, select, setmetatable, type =
11 error, ipairs, pairs, pcall, require, select, setmetatable, type
12 local debug, io, math, package, string, table =
13 debug, io, math, package, string, table
14 local io_lines = io.lines
15 local io_read = io.read
16 local io_open = io.open
17 local io_popen = io.popen
18 local io_tmpfile = io.tmpfile
19 local unpack = lua_version == "5.1" and unpack or table.unpack
20 local debug_setmetatable = type(debug) == "table" and debug.setmetatable
21
22 -- create module table
23 M = {}
24 local M_meta = {
25 __index = _G,
26 -- __newindex is set at the end
27 }
28 setmetatable(M, M_meta)
29
30 -- create subtables
31 M.io = setmetatable({}, { __index = io })
32 M.math = setmetatable({}, { __index = math })
33 M.string = setmetatable({}, { __index = string })
34 M.table = setmetatable({}, { __index = table })
35 M.utf8 = {}
36
37
38 -- select the most powerful getmetatable function available
39 local gmt = type(debug) == "table" and debug.getmetatable or
40 getmetatable or function() return false end
41
42 -- type checking functions
43 local checkinteger -- forward declararation
44
45 local function argcheck(cond, i, f, extra)
46 if not cond then
47 error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0)
48 end
49 end
50
51
52 -- load utf8 library
53 local utf8_ok, utf8lib = pcall(require, "compat53.utf8")
54 if utf8_ok then
55 if lua_version == "5.1" then
56 utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*"
57 end
58 for k,v in pairs(utf8lib) do
59 M.utf8[k] = v
60 end
61 package.loaded["utf8"] = M.utf8
62 end
63
64
65 -- load table library
66 local table_ok, tablib = pcall(require, "compat53.table")
67 if table_ok then
68 for k,v in pairs(tablib) do
69 M.table[k] = v
70 end
71 end
72
73
74 -- load io functions
75 local io_ok, iolib = pcall(require, "compat53.io")
76 if io_ok then
77 for k,v in pairs(iolib) do
78 M.io[k] = v
79 end
80 end
81
82
83 -- load string packing functions
84 local str_ok, strlib = pcall(require, "compat53.string")
85 if str_ok then
86 for k,v in pairs(strlib) do
87 M.string[k] = v
88 end
89 end
90
91
92 -- try Roberto's struct module for string packing/unpacking if
93 -- compat53.string is unavailable
94 if not str_ok then
95 local struct_ok, struct = pcall(require, "struct")
96 if struct_ok then
97 M.string.pack = struct.pack
98 M.string.packsize = struct.size
99 M.string.unpack = struct.unpack
100 end
101 end
102
103
104 -- update math library
105 do
106 local maxint, minint = 1
107
108 while maxint+1 > maxint and 2*maxint > maxint do
109 maxint = maxint * 2
110 end
111 if 2*maxint <= maxint then
112 maxint = 2*maxint-1
113 minint = -maxint-1
114 else
115 maxint = maxint
116 minint = -maxint
117 end
118 M.math.maxinteger = maxint
119 M.math.mininteger = minint
120
121 function M.math.tointeger(n)
122 n = tonumber(n)
123 if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then
124 return n
125 end
126 return nil
127 end
128
129 function M.math.type(n)
130 if type(n) == "number" then
131 if n <= maxint and n >= minint and n % 1 == 0 then
132 return "integer"
133 else
134 return "float"
135 end
136 else
137 return nil
138 end
139 end
140
141 function checkinteger(x, i, f)
142 local t = type(x)
143 if t ~= "number" then
144 error("bad argument #"..i.." to '"..f..
145 "' (number expected, got "..t..")", 0)
146 elseif x > maxint or x < minint or x % 1 ~= 0 then
147 error("bad argument #"..i.." to '"..f..
148 "' (number has no integer representation)", 0)
149 else
150 return x
151 end
152 end
153
154 function M.math.ult(m, n)
155 m = checkinteger(m, "1", "math.ult")
156 n = checkinteger(n, "2", "math.ult")
157 if m >= 0 and n < 0 then
158 return true
159 elseif m < 0 and n >= 0 then
160 return false
161 else
162 return m < n
163 end
164 end
165 end
166
167
168 -- assert should allow non-string error objects
169 function M.assert(cond, ...)
170 if cond then
171 return cond, ...
172 elseif select('#', ...) > 0 then
173 error((...), 0)
174 else
175 error("assertion failed!", 0)
176 end
177 end
178
179
180 -- ipairs should respect __index metamethod
181 do
182 local function ipairs_iterator(st, var)
183 var = var + 1
184 local val = st[var]
185 if val ~= nil then
186 return var, st[var]
187 end
188 end
189 function M.ipairs(t)
190 if gmt(t) ~= nil then -- t has metatable
191 return ipairs_iterator, t, 0
192 else
193 return ipairs(t)
194 end
195 end
196 end
197
198
199 -- make '*' optional for io.read and io.lines
200 do
201 local function addasterisk(fmt)
202 if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then
203 return "*"..fmt
204 else
205 return fmt
206 end
207 end
208
209 function M.io.read(...)
210 local n = select('#', ...)
211 for i = 1, n do
212 local a = select(i, ...)
213 local b = addasterisk(a)
214 -- as an optimization we only allocate a table for the
215 -- modified format arguments when we have a '*' somewhere.
216 if a ~= b then
217 local args = { ... }
218 args[i] = b
219 for j = i+1, n do
220 args[j] = addasterisk(args[j])
221 end
222 return io_read(unpack(args, 1, n))
223 end
224 end
225 return io_read(...)
226 end
227
228 -- PUC-Rio Lua 5.1 uses a different implementation for io.lines!
229 function M.io.lines(...)
230 local n = select('#', ...)
231 for i = 2, n do
232 local a = select(i, ...)
233 local b = addasterisk(a)
234 -- as an optimization we only allocate a table for the
235 -- modified format arguments when we have a '*' somewhere.
236 if a ~= b then
237 local args = { ... }
238 args[i] = b
239 for j = i+1, n do
240 args[j] = addasterisk(args[j])
241 end
242 return io_lines(unpack(args, 1, n))
243 end
244 end
245 return io_lines(...)
246 end
247 end
248
249
250 -- update table library (if C module not available)
251 if not table_ok then
252 local table_concat = table.concat
253 local table_insert = table.insert
254 local table_remove = table.remove
255 local table_sort = table.sort
256
257 function M.table.concat(list, sep, i, j)
258 local mt = gmt(list)
259 if type(mt) == "table" and type(mt.__len) == "function" then
260 local src = list
261 list, i, j = {}, i or 1, j or mt.__len(src)
262 for k = i, j do
263 list[k] = src[k]
264 end
265 end
266 return table_concat(list, sep, i, j)
267 end
268
269 function M.table.insert(list, ...)
270 local mt = gmt(list)
271 local has_mt = type(mt) == "table"
272 local has_len = has_mt and type(mt.__len) == "function"
273 if has_mt and (has_len or mt.__index or mt.__newindex) then
274 local e = (has_len and mt.__len(list) or #list)+1
275 local nargs, pos, value = select('#', ...), ...
276 if nargs == 1 then
277 pos, value = e, pos
278 elseif nargs == 2 then
279 pos = checkinteger(pos, "2", "table.insert")
280 argcheck(1 <= pos and pos <= e, "2", "table.insert",
281 "position out of bounds" )
282 else
283 error("wrong number of arguments to 'insert'", 0)
284 end
285 for i = e-1, pos, -1 do
286 list[i+1] = list[i]
287 end
288 list[pos] = value
289 else
290 return table_insert(list, ...)
291 end
292 end
293
294 function M.table.move(a1, f, e, t, a2)
295 a2 = a2 or a1
296 f = checkinteger(f, "2", "table.move")
297 argcheck(f > 0, "2", "table.move",
298 "initial position must be positive")
299 e = checkinteger(e, "3", "table.move")
300 t = checkinteger(t, "4", "table.move")
301 if e >= f then
302 local m, n, d = 0, e-f, 1
303 if t > f then m, n, d = n, m, -1 end
304 for i = m, n, d do
305 a2[t+i] = a1[f+i]
306 end
307 end
308 return a2
309 end
310
311 function M.table.remove(list, pos)
312 local mt = gmt(list)
313 local has_mt = type(mt) == "table"
314 local has_len = has_mt and type(mt.__len) == "function"
315 if has_mt and (has_len or mt.__index or mt.__newindex) then
316 local e = (has_len and mt.__len(list) or #list)
317 pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e
318 if pos ~= e then
319 argcheck(1 <= pos and pos <= e+1, "2", "table.remove",
320 "position out of bounds" )
321 end
322 local result = list[pos]
323 while pos < e do
324 list[pos] = list[pos+1]
325 pos = pos + 1
326 end
327 list[pos] = nil
328 return result
329 else
330 return table_remove(list, pos)
331 end
332 end
333
334 do
335 local function pivot(list, cmp, a, b)
336 local m = b - a
337 if m > 2 then
338 local c = a + (m-m%2)/2
339 local x, y, z = list[a], list[b], list[c]
340 if not cmp(x, y) then
341 x, y, a, b = y, x, b, a
342 end
343 if not cmp(y, z) then
344 y, b = z, c
345 end
346 if not cmp(x, y) then
347 y, b = x, a
348 end
349 return b, y
350 else
351 return b, list[b]
352 end
353 end
354
355 local function lt_cmp(a, b)
356 return a < b
357 end
358
359 local function qsort(list, cmp, b, e)
360 if b < e then
361 local i, j, k, val = b, e, pivot(list, cmp, b, e)
362 while i < j do
363 while i < j and cmp(list[i], val) do
364 i = i + 1
365 end
366 while i < j and not cmp(list[j], val) do
367 j = j - 1
368 end
369 if i < j then
370 list[i], list[j] = list[j], list[i]
371 if i == k then k = j end -- update pivot position
372 i, j = i+1, j-1
373 end
374 end
375 if i ~= k and not cmp(list[i], val) then
376 list[i], list[k] = val, list[i]
377 k = i -- update pivot position
378 end
379 qsort(list, cmp, b, i == k and i-1 or i)
380 return qsort(list, cmp, i+1, e)
381 end
382 end
383
384 function M.table.sort(list, cmp)
385 local mt = gmt(list)
386 local has_mt = type(mt) == "table"
387 local has_len = has_mt and type(mt.__len) == "function"
388 if has_len then
389 cmp = cmp or lt_cmp
390 local len = mt.__len(list)
391 return qsort(list, cmp, 1, len)
392 else
393 return table_sort(list, cmp)
394 end
395 end
396 end
397
398 local function unpack_helper(list, i, j, ...)
399 if j < i then
400 return ...
401 else
402 return unpack_helper(list, i, j-1, list[j], ...)
403 end
404 end
405 function M.table.unpack(list, i, j)
406 local mt = gmt(list)
407 local has_mt = type(mt) == "table"
408 local has_len = has_mt and type(mt.__len) == "function"
409 if has_mt and (has_len or mt.__index) then
410 i, j = i or 1, j or (has_len and mt.__len(list)) or #list
411 return unpack_helper(list, i, j)
412 else
413 return unpack(list, i, j)
414 end
415 end
416 end -- update table library
417
418
419 -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2
420 if lua_version == "5.1" then
421 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
422 local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ"
423 local is_luajit52 = is_luajit and
424 #setmetatable({}, { __len = function() return 1 end }) == 1
425
426 -- cache globals in upvalues
427 local load, loadfile, loadstring, setfenv, xpcall =
428 load, loadfile, loadstring, setfenv, xpcall
429 local coroutine, os = coroutine, os
430 local coroutine_create = coroutine.create
431 local coroutine_resume = coroutine.resume
432 local coroutine_running = coroutine.running
433 local coroutine_status = coroutine.status
434 local coroutine_yield = coroutine.yield
435 local io_input = io.input
436 local io_open = io.open
437 local io_output = io.output
438 local io_write = io.write
439 local math_log = math.log
440 local os_execute = os.execute
441 local string_find = string.find
442 local string_format = string.format
443 local string_gmatch = string.gmatch
444 local string_gsub = string.gsub
445 local string_match = string.match
446 local string_rep = string.rep
447 local table_concat = table.concat
448
449 -- create subtables
450 M.coroutine = setmetatable({}, { __index = coroutine })
451 M.os = setmetatable({}, { __index = os })
452 M.package = setmetatable({}, { __index = package })
453
454 -- handle debug functions
455 if type(debug) == "table" then
456 local debug_setfenv = debug.setfenv
457 local debug_getfenv = debug.getfenv
458
459 M.debug = setmetatable({}, { __index = debug })
460
461 if not is_luajit52 then
462 function M.debug.setuservalue(obj, value)
463 if type(obj) ~= "userdata" then
464 error("bad argument #1 to 'setuservalue' (userdata expected, got "..
465 type(obj)..")", 2)
466 end
467 if value == nil then value = _G end
468 if type(value) ~= "table" then
469 error("bad argument #2 to 'setuservalue' (table expected, got "..
470 type(value)..")", 2)
471 end
472 return debug_setfenv(obj, value)
473 end
474
475 function M.debug.getuservalue(obj)
476 if type(obj) ~= "userdata" then
477 return nil
478 else
479 local v = debug_getfenv(obj)
480 if v == _G or v == package then
481 return nil
482 end
483 return v
484 end
485 end
486
487 function M.debug.setmetatable(value, tab)
488 debug_setmetatable(value, tab)
489 return value
490 end
491 end -- not luajit with compat52 enabled
492 end -- debug table available
493
494
495 if not is_luajit52 then
496 function M.pairs(t)
497 local mt = gmt(t)
498 if type(mt) == "table" and type(mt.__pairs) == "function" then
499 return mt.__pairs(t)
500 else
501 return pairs(t)
502 end
503 end
504 end
505
506
507 if not is_luajit then
508 local function check_mode(mode, prefix)
509 local has = { text = false, binary = false }
510 for i = 1,#mode do
511 local c = mode:sub(i, i)
512 if c == "t" then has.text = true end
513 if c == "b" then has.binary = true end
514 end
515 local t = prefix:sub(1, 1) == "\27" and "binary" or "text"
516 if not has[t] then
517 return "attempt to load a "..t.." chunk (mode is '"..mode.."')"
518 end
519 end
520
521 function M.load(ld, source, mode, env)
522 mode = mode or "bt"
523 local chunk, msg
524 if type( ld ) == "string" then
525 if mode ~= "bt" then
526 local merr = check_mode(mode, ld)
527 if merr then return nil, merr end
528 end
529 chunk, msg = loadstring(ld, source)
530 else
531 local ld_type = type(ld)
532 if ld_type ~= "function" then
533 error("bad argument #1 to 'load' (function expected, got "..
534 ld_type..")", 2)
535 end
536 if mode ~= "bt" then
537 local checked, merr = false, nil
538 local function checked_ld()
539 if checked then
540 return ld()
541 else
542 checked = true
543 local v = ld()
544 merr = check_mode(mode, v or "")
545 if merr then return nil end
546 return v
547 end
548 end
549 chunk, msg = load(checked_ld, source)
550 if merr then return nil, merr end
551 else
552 chunk, msg = load(ld, source)
553 end
554 end
555 if not chunk then
556 return chunk, msg
557 end
558 if env ~= nil then
559 setfenv(chunk, env)
560 end
561 return chunk
562 end
563
564 M.loadstring = M.load
565
566 function M.loadfile(file, mode, env)
567 mode = mode or "bt"
568 if mode ~= "bt" then
569 local f = io_open(file, "rb")
570 if f then
571 local prefix = f:read(1)
572 f:close()
573 if prefix then
574 local merr = check_mode(mode, prefix)
575 if merr then return nil, merr end
576 end
577 end
578 end
579 local chunk, msg = loadfile(file)
580 if not chunk then
581 return chunk, msg
582 end
583 if env ~= nil then
584 setfenv(chunk, env)
585 end
586 return chunk
587 end
588 end -- not luajit
589
590
591 if not is_luajit52 then
592 function M.rawlen(v)
593 local t = type(v)
594 if t ~= "string" and t ~= "table" then
595 error("bad argument #1 to 'rawlen' (table or string expected)", 2)
596 end
597 return #v
598 end
599 end
600
601
602 if not is_luajit then
603 function M.xpcall(f, msgh, ...)
604 local args, n = { ... }, select('#', ...)
605 return xpcall(function() return f(unpack(args, 1, n)) end, msgh)
606 end
607 end
608
609
610 if not is_luajit52 then
611 function M.os.execute(cmd)
612 local code = os_execute(cmd)
613 -- Lua 5.1 does not report exit by signal.
614 if code == 0 then
615 return true, "exit", code
616 else
617 if package.config:sub(1, 1) == '/' then
618 code = code/256 -- only correct on Linux!
619 end
620 return nil, "exit", code
621 end
622 end
623 end
624
625
626 if not table_ok and not is_luajit52 then
627 M.table.pack = function(...)
628 return { n = select('#', ...), ... }
629 end
630 end
631
632
633 local main_coroutine = coroutine_create(function() end)
634
635 function M.coroutine.create(func)
636 local success, result = pcall(coroutine_create, func)
637 if not success then
638 if type(func) ~= "function" then
639 error("bad argument #1 (function expected)", 0)
640 end
641 result = coroutine_create(function(...) return func(...) end)
642 end
643 return result
644 end
645
646 if not is_luajit52 then
647 function M.coroutine.running()
648 local co = coroutine_running()
649 if co then
650 return co, false
651 else
652 return main_coroutine, true
653 end
654 end
655 end
656
657 function M.coroutine.yield(...)
658 local co, flag = coroutine_running()
659 if co and not flag then
660 return coroutine_yield(...)
661 else
662 error("attempt to yield from outside a coroutine", 0)
663 end
664 end
665
666 if not is_luajit then
667 function M.coroutine.resume(co, ...)
668 if co == main_coroutine then
669 return false, "cannot resume non-suspended coroutine"
670 else
671 return coroutine_resume(co, ...)
672 end
673 end
674
675 function M.coroutine.status(co)
676 local notmain = coroutine_running()
677 if co == main_coroutine then
678 return notmain and "normal" or "running"
679 else
680 return coroutine_status(co)
681 end
682 end
683 end -- not luajit
684
685
686 if not is_luajit then
687 M.math.log = function(x, base)
688 if base ~= nil then
689 return math_log(x)/math_log(base)
690 else
691 return math_log(x)
692 end
693 end
694 end
695
696
697 if not is_luajit then
698 function M.package.searchpath(name, path, sep, rep)
699 sep = (sep or "."):gsub("(%p)", "%%%1")
700 rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1")
701 local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1")
702 local msg = {}
703 for subpath in path:gmatch("[^;]+") do
704 local fpath = subpath:gsub("%?", pname)
705 local f = io_open(fpath, "r")
706 if f then
707 f:close()
708 return fpath
709 end
710 msg[#msg+1] = "\n\tno file '" .. fpath .. "'"
711 end
712 return nil, table_concat(msg)
713 end
714 end
715
716
717 local function fix_pattern(pattern)
718 return (string_gsub(pattern, "%z", "%%z"))
719 end
720
721 function M.string.find(s, pattern, ...)
722 return string_find(s, fix_pattern(pattern), ...)
723 end
724
725 function M.string.gmatch(s, pattern)
726 return string_gmatch(s, fix_pattern(pattern))
727 end
728
729 function M.string.gsub(s, pattern, ...)
730 return string_gsub(s, fix_pattern(pattern), ...)
731 end
732
733 function M.string.match(s, pattern, ...)
734 return string_match(s, fix_pattern(pattern), ...)
735 end
736
737 if not is_luajit then
738 function M.string.rep(s, n, sep)
739 if sep ~= nil and sep ~= "" and n >= 2 then
740 return s .. string_rep(sep..s, n-1)
741 else
742 return string_rep(s, n)
743 end
744 end
745 end
746
747 if not is_luajit then
748 do
749 local addqt = {
750 ["\n"] = "\\\n",
751 ["\\"] = "\\\\",
752 ["\""] = "\\\""
753 }
754
755 local function addquoted(c, d)
756 return (addqt[c] or string_format(d~="" and "\\%03d" or "\\%d", c:byte()))..d
757 end
758
759 function M.string.format(fmt, ...)
760 local args, n = { ... }, select('#', ...)
761 local i = 0
762 local function adjust_fmt(lead, mods, kind)
763 if #lead % 2 == 0 then
764 i = i + 1
765 if kind == "s" then
766 args[i] = _G.tostring(args[i])
767 elseif kind == "q" then
768 args[i] = '"'..string_gsub(args[i], "([%z%c\\\"\n])(%d?)", addquoted)..'"'
769 return lead.."%"..mods.."s"
770 end
771 end
772 end
773 fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt)
774 return string_format(fmt, unpack(args, 1, n))
775 end
776 end
777 end
778
779
780 function M.io.write(...)
781 local res, msg, errno = io_write(...)
782 if res then
783 return io_output()
784 else
785 return nil, msg, errno
786 end
787 end
788
789 if not is_luajit then
790 local function helper(st, var_1, ...)
791 if var_1 == nil then
792 if st.doclose then st.f:close() end
793 if (...) ~= nil then
794 error((...), 2)
795 end
796 end
797 return var_1, ...
798 end
799
800 local function lines_iterator(st)
801 return helper(st, st.f:read(unpack(st, 1, st.n)))
802 end
803
804 function M.io.lines(fname, ...)
805 local doclose, file, msg
806 if fname ~= nil then
807 doclose, file, msg = true, io_open(fname, "r")
808 if not file then error(msg, 2) end
809 else
810 doclose, file = false, io_input()
811 end
812 local st = { f=file, doclose=doclose, n=select('#', ...), ... }
813 for i = 1, st.n do
814 local t = type(st[i])
815 if t == "string" then
816 local fmt = st[i]:match("^%*?([aln])")
817 if not fmt then
818 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
819 end
820 st[i] = "*"..fmt
821 elseif t ~= "number" then
822 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
823 end
824 end
825 return lines_iterator, st
826 end
827 end -- not luajit
828
829 if is_luajit then
830 local compat_file_meta = {}
831 local compat_file_meta_loaded = 0
832
833 local function load_compat_file_meta(file_meta)
834 -- fill compat_file_meta with original entries
835 for k, v in pairs(file_meta) do
836 compat_file_meta[k] = v
837 end
838 compat_file_meta.__index = {}
839 for k, v in pairs(file_meta.__index) do
840 compat_file_meta.__index[k] = v
841 end
842
843 compat_file_meta_loaded = 1
844
845 -- update it with compatibility functions
846 local file_mt_ok, file_mt = pcall(require, "compat53.file_mt")
847 if file_mt_ok then
848 file_mt.update_file_meta(compat_file_meta, is_luajit52)
849
850 compat_file_meta_loaded = 2
851 end
852 end
853
854 local function return_fd(fd, err, code)
855 if not fd then
856 return fd, err, code
857 end
858 if fd and debug_setmetatable then
859 if compat_file_meta_loaded == 0 then
860 local file_meta = gmt(fd)
861 load_compat_file_meta(file_meta)
862 end
863 if compat_file_meta_loaded == 2 then
864 debug_setmetatable(fd, compat_file_meta)
865 end
866 end
867 return fd
868 end
869
870 function M.io.open(...)
871 return return_fd(io_open(...))
872 end
873
874 function M.io.popen(...)
875 return return_fd(io_popen(...))
876 end
877
878 function M.io.tmpfile(...)
879 return return_fd(io_tmpfile(...))
880 end
881 end
882
883 end -- lua 5.1
884
885 -- further write should be forwarded to _G
886 M_meta.__newindex = _G
887
888end -- lua < 5.3
889
890
891-- return module table
892return M
893
894-- vi: set expandtab softtabstop=3 shiftwidth=3 :