aboutsummaryrefslogtreecommitdiff
path: root/vendor/compat53/module.lua
diff options
context:
space:
mode:
authortobil4sk <tobil4sk@outlook.com>2026-02-03 22:47:50 +0000
committerGitHub <noreply@github.com>2026-02-03 19:47:50 -0300
commit47301d83aba58925e1b9594023621ebb27070cdb (patch)
tree73021b5366687ec1683b9e66505e74f22f71d31b /vendor/compat53/module.lua
parentacf1f47e7f1b1ecbc147e41cae51ddfd06ad898d (diff)
downloadluarocks-main.tar.gz
luarocks-main.tar.bz2
luarocks-main.zip
Improve flexibility around vendored librariesmain
compat53 is vendored since #1757 as it is required to run luarocks with lua 5.1 or 5.2. However, this introduced some issues as the GNUmakefile install rule places these in the same place where `luarocks install compat53` would install them. This means you get conflicts if you install the actual package: ``` Warning: /.../prefix/share/lua/5.1/compat53/init.lua is not tracked by this installation of LuaRocks. Moving it to /.../prefix/share/lua/5.1/compat53/init.lua~ Warning: /.../prefix/share/lua/5.1/compat53/module.lua is not tracked by this installation of LuaRocks. Moving it to /.../prefix/share/lua/5.1/compat53/module.lua~ Warning: /.../prefix/share/lua/5.1/compat53/file_mt.lua is not tracked by this installation of LuaRocks. Moving it to /.../prefix/share/lua/5.1/compat53/file_mt.lua~ ``` It is also not ideal for linux package maintainers to include a vendored package, see: https://github.com/luarocks/luarocks/pull/1757#issuecomment-3409873412. To solve these issues, this patchset makes the following changes: - GNUmakefile now places the compat53 files under `luarocks/vendor/compat53` (which is added internally to the luarocks script's `package.path`). This way a user's installation of compat53 does not interfere at all with luarocks one. - Added `--with-system-compat53` option to configure script for external packaging systems. - Fixed install.bat's logic for deciding whether to vendor compat53, as the current script includes it for every version. install.bat already places luarocks sources outside of LUAPATH, so that part can stay as is. I've also inverted the version check to avoid the need for future patches like: #1850.
Diffstat (limited to 'vendor/compat53/module.lua')
-rw-r--r--vendor/compat53/module.lua894
1 files changed, 894 insertions, 0 deletions
diff --git a/vendor/compat53/module.lua b/vendor/compat53/module.lua
new file mode 100644
index 00000000..b580e536
--- /dev/null
+++ b/vendor/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((...), 2)
174 else
175 error("assertion failed!", 2)
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 :