• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lunarmodules / Penlight / 580

07 Aug 2025 08:56PM UTC coverage: 89.265% (+0.4%) from 88.871%
580

Pull #498

appveyor

Tieske
fix(*): some Lua 5.5 fixes for constant loop variables

see #497
Pull Request #498: fix(*): some Lua 5.5 fixes for constant loop variables

12 of 13 new or added lines in 4 files covered. (92.31%)

79 existing lines in 14 files now uncovered.

5480 of 6139 relevant lines covered (89.27%)

165.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.85
/lua/pl/compat.lua
1
----------------
2
--- Lua 5.1/5.2/5.3 compatibility.
3
-- Injects `table.pack`, `table.unpack`, and `package.searchpath` in the global
4
-- environment, to make sure they are available for Lua 5.1 and LuaJIT.
5
--
6
-- All other functions are exported as usual in the returned module table.
7
--
8
-- NOTE: everything in this module is also available in `pl.utils`.
9
-- @module pl.compat
10
local compat = {}
176✔
11

12
--- boolean flag this is Lua 5.1 (or LuaJIT).
13
-- @field lua51
14
compat.lua51 = _VERSION == 'Lua 5.1'
176✔
15

16
--- boolean flag this is LuaJIT.
17
-- @field jit
18
compat.jit = (tostring(assert):match('builtin') ~= nil)
176✔
19

20
--- boolean flag this is LuaJIT with 5.2 compatibility compiled in.
21
-- @field jit52
22
if compat.jit then
176✔
23
    -- 'goto' is a keyword when 52 compatibility is enabled in LuaJit
UNCOV
24
    compat.jit52 = not loadstring("local goto = 1")
×
25
end
26

27
--- the directory separator character for the current platform.
28
-- @field dir_separator
29
compat.dir_separator = _G.package.config:sub(1,1)
176✔
30

31
--- boolean flag this is a Windows platform.
32
-- @field is_windows
33
compat.is_windows = compat.dir_separator == '\\'
176✔
34

35
--- execute a shell command, in a compatible and platform independent way.
36
-- This is a compatibility function that returns the same for Lua 5.1 and
37
-- Lua 5.2+.
38
--
39
-- NOTE: Windows systems can use signed 32bit integer exitcodes. Posix systems
40
-- only use exitcodes 0-255, anything else is undefined.
41
--
42
-- NOTE2: In Lua 5.2 and 5.3 a Windows exitcode of -1 would not properly be
43
-- returned, this function will return it properly for all versions.
44
-- @param cmd a shell command
45
-- @return true if successful
46
-- @return actual return code
47
function compat.execute(cmd)
176✔
48
    local res1,res2,res3 = os.execute(cmd)
184✔
49
    if res2 == "No error" and res3 == 0 and compat.is_windows then
184✔
50
      -- os.execute bug in Lua 5.2/5.3 not reporting -1 properly on Windows
51
      -- this was fixed in 5.4
52
      res3 = -1
8✔
53
    end
54
    if compat.lua51 and not compat.jit52 then
184✔
55
        if compat.is_windows then
46✔
56
            return res1==0,res1
46✔
57
        else
UNCOV
58
            res1 = res1 > 255 and res1 / 256 or res1
×
UNCOV
59
            return res1==0,res1
×
60
        end
61
    else
UNCOV
62
        if compat.is_windows then
138✔
63
            return res3==0,res3
138✔
64
        else
UNCOV
65
            return not not res1,res3
×
66
        end
67
    end
68
end
69

70
----------------
71
-- Load Lua code as a text or binary chunk (in a Lua 5.2 compatible way).
72
-- @param ld code string or loader
73
-- @param[opt] source name of chunk for errors
74
-- @param[opt] mode 'b', 't' or 'bt'
75
-- @param[opt] env environment to load the chunk in
76
-- @function compat.load
77

