diff options
| author | tobil4sk <tobil4sk@outlook.com> | 2026-02-03 22:47:50 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-03 19:47:50 -0300 |
| commit | 47301d83aba58925e1b9594023621ebb27070cdb (patch) | |
| tree | 73021b5366687ec1683b9e66505e74f22f71d31b /vendor/compat53/init.lua | |
| parent | acf1f47e7f1b1ecbc147e41cae51ddfd06ad898d (diff) | |
| download | luarocks-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/init.lua')
| -rw-r--r-- | vendor/compat53/init.lua | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/vendor/compat53/init.lua b/vendor/compat53/init.lua new file mode 100644 index 00000000..b5075713 --- /dev/null +++ b/vendor/compat53/init.lua | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | local lua_version = _VERSION:sub(-3) | ||
| 2 | |||
| 3 | |||
| 4 | if lua_version < "5.3" then | ||
| 5 | |||
| 6 | local _G, pairs, require, select, type = | ||
| 7 | _G, pairs, require, select, type | ||
| 8 | local debug, io = debug, io | ||
| 9 | local unpack = lua_version == "5.1" and unpack or table.unpack | ||
| 10 | |||
| 11 | local M = require("compat53.module") | ||
| 12 | |||
| 13 | -- select the most powerful getmetatable function available | ||
| 14 | local gmt = type(debug) == "table" and debug.getmetatable or | ||
| 15 | getmetatable or function() return false end | ||
| 16 | -- metatable for file objects from Lua's standard io library | ||
| 17 | local file_meta = gmt(io.stdout) | ||
| 18 | |||
| 19 | |||
| 20 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) | ||
| 21 | local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" | ||
| 22 | local is_luajit52 = is_luajit and | ||
| 23 | #setmetatable({}, { __len = function() return 1 end }) == 1 | ||
| 24 | |||
| 25 | |||
| 26 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then | ||
| 27 | local file_mt = require("compat53.file_mt") | ||
| 28 | file_mt.update_file_meta(file_meta, is_luajit52) | ||
| 29 | end -- got a valid metatable for file objects | ||
| 30 | |||
| 31 | |||
| 32 | -- changes for Lua 5.1 only | ||
| 33 | if lua_version == "5.1" then | ||
| 34 | |||
| 35 | -- cache globals | ||
| 36 | local error, pcall, rawset, setmetatable, tostring, xpcall = | ||
| 37 | error, pcall, rawset, setmetatable, tostring, xpcall | ||
| 38 | local coroutine, package, string = coroutine, package, string | ||
| 39 | local coroutine_resume = coroutine.resume | ||
| 40 | local coroutine_running = coroutine.running | ||
| 41 | local coroutine_status = coroutine.status | ||
| 42 | local coroutine_yield = coroutine.yield | ||
| 43 | local io_type = io.type | ||
| 44 | |||
| 45 | |||
| 46 | -- make package.searchers available as an alias for package.loaders | ||
| 47 | local p_index = { searchers = package.loaders } | ||
| 48 | setmetatable(package, { | ||
| 49 | __index = p_index, | ||
| 50 | __newindex = function(p, k, v) | ||
| 51 | if k == "searchers" then | ||
| 52 | rawset(p, "loaders", v) | ||
| 53 | p_index.searchers = v | ||
| 54 | else | ||
| 55 | rawset(p, k, v) | ||
| 56 | end | ||
| 57 | end | ||
| 58 | }) | ||
| 59 | |||
| 60 | |||
| 61 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then | ||
| 62 | if not is_luajit then | ||
| 63 | local function helper(_, var_1, ...) | ||
| 64 | if var_1 == nil then | ||
| 65 | if (...) ~= nil then | ||
| 66 | error((...), 2) | ||
| 67 | end | ||
| 68 | end | ||
| 69 | return var_1, ... | ||
| 70 | end | ||
| 71 | |||
| 72 | local function lines_iterator(st) | ||
| 73 | return helper(st, st.f:read(unpack(st, 1, st.n))) | ||
| 74 | end | ||
| 75 | |||
| 76 | local file_write = file_meta.__index.write | ||
| 77 | file_meta.__index.write = function(self, ...) | ||
| 78 | local res, msg, errno = file_write(self, ...) | ||
| 79 | if res then | ||
| 80 | return self | ||
| 81 | else | ||
| 82 | return nil, msg, errno | ||
| 83 | end | ||
| 84 | end | ||
| 85 | |||
| 86 | file_meta.__index.lines = function(self, ...) | ||
| 87 | if io_type(self) == "closed file" then | ||
| 88 | error("attempt to use a closed file", 2) | ||
| 89 | end | ||
| 90 | local st = { f=self, n=select('#', ...), ... } | ||
| 91 | for i = 1, st.n do | ||
| 92 | local t = type(st[i]) | ||
| 93 | if t == "string" then | ||
| 94 | local fmt = st[i]:match("^*?([aln])") | ||
| 95 | if not fmt then | ||
| 96 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) | ||
| 97 | end | ||
| 98 | st[i] = "*"..fmt | ||
| 99 | elseif t ~= "number" then | ||
| 100 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) | ||
| 101 | end | ||
| 102 | end | ||
| 103 | return lines_iterator, st | ||
| 104 | end | ||
| 105 | end -- not luajit | ||
| 106 | end -- file_meta valid | ||
| 107 | |||
| 108 | |||
| 109 | -- the (x)pcall implementations start a new coroutine internally | ||
| 110 | -- to allow yielding even in Lua 5.1. to allow for accurate | ||
| 111 | -- stack traces we keep track of the nested coroutine activations | ||
| 112 | -- in the weak tables below: | ||
| 113 | local weak_meta = { __mode = "kv" } | ||
| 114 | -- maps the internal pcall coroutines to the user coroutine that | ||
| 115 | -- *should* be running if pcall didn't use coroutines internally | ||
| 116 | local pcall_mainOf = setmetatable({}, weak_meta) | ||
| 117 | -- table that maps each running coroutine started by pcall to | ||
| 118 | -- the coroutine that resumed it (user coroutine *or* pcall | ||
| 119 | -- coroutine!) | ||
| 120 | local pcall_previous = setmetatable({}, weak_meta) | ||
| 121 | -- reverse of `pcall_mainOf`. maps a user coroutine to the | ||
| 122 | -- currently active pcall coroutine started within it | ||
| 123 | local pcall_callOf = setmetatable({}, weak_meta) | ||
| 124 | -- similar to `pcall_mainOf` but is used only while executing | ||
| 125 | -- the error handler of xpcall (thus no nesting is necessary!) | ||
| 126 | local xpcall_running = setmetatable({}, weak_meta) | ||
| 127 | |||
| 128 | -- handle debug functions | ||
| 129 | if type(debug) == "table" then | ||
| 130 | local debug_getinfo = debug.getinfo | ||
| 131 | local debug_traceback = debug.traceback | ||
| 132 | |||
| 133 | if not is_luajit then | ||
| 134 | local function calculate_trace_level(co, level) | ||
| 135 | if level ~= nil then | ||
| 136 | for out = 1, 1/0 do | ||
| 137 | local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") | ||
| 138 | if info == nil then | ||
| 139 | local max = out-1 | ||
| 140 | if level <= max then | ||
| 141 | return level | ||
| 142 | end | ||
| 143 | return nil, level-max | ||
| 144 | end | ||
| 145 | end | ||
| 146 | end | ||
| 147 | return 1 | ||
| 148 | end | ||
| 149 | |||
| 150 | local stack_pattern = "\nstack traceback:" | ||
| 151 | local stack_replace = "" | ||
| 152 | function debug.traceback(co, msg, level) | ||
| 153 | local lvl | ||
| 154 | local nilmsg | ||
| 155 | if type(co) ~= "thread" then | ||
| 156 | co, msg, level = coroutine_running(), co, msg | ||
| 157 | end | ||
| 158 | if msg == nil then | ||
| 159 | msg = "" | ||
| 160 | nilmsg = true | ||
| 161 | elseif type(msg) ~= "string" then | ||
| 162 | return msg | ||
| 163 | end | ||
| 164 | if co == nil then | ||
| 165 | msg = debug_traceback(msg, level or 1) | ||
| 166 | else | ||
| 167 | local xpco = xpcall_running[co] | ||
| 168 | if xpco ~= nil then | ||
| 169 | lvl, level = calculate_trace_level(xpco, level) | ||
| 170 | if lvl then | ||
| 171 | msg = debug_traceback(xpco, msg, lvl) | ||
| 172 | else | ||
| 173 | msg = msg..stack_pattern | ||
| 174 | end | ||
| 175 | lvl, level = calculate_trace_level(co, level) | ||
| 176 | if lvl then | ||
| 177 | local trace = debug_traceback(co, "", lvl) | ||
| 178 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 179 | end | ||
| 180 | else | ||
| 181 | co = pcall_callOf[co] or co | ||
| 182 | lvl, level = calculate_trace_level(co, level) | ||
| 183 | if lvl then | ||
| 184 | msg = debug_traceback(co, msg, lvl) | ||
| 185 | else | ||
| 186 | msg = msg..stack_pattern | ||
| 187 | end | ||
| 188 | end | ||
| 189 | co = pcall_previous[co] | ||
| 190 | while co ~= nil do | ||
| 191 | lvl, level = calculate_trace_level(co, level) | ||
| 192 | if lvl then | ||
| 193 | local trace = debug_traceback(co, "", lvl) | ||
| 194 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 195 | end | ||
| 196 | co = pcall_previous[co] | ||
| 197 | end | ||
| 198 | end | ||
| 199 | if nilmsg then | ||
| 200 | msg = msg:gsub("^\n", "") | ||
| 201 | end | ||
| 202 | msg = msg:gsub("\n\t%(tail call%): %?", "\000") | ||
| 203 | msg = msg:gsub("\n\t%.%.%.\n", "\001\n") | ||
| 204 | msg = msg:gsub("\n\t%.%.%.$", "\001") | ||
| 205 | msg = msg:gsub("(%z+)\001(%z+)", function(some, other) | ||
| 206 | return "\n\t(..."..#some+#other.."+ tail call(s)...)" | ||
| 207 | end) | ||
| 208 | msg = msg:gsub("\001(%z+)", function(zeros) | ||
| 209 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 210 | end) | ||
| 211 | msg = msg:gsub("(%z+)\001", function(zeros) | ||
| 212 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 213 | end) | ||
| 214 | msg = msg:gsub("%z+", function(zeros) | ||
| 215 | return "\n\t(..."..#zeros.." tail call(s)...)" | ||
| 216 | end) | ||
| 217 | msg = msg:gsub("\001", function() | ||
| 218 | return "\n\t..." | ||
| 219 | end) | ||
| 220 | return msg | ||
| 221 | end | ||
| 222 | end -- is not luajit | ||
| 223 | end -- debug table available | ||
| 224 | |||
| 225 | |||
| 226 | if not is_luajit52 then | ||
| 227 | local coroutine_running52 = M.coroutine.running | ||
| 228 | function M.coroutine.running() | ||
| 229 | local co, ismain = coroutine_running52() | ||
| 230 | if ismain then | ||
| 231 | return co, true | ||
| 232 | else | ||
| 233 | return pcall_mainOf[co] or co, false | ||
| 234 | end | ||
| 235 | end | ||
| 236 | end | ||
| 237 | |||
| 238 | if not is_luajit then | ||
| 239 | local function pcall_results(current, call, success, ...) | ||
| 240 | if coroutine_status(call) == "suspended" then | ||
| 241 | return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) | ||
| 242 | end | ||
| 243 | if pcall_previous then | ||
| 244 | pcall_previous[call] = nil | ||
| 245 | local main = pcall_mainOf[call] | ||
| 246 | if main == current then current = nil end | ||
| 247 | pcall_callOf[main] = current | ||
| 248 | end | ||
| 249 | pcall_mainOf[call] = nil | ||
| 250 | return success, ... | ||
| 251 | end | ||
| 252 | |||
| 253 | local function pcall_exec(current, call, ...) | ||
| 254 | local main = pcall_mainOf[current] or current | ||
| 255 | pcall_mainOf[call] = main | ||
| 256 | if pcall_previous then | ||
| 257 | pcall_previous[call] = current | ||
| 258 | pcall_callOf[main] = call | ||
| 259 | end | ||
| 260 | return pcall_results(current, call, coroutine_resume(call, ...)) | ||
| 261 | end | ||
| 262 | |||
| 263 | local coroutine_create52 = M.coroutine.create | ||
| 264 | |||
| 265 | local function pcall_coroutine(func) | ||
| 266 | if type(func) ~= "function" then | ||
| 267 | local callable = func | ||
| 268 | func = function (...) return callable(...) end | ||
| 269 | end | ||
| 270 | return coroutine_create52(func) | ||
| 271 | end | ||
| 272 | |||
| 273 | function M.pcall(func, ...) | ||
| 274 | local current = coroutine_running() | ||
| 275 | if not current then return pcall(func, ...) end | ||
| 276 | return pcall_exec(current, pcall_coroutine(func), ...) | ||
| 277 | end | ||
| 278 | |||
| 279 | local function xpcall_catch(current, call, msgh, success, ...) | ||
| 280 | if not success then | ||
| 281 | xpcall_running[current] = call | ||
| 282 | local ok, result = pcall(msgh, ...) | ||
| 283 | xpcall_running[current] = nil | ||
| 284 | if not ok then | ||
| 285 | return false, "error in error handling ("..tostring(result)..")" | ||
| 286 | end | ||
| 287 | return false, result | ||
| 288 | end | ||
| 289 | return true, ... | ||
| 290 | end | ||
| 291 | |||
| 292 | function M.xpcall(f, msgh, ...) | ||
| 293 | local current = coroutine_running() | ||
| 294 | if not current then | ||
| 295 | local args, n = { ... }, select('#', ...) | ||
| 296 | return xpcall(function() return f(unpack(args, 1, n)) end, msgh) | ||
| 297 | end | ||
| 298 | local call = pcall_coroutine(f) | ||
| 299 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) | ||
| 300 | end | ||
| 301 | end -- not luajit | ||
| 302 | |||
| 303 | end -- lua 5.1 | ||
| 304 | |||
| 305 | |||
| 306 | -- handle exporting to global scope | ||
| 307 | local function extend_table(from, to) | ||
| 308 | if from ~= to then | ||
| 309 | for k,v in pairs(from) do | ||
| 310 | if type(v) == "table" and | ||
| 311 | type(to[k]) == "table" and | ||
| 312 | v ~= to[k] then | ||
| 313 | extend_table(v, to[k]) | ||
| 314 | else | ||
| 315 | to[k] = v | ||
| 316 | end | ||
| 317 | end | ||
| 318 | end | ||
| 319 | end | ||
| 320 | |||
| 321 | extend_table(M, _G) | ||
| 322 | |||
| 323 | end -- lua < 5.3 | ||
| 324 | |||
| 325 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : | ||