78
---------------
79
-- Get environment of a function (in a Lua 5.1 compatible way).
80
-- Not 100% compatible, so with Lua 5.2 it may return nil for a function with no
81
-- global references!
82
-- Based on code by [Sergey Rozhenko](http://lua-users.org/lists/lua-l/2010-06/msg00313.html)
83
-- @param f a function or a call stack reference
84
-- @function compat.getfenv
85

86
---------------
87
-- Set environment of a function (in a Lua 5.1 compatible way).
88
-- @param f a function or a call stack reference
89
-- @param env a table that becomes the new environment of `f`
90
-- @function compat.setfenv
91

92
if compat.lua51 then -- define Lua 5.2 style load()
176✔
93
    if not compat.jit then -- but LuaJIT's load _is_ compatible
44✔
94
        local lua51_load = load
44✔
95
        function compat.load(str,src,mode,env)
44✔
96
            local chunk,err
97
            if type(str) == 'string' then
135✔
98
                if str:byte(1) == 27 and not (mode or 'bt'):find 'b' then
134✔
99
                    return nil,"attempt to load a binary chunk"
1✔
100
                end
101
                chunk,err = loadstring(str,src)
133✔
102
            else
103
                chunk,err = lua51_load(str,src)
1✔
104
            end
105
            if chunk and env then setfenv(chunk,env) end
134✔
106
            return chunk,err
134✔
107
        end
108
    else
UNCOV
109
        compat.load = load
×
110
    end
111
    compat.setfenv, compat.getfenv = setfenv, getfenv
44✔
112
else
UNCOV
113
    compat.load = load
132✔
114
    -- setfenv/getfenv replacements for Lua 5.2
115
    -- by Sergey Rozhenko
116
    -- http://lua-users.org/lists/lua-l/2010-06/msg00313.html
117
    -- Roberto Ierusalimschy notes that it is possible for getfenv to return nil
118
    -- in the case of a function with no globals:
119
    -- http://lua-users.org/lists/lua-l/2010-06/msg00315.html
UNCOV
120
    function compat.setfenv(f, t)
132✔
UNCOV
121
        f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
6✔
122
        local name
UNCOV
123
        local up = 0
6✔
124
        repeat
UNCOV
125
            up = up + 1
15✔
UNCOV
126
            name = debug.getupvalue(f, up)
15✔
UNCOV
127
        until name == '_ENV' or name == nil
15✔
UNCOV
128
        if name then
6✔
UNCOV
129
            debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue
6✔
UNCOV
130
            debug.setupvalue(f, up, t)
6✔
131
        end
UNCOV
132
        if f ~= 0 then return f end
6✔
133
    end
134

UNCOV
135
    function compat.getfenv(f)
132✔
UNCOV
136
        local f = f or 0
27✔
UNCOV
137
        f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
27✔
138
        local name, val
UNCOV
139
        local up = 0
27✔
140
        repeat
UNCOV
141
            up = up + 1
36✔
UNCOV
142
            name, val = debug.getupvalue(f, up)
36✔
UNCOV
143
        until name == '_ENV' or name == nil
36✔
UNCOV
144
        return val
27✔
145
    end
146
end
147

148

149
--- Global exported functions (for Lua 5.1 & LuaJIT)
150
-- @section lua52
151

152
--- pack an argument list into a table.
153
-- @param ... any arguments
154
-- @return a table with field n set to the length
155
-- @function table.pack
156
if not table.pack then
176✔
157
    function table.pack (...)       -- luacheck: ignore
88✔
158
        return {n=select('#',...); ...}
79✔
159
    end
160
end
161

162
--- unpack a table and return the elements.
163
--
164
-- NOTE: this version does NOT honor the n field, and hence it is not nil-safe.
165
-- See `utils.unpack` for a version that is nil-safe.
166
-- @param t table to unpack
167
-- @param[opt] i index from which to start unpacking, defaults to 1
168
-- @param[opt] j index of the last element to unpack, defaults to #t
169
-- @return multiple return values from the table
170
-- @function table.unpack
171
-- @see utils.unpack
172
if not table.unpack then
176✔
173
    table.unpack = unpack           -- luacheck: ignore
44✔
174
end
175

176
--- return the full path where a file name would be matched.
177
-- This function was introduced in Lua 5.2, so this compatibility version
178
-- will be injected in Lua 5.1 engines.
179
-- @string name file name, possibly dotted
180
-- @string path a path-template in the same form as package.path or package.cpath
181
-- @string[opt] sep template separate character to be replaced by path separator. Default: "."
182
-- @string[opt] rep the path separator to use, defaults to system separator. Default; "/" on Unixes, "\" on Windows.
183
-- @see path.package_path
184
-- @function package.searchpath
185
-- @return on success: path of the file
186
-- @return on failure: nil, error string listing paths tried
187
if not package.searchpath then
176✔
188
    function package.searchpath (name,path,sep,rep)    -- luacheck: ignore
88✔
189
        if type(name) ~= "string" then
4✔
190
            error(("bad argument #1 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
191
        end
192
        if type(path) ~= "string" then
4✔
193
            error(("bad argument #2 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
194
        end
195
        if sep ~= nil and type(sep) ~= "string" then
4✔
196
            error(("bad argument #3 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
197
        end
198
        if rep ~= nil and type(rep) ~= "string" then
4✔
199
            error(("bad argument #4 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
200
        end
201
        sep = sep or "."
4✔
202
        rep = rep or compat.dir_separator
4✔
203
        do
204
          local s, e = name:find(sep, nil, true)
4✔
205
          while s do
10✔
206
            name = name:sub(1, s-1) .. rep .. name:sub(e+1, -1)
6✔
207
            s, e = name:find(sep, s + #rep + 1, true)
6✔
208
          end
209
        end
210
        local tried = {}
4✔
211
        for m in path:gmatch('[^;]+') do
10✔
212
            local nm = m:gsub('?', name)
8✔
213
            tried[#tried+1] = nm
8✔
214
            local f = io.open(nm,'r')
8✔
215
            if f then f:close(); return nm end
8✔
216
        end
217
        return nil, "\tno file '" .. table.concat(tried, "'\n\tno file '") .. "'"
2✔
218
    end
219
end
220

221
--- Global exported functions (for Lua < 5.4)
222
-- @section lua54
223

224
--- raise a warning message.
225
-- This functions mimics the `warn` function added in Lua 5.4.
226
-- @function warn
227
-- @param ... any arguments
228
if not rawget(_G, "warn") then
176✔
229
    local enabled = false
132✔
230
    local function warn(arg1, ...)
231
        if type(arg1) == "string" and arg1:sub(1, 1) == "@" then
24✔
232
            -- control message
233
            if arg1 == "@on" then
×
234
                enabled = true
×
235
                return
×
236
            end
237
            if arg1 == "@off" then
×
238
                enabled = false
×
239
                return
×
240
            end
241
            return -- ignore unknown control messages
×
242
        end
243
        if enabled then
24✔
244
          io.stderr:write("Lua warning: ", arg1, ...)
×
245
          io.stderr:write("\n")
×
246
        end
247
    end
248
    -- use rawset to bypass OpenResty's protection of global scope
249
    rawset(_G, "warn", warn)
132✔
250
end
251

252
return compat
176✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc