mtxrun.lua /size: 676 Kb    last modification: 2021-10-28 13:50
1
#
!
/
usr
/
bin
/
env
texlua
2 3
if
not
modules
then
modules
=
{
}
end
modules
[
'
mtxrun
'
]
=
{
4
version
=
1
.
001
,
5
comment
=
"
runner, lua replacement for texmfstart.rb
"
,
6
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
7
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
8
license
=
"
see context related readme files
"
9
}
10 11
-- one can make a stub:
12 13
-- mtxrun :
14
--
15
-- #!/bin/sh
16
-- env LUATEXDIR=/....../texmf/scripts/context/lua luatex --luaonly mtxrun.lua "$@"
17 18
-- mtxrun.cmd :
19
--
20
-- @luatex --luaonly %~d0%~p0mtxrun.lua %*
21 22
-- filename : mtxrun.lua
23
-- comment : companion to context.tex
24
-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
25
-- copyright: PRAGMA ADE / ConTeXt Development Team
26
-- license : see context related readme files
27 28
-- This script is based on texmfstart.rb but does not use kpsewhich to locate files.
29
-- Although kpse is a library it never came to opening up its interface to other
30
-- programs (esp scripting languages) and so we do it ourselves. The lua variant
31
-- evolved out of an experimental ruby one. Interesting is that using a scripting
32
-- language instead of c does not have a speed penalty. Actually the lua variant is
33
-- more efficient, especially when multiple calls to kpsewhich are involved. The lua
34
-- library also gives way more control.
35 36
-- When libraries used here are updates you can run
37
--
38
-- mtxrun --selfmerge
39
--
40
-- to update the embedded code. After that you might need to run
41
--
42
-- mtxrun --selfupdate
43
--
44
-- to copy the new script (from scripts/context/lua) to location where
45
-- binaries are expected. If you want to remove the embedded code you can run
46
--
47
-- mtxxun --selfclean
48 49
-- to be done / considered
50
--
51
-- support for --exec or make it default
52
-- support for jar files (or maybe not, never used, too messy)
53
-- support for $RUBYINPUTS cum suis (if still needed)
54
-- remember for subruns: _CTX_K_V_#{original}_
55
-- remember for subruns: _CTX_K_S_#{original}_
56
-- remember for subruns: TEXMFSTART.#{original} [tex.rb texmfstart.rb]
57 58
-- begin library merge
59 60 61 62
do
-- create closure to overcome 200 locals limit
63 64
package
.
loaded
[
"
l-bit32
"
]
=
package
.
loaded
[
"
l-bit32
"
]
or
true
65 66
-- original size: 3607, stripped down to: 3009
67 68
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-bit32
'
]
=
{
69
version
=
1
.
001
,
70
license
=
"
the same as regular Lua
"
,
71
source
=
"
bitwise.lua, v 1.24 2014/12/26 17:20:53 roberto
"
,
72
comment
=
"
drop-in for bit32, adapted a bit by Hans Hagen
"
,
73
}
74
if
bit32
then
75
elseif
utf8
then
76
load
(
[[
77local select = select -- instead of: arg = { ... } 78bit32 = { 79 bnot = function (a) 80 return ~a & 0xFFFFFFFF 81 end, 82 band = function (x, y, z, ...) 83 if not z then 84 return ((x or -1) & (y or -1)) & 0xFFFFFFFF 85 else 86 local res = x & y & z 87 for i=1,select("#",...) do 88 res = res & select(i,...) 89 end 90 return res & 0xFFFFFFFF 91 end 92 end, 93 bor = function (x, y, z, ...) 94 if not z then 95 return ((x or 0) | (y or 0)) & 0xFFFFFFFF 96 else 97 local res = x | y | z 98 for i=1,select("#",...) do 99 res = res | select(i,...) 100 end 101 return res & 0xFFFFFFFF 102 end 103 end, 104 bxor = function (x, y, z, ...) 105 if not z then 106 return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF 107 else 108 local res = x ~ y ~ z 109 for i=1,select("#",...) do 110 res = res ~ select(i,...) 111 end 112 return res & 0xFFFFFFFF 113 end 114 end, 115 btest = function (x, y, z, ...) 116 if not z then 117 return (((x or -1) & (y or -1)) & 0xFFFFFFFF) ~= 0 118 else 119 local res = x & y & z 120 for i=1,select("#",...) do 121 res = res & select(i,...) 122 end 123 return (res & 0xFFFFFFFF) ~= 0 124 end 125 end, 126 lshift = function (a, b) 127 return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF 128 end, 129 rshift = function (a, b) 130 return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF 131 end, 132 arshift = function (a, b) 133 a = a & 0xFFFFFFFF 134 if b <= 0 or (a & 0x80000000) == 0 then 135 return (a >> b) & 0xFFFFFFFF 136 else 137 return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF 138 end 139 end, 140 lrotate = function (a ,b) 141 b = b & 31 142 a = a & 0xFFFFFFFF 143 a = (a << b) | (a >> (32 - b)) 144 return a & 0xFFFFFFFF 145 end, 146 rrotate = function (a, b) 147 b = -b & 31 148 a = a & 0xFFFFFFFF 149 a = (a << b) | (a >> (32 - b)) 150 return a & 0xFFFFFFFF 151 end, 152 extract = function (a, f, w) 153 return (a >> f) & ~(-1 << (w or 1)) 154 end, 155 replace = function (a, v, f, w) 156 local mask = ~(-1 << (w or 1)) 157 return ((a & ~(mask << f)) | ((v & mask) << f)) & 0xFFFFFFFF 158 end, 159} 160
]]
)
(
)
161
elseif
bit
then
162
load
(
[[
163local band, bnot, rshift, lshift = bit.band, bit.bnot, bit.rshift, bit.lshift 164bit32 = { 165 arshift = bit.arshift, 166 band = band, 167 bnot = bnot, 168 bor = bit.bor, 169 bxor = bit.bxor, 170 btest = function(...) 171 return band(...) ~= 0 172 end, 173 extract = function(a,f,w) 174 return band(rshift(a,f),2^(w or 1)-1) 175 end, 176 lrotate = bit.rol, 177 lshift = lshift, 178 replace = function(a,v,f,w) 179 local mask = 2^(w or 1)-1 180 return band(a,bnot(lshift(mask,f)))+lshift(band(v,mask),f) 181 end, 182 rrotate = bit.ror, 183 rshift = rshift, 184} 185
]]
)
(
)
186
else
187
xpcall
(
function
(
)
local
_
,
t
=
require
(
"
bit32
"
)
if
t
then
bit32
=
t
end
return
end
,
function
(
)
end
)
188
end
189 190 191
end
-- of closure
192 193
do
-- create closure to overcome 200 locals limit
194 195
package
.
loaded
[
"
l-lua
"
]
=
package
.
loaded
[
"
l-lua
"
]
or
true
196 197
-- original size: 6405, stripped down to: 2865
198 199
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-lua
'
]
=
{
200
version
=
1
.
001
,
201
comment
=
"
companion to luat-lib.mkiv
"
,
202
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
203
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
204
license
=
"
see context related readme files
"
205
}
206
local
next
,
type
,
tonumber
=
next
,
type
,
tonumber
207
LUAMAJORVERSION
,
LUAMINORVERSION
=
string
.
match
(
_VERSION
,
"
^[^%d]+(%d+)%.(%d+).*$
"
)
208
LUAMAJORVERSION
=
tonumber
(
LUAMAJORVERSION
)
or
5
209
LUAMINORVERSION
=
tonumber
(
LUAMINORVERSION
)
or
1
210
LUAVERSION
=
LUAMAJORVERSION
+
LUAMINORVERSION
/
10
211
if
LUAVERSION
<
5
.
2
and
jit
then
212
MINORVERSION
=
2
213
LUAVERSION
=
5
.
2
214
end
215
if
not
lpeg
then
216
lpeg
=
require
(
"
lpeg
"
)
217
end
218
if
loadstring
then
219
local
loadnormal
=
load
220
function
load
(
first
,
...
)
221
if
type
(
first
)
=
=
"
string
"
then
222
return
loadstring
(
first
,
...
)
223
else
224
return
loadnormal
(
first
,
...
)
225
end
226
end
227
else
228
loadstring
=
load
229
end
230
if
not
ipairs
then
231
local
function
iterate
(
a
,
i
)
232
i
=
i
+
1
233
local
v
=
a
[
i
]
234
if
v
~
=
nil
then
235
return
i
,
v
236
end
237
end
238
function
ipairs
(
a
)
239
return
iterate
,
a
,
0
240
end
241
end
242
if
not
pairs
then
243
function
pairs
(
t
)
244
return
next
,
t
245
end
246
end
247
if
not
table
.
unpack
then
248
table
.
unpack
=
_G
.
unpack
249
elseif
not
unpack
then
250
_G
.
unpack
=
table
.
unpack
251
end
252
if
not
package
.
loaders
then
253
package
.
loaders
=
package
.
searchers
254
end
255
local
print
,
select
,
tostring
=
print
,
select
,
tostring
256
local
inspectors
=
{
}
257
function
setinspector
(
kind
,
inspector
)
258
inspectors
[
kind
]
=
inspector
259
end
260
function
inspect
(
...
)
261
for
s
=
1
,
select
(
"
#
"
,
...
)
do
262
local
value
=
select
(
s
,
...
)
263
if
value
=
=
nil
then
264
print
(
"
nil
"
)
265
else
266
local
done
=
false
267
local
kind
=
type
(
value
)
268
local
inspector
=
inspectors
[
kind
]
269
if
inspector
then
270
done
=
inspector
(
value
)
271
if
done
then
272
break
273
end
274
end
275
for
kind
,
inspector
in
next
,
inspectors
do
276
done
=
inspector
(
value
)
277
if
done
then
278
break
279
end
280
end
281
if
not
done
then
282
print
(
tostring
(
value
)
)
283
end
284
end
285
end
286
end
287
local
dummy
=
function
(
)
end
288
function
optionalrequire
(
...
)
289
local
ok
,
result
=
xpcall
(
require
,
dummy
,
...
)
290
if
ok
then
291
return
result
292
end
293
end
294
local
flush
=
io
.
flush
295
if
flush
then
296
local
execute
=
os
.
execute
if
execute
then
function
os
.
execute
(
...
)
flush
(
)
return
execute
(
...
)
end
end
297
local
exec
=
os
.
exec
if
exec
then
function
os
.
exec
(
...
)
flush
(
)
return
exec
(
...
)
end
end
298
local
spawn
=
os
.
spawn
if
spawn
then
function
os
.
spawn
(
...
)
flush
(
)
return
spawn
(
...
)
end
end
299
local
popen
=
io
.
popen
if
popen
then
function
io
.
popen
(
...
)
flush
(
)
return
popen
(
...
)
end
end
300
end
301
FFISUPPORTED
=
type
(
ffi
)
=
=
"
table
"
and
ffi
.
os
~
=
"
"
and
ffi
.
arch
~
=
"
"
and
ffi
.
load
302
if
not
FFISUPPORTED
then
303
local
okay
;
okay
,
ffi
=
pcall
(
require
,
"
ffi
"
)
304
FFISUPPORTED
=
type
(
ffi
)
=
=
"
table
"
and
ffi
.
os
~
=
"
"
and
ffi
.
arch
~
=
"
"
and
ffi
.
load
305
end
306
if
not
FFISUPPORTED
then
307
ffi
=
nil
308
elseif
not
ffi
.
number
then
309
ffi
.
number
=
tonumber
310
end
311
if
LUAVERSION
>
5
.
3
then
312
end
313
if
status
and
os
.
setenv
then
314
os
.
setenv
(
"
engine
"
,
string
.
lower
(
status
.
luatex_engine
or
"
unknown
"
)
)
315
end
316 317 318
end
-- of closure
319 320
do
-- create closure to overcome 200 locals limit
321 322
package
.
loaded
[
"
l-macro
"
]
=
package
.
loaded
[
"
l-macro
"
]
or
true
323 324
-- original size: 10130, stripped down to: 5990
325 326
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-macros
'
]
=
{
327
version
=
1
.
001
,
328
comment
=
"
companion to luat-lib.mkiv
"
,
329
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
330
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
331
license
=
"
see context related readme files
"
332
}
333
local
S
,
P
,
R
,
V
,
C
,
Cs
,
Cc
,
Ct
,
Carg
=
lpeg
.
S
,
lpeg
.
P
,
lpeg
.
R
,
lpeg
.
V
,
lpeg
.
C
,
lpeg
.
Cs
,
lpeg
.
Cc
,
lpeg
.
Ct
,
lpeg
.
Carg
334
local
lpegmatch
=
lpeg
.
match
335
local
concat
=
table
.
concat
336
local
format
,
sub
,
match
=
string
.
format
,
string
.
sub
,
string
.
match
337
local
next
,
load
,
type
=
next
,
load
,
type
338
local
newline
=
S
(
"
\n\r
"
)
^
1
339
local
continue
=
P
(
"
\\
"
)
*
newline
340
local
whitespace
=
S
(
"
\t\n\r
"
)
341
local
spaces
=
S
(
"
\t
"
)
+
continue
342
local
nametoken
=
R
(
"
az
"
,
"
AZ
"
,
"
__
"
,
"
09
"
)
343
local
name
=
nametoken
^
1
344
local
body
=
(
(
continue
/
"
"
+
1
)
-
newline
)
^
1
345
local
lparent
=
P
(
"
(
"
)
346
local
rparent
=
P
(
"
)
"
)
347
local
noparent
=
1
-
(
lparent
+
rparent
)
348
local
nested
=
P
{
lparent
*
(
noparent
+
V
(
1
)
)
^
0
*
rparent
}
349
local
escaped
=
P
(
"
\\
"
)
*
P
(
1
)
350
local
squote
=
P
(
"
'
"
)
351
local
dquote
=
P
(
'
"
'
)
352
local
quoted
=
dquote
*
(
escaped
+
(
1
-
dquote
)
)
^
0
*
dquote
+
squote
*
(
escaped
+
(
1
-
squote
)
)
^
0
*
squote
353
local
arguments
=
lparent
*
Ct
(
(
Cs
(
(
nested
+
(
quoted
+
1
-
S
(
"
),
"
)
)
)
^
1
)
+
S
(
"
,
"
)
)
^
0
)
*
rparent
354
local
macros
=
lua
.
macros
or
{
}
355
lua
.
macros
=
macros
356
local
patterns
=
{
}
357
local
definitions
=
{
}
358
local
resolve
359
local
subparser
360
local
report_lua
=
function
(
...
)
361
if
logs
and
logs
.
reporter
then
362
report_lua
=
logs
.
reporter
(
"
system
"
,
"
lua
"
)
363
report_lua
(
...
)
364
else
365
print
(
format
(
...
)
)
366
end
367
end
368
local
safeguard
=
P
(
"
local
"
)
*
whitespace
^
1
*
name
*
(
whitespace
+
P
(
"
=
"
)
)
369
resolve
=
safeguard
+
C
(
C
(
name
)
*
(
arguments
^
-1
)
)
/
function
(
raw
,
s
,
a
)
370
local
d
=
definitions
[
s
]
371
if
d
then
372
if
a
then
373
local
n
=
#
a
374
local
p
=
patterns
[
s
]
[
n
]
375
if
p
then
376
local
d
=
d
[
n
]
377
for
i
=
1
,
n
do
378
a
[
i
]
=
lpegmatch
(
subparser
,
a
[
i
]
)
or
a
[
i
]
379
end
380
return
lpegmatch
(
p
,
d
,
1
,
a
)
or
d
381
else
382
return
raw
383
end
384
else
385
return
d
[
0
]
or
raw
386
end
387
elseif
a
then
388
for
i
=
1
,
#
a
do
389
a
[
i
]
=
lpegmatch
(
subparser
,
a
[
i
]
)
or
a
[
i
]
390
end
391
return
s
.
.
"
(
"
.
.
concat
(
a
,
"
,
"
)
.
.
"
)
"
392
else
393
return
raw
394
end
395
end
396
subparser
=
Cs
(
(
resolve
+
P
(
1
)
)
^
1
)
397
local
enddefine
=
P
(
"
#enddefine
"
)
/
"
"
398
local
beginregister
=
(
C
(
name
)
*
(
arguments
+
Cc
(
false
)
)
*
C
(
(
1
-
enddefine
)
^
1
)
*
enddefine
)
/
function
(
k
,
a
,
v
)
399
local
n
=
0
400
if
a
then
401
n
=
#
a
402
local
pattern
=
P
(
false
)
403
for
i
=
1
,
n
do
404
pattern
=
pattern
+
(
P
(
a
[
i
]
)
*
Carg
(
1
)
)
/
function
(
t
)
return
t
[
i
]
end
405
end
406
pattern
=
Cs
(
(
pattern
+
P
(
1
)
)
^
1
)
407
local
p
=
patterns
[
k
]
408
if
not
p
then
409
p
=
{
[
0
]
=
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
}
410
patterns
[
k
]
=
p
411
end
412
p
[
n
]
=
pattern
413
end
414
local
d
=
definitions
[
k
]
415
if
not
d
then
416
d
=
{
a
=
a
,
[
0
]
=
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
}
417
definitions
[
k
]
=
d
418
end
419
d
[
n
]
=
lpegmatch
(
subparser
,
v
)
or
v
420
return
"
"
421
end
422
local
register
=
(
Cs
(
name
)
*
(
arguments
+
Cc
(
false
)
)
*
spaces
^
0
*
Cs
(
body
)
)
/
function
(
k
,
a
,
v
)
423
local
n
=
0
424
if
a
then
425
n
=
#
a
426
local
pattern
=
P
(
false
)
427
for
i
=
1
,
n
do
428
pattern
=
pattern
+
(
P
(
a
[
i
]
)
*
Carg
(
1
)
)
/
function
(
t
)
return
t
[
i
]
end
429
end
430
pattern
=
Cs
(
(
pattern
+
P
(
1
)
)
^
1
)
431
local
p
=
patterns
[
k
]
432
if
not
p
then
433
p
=
{
[
0
]
=
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
}
434
patterns
[
k
]
=
p
435
end
436
p
[
n
]
=
pattern
437
end
438
local
d
=
definitions
[
k
]
439
if
not
d
then
440
d
=
{
a
=
a
,
[
0
]
=
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
,
false
}
441
definitions
[
k
]
=
d
442
end
443
d
[
n
]
=
lpegmatch
(
subparser
,
v
)
or
v
444
return
"
"
445
end
446
local
unregister
=
(
C
(
name
)
*
spaces
^
0
*
(
arguments
+
Cc
(
false
)
)
)
/
function
(
k
,
a
)
447
local
n
=
0
448
if
a
then
449
n
=
#
a
450
local
p
=
patterns
[
k
]
451
if
p
then
452
p
[
n
]
=
false
453
end
454
end
455
local
d
=
definitions
[
k
]
456
if
d
then
457
d
[
n
]
=
false
458
end
459
return
"
"
460
end
461
local
begindefine
=
(
P
(
"
begindefine
"
)
*
spaces
^
0
/
"
"
)
*
beginregister
462
local
define
=
(
P
(
"
define
"
)
*
spaces
^
0
/
"
"
)
*
register
463
local
undefine
=
(
P
(
"
undefine
"
)
*
spaces
^
0
/
"
"
)
*
unregister
464
local
parser
=
Cs
(
(
(
(
P
(
"
#
"
)
/
"
"
)
*
(
define
+
begindefine
+
undefine
)
*
(
newline
^
0
/
"
"
)
)
+
resolve
+
P
(
1
)
)
^
0
)
465
function
macros
.
reset
(
)
466
definitions
=
{
}
467
patterns
=
{
}
468
end
469
function
macros
.
showdefinitions
(
)
470
for
name
,
list
in
table
.
sortedhash
(
definitions
)
do
471
local
arguments
=
list
.
a
472
if
arguments
then
473
arguments
=
"
(
"
.
.
concat
(
arguments
,
"
,
"
)
.
.
"
)
"
474
else
475
arguments
=
"
"
476
end
477
print
(
"
macro:
"
.
.
name
.
.
arguments
)
478
for
i
=
0
,
#
list
do
479
local
l
=
list
[
i
]
480
if
l
then
481
print
(
"
"
.
.
l
)
482
end
483
end
484
end
485
end
486
function
macros
.
resolvestring
(
str
)
487
return
lpegmatch
(
parser
,
str
)
or
str
488
end
489
function
macros
.
resolving
(
)
490
return
next
(
patterns
)
491
end
492
local
function
reload
(
path
,
name
,
data
)
493
local
only
=
match
(
name
,
"
.-([^/]+)%.lua
"
)
494
if
only
and
only
~
=
"
"
then
495
local
name
=
path
.
.
"
/
"
.
.
only
496
local
f
=
io
.
open
(
name
,
"
wb
"
)
497
f
:
write
(
data
)
498
f
:
close
(
)
499
local
f
=
loadfile
(
name
)
500
os
.
remove
(
name
)
501
return
f
502
end
503
end
504
local
function
reload
(
path
,
name
,
data
)
505
if
path
and
path
~
=
"
"
then
506
local
only
=
string
.
match
(
name
,
"
.-([^/]+)%.lua
"
)
507
if
only
and
only
~
=
"
"
then
508
local
name
=
path
.
.
"
/
"
.
.
only
.
.
"
-macro.lua
"
509
local
f
=
io
.
open
(
name
,
"
wb
"
)
510
if
f
then
511
f
:
write
(
data
)
512
f
:
close
(
)
513
local
l
=
loadfile
(
name
)
514
os
.
remove
(
name
)
515
return
l
516
end
517
end
518
end
519
return
load
(
data
,
name
)
520
end
521
local
function
loaded
(
name
,
trace
,
detail
)
522
local
f
=
io
.
open
(
name
,
"
rb
"
)
523
if
not
f
then
524
return
false
,
format
(
"
file '%s' not found
"
,
name
)
525
end
526
local
c
=
f
:
read
(
"
*a
"
)
527
if
not
c
then
528
return
false
,
format
(
"
file '%s' is invalid
"
,
name
)
529
end
530
f
:
close
(
)
531
local
n
=
lpegmatch
(
parser
,
c
)
532
if
trace
then
533
if
#
n
~
=
#
c
then
534
report_lua
(
"
macros expanded in '%s' (%i => %i bytes)
"
,
name
,
#
c
,
#
n
)
535
if
detail
then
536
report_lua
(
)
537
report_lua
(
n
)
538
report_lua
(
)
539
end
540
elseif
detail
then
541
report_lua
(
"
no macros expanded in '%s'
"
,
name
)
542
end
543
end
544
return
reload
(
lfs
and
lfs
.
currentdir
(
)
,
name
,
n
)
545
end
546
macros
.
loaded
=
loaded
547
function
required
(
name
,
trace
)
548
local
filename
=
file
.
addsuffix
(
name
,
"
lua
"
)
549
local
fullname
=
resolvers
and
resolvers
.
findfile
(
filename
)
or
filename
550
if
not
fullname
or
fullname
=
=
"
"
then
551
return
false
552
end
553
local
codeblob
=
package
.
loaded
[
fullname
]
554
if
codeblob
then
555
return
codeblob
556
end
557
local
code
,
message
=
loaded
(
fullname
,
macros
,
trace
,
trace
)
558
if
type
(
code
)
=
=
"
function
"
then
559
code
=
code
(
)
560
else
561
report_lua
(
"
error when loading '%s'
"
,
fullname
)
562
return
false
,
message
563
end
564
if
code
=
=
nil
then
565
code
=
false
566
end
567
package
.
loaded
[
fullname
]
=
code
568
return
code
569
end
570
macros
.
required
=
required
571 572 573
end
-- of closure
574 575
do
-- create closure to overcome 200 locals limit
576 577
package
.
loaded
[
"
l-sandbox
"
]
=
package
.
loaded
[
"
l-sandbox
"
]
or
true
578 579
-- original size: 9604, stripped down to: 6394
580 581
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-sandbox
'
]
=
{
582
version
=
1
.
001
,
583
comment
=
"
companion to luat-lib.mkiv
"
,
584
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
585
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
586
license
=
"
see context related readme files
"
587
}
588
local
global
=
_G
589
local
next
=
next
590
local
unpack
=
unpack
or
table
.
unpack
591
local
type
=
type
592
local
tprint
=
texio
and
texio
.
write_nl
or
print
593
local
tostring
=
tostring
594
local
format
=
string
.
format
595
local
concat
=
table
.
concat
596
local
sort
=
table
.
sort
597
local
gmatch
=
string
.
gmatch
598
local
gsub
=
string
.
gsub
599
local
requiem
=
require
600
sandbox
=
{
}
601
local
sandboxed
=
false
602
local
overloads
=
{
}
603
local
skiploads
=
{
}
604
local
initializers
=
{
}
605
local
finalizers
=
{
}
606
local
originals
=
{
}
607
local
comments
=
{
}
608
local
trace
=
false
609
local
logger
=
false
610
local
blocked
=
{
}
611
local
function
report
(
...
)
612
tprint
(
"
sandbox !
"
.
.
format
(
...
)
)
613
end
614
sandbox
.
report
=
report
615
function
sandbox
.
setreporter
(
r
)
616
report
=
r
617
sandbox
.
report
=
r
618
end
619
function
sandbox
.
settrace
(
v
)
620
trace
=
v
621
end
622
function
sandbox
.
setlogger
(
l
)
623
logger
=
type
(
l
)
=
=
"
function
"
and
l
or
false
624
end
625
local
function
register
(
func
,
overload
,
comment
)
626
if
type
(
func
)
=
=
"
function
"
then
627
if
type
(
overload
)
=
=
"
string
"
then
628
comment
=
overload
629
overload
=
nil
630
end
631
local
function
f
(
...
)
632
if
sandboxed
then
633
local
overload
=
overloads
[
f
]
634
if
overload
then
635
if
logger
then
636
local
result
=
{
overload
(
func
,
...
)
}
637
logger
{
638
comment
=
comments
[
f
]
or
tostring
(
f
)
,
639
arguments
=
{
...
}
,
640
result
=
result
[
1
]
and
true
or
false
,
641
}
642
return
unpack
(
result
)
643
else
644
return
overload
(
func
,
...
)
645
end
646
else
647
end
648
else
649
return
func
(
...
)
650
end
651
end
652
if
comment
then
653
comments
[
f
]
=
comment
654
if
trace
then
655
report
(
"
registering function: %s
"
,
comment
)
656
end
657
end
658
overloads
[
f
]
=
overload
or
false
659
originals
[
f
]
=
func
660
return
f
661
end
662
end
663
local
function
redefine
(
func
,
comment
)
664
if
type
(
func
)
=
=
"
function
"
then
665
skiploads
[
func
]
=
comment
or
comments
[
func
]
or
"
unknown
"
666
if
overloads
[
func
]
=
=
false
then
667
overloads
[
func
]
=
nil
668
end
669
end
670
end
671
sandbox
.
register
=
register
672
sandbox
.
redefine
=
redefine
673
function
sandbox
.
original
(
func
)
674
return
originals
and
originals
[
func
]
or
func
675
end
676
function
sandbox
.
overload
(
func
,
overload
,
comment
)
677
comment
=
comment
or
comments
[
func
]
or
"
?
"
678
if
type
(
func
)
~
=
"
function
"
then
679
if
trace
then
680
report
(
"
overloading unknown function: %s
"
,
comment
)
681
end
682
elseif
type
(
overload
)
~
=
"
function
"
then
683
if
trace
then
684
report
(
"
overloading function with bad overload: %s
"
,
comment
)
685
end
686
elseif
overloads
[
func
]
=
=
nil
then
687
if
trace
then
688
report
(
"
function is not registered: %s
"
,
comment
)
689
end
690
elseif
skiploads
[
func
]
then
691
if
trace
then
692
report
(
"
function is not skipped: %s
"
,
comment
)
693
end
694
else
695
if
trace
then
696
report
(
"
overloading function: %s
"
,
comment
)
697
end
698
overloads
[
func
]
=
overload
699
end
700
return
func
701
end
702
local
function
whatever
(
specification
,
what
,
target
)
703
if
type
(
specification
)
~
=
"
table
"
then
704
report
(
"
%s needs a specification
"
,
what
)
705
elseif
type
(
specification
.
category
)
~
=
"
string
"
or
type
(
specification
.
action
)
~
=
"
function
"
then
706
report
(
"
%s needs a category and action
"
,
what
)
707
elseif
not
sandboxed
then
708
target
[
#
target
+
1
]
=
specification
709
elseif
trace
then
710
report
(
"
already enabled, discarding %s
"
,
what
)
711
end
712
end
713
function
sandbox
.
initializer
(
specification
)
714
whatever
(
specification
,
"
initializer
"
,
initializers
)
715
end
716
function
sandbox
.
finalizer
(
specification
)
717
whatever
(
specification
,
"
finalizer
"
,
finalizers
)
718
end
719
function
require
(
name
)
720
local
n
=
gsub
(
name
,
"
^.*[\\/]
"
,
"
"
)
721
local
n
=
gsub
(
n
,
"
[%.].*$
"
,
"
"
)
722
local
b
=
blocked
[
n
]
723
if
b
=
=
false
then
724
return
nil
725
elseif
b
then
726
if
trace
then
727
report
(
"
using blocked: %s
"
,
n
)
728
end
729
return
b
730
else
731
if
trace
then
732
report
(
"
requiring: %s
"
,
name
)
733
end
734
return
requiem
(
name
)
735
end
736
end
737
function
blockrequire
(
name
,
lib
)
738
if
trace
then
739
report
(
"
preventing reload of: %s
"
,
name
)
740
end
741
blocked
[
name
]
=
lib
or
_G
[
name
]
or
false
742
end
743
function
sandbox
.
enable
(
)
744
if
not
sandboxed
then
745
debug
=
{
746
traceback
=
debug
.
traceback
,
747
}
748
for
i
=
1
,
#
initializers
do
749
initializers
[
i
]
.
action
(
)
750
end
751
for
i
=
1
,
#
finalizers
do
752
finalizers
[
i
]
.
action
(
)
753
end
754
local
nnot
=
0
755
local
nyes
=
0
756
local
cnot
=
{
}
757
local
cyes
=
{
}
758
local
skip
=
{
}
759
for
k
,
v
in
next
,
overloads
do
760
local
c
=
comments
[
k
]
761
if
v
then
762
if
c
then
763
cyes
[
#
cyes
+
1
]
=
c
764
else
765
nyes
=
nyes
+
1
766
end
767
else
768
if
c
then
769
cnot
[
#
cnot
+
1
]
=
c
770
else
771
nnot
=
nnot
+
1
772
end
773
end
774
end
775
for
k
,
v
in
next
,
skiploads
do
776
skip
[
#
skip
+
1
]
=
v
777
end
778
if
#
cyes
>
0
then
779
sort
(
cyes
)
780
report
(
"
overloaded known: %s
"
,
concat
(
cyes
,
"
|
"
)
)
781
end
782
if
nyes
>
0
then
783
report
(
"
overloaded unknown: %s
"
,
nyes
)
784
end
785
if
#
cnot
>
0
then
786
sort
(
cnot
)
787
report
(
"
not overloaded known: %s
"
,
concat
(
cnot
,
"
|
"
)
)
788
end
789
if
nnot
>
0
then
790
report
(
"
not overloaded unknown: %s
"
,
nnot
)
791
end
792
if
#
skip
>
0
then
793
sort
(
skip
)
794
report
(
"
not overloaded redefined: %s
"
,
concat
(
skip
,
"
|
"
)
)
795
end
796
initializers
=
nil
797
finalizers
=
nil
798
originals
=
nil
799
sandboxed
=
true
800
end
801
end
802
blockrequire
(
"
lfs
"
,
lfs
)
803
blockrequire
(
"
io
"
,
io
)
804
blockrequire
(
"
os
"
,
os
)
805
blockrequire
(
"
ffi
"
,
ffi
)
806
local
function
supported
(
library
)
807
local
l
=
_G
[
library
]
808
return
l
809
end
810
loadfile
=
register
(
loadfile
,
"
loadfile
"
)
811
if
supported
(
"
lua
"
)
then
812
lua
.
openfile
=
register
(
lua
.
openfile
,
"
lua.openfile
"
)
813
end
814
if
supported
(
"
io
"
)
then
815
io
.
open
=
register
(
io
.
open
,
"
io.open
"
)
816
io
.
popen
=
register
(
io
.
popen
,
"
io.popen
"
)
817
io
.
lines
=
register
(
io
.
lines
,
"
io.lines
"
)
818
io
.
output
=
register
(
io
.
output
,
"
io.output
"
)
819
io
.
input
=
register
(
io
.
input
,
"
io.input
"
)
820
end
821
if
supported
(
"
os
"
)
then
822
os
.
execute
=
register
(
os
.
execute
,
"
os.execute
"
)
823
os
.
spawn
=
register
(
os
.
spawn
,
"
os.spawn
"
)
824
os
.
exec
=
register
(
os
.
exec
,
"
os.exec
"
)
825
os
.
rename
=
register
(
os
.
rename
,
"
os.rename
"
)
826
os
.
remove
=
register
(
os
.
remove
,
"
os.remove
"
)
827
end
828
if
supported
(
"
lfs
"
)
then
829
lfs
.
chdir
=
register
(
lfs
.
chdir
,
"
lfs.chdir
"
)
830
lfs
.
mkdir
=
register
(
lfs
.
mkdir
,
"
lfs.mkdir
"
)
831
lfs
.
rmdir
=
register
(
lfs
.
rmdir
,
"
lfs.rmdir
"
)
832
lfs
.
isfile
=
register
(
lfs
.
isfile
,
"
lfs.isfile
"
)
833
lfs
.
isdir
=
register
(
lfs
.
isdir
,
"
lfs.isdir
"
)
834
lfs
.
attributes
=
register
(
lfs
.
attributes
,
"
lfs.attributes
"
)
835
lfs
.
dir
=
register
(
lfs
.
dir
,
"
lfs.dir
"
)
836
lfs
.
lock_dir
=
register
(
lfs
.
lock_dir
,
"
lfs.lock_dir
"
)
837
lfs
.
touch
=
register
(
lfs
.
touch
,
"
lfs.touch
"
)
838
lfs
.
link
=
register
(
lfs
.
link
,
"
lfs.link
"
)
839
lfs
.
setmode
=
register
(
lfs
.
setmode
,
"
lfs.setmode
"
)
840
lfs
.
readlink
=
register
(
lfs
.
readlink
,
"
lfs.readlink
"
)
841
lfs
.
shortname
=
register
(
lfs
.
shortname
,
"
lfs.shortname
"
)
842
lfs
.
symlinkattributes
=
register
(
lfs
.
symlinkattributes
,
"
lfs.symlinkattributes
"
)
843
end
844 845 846
end
-- of closure
847 848
do
-- create closure to overcome 200 locals limit
849 850
package
.
loaded
[
"
l-package
"
]
=
package
.
loaded
[
"
l-package
"
]
or
true
851 852
-- original size: 12566, stripped down to: 8937
853 854
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-package
'
]
=
{
855
version
=
1
.
001
,
856
comment
=
"
companion to luat-lib.mkiv
"
,
857
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
858
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
859
license
=
"
see context related readme files
"
860
}
861
local
type
,
unpack
=
type
,
unpack
862
local
gsub
,
format
,
find
=
string
.
gsub
,
string
.
format
,
string
.
find
863
local
insert
,
remove
=
table
.
insert
,
table
.
remove
864
local
P
,
S
,
Cs
,
lpegmatch
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
Cs
,
lpeg
.
match
865
local
package
=
package
866
local
searchers
=
package
.
searchers
or
package
.
loaders
867
local
filejoin
=
file
and
file
.
join
or
function
(
path
,
name
)
return
path
.
.
"
/
"
.
.
name
end
868
local
isreadable
=
file
and
file
.
is_readable
or
function
(
name
)
local
f
=
io
.
open
(
name
)
if
f
then
f
:
close
(
)
return
true
end
end
869
local
addsuffix
=
file
and
file
.
addsuffix
or
function
(
name
,
suffix
)
return
name
.
.
"
.
"
.
.
suffix
end
870
local
function
cleanpath
(
path
)
871
return
path
872
end
873
local
pattern
=
Cs
(
(
(
(
1
-
S
(
"
\\/
"
)
)
^
0
*
(
S
(
"
\\/
"
)
^
1
/
"
/
"
)
)
^
0
*
(
P
(
"
.
"
)
^
1
/
"
/
"
+
P
(
1
)
)
^
1
)
*
-1
)
874
local
function
lualibfile
(
name
)
875
return
lpegmatch
(
pattern
,
name
)
or
name
876
end
877
local
offset
=
luarocks
and
1
or
0
878
local
helpers
=
package
.
helpers
or
{
879
cleanpath
=
cleanpath
,
880
lualibfile
=
lualibfile
,
881
trace
=
false
,
882
report
=
function
(
...
)
print
(
format
(
...
)
)
end
,
883
builtin
=
{
884
[
"
preload table
"
]
=
searchers
[
1
+
offset
]
,
885
[
"
path specification
"
]
=
searchers
[
2
+
offset
]
,
886
[
"
cpath specification
"
]
=
searchers
[
3
+
offset
]
,
887
[
"
all in one fallback
"
]
=
searchers
[
4
+
offset
]
,
888
}
,
889
methods
=
{
}
,
890
sequence
=
{
891
"
reset loaded
"
,
892
"
already loaded
"
,
893
"
preload table
"
,
894
"
qualified path
"
,
895
"
lua extra list
"
,
896
"
lib extra list
"
,
897
"
path specification
"
,
898
"
cpath specification
"
,
899
"
all in one fallback
"
,
900
"
not loaded
"
,
901
}
902
}
903
package
.
helpers
=
helpers
904
local
methods
=
helpers
.
methods
905
local
builtin
=
helpers
.
builtin
906
local
extraluapaths
=
{
}
907
local
extralibpaths
=
{
}
908
local
checkedfiles
=
{
}
909
local
luapaths
=
nil
910
local
libpaths
=
nil
911
local
oldluapath
=
nil
912
local
oldlibpath
=
nil
913
local
nofextralua
=
-1
914
local
nofextralib
=
-1
915
local
nofpathlua
=
-1
916
local
nofpathlib
=
-1
917
local
function
listpaths
(
what
,
paths
)
918
local
nofpaths
=
#
paths
919
if
nofpaths
>
0
then
920
for
i
=
1
,
nofpaths
do
921
helpers
.
report
(
"
using %s path %i: %s
"
,
what
,
i
,
paths
[
i
]
)
922
end
923
else
924
helpers
.
report
(
"
no %s paths defined
"
,
what
)
925
end
926
return
nofpaths
927
end
928
local
function
getextraluapaths
(
)
929
if
helpers
.
trace
and
#
extraluapaths
~
=
nofextralua
then
930
nofextralua
=
listpaths
(
"
extra lua
"
,
extraluapaths
)
931
end
932
return
extraluapaths
933
end
934
local
function
getextralibpaths
(
)
935
if
helpers
.
trace
and
#
extralibpaths
~
=
nofextralib
then
936
nofextralib
=
listpaths
(
"
extra lib
"
,
extralibpaths
)
937
end
938
return
extralibpaths
939
end
940
local
function
getluapaths
(
)
941
local
luapath
=
package
.
path
or
"
"
942
if
oldluapath
~
=
luapath
then
943
luapaths
=
file
.
splitpath
(
luapath
,
"
;
"
)
944
oldluapath
=
luapath
945
nofpathlua
=
-1
946
end
947
if
helpers
.
trace
and
#
luapaths
~
=
nofpathlua
then
948
nofpathlua
=
listpaths
(
"
builtin lua
"
,
luapaths
)
949
end
950
return
luapaths
951
end
952
local
function
getlibpaths
(
)
953
local
libpath
=
package
.
cpath
or
"
"
954
if
oldlibpath
~
=
libpath
then
955
libpaths
=
file
.
splitpath
(
libpath
,
"
;
"
)
956
oldlibpath
=
libpath
957
nofpathlib
=
-1
958
end
959
if
helpers
.
trace
and
#
libpaths
~
=
nofpathlib
then
960
nofpathlib
=
listpaths
(
"
builtin lib
"
,
libpaths
)
961
end
962
return
libpaths
963
end
964
package
.
luapaths
=
getluapaths
965
package
.
libpaths
=
getlibpaths
966
package
.
extraluapaths
=
getextraluapaths
967
package
.
extralibpaths
=
getextralibpaths
968
local
hashes
=
{
969
lua
=
{
}
,
970
lib
=
{
}
,
971
}
972
local
function
registerpath
(
tag
,
what
,
target
,
...
)
973
local
pathlist
=
{
...
}
974
local
cleanpath
=
helpers
.
cleanpath
975
local
trace
=
helpers
.
trace
976
local
report
=
helpers
.
report
977
local
hash
=
hashes
[
what
]
978
local
function
add
(
path
)
979
local
path
=
cleanpath
(
path
)
980
if
not
hash
[
path
]
then
981
target
[
#
target
+
1
]
=
path
982
hash
[
path
]
=
true
983
if
trace
then
984
report
(
"
registered %s path %s: %s
"
,
tag
,
#
target
,
path
)
985
end
986
else
987
if
trace
then
988
report
(
"
duplicate %s path: %s
"
,
tag
,
path
)
989
end
990
end
991
end
992
for
p
=
1
,
#
pathlist
do
993
local
path
=
pathlist
[
p
]
994
if
type
(
path
)
=
=
"
table
"
then
995
for
i
=
1
,
#
path
do
996
add
(
path
[
i
]
)
997
end
998
else
999
add
(
path
)
1000
end
1001
end
1002
end
1003
local
function
pushpath
(
tag
,
what
,
target
,
path
)
1004
local
path
=
helpers
.
cleanpath
(
path
)
1005
insert
(
target
,
1
,
path
)
1006
if
helpers
.
trace
then
1007
helpers
.
report
(
"
pushing %s path in front: %s
"
,
tag
,
path
)
1008
end
1009
end
1010
local
function
poppath
(
tag
,
what
,
target
)
1011
local
path
=
remove
(
target
,
1
)
1012
if
helpers
.
trace
then
1013
if
path
then
1014
helpers
.
report
(
"
popping %s path from front: %s
"
,
tag
,
path
)
1015
else
1016
helpers
.
report
(
"
no %s path to pop
"
,
tag
)
1017
end
1018
end
1019
end
1020
helpers
.
registerpath
=
registerpath
1021
function
package
.
extraluapath
(
...
)
1022
registerpath
(
"
extra lua
"
,
"
lua
"
,
extraluapaths
,
...
)
1023
end
1024
function
package
.
pushluapath
(
path
)
1025
pushpath
(
"
extra lua
"
,
"
lua
"
,
extraluapaths
,
path
)
1026
end
1027
function
package
.
popluapath
(
)
1028
poppath
(
"
extra lua
"
,
"
lua
"
,
extraluapaths
)
1029
end
1030
function
package
.
extralibpath
(
...
)
1031
registerpath
(
"
extra lib
"
,
"
lib
"
,
extralibpaths
,
...
)
1032
end
1033
function
package
.
pushlibpath
(
path
)
1034
pushpath
(
"
extra lib
"
,
"
lib
"
,
extralibpaths
,
path
)
1035
end
1036
function
package
.
poplibpath
(
)
1037
poppath
(
"
extra lib
"
,
"
lua
"
,
extralibpaths
)
1038
end
1039
local
function
loadedaslib
(
resolved
,
rawname
)
1040
local
base
=
gsub
(
rawname
,
"
%.
"
,
"
_
"
)
1041
local
init
=
"
luaopen_
"
.
.
gsub
(
base
,
"
%.
"
,
"
_
"
)
1042
local
data
=
{
resolved
,
init
,
"
"
}
1043
checkedfiles
[
#
checkedfiles
+
1
]
=
data
1044
if
helpers
.
trace
then
1045
helpers
.
report
(
"
calling loadlib with '%s' with init '%s'
"
,
resolved
,
init
)
1046
end
1047
local
a
,
b
,
c
=
package
.
loadlib
(
resolved
,
init
)
1048
if
not
a
and
type
(
b
)
=
=
"
string
"
then
1049
data
[
3
]
=
string
.
fullstrip
(
b
or
"
unknown error
"
)
1050
end
1051
return
a
,
b
,
c
1052
end
1053
helpers
.
loadedaslib
=
loadedaslib
1054
local
function
loadedbypath
(
name
,
rawname
,
paths
,
islib
,
what
)
1055
local
trace
=
helpers
.
trace
1056
for
p
=
1
,
#
paths
do
1057
local
path
=
paths
[
p
]
1058
local
resolved
=
filejoin
(
path
,
name
)
1059
if
trace
then
1060
helpers
.
report
(
"
%s path, identifying '%s' on '%s'
"
,
what
,
name
,
path
)
1061
end
1062
if
isreadable
(
resolved
)
then
1063
if
trace
then
1064
helpers
.
report
(
"
%s path, '%s' found on '%s'
"
,
what
,
name
,
resolved
)
1065
end
1066
if
islib
then
1067
return
loadedaslib
(
resolved
,
rawname
)
1068
else
1069
return
loadfile
(
resolved
)
1070
end
1071
end
1072
end
1073
end
1074
helpers
.
loadedbypath
=
loadedbypath
1075
local
function
loadedbyname
(
name
,
rawname
)
1076
if
find
(
name
,
"
^/
"
)
or
find
(
name
,
"
^[a-zA-Z]:/
"
)
then
1077
local
trace
=
helpers
.
trace
1078
if
trace
then
1079
helpers
.
report
(
"
qualified name, identifying '%s'
"
,
what
,
name
)
1080
end
1081
if
isreadable
(
name
)
then
1082
if
trace
then
1083
helpers
.
report
(
"
qualified name, '%s' found
"
,
what
,
name
)
1084
end
1085
return
loadfile
(
name
)
1086
end
1087
end
1088
end
1089
helpers
.
loadedbyname
=
loadedbyname
1090
methods
[
"
reset loaded
"
]
=
function
(
name
)
1091
checkedfiles
=
{
}
1092
return
false
1093
end
1094
methods
[
"
already loaded
"
]
=
function
(
name
)
1095
return
package
.
loaded
[
name
]
1096
end
1097
methods
[
"
preload table
"
]
=
function
(
name
)
1098
local
f
=
builtin
[
"
preload table
"
]
1099
if
f
then
1100
return
f
(
name
)
1101
end
1102
end
1103
methods
[
"
qualified path
"
]
=
function
(
name
)
1104
return
loadedbyname
(
addsuffix
(
lualibfile
(
name
)
,
"
lua
"
)
,
name
)
1105
end
1106
methods
[
"
lua extra list
"
]
=
function
(
name
)
1107
return
loadedbypath
(
addsuffix
(
lualibfile
(
name
)
,
"
lua
"
)
,
name
,
getextraluapaths
(
)
,
false
,
"
lua
"
)
1108
end
1109
methods
[
"
lib extra list
"
]
=
function
(
name
)
1110
return
loadedbypath
(
addsuffix
(
lualibfile
(
name
)
,
os
.
libsuffix
)
,
name
,
getextralibpaths
(
)
,
true
,
"
lib
"
)
1111
end
1112
methods
[
"
path specification
"
]
=
function
(
name
)
1113
local
f
=
builtin
[
"
path specification
"
]
1114
if
f
then
1115
getluapaths
(
)
1116
return
f
(
name
)
1117
end
1118
end
1119
methods
[
"
cpath specification
"
]
=
function
(
name
)
1120
local
f
=
builtin
[
"
cpath specification
"
]
1121
if
f
then
1122
getlibpaths
(
)
1123
return
f
(
name
)
1124
end
1125
end
1126
methods
[
"
all in one fallback
"
]
=
function
(
name
)
1127
local
f
=
builtin
[
"
all in one fallback
"
]
1128
if
f
then
1129
return
f
(
name
)
1130
end
1131
end
1132
methods
[
"
not loaded
"
]
=
function
(
name
)
1133
if
helpers
.
trace
then
1134
helpers
.
report
(
"
unable to locate '%s'
"
,
name
or
"
?
"
)
1135
for
i
=
1
,
#
checkedfiles
do
1136
helpers
.
report
(
"
checked file '%s', initializer '%s', message '%s'
"
,
unpack
(
checkedfiles
[
i
]
)
)
1137
end
1138
end
1139
return
nil
1140
end
1141
local
level
=
0
1142
local
used
=
{
}
1143
helpers
.
traceused
=
false
1144
function
helpers
.
loaded
(
name
)
1145
local
sequence
=
helpers
.
sequence
1146
level
=
level
+
1
1147
for
i
=
1
,
#
sequence
do
1148
local
method
=
sequence
[
i
]
1149
local
lookup
=
method
and
methods
[
method
]
1150
if
type
(
lookup
)
=
=
"
function
"
then
1151
if
helpers
.
trace
then
1152
helpers
.
report
(
"
%s, level '%s', method '%s', name '%s'
"
,
"
locating
"
,
level
,
method
,
name
)
1153
end
1154
local
result
,
rest
=
lookup
(
name
)
1155
if
type
(
result
)
=
=
"
function
"
then
1156
if
helpers
.
trace
then
1157
helpers
.
report
(
"
%s, level '%s', method '%s', name '%s'
"
,
"
found
"
,
level
,
method
,
name
)
1158
end
1159
if
helpers
.
traceused
then
1160
used
[
#
used
+
1
]
=
{
level
=
level
,
name
=
name
}
1161
end
1162
level
=
level
-1
1163
return
result
,
rest
1164
end
1165
end
1166
end
1167
level
=
level
-1
1168
return
nil
1169
end
1170
function
helpers
.
showused
(
)
1171
local
n
=
#
used
1172
if
n
>
0
then
1173
helpers
.
report
(
"
%s libraries loaded:
"
,
n
)
1174
helpers
.
report
(
)
1175
for
i
=
1
,
n
do
1176
local
u
=
used
[
i
]
1177
helpers
.
report
(
"
%i %a
"
,
u
.
level
,
u
.
name
)
1178
end
1179
helpers
.
report
(
)
1180
end
1181
end
1182
function
helpers
.
unload
(
name
)
1183
if
helpers
.
trace
then
1184
if
package
.
loaded
[
name
]
then
1185
helpers
.
report
(
"
unloading, name '%s', %s
"
,
name
,
"
done
"
)
1186
else
1187
helpers
.
report
(
"
unloading, name '%s', %s
"
,
name
,
"
not loaded
"
)
1188
end
1189
end
1190
package
.
loaded
[
name
]
=
nil
1191
end
1192
table
.
insert
(
searchers
,
1
,
helpers
.
loaded
)
1193
if
context
then
1194
package
.
path
=
"
"
1195
end
1196 1197 1198
end
-- of closure
1199 1200
do
-- create closure to overcome 200 locals limit
1201 1202
package
.
loaded
[
"
l-lpeg
"
]
=
package
.
loaded
[
"
l-lpeg
"
]
or
true
1203 1204
-- original size: 38742, stripped down to: 19489
1205 1206
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-lpeg
'
]
=
{
1207
version
=
1
.
001
,
1208
comment
=
"
companion to luat-lib.mkiv
"
,
1209
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
1210
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
1211
license
=
"
see context related readme files
"
1212
}
1213
lpeg
=
require
(
"
lpeg
"
)
1214
local
lpeg
=
lpeg
1215
if
not
lpeg
.
print
then
function
lpeg
.
print
(
...
)
print
(
lpeg
.
pcode
(
...
)
)
end
end
1216
local
type
,
next
,
tostring
=
type
,
next
,
tostring
1217
local
byte
,
char
,
gmatch
,
format
=
string
.
byte
,
string
.
char
,
string
.
gmatch
,
string
.
format
1218
local
floor
=
math
.
floor
1219
local
P
,
R
,
S
,
V
,
Ct
,
C
,
Cs
,
Cc
,
Cp
,
Cmt
=
lpeg
.
P
,
lpeg
.
R
,
lpeg
.
S
,
lpeg
.
V
,
lpeg
.
Ct
,
lpeg
.
C
,
lpeg
.
Cs
,
lpeg
.
Cc
,
lpeg
.
Cp
,
lpeg
.
Cmt
1220
local
lpegtype
,
lpegmatch
,
lpegprint
=
lpeg
.
type
,
lpeg
.
match
,
lpeg
.
print
1221
if
setinspector
then
1222
setinspector
(
"
lpeg
"
,
function
(
v
)
if
lpegtype
(
v
)
then
lpegprint
(
v
)
return
true
end
end
)
1223
end
1224
lpeg
.
patterns
=
lpeg
.
patterns
or
{
}
1225
local
patterns
=
lpeg
.
patterns
1226
local
anything
=
P
(
1
)
1227
local
endofstring
=
P
(
-1
)
1228
local
alwaysmatched
=
P
(
true
)
1229
patterns
.
anything
=
anything
1230
patterns
.
endofstring
=
endofstring
1231
patterns
.
beginofstring
=
alwaysmatched
1232
patterns
.
alwaysmatched
=
alwaysmatched
1233
local
sign
=
S
(
'
+-
'
)
1234
local
zero
=
P
(
'
0
'
)
1235
local
digit
=
R
(
'
09
'
)
1236
local
digits
=
digit
^
1
1237
local
octdigit
=
R
(
"
07
"
)
1238
local
octdigits
=
octdigit
^
1
1239
local
lowercase
=
R
(
"
az
"
)
1240
local
uppercase
=
R
(
"
AZ
"
)
1241
local
underscore
=
P
(
"
_
"
)
1242
local
hexdigit
=
digit
+
lowercase
+
uppercase
1243
local
hexdigits
=
hexdigit
^
1
1244
local
cr
,
lf
,
crlf
=
P
(
"
\r
"
)
,
P
(
"
\n
"
)
,
P
(
"
\r\n
"
)
1245
local
newline
=
P
(
"
\r
"
)
*
(
P
(
"
\n
"
)
+
P
(
true
)
)
+
P
(
"
\n
"
)
1246
local
escaped
=
P
(
"
\\
"
)
*
anything
1247
local
squote
=
P
(
"
'
"
)
1248
local
dquote
=
P
(
'
"
'
)
1249
local
space
=
P
(
"
"
)
1250
local
period
=
P
(
"
.
"
)
1251
local
comma
=
P
(
"
,
"
)
1252
local
utfbom_32_be
=
P
(
'
\000\000\254\255
'
)
1253
local
utfbom_32_le
=
P
(
'
\255\254\000\000
'
)
1254
local
utfbom_16_be
=
P
(
'
\254\255
'
)
1255
local
utfbom_16_le
=
P
(
'
\255\254
'
)
1256
local
utfbom_8
=
P
(
'
\239\187\191
'
)
1257
local
utfbom
=
utfbom_32_be
+
utfbom_32_le
+
utfbom_16_be
+
utfbom_16_le
+
utfbom_8
1258
local
utftype
=
utfbom_32_be
*
Cc
(
"
utf-32-be
"
)
+
utfbom_32_le
*
Cc
(
"
utf-32-le
"
)
+
utfbom_16_be
*
Cc
(
"
utf-16-be
"
)
+
utfbom_16_le
*
Cc
(
"
utf-16-le
"
)
+
utfbom_8
*
Cc
(
"
utf-8
"
)
+
alwaysmatched
*
Cc
(
"
utf-8
"
)
1259
local
utfstricttype
=
utfbom_32_be
*
Cc
(
"
utf-32-be
"
)
+
utfbom_32_le
*
Cc
(
"
utf-32-le
"
)
+
utfbom_16_be
*
Cc
(
"
utf-16-be
"
)
+
utfbom_16_le
*
Cc
(
"
utf-16-le
"
)
+
utfbom_8
*
Cc
(
"
utf-8
"
)
1260
local
utfoffset
=
utfbom_32_be
*
Cc
(
4
)
+
utfbom_32_le
*
Cc
(
4
)
+
utfbom_16_be
*
Cc
(
2
)
+
utfbom_16_le
*
Cc
(
2
)
+
utfbom_8
*
Cc
(
3
)
+
Cc
(
0
)
1261
local
utf8next
=
R
(
"
\128\191
"
)
1262
patterns
.
utfbom_32_be
=
utfbom_32_be
1263
patterns
.
utfbom_32_le
=
utfbom_32_le
1264
patterns
.
utfbom_16_be
=
utfbom_16_be
1265
patterns
.
utfbom_16_le
=
utfbom_16_le
1266
patterns
.
utfbom_8
=
utfbom_8
1267
patterns
.
utf_16_be_nl
=
P
(
"
\000\r\000\n
"
)
+
P
(
"
\000\r
"
)
+
P
(
"
\000\n
"
)
1268
patterns
.
utf_16_le_nl
=
P
(
"
\r\000\n\000
"
)
+
P
(
"
\r\000
"
)
+
P
(
"
\n\000
"
)
1269
patterns
.
utf_32_be_nl
=
P
(
"
\000\000\000\r\000\000\000\n
"
)
+
P
(
"
\000\000\000\r
"
)
+
P
(
"
\000\000\000\n
"
)
1270
patterns
.
utf_32_le_nl
=
P
(
"
\r\000\000\000\n\000\000\000
"
)
+
P
(
"
\r\000\000\000
"
)
+
P
(
"
\n\000\000\000
"
)
1271
patterns
.
utf8one
=
R
(
"
\000\127
"
)
1272
patterns
.
utf8two
=
R
(
"
\194\223
"
)
*
utf8next
1273
patterns
.
utf8three
=
R
(
"
\224\239
"
)
*
utf8next
*
utf8next
1274
patterns
.
utf8four
=
R
(
"
\240\244
"
)
*
utf8next
*
utf8next
*
utf8next
1275
patterns
.
utfbom
=
utfbom
1276
patterns
.
utftype
=
utftype
1277
patterns
.
utfstricttype
=
utfstricttype
1278
patterns
.
utfoffset
=
utfoffset
1279
local
utf8char
=
patterns
.
utf8one
+
patterns
.
utf8two
+
patterns
.
utf8three
+
patterns
.
utf8four
1280
local
validutf8char
=
utf8char
^
0
*
endofstring
*
Cc
(
true
)
+
Cc
(
false
)
1281
local
utf8character
=
P
(
1
)
*
R
(
"
\128\191
"
)
^
0
1282
patterns
.
utf8
=
utf8char
1283
patterns
.
utf8char
=
utf8char
1284
patterns
.
utf8character
=
utf8character
1285
patterns
.
validutf8
=
validutf8char
1286
patterns
.
validutf8char
=
validutf8char
1287
local
eol
=
S
(
"
\n\r
"
)
1288
local
spacer
=
S
(
"
\t\f\v
"
)
1289
local
whitespace
=
eol
+
spacer
1290
local
nonspacer
=
1
-
spacer
1291
local
nonwhitespace
=
1
-
whitespace
1292
patterns
.
eol
=
eol
1293
patterns
.
spacer
=
spacer
1294
patterns
.
whitespace
=
whitespace
1295
patterns
.
nonspacer
=
nonspacer
1296
patterns
.
nonwhitespace
=
nonwhitespace
1297
local
stripper
=
spacer
^
0
*
C
(
(
spacer
^
0
*
nonspacer
^
1
)
^
0
)
1298
local
fullstripper
=
whitespace
^
0
*
C
(
(
whitespace
^
0
*
nonwhitespace
^
1
)
^
0
)
1299
local
collapser
=
Cs
(
spacer
^
0
/
"
"
*
nonspacer
^
0
*
(
(
spacer
^
0
/
"
"
*
nonspacer
^
1
)
^
0
)
)
1300
local
nospacer
=
Cs
(
(
whitespace
^
1
/
"
"
+
nonwhitespace
^
1
)
^
0
)
1301
local
b_collapser
=
Cs
(
whitespace
^
0
/
"
"
*
(
nonwhitespace
^
1
+
whitespace
^
1
/
"
"
)
^
0
)
1302
local
m_collapser
=
Cs
(
(
nonwhitespace
^
1
+
whitespace
^
1
/
"
"
)
^
0
)
1303
local
e_collapser
=
Cs
(
(
whitespace
^
1
*
endofstring
/
"
"
+
nonwhitespace
^
1
+
whitespace
^
1
/
"
"
)
^
0
)
1304
local
x_collapser
=
Cs
(
(
nonwhitespace
^
1
+
whitespace
^
1
/
"
"
)
^
0
)
1305
local
b_stripper
=
Cs
(
spacer
^
0
/
"
"
*
(
nonspacer
^
1
+
spacer
^
1
/
"
"
)
^
0
)
1306
local
m_stripper
=
Cs
(
(
nonspacer
^
1
+
spacer
^
1
/
"
"
)
^
0
)
1307
local
e_stripper
=
Cs
(
(
spacer
^
1
*
endofstring
/
"
"
+
nonspacer
^
1
+
spacer
^
1
/
"
"
)
^
0
)
1308
local
x_stripper
=
Cs
(
(
nonspacer
^
1
+
spacer
^
1
/
"
"
)
^
0
)
1309
patterns
.
stripper
=
stripper
1310
patterns
.
fullstripper
=
fullstripper
1311
patterns
.
collapser
=
collapser
1312
patterns
.
nospacer
=
nospacer
1313
patterns
.
b_collapser
=
b_collapser
1314
patterns
.
m_collapser
=
m_collapser
1315
patterns
.
e_collapser
=
e_collapser
1316
patterns
.
x_collapser
=
x_collapser
1317
patterns
.
b_stripper
=
b_stripper
1318
patterns
.
m_stripper
=
m_stripper
1319
patterns
.
e_stripper
=
e_stripper
1320
patterns
.
x_stripper
=
x_stripper
1321
patterns
.
lowercase
=
lowercase
1322
patterns
.
uppercase
=
uppercase
1323
patterns
.
letter
=
patterns
.
lowercase
+
patterns
.
uppercase
1324
patterns
.
space
=
space
1325
patterns
.
tab
=
P
(
"
\t
"
)
1326
patterns
.
spaceortab
=
patterns
.
space
+
patterns
.
tab
1327
patterns
.
newline
=
newline
1328
patterns
.
emptyline
=
newline
^
1
1329
patterns
.
equal
=
P
(
"
=
"
)
1330
patterns
.
comma
=
comma
1331
patterns
.
commaspacer
=
comma
*
spacer
^
0
1332
patterns
.
period
=
period
1333
patterns
.
colon
=
P
(
"
:
"
)
1334
patterns
.
semicolon
=
P
(
"
;
"
)
1335
patterns
.
underscore
=
underscore
1336
patterns
.
escaped
=
escaped
1337
patterns
.
squote
=
squote
1338
patterns
.
dquote
=
dquote
1339
patterns
.
nosquote
=
(
escaped
+
(
1
-
squote
)
)
^
0
1340
patterns
.
nodquote
=
(
escaped
+
(
1
-
dquote
)
)
^
0
1341
patterns
.
unsingle
=
(
squote
/
"
"
)
*
patterns
.
nosquote
*
(
squote
/
"
"
)
1342
patterns
.
undouble
=
(
dquote
/
"
"
)
*
patterns
.
nodquote
*
(
dquote
/
"
"
)
1343
patterns
.
unquoted
=
patterns
.
undouble
+
patterns
.
unsingle
1344
patterns
.
unspacer
=
(
(
patterns
.
spacer
^
1
)
/
"
"
)
^
0
1345
patterns
.
singlequoted
=
squote
*
patterns
.
nosquote
*
squote
1346
patterns
.
doublequoted
=
dquote
*
patterns
.
nodquote
*
dquote
1347
patterns
.
quoted
=
patterns
.
doublequoted
+
patterns
.
singlequoted
1348
patterns
.
digit
=
digit
1349
patterns
.
digits
=
digits
1350
patterns
.
octdigit
=
octdigit
1351
patterns
.
octdigits
=
octdigits
1352
patterns
.
hexdigit
=
hexdigit
1353
patterns
.
hexdigits
=
hexdigits
1354
patterns
.
sign
=
sign
1355
patterns
.
cardinal
=
digits
1356
patterns
.
integer
=
sign
^
-1
*
digits
1357
patterns
.
unsigned
=
digit
^
0
*
period
*
digits
1358
patterns
.
float
=
sign
^
-1
*
patterns
.
unsigned
1359
patterns
.
cunsigned
=
digit
^
0
*
comma
*
digits
1360
patterns
.
cpunsigned
=
digit
^
0
*
(
period
+
comma
)
*
digits
1361
patterns
.
cfloat
=
sign
^
-1
*
patterns
.
cunsigned
1362
patterns
.
cpfloat
=
sign
^
-1
*
patterns
.
cpunsigned
1363
patterns
.
number
=
patterns
.
float
+
patterns
.
integer
1364
patterns
.
cnumber
=
patterns
.
cfloat
+
patterns
.
integer
1365
patterns
.
cpnumber
=
patterns
.
cpfloat
+
patterns
.
integer
1366
patterns
.
oct
=
zero
*
octdigits
1367
patterns
.
octal
=
patterns
.
oct
1368
patterns
.
HEX
=
zero
*
P
(
"
X
"
)
*
(
digit
+
uppercase
)
^
1
1369
patterns
.
hex
=
zero
*
P
(
"
x
"
)
*
(
digit
+
lowercase
)
^
1
1370
patterns
.
hexadecimal
=
zero
*
S
(
"
xX
"
)
*
hexdigits
1371
patterns
.
hexafloat
=
sign
^
-1
*
zero
*
S
(
"
xX
"
)
*
(
hexdigit
^
0
*
period
*
hexdigits
+
hexdigits
*
period
*
hexdigit
^
0
+
hexdigits
)
*
(
S
(
"
pP
"
)
*
sign
^
-1
*
hexdigits
)
^
-1
1372
patterns
.
decafloat
=
sign
^
-1
*
(
digit
^
0
*
period
*
digits
+
digits
*
period
*
digit
^
0
+
digits
)
*
S
(
"
eE
"
)
*
sign
^
-1
*
digits
1373
patterns
.
propername
=
(
uppercase
+
lowercase
+
underscore
)
*
(
uppercase
+
lowercase
+
underscore
+
digit
)
^
0
*
endofstring
1374
patterns
.
somecontent
=
(
anything
-
newline
-
space
)
^
1
1375
patterns
.
beginline
=
#
(
1
-
newline
)
1376
patterns
.
longtostring
=
Cs
(
whitespace
^
0
/
"
"
*
(
(
patterns
.
quoted
+
nonwhitespace
^
1
+
whitespace
^
1
/
"
"
*
(
endofstring
+
Cc
(
"
"
)
)
)
^
0
)
)
1377
local
function
anywhere
(
pattern
)
1378
return
(
1
-
P
(
pattern
)
)
^
0
*
P
(
pattern
)
1379
end
1380
lpeg
.
anywhere
=
anywhere
1381
function
lpeg
.
instringchecker
(
p
)
1382
p
=
anywhere
(
p
)
1383
return
function
(
str
)
1384
return
lpegmatch
(
p
,
str
)
and
true
or
false
1385
end
1386
end
1387
function
lpeg
.
splitter
(
pattern
,
action
)
1388
if
action
then
1389
return
(
(
(
1
-
P
(
pattern
)
)
^
1
)
/
action
+
1
)
^
0
1390
else
1391
return
(
Cs
(
(
1
-
P
(
pattern
)
)
^
1
)
+
1
)
^
0
1392
end
1393
end
1394
function
lpeg
.
tsplitter
(
pattern
,
action
)
1395
if
action
then
1396
return
Ct
(
(
(
(
1
-
P
(
pattern
)
)
^
1
)
/
action
+
1
)
^
0
)
1397
else
1398
return
Ct
(
(
Cs
(
(
1
-
P
(
pattern
)
)
^
1
)
+
1
)
^
0
)
1399
end
1400
end
1401
local
splitters_s
,
splitters_m
,
splitters_t
=
{
}
,
{
}
,
{
}
1402
local
function
splitat
(
separator
,
single
)
1403
local
splitter
=
(
single
and
splitters_s
[
separator
]
)
or
splitters_m
[
separator
]
1404
if
not
splitter
then
1405
separator
=
P
(
separator
)
1406
local
other
=
C
(
(
1
-
separator
)
^
0
)
1407
if
single
then
1408
local
any
=
anything
1409
splitter
=
other
*
(
separator
*
C
(
any
^
0
)
+
"
"
)
1410
splitters_s
[
separator
]
=
splitter
1411
else
1412
splitter
=
other
*
(
separator
*
other
)
^
0
1413
splitters_m
[
separator
]
=
splitter
1414
end
1415
end
1416
return
splitter
1417
end
1418
local
function
tsplitat
(
separator
)
1419
local
splitter
=
splitters_t
[
separator
]
1420
if
not
splitter
then
1421
splitter
=
Ct
(
splitat
(
separator
)
)
1422
splitters_t
[
separator
]
=
splitter
1423
end
1424
return
splitter
1425
end
1426
lpeg
.
splitat
=
splitat
1427
lpeg
.
tsplitat
=
tsplitat
1428
function
string
.
splitup
(
str
,
separator
)
1429
if
not
separator
then
1430
separator
=
"
,
"
1431
end
1432
return
lpegmatch
(
splitters_m
[
separator
]
or
splitat
(
separator
)
,
str
)
1433
end
1434
local
cache
=
{
}
1435
function
lpeg
.
split
(
separator
,
str
)
1436
local
c
=
cache
[
separator
]
1437
if
not
c
then
1438
c
=
tsplitat
(
separator
)
1439
cache
[
separator
]
=
c
1440
end
1441
return
lpegmatch
(
c
,
str
)
1442
end
1443
function
string
.
split
(
str
,
separator
)
1444
if
separator
then
1445
local
c
=
cache
[
separator
]
1446
if
not
c
then
1447
c
=
tsplitat
(
separator
)
1448
cache
[
separator
]
=
c
1449
end
1450
return
lpegmatch
(
c
,
str
)
1451
else
1452
return
{
str
}
1453
end
1454
end
1455
local
spacing
=
patterns
.
spacer
^
0
*
newline
1456
local
empty
=
spacing
*
Cc
(
"
"
)
1457
local
nonempty
=
Cs
(
(
1
-
spacing
)
^
1
)
*
spacing
^
-1
1458
local
content
=
(
empty
+
nonempty
)
^
1
1459
patterns
.
textline
=
content
1460
local
linesplitter
=
tsplitat
(
newline
)
1461
patterns
.
linesplitter
=
linesplitter
1462
function
string
.
splitlines
(
str
)
1463
return
lpegmatch
(
linesplitter
,
str
)
1464
end
1465
local
cache
=
{
}
1466
function
lpeg
.
checkedsplit
(
separator
,
str
)
1467
local
c
=
cache
[
separator
]
1468
if
not
c
then
1469
separator
=
P
(
separator
)
1470
local
other
=
C
(
(
1
-
separator
)
^
1
)
1471
c
=
Ct
(
separator
^
0
*
other
*
(
separator
^
1
*
other
)
^
0
)
1472
cache
[
separator
]
=
c
1473
end
1474
return
lpegmatch
(
c
,
str
)
1475
end
1476
function
string
.
checkedsplit
(
str
,
separator
)
1477
local
c
=
cache
[
separator
]
1478
if
not
c
then
1479
separator
=
P
(
separator
)
1480
local
other
=
C
(
(
1
-
separator
)
^
1
)
1481
c
=
Ct
(
separator
^
0
*
other
*
(
separator
^
1
*
other
)
^
0
)
1482
cache
[
separator
]
=
c
1483
end
1484
return
lpegmatch
(
c
,
str
)
1485
end
1486
local
function
f2
(
s
)
local
c1
,
c2
=
byte
(
s
,
1
,
2
)
return
c1
*
64
+
c2
-12416
end
1487
local
function
f3
(
s
)
local
c1
,
c2
,
c3
=
byte
(
s
,
1
,
3
)
return
(
c1
*
64
+
c2
)
*
64
+
c3
-925824
end
1488
local
function
f4
(
s
)
local
c1
,
c2
,
c3
,
c4
=
byte
(
s
,
1
,
4
)
return
(
(
c1
*
64
+
c2
)
*
64
+
c3
)
*
64
+
c4
-63447168
end
1489
local
utf8byte
=
patterns
.
utf8one
/
byte
+
patterns
.
utf8two
/
f2
+
patterns
.
utf8three
/
f3
+
patterns
.
utf8four
/
f4
1490
patterns
.
utf8byte
=
utf8byte
1491
local
cache
=
{
}
1492
function
lpeg
.
stripper
(
str
)
1493
if
type
(
str
)
=
=
"
string
"
then
1494
local
s
=
cache
[
str
]
1495
if
not
s
then
1496
s
=
Cs
(
(
(
S
(
str
)
^
1
)
/
"
"
+
1
)
^
0
)
1497
cache
[
str
]
=
s
1498
end
1499
return
s
1500
else
1501
return
Cs
(
(
(
str
^
1
)
/
"
"
+
1
)
^
0
)
1502
end
1503
end
1504
local
cache
=
{
}
1505
function
lpeg
.
keeper
(
str
)
1506
if
type
(
str
)
=
=
"
string
"
then
1507
local
s
=
cache
[
str
]
1508
if
not
s
then
1509
s
=
Cs
(
(
(
(
1
-
S
(
str
)
)
^
1
)
/
"
"
+
1
)
^
0
)
1510
cache
[
str
]
=
s
1511
end
1512
return
s
1513
else
1514
return
Cs
(
(
(
(
1
-
str
)
^
1
)
/
"
"
+
1
)
^
0
)
1515
end
1516
end
1517
function
lpeg
.
frontstripper
(
str
)
1518
return
(
P
(
str
)
+
P
(
true
)
)
*
Cs
(
anything
^
0
)
1519
end
1520
function
lpeg
.
endstripper
(
str
)
1521
return
Cs
(
(
1
-
P
(
str
)
*
endofstring
)
^
0
)
1522
end
1523
function
lpeg
.
replacer
(
one
,
two
,
makefunction
,
isutf
)
1524
local
pattern
1525
local
u
=
isutf
and
utf8char
or
1
1526
if
type
(
one
)
=
=
"
table
"
then
1527
local
no
=
#
one
1528
local
p
=
P
(
false
)
1529
if
no
=
=
0
then
1530
for
k
,
v
in
next
,
one
do
1531
p
=
p
+
P
(
k
)
/
v
1532
end
1533
pattern
=
Cs
(
(
p
+
u
)
^
0
)
1534
elseif
no
=
=
1
then
1535
local
o
=
one
[
1
]
1536
one
,
two
=
P
(
o
[
1
]
)
,
o
[
2
]
1537
pattern
=
Cs
(
(
one
/
two
+
u
)
^
0
)
1538
else
1539
for
i
=
1
,
no
do
1540
local
o
=
one
[
i
]
1541
p
=
p
+
P
(
o
[
1
]
)
/
o
[
2
]
1542
end
1543
pattern
=
Cs
(
(
p
+
u
)
^
0
)
1544
end
1545
else
1546
pattern
=
Cs
(
(
P
(
one
)
/
(
two
or
"
"
)
+
u
)
^
0
)
1547
end
1548
if
makefunction
then
1549
return
function
(
str
)
1550
return
lpegmatch
(
pattern
,
str
)
1551
end
1552
else
1553
return
pattern
1554
end
1555
end
1556
function
lpeg
.
finder
(
lst
,
makefunction
,
isutf
)
1557
local
pattern
1558
if
type
(
lst
)
=
=
"
table
"
then
1559
pattern
=
P
(
false
)
1560
if
#
lst
=
=
0
then
1561
for
k
,
v
in
next
,
lst
do
1562
pattern
=
pattern
+
P
(
k
)
1563
end
1564
else
1565
for
i
=
1
,
#
lst
do
1566
pattern
=
pattern
+
P
(
lst
[
i
]
)
1567
end
1568
end
1569
else
1570
pattern
=
P
(
lst
)
1571
end
1572
if
isutf
then
1573
pattern
=
(
(
utf8char
or
1
)
-
pattern
)
^
0
*
pattern
1574
else
1575
pattern
=
(
1
-
pattern
)
^
0
*
pattern
1576
end
1577
if
makefunction
then
1578
return
function
(
str
)
1579
return
lpegmatch
(
pattern
,
str
)
1580
end
1581
else
1582
return
pattern
1583
end
1584
end
1585
local
splitters_f
,
splitters_s
=
{
}
,
{
}
1586
function
lpeg
.
firstofsplit
(
separator
)
1587
local
splitter
=
splitters_f
[
separator
]
1588
if
not
splitter
then
1589
local
pattern
=
P
(
separator
)
1590
splitter
=
C
(
(
1
-
pattern
)
^
0
)
1591
splitters_f
[
separator
]
=
splitter
1592
end
1593
return
splitter
1594
end
1595
function
lpeg
.
secondofsplit
(
separator
)
1596
local
splitter
=
splitters_s
[
separator
]
1597
if
not
splitter
then
1598
local
pattern
=
P
(
separator
)
1599
splitter
=
(
1
-
pattern
)
^
0
*
pattern
*
C
(
anything
^
0
)
1600
splitters_s
[
separator
]
=
splitter
1601
end
1602
return
splitter
1603
end
1604
local
splitters_s
,
splitters_p
=
{
}
,
{
}
1605
function
lpeg
.
beforesuffix
(
separator
)
1606
local
splitter
=
splitters_s
[
separator
]
1607
if
not
splitter
then
1608
local
pattern
=
P
(
separator
)
1609
splitter
=
C
(
(
1
-
pattern
)
^
0
)
*
pattern
*
endofstring
1610
splitters_s
[
separator
]
=
splitter
1611
end
1612
return
splitter
1613
end
1614
function
lpeg
.
afterprefix
(
separator
)
1615
local
splitter
=
splitters_p
[
separator
]
1616
if
not
splitter
then
1617
local
pattern
=
P
(
separator
)
1618
splitter
=
pattern
*
C
(
anything
^
0
)
1619
splitters_p
[
separator
]
=
splitter
1620
end
1621
return
splitter
1622
end
1623
function
lpeg
.
balancer
(
left
,
right
)
1624
left
,
right
=
P
(
left
)
,
P
(
right
)
1625
return
P
{
left
*
(
(
1
-
left
-
right
)
+
V
(
1
)
)
^
0
*
right
}
1626
end
1627
function
lpeg
.
counter
(
pattern
,
action
)
1628
local
n
=
0
1629
local
pattern
=
(
P
(
pattern
)
/
function
(
)
n
=
n
+
1
end
+
anything
)
^
0
1630
if
action
then
1631
return
function
(
str
)
n
=
0
;
lpegmatch
(
pattern
,
str
)
;
action
(
n
)
end
1632
else
1633
return
function
(
str
)
n
=
0
;
lpegmatch
(
pattern
,
str
)
;
return
n
end
1634
end
1635
end
1636
function
lpeg
.
is_lpeg
(
p
)
1637
return
p
and
lpegtype
(
p
)
=
=
"
pattern
"
1638
end
1639
function
lpeg
.
oneof
(
list
,
...
)
1640
if
type
(
list
)
~
=
"
table
"
then
1641
list
=
{
list
,
...
}
1642
end
1643
local
p
=
P
(
list
[
1
]
)
1644
for
l
=
2
,
#
list
do
1645
p
=
p
+
P
(
list
[
l
]
)
1646
end
1647
return
p
1648
end
1649
local
sort
=
table
.
sort
1650
local
function
copyindexed
(
old
)
1651
local
new
=
{
}
1652
for
i
=
1
,
#
old
do
1653
new
[
i
]
=
old
1654
end
1655
return
new
1656
end
1657
local
function
sortedkeys
(
tab
)
1658
local
keys
,
s
=
{
}
,
0
1659
for
key
,
_
in
next
,
tab
do
1660
s
=
s
+
1
1661
keys
[
s
]
=
key
1662
end
1663
sort
(
keys
)
1664
return
keys
1665
end
1666
function
lpeg
.
append
(
list
,
pp
,
delayed
,
checked
)
1667
local
p
=
pp
1668
if
#
list
>
0
then
1669
local
keys
=
copyindexed
(
list
)
1670
sort
(
keys
)
1671
for
i
=
#
keys
,
1
,
-1
do
1672
local
k
=
keys
[
i
]
1673
if
p
then
1674
p
=
P
(
k
)
+
p
1675
else
1676
p
=
P
(
k
)
1677
end
1678
end
1679
elseif
delayed
then
1680
local
keys
=
sortedkeys
(
list
)
1681
if
p
then
1682
for
i
=
1
,
#
keys
,
1
do
1683
local
k
=
keys
[
i
]
1684
local
v
=
list
[
k
]
1685
p
=
P
(
k
)
/
list
+
p
1686
end
1687
else
1688
for
i
=
1
,
#
keys
do
1689
local
k
=
keys
[
i
]
1690
local
v
=
list
[
k
]
1691
if
p
then
1692
p
=
P
(
k
)
+
p
1693
else
1694
p
=
P
(
k
)
1695
end
1696
end
1697
if
p
then
1698
p
=
p
/
list
1699
end
1700
end
1701
elseif
checked
then
1702
local
keys
=
sortedkeys
(
list
)
1703
for
i
=
1
,
#
keys
do
1704
local
k
=
keys
[
i
]
1705
local
v
=
list
[
k
]
1706
if
p
then
1707
if
k
=
=
v
then
1708
p
=
P
(
k
)
+
p
1709
else
1710
p
=
P
(
k
)
/
v
+
p
1711
end
1712
else
1713
if
k
=
=
v
then
1714
p
=
P
(
k
)
1715
else
1716
p
=
P
(
k
)
/
v
1717
end
1718
end
1719
end
1720
else
1721
local
keys
=
sortedkeys
(
list
)
1722
for
i
=
1
,
#
keys
do
1723
local
k
=
keys
[
i
]
1724
local
v
=
list
[
k
]
1725
if
p
then
1726
p
=
P
(
k
)
/
v
+
p
1727
else
1728
p
=
P
(
k
)
/
v
1729
end
1730
end
1731
end
1732
return
p
1733
end
1734
local
p_false
=
P
(
false
)
1735
local
p_true
=
P
(
true
)
1736
local
lower
=
utf
and
utf
.
lower
or
string
.
lower
1737
local
upper
=
utf
and
utf
.
upper
or
string
.
upper
1738
function
lpeg
.
setutfcasers
(
l
,
u
)
1739
lower
=
l
or
lower
1740
upper
=
u
or
upper
1741
end
1742
local
function
make1
(
t
,
rest
)
1743
local
p
=
p_false
1744
local
keys
=
sortedkeys
(
t
)
1745
for
i
=
1
,
#
keys
do
1746
local
k
=
keys
[
i
]
1747
if
k
~
=
"
"
then
1748
local
v
=
t
[
k
]
1749
if
v
=
=
true
then
1750
p
=
p
+
P
(
k
)
*
p_true
1751
elseif
v
=
=
false
then
1752
else
1753
p
=
p
+
P
(
k
)
*
make1
(
v
,
v
[
"
"
]
)
1754
end
1755
end
1756
end
1757
if
rest
then
1758
p
=
p
+
p_true
1759
end
1760
return
p
1761
end
1762
local
function
make2
(
t
,
rest
)
1763
local
p
=
p_false
1764
local
keys
=
sortedkeys
(
t
)
1765
for
i
=
1
,
#
keys
do
1766
local
k
=
keys
[
i
]
1767
if
k
~
=
"
"
then
1768
local
v
=
t
[
k
]
1769
if
v
=
=
true
then
1770
p
=
p
+
(
P
(
lower
(
k
)
)
+
P
(
upper
(
k
)
)
)
*
p_true
1771
elseif
v
=
=
false
then
1772
else
1773
p
=
p
+
(
P
(
lower
(
k
)
)
+
P
(
upper
(
k
)
)
)
*
make2
(
v
,
v
[
"
"
]
)
1774
end
1775
end
1776
end
1777
if
rest
then
1778
p
=
p
+
p_true
1779
end
1780
return
p
1781
end
1782
local
function
utfchartabletopattern
(
list
,
insensitive
)
1783
local
tree
=
{
}
1784
local
n
=
#
list
1785
if
n
=
=
0
then
1786
for
s
in
next
,
list
do
1787
local
t
=
tree
1788
local
p
,
pk
1789
for
c
in
gmatch
(
s
,
"
.
"
)
do
1790
if
t
=
=
true
then
1791
t
=
{
[
c
]
=
true
,
[
"
"
]
=
true
}
1792
p
[
pk
]
=
t
1793
p
=
t
1794
t
=
false
1795
elseif
t
=
=
false
then
1796
t
=
{
[
c
]
=
false
}
1797
p
[
pk
]
=
t
1798
p
=
t
1799
t
=
false
1800
else
1801
local
tc
=
t
[
c
]
1802
if
not
tc
then
1803
tc
=
false
1804
t
[
c
]
=
false
1805
end
1806
p
=
t
1807
t
=
tc
1808
end
1809
pk
=
c
1810
end
1811
if
t
=
=
false
then
1812
p
[
pk
]
=
true
1813
elseif
t
=
=
true
then
1814
else
1815
t
[
"
"
]
=
true
1816
end
1817
end
1818
else
1819
for
i
=
1
,
n
do
1820
local
s
=
list
[
i
]
1821
local
t
=
tree
1822
local
p
,
pk
1823
for
c
in
gmatch
(
s
,
"
.
"
)
do
1824
if
t
=
=
true
then
1825
t
=
{
[
c
]
=
true
,
[
"
"
]
=
true
}
1826
p
[
pk
]
=
t
1827
p
=
t
1828
t
=
false
1829
elseif
t
=
=
false
then
1830
t
=
{
[
c
]
=
false
}
1831
p
[
pk
]
=
t
1832
p
=
t
1833
t
=
false
1834
else
1835
local
tc
=
t
[
c
]
1836
if
not
tc
then
1837
tc
=
false
1838
t
[
c
]
=
false
1839
end
1840
p
=
t
1841
t
=
tc
1842
end
1843
pk
=
c
1844
end
1845
if
t
=
=
false
then
1846
p
[
pk
]
=
true
1847
elseif
t
=
=
true
then
1848
else
1849
t
[
"
"
]
=
true
1850
end
1851
end
1852
end
1853
return
(
insensitive
and
make2
or
make1
)
(
tree
)
1854
end
1855
lpeg
.
utfchartabletopattern
=
utfchartabletopattern
1856
function
lpeg
.
utfreplacer
(
list
,
insensitive
)
1857
local
pattern
=
Cs
(
(
utfchartabletopattern
(
list
,
insensitive
)
/
list
+
utf8character
)
^
0
)
1858
return
function
(
str
)
1859
return
lpegmatch
(
pattern
,
str
)
or
str
1860
end
1861
end
1862
patterns
.
containseol
=
lpeg
.
finder
(
eol
)
1863
local
function
nextstep
(
n
,
step
,
result
)
1864
local
m
=
n
%
step
1865
local
d
=
floor
(
n
/
step
)
1866
if
d
>
0
then
1867
local
v
=
V
(
tostring
(
step
)
)
1868
local
s
=
result
.
start
1869
for
i
=
1
,
d
do
1870
if
s
then
1871
s
=
v
*
s
1872
else
1873
s
=
v
1874
end
1875
end
1876
result
.
start
=
s
1877
end
1878
if
step
>
1
and
result
.
start
then
1879
local
v
=
V
(
tostring
(
step
/
2
)
)
1880
result
[
tostring
(
step
)
]
=
v
*
v
1881
end
1882
if
step
>
0
then
1883
return
nextstep
(
m
,
step
/
2
,
result
)
1884
else
1885
return
result
1886
end
1887
end
1888
function
lpeg
.
times
(
pattern
,
n
)
1889
return
P
(
nextstep
(
n
,
2
^
16
,
{
"
start
"
,
[
"
1
"
]
=
pattern
}
)
)
1890
end
1891
do
1892
local
trailingzeros
=
zero
^
0
*
-
digit
1893
local
stripper
=
Cs
(
(
1894
digits
*
(
1895
period
*
trailingzeros
/
"
"
+
period
*
(
digit
-
trailingzeros
)
^
1
*
(
trailingzeros
/
"
"
)
1896
)
+
1
1897
)
^
0
)
1898
lpeg
.
patterns
.
stripzeros
=
stripper
1899
local
nonzero
=
digit
-
zero
1900
local
trailingzeros
=
zero
^
1
*
endofstring
1901
local
stripper
=
Cs
(
(
1
-
period
)
^
0
*
(
1902
period
*
trailingzeros
/
"
"
+
period
*
(
nonzero
^
1
+
(
trailingzeros
/
"
"
)
+
zero
^
1
)
^
0
+
endofstring
1903
)
)
1904
lpeg
.
patterns
.
stripzero
=
stripper
1905
end
1906
local
byte_to_HEX
=
{
}
1907
local
byte_to_hex
=
{
}
1908
local
byte_to_dec
=
{
}
1909
local
hex_to_byte
=
{
}
1910
for
i
=
0
,
255
do
1911
local
H
=
format
(
"
%02X
"
,
i
)
1912
local
h
=
format
(
"
%02x
"
,
i
)
1913
local
d
=
format
(
"
%03i
"
,
i
)
1914
local
c
=
char
(
i
)
1915
byte_to_HEX
[
c
]
=
H
1916
byte_to_hex
[
c
]
=
h
1917
byte_to_dec
[
c
]
=
d
1918
hex_to_byte
[
h
]
=
c
1919
hex_to_byte
[
H
]
=
c
1920
end
1921
local
hextobyte
=
P
(
2
)
/
hex_to_byte
1922
local
bytetoHEX
=
P
(
1
)
/
byte_to_HEX
1923
local
bytetohex
=
P
(
1
)
/
byte_to_hex
1924
local
bytetodec
=
P
(
1
)
/
byte_to_dec
1925
local
hextobytes
=
Cs
(
hextobyte
^
0
)
1926
local
bytestoHEX
=
Cs
(
bytetoHEX
^
0
)
1927
local
bytestohex
=
Cs
(
bytetohex
^
0
)
1928
local
bytestodec
=
Cs
(
bytetodec
^
0
)
1929
patterns
.
hextobyte
=
hextobyte
1930
patterns
.
bytetoHEX
=
bytetoHEX
1931
patterns
.
bytetohex
=
bytetohex
1932
patterns
.
bytetodec
=
bytetodec
1933
patterns
.
hextobytes
=
hextobytes
1934
patterns
.
bytestoHEX
=
bytestoHEX
1935
patterns
.
bytestohex
=
bytestohex
1936
patterns
.
bytestodec
=
bytestodec
1937
function
string
.
toHEX
(
s
)
1938
if
not
s
or
s
=
=
"
"
then
1939
return
s
1940
else
1941
return
lpegmatch
(
bytestoHEX
,
s
)
1942
end
1943
end
1944
function
string
.
tohex
(
s
)
1945
if
not
s
or
s
=
=
"
"
then
1946
return
s
1947
else
1948
return
lpegmatch
(
bytestohex
,
s
)
1949
end
1950
end
1951
function
string
.
todec
(
s
)
1952
if
not
s
or
s
=
=
"
"
then
1953
return
s
1954
else
1955
return
lpegmatch
(
bytestodec
,
s
)
1956
end
1957
end
1958
function
string
.
tobytes
(
s
)
1959
if
not
s
or
s
=
=
"
"
then
1960
return
s
1961
else
1962
return
lpegmatch
(
hextobytes
,
s
)
1963
end
1964
end
1965
local
patterns
=
{
}
1966
local
function
containsws
(
what
)
1967
local
p
=
patterns
[
what
]
1968
if
not
p
then
1969
local
p1
=
P
(
what
)
*
(
whitespace
+
endofstring
)
*
Cc
(
true
)
1970
local
p2
=
whitespace
*
P
(
p1
)
1971
p
=
P
(
p1
)
+
P
(
1
-
p2
)
^
0
*
p2
+
Cc
(
false
)
1972
patterns
[
what
]
=
p
1973
end
1974
return
p
1975
end
1976
lpeg
.
containsws
=
containsws
1977
function
string
.
containsws
(
str
,
what
)
1978
return
lpegmatch
(
patterns
[
what
]
or
containsws
(
what
)
,
str
)
1979
end
1980 1981 1982
end
-- of closure
1983 1984
do
-- create closure to overcome 200 locals limit
1985 1986
package
.
loaded
[
"
l-function
"
]
=
package
.
loaded
[
"
l-function
"
]
or
true
1987 1988
-- original size: 361, stripped down to: 317
1989 1990
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-functions
'
]
=
{
1991
version
=
1
.
001
,
1992
comment
=
"
companion to luat-lib.mkiv
"
,
1993
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
1994
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
1995
license
=
"
see context related readme files
"
1996
}
1997
functions
=
functions
or
{
}
1998
function
functions
.
dummy
(
)
end
1999 2000 2001
end
-- of closure
2002 2003
do
-- create closure to overcome 200 locals limit
2004 2005
package
.
loaded
[
"
l-string
"
]
=
package
.
loaded
[
"
l-string
"
]
or
true
2006 2007
-- original size: 6644, stripped down to: 3410
2008 2009
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-string
'
]
=
{
2010
version
=
1
.
001
,
2011
comment
=
"
companion to luat-lib.mkiv
"
,
2012
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
2013
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
2014
license
=
"
see context related readme files
"
2015
}
2016
local
string
=
string
2017
local
sub
,
gmatch
,
format
,
char
,
byte
,
rep
,
lower
=
string
.
sub
,
string
.
gmatch
,
string
.
format
,
string
.
char
,
string
.
byte
,
string
.
rep
,
string
.
lower
2018
local
lpegmatch
,
patterns
=
lpeg
.
match
,
lpeg
.
patterns
2019
local
P
,
S
,
C
,
Ct
,
Cc
,
Cs
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
C
,
lpeg
.
Ct
,
lpeg
.
Cc
,
lpeg
.
Cs
2020
local
unquoted
=
patterns
.
squote
*
C
(
patterns
.
nosquote
)
*
patterns
.
squote
+
patterns
.
dquote
*
C
(
patterns
.
nodquote
)
*
patterns
.
dquote
2021
function
string
.
unquoted
(
str
)
2022
return
lpegmatch
(
unquoted
,
str
)
or
str
2023
end
2024
function
string
.
quoted
(
str
)
2025
return
format
(
"
%q
"
,
str
)
2026
end
2027
function
string
.
count
(
str
,
pattern
)
2028
local
n
=
0
2029
for
_
in
gmatch
(
str
,
pattern
)
do
2030
n
=
n
+
1
2031
end
2032
return
n
2033
end
2034
function
string
.
limit
(
str
,
n
,
sentinel
)
2035
if
#
str
>
n
then
2036
sentinel
=
sentinel
or
"
...
"
2037
return
sub
(
str
,
1
,
(
n
-
#
sentinel
)
)
.
.
sentinel
2038
else
2039
return
str
2040
end
2041
end
2042
local
stripper
=
patterns
.
stripper
2043
local
fullstripper
=
patterns
.
fullstripper
2044
local
collapser
=
patterns
.
collapser
2045
local
nospacer
=
patterns
.
nospacer
2046
local
longtostring
=
patterns
.
longtostring
2047
function
string
.
strip
(
str
)
2048
return
str
and
lpegmatch
(
stripper
,
str
)
or
"
"
2049
end
2050
function
string
.
fullstrip
(
str
)
2051
return
str
and
lpegmatch
(
fullstripper
,
str
)
or
"
"
2052
end
2053
function
string
.
collapsespaces
(
str
)
2054
return
str
and
lpegmatch
(
collapser
,
str
)
or
"
"
2055
end
2056
function
string
.
nospaces
(
str
)
2057
return
str
and
lpegmatch
(
nospacer
,
str
)
or
"
"
2058
end
2059
function
string
.
longtostring
(
str
)
2060
return
str
and
lpegmatch
(
longtostring
,
str
)
or
"
"
2061
end
2062
local
pattern
=
P
(
"
"
)
^
0
*
P
(
-1
)
2063
function
string
.
is_empty
(
str
)
2064
if
not
str
or
str
=
=
"
"
then
2065
return
true
2066
else
2067
return
lpegmatch
(
pattern
,
str
)
and
true
or
false
2068
end
2069
end
2070
local
anything
=
patterns
.
anything
2071
local
moreescapes
=
Cc
(
"
%
"
)
*
S
(
"
.-+%?()[]*$^{}
"
)
2072
local
allescapes
=
Cc
(
"
%
"
)
*
S
(
"
.-+%?()[]*
"
)
2073
local
someescapes
=
Cc
(
"
%
"
)
*
S
(
"
.-+%()[]
"
)
2074
local
matchescapes
=
Cc
(
"
.
"
)
*
S
(
"
*?
"
)
2075
local
pattern_m
=
Cs
(
(
moreescapes
+
anything
)
^
0
)
2076
local
pattern_a
=
Cs
(
(
allescapes
+
anything
)
^
0
)
2077
local
pattern_b
=
Cs
(
(
someescapes
+
matchescapes
+
anything
)
^
0
)
2078
local
pattern_c
=
Cs
(
Cc
(
"
^
"
)
*
(
someescapes
+
matchescapes
+
anything
)
^
0
*
Cc
(
"
$
"
)
)
2079
function
string
.
escapedpattern
(
str
,
simple
)
2080
return
lpegmatch
(
simple
and
pattern_b
or
pattern_a
,
str
)
2081
end
2082
function
string
.
topattern
(
str
,
lowercase
,
strict
)
2083
if
str
=
=
"
"
or
type
(
str
)
~
=
"
string
"
then
2084
return
"
.*
"
2085
elseif
strict
=
=
"
all
"
then
2086
str
=
lpegmatch
(
pattern_m
,
str
)
2087
elseif
strict
then
2088
str
=
lpegmatch
(
pattern_c
,
str
)
2089
else
2090
str
=
lpegmatch
(
pattern_b
,
str
)
2091
end
2092
if
lowercase
then
2093
return
lower
(
str
)
2094
else
2095
return
str
2096
end
2097
end
2098
function
string
.
valid
(
str
,
default
)
2099
return
(
type
(
str
)
=
=
"
string
"
and
str
~
=
"
"
and
str
)
or
default
or
nil
2100
end
2101
string
.
itself
=
function
(
s
)
return
s
end
2102
local
pattern_c
=
Ct
(
C
(
1
)
^
0
)
2103
local
pattern_b
=
Ct
(
(
C
(
1
)
/
byte
)
^
0
)
2104
function
string
.
totable
(
str
,
bytes
)
2105
return
lpegmatch
(
bytes
and
pattern_b
or
pattern_c
,
str
)
2106
end
2107
local
replacer
=
lpeg
.
replacer
(
"
@
"
,
"
%%
"
)
2108
function
string
.
tformat
(
fmt
,
...
)
2109
return
format
(
lpegmatch
(
replacer
,
fmt
)
,
...
)
2110
end
2111
string
.
quote
=
string
.
quoted
2112
string
.
unquote
=
string
.
unquoted
2113
if
not
string
.
bytetable
then
2114
local
limit
=
5000
2115
function
string
.
bytetable
(
str
)
2116
local
n
=
#
str
2117
if
n
>
limit
then
2118
local
t
=
{
byte
(
str
,
1
,
limit
)
}
2119
for
i
=
limit
+
1
,
n
do
2120
t
[
i
]
=
byte
(
str
,
i
)
2121
end
2122
return
t
2123
else
2124
return
{
byte
(
str
,
1
,
n
)
}
2125
end
2126
end
2127
end
2128 2129 2130
end
-- of closure
2131 2132
do
-- create closure to overcome 200 locals limit
2133 2134
package
.
loaded
[
"
l-table
"
]
=
package
.
loaded
[
"
l-table
"
]
or
true
2135 2136
-- original size: 41758, stripped down to: 22643
2137 2138
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-table
'
]
=
{
2139
version
=
1
.
001
,
2140
comment
=
"
companion to luat-lib.mkiv
"
,
2141
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
2142
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
2143
license
=
"
see context related readme files
"
2144
}
2145
local
type
,
next
,
tostring
,
tonumber
,
select
,
rawget
=
type
,
next
,
tostring
,
tonumber
,
select
,
rawget
2146
local
table
,
string
=
table
,
string
2147
local
concat
,
sort
=
table
.
concat
,
table
.
sort
2148
local
format
,
lower
,
dump
=
string
.
format
,
string
.
lower
,
string
.
dump
2149
local
getmetatable
,
setmetatable
=
getmetatable
,
setmetatable
2150
local
lpegmatch
,
patterns
=
lpeg
.
match
,
lpeg
.
patterns
2151
local
floor
=
math
.
floor
2152
local
stripper
=
patterns
.
stripper
2153
function
table
.
getn
(
t
)
2154
return
t
and
#
t
2155
end
2156
function
table
.
strip
(
tab
)
2157
local
lst
=
{
}
2158
local
l
=
0
2159
for
i
=
1
,
#
tab
do
2160
local
s
=
lpegmatch
(
stripper
,
tab
[
i
]
)
or
"
"
2161
if
s
=
=
"
"
then
2162
else
2163
l
=
l
+
1
2164
lst
[
l
]
=
s
2165
end
2166
end
2167
return
lst
2168
end
2169
function
table
.
keys
(
t
)
2170
if
t
then
2171
local
keys
=
{
}
2172
local
k
=
0
2173
for
key
in
next
,
t
do
2174
k
=
k
+
1
2175
keys
[
k
]
=
key
2176
end
2177
return
keys
2178
else
2179
return
{
}
2180
end
2181
end
2182
local
function
compare
(
a
,
b
)
2183
local
ta
=
type
(
a
)
2184
if
ta
=
=
"
number
"
then
2185
local
tb
=
type
(
b
)
2186
if
ta
=
=
tb
then
2187
return
a
<
b
2188
elseif
tb
=
=
"
string
"
then
2189
return
tostring
(
a
)
<
b
2190
end
2191
elseif
ta
=
=
"
string
"
then
2192
local
tb
=
type
(
b
)
2193
if
ta
=
=
tb
then
2194
return
a
<
b
2195
else
2196
return
a
<
tostring
(
b
)
2197
end
2198
end
2199
return
tostring
(
a
)
<
tostring
(
b
)
2200
end
2201
local
function
sortedkeys
(
tab
)
2202
if
tab
then
2203
local
srt
=
{
}
2204
local
category
=
0
2205
local
s
=
0
2206
for
key
in
next
,
tab
do
2207
s
=
s
+
1
2208
srt
[
s
]
=
key
2209
if
category
~
=
3
then
2210
local
tkey
=
type
(
key
)
2211
if
category
=
=
1
then
2212
if
tkey
~
=
"
string
"
then
2213
category
=
3
2214
end
2215
elseif
category
=
=
2
then
2216
if
tkey
~
=
"
number
"
then
2217
category
=
3
2218
end
2219
else
2220
if
tkey
=
=
"
string
"
then
2221
category
=
1
2222
elseif
tkey
=
=
"
number
"
then
2223
category
=
2
2224
else
2225
category
=
3
2226
end
2227
end
2228
end
2229
end
2230
if
s
<
2
then
2231
elseif
category
=
=
3
then
2232
sort
(
srt
,
compare
)
2233
else
2234
sort
(
srt
)
2235
end
2236
return
srt
2237
else
2238
return
{
}
2239
end
2240
end
2241
local
function
sortedhashonly
(
tab
)
2242
if
tab
then
2243
local
srt
=
{
}
2244
local
s
=
0
2245
for
key
in
next
,
tab
do
2246
if
type
(
key
)
=
=
"
string
"
then
2247
s
=
s
+
1
2248
srt
[
s
]
=
key
2249
end
2250
end
2251
if
s
>
1
then
2252
sort
(
srt
)
2253
end
2254
return
srt
2255
else
2256
return
{
}
2257
end
2258
end
2259
local
function
sortedindexonly
(
tab
)
2260
if
tab
then
2261
local
srt
=
{
}
2262
local
s
=
0
2263
for
key
in
next
,
tab
do
2264
if
type
(
key
)
=
=
"
number
"
then
2265
s
=
s
+
1
2266
srt
[
s
]
=
key
2267
end
2268
end
2269
if
s
>
1
then
2270
sort
(
srt
)
2271
end
2272
return
srt
2273
else
2274
return
{
}
2275
end
2276
end
2277
local
function
sortedhashkeys
(
tab
,
cmp
)
2278
if
tab
then
2279
local
srt
=
{
}
2280
local
s
=
0
2281
for
key
in
next
,
tab
do
2282
if
key
then
2283
s
=
s
+
1
2284
srt
[
s
]
=
key
2285
end
2286
end
2287
if
s
>
1
then
2288
sort
(
srt
,
cmp
)
2289
end
2290
return
srt
2291
else
2292
return
{
}
2293
end
2294
end
2295
function
table
.
allkeys
(
t
)
2296
local
keys
=
{
}
2297
for
k
,
v
in
next
,
t
do
2298
for
k
in
next
,
v
do
2299
keys
[
k
]
=
true
2300
end
2301
end
2302
return
sortedkeys
(
keys
)
2303
end
2304
table
.
sortedkeys
=
sortedkeys
2305
table
.
sortedhashonly
=
sortedhashonly
2306
table
.
sortedindexonly
=
sortedindexonly
2307
table
.
sortedhashkeys
=
sortedhashkeys
2308
local
function
nothing
(
)
end
2309
local
function
sortedhash
(
t
,
cmp
)
2310
if
t
then
2311
local
s
2312
if
cmp
then
2313
s
=
sortedhashkeys
(
t
,
function
(
a
,
b
)
return
cmp
(
t
,
a
,
b
)
end
)
2314
else
2315
s
=
sortedkeys
(
t
)
2316
end
2317
local
m
=
#
s
2318
if
m
=
=
1
then
2319
return
next
,
t
2320
elseif
m
>
0
then
2321
local
n
=
0
2322
return
function
(
)
2323
if
n
<
m
then
2324
n
=
n
+
1
2325
local
k
=
s
[
n
]
2326
return
k
,
t
[
k
]
2327
end
2328
end
2329
end
2330
end
2331
return
nothing
2332
end
2333
table
.
sortedhash
=
sortedhash
2334
table
.
sortedpairs
=
sortedhash
2335
function
table
.
append
(
t
,
list
)
2336
local
n
=
#
t
2337
for
i
=
1
,
#
list
do
2338
n
=
n
+
1
2339
t
[
n
]
=
list
[
i
]
2340
end
2341
return
t
2342
end
2343
function
table
.
prepend
(
t
,
list
)
2344
local
nl
=
#
list
2345
local
nt
=
nl
+
#
t
2346
for
i
=
#
t
,
1
,
-1
do
2347
t
[
nt
]
=
t
[
i
]
2348
nt
=
nt
-1
2349
end
2350
for
i
=
1
,
#
list
do
2351
t
[
i
]
=
list
[
i
]
2352
end
2353
return
t
2354
end
2355
function
table
.
merge
(
t
,
...
)
2356
if
not
t
then
2357
t
=
{
}
2358
end
2359
for
i
=
1
,
select
(
"
#
"
,
...
)
do
2360
for
k
,
v
in
next
,
(
select
(
i
,
...
)
)
do
2361
t
[
k
]
=
v
2362
end
2363
end
2364
return
t
2365
end
2366
function
table
.
merged
(
...
)
2367
local
t
=
{
}
2368
for
i
=
1
,
select
(
"
#
"
,
...
)
do
2369
for
k
,
v
in
next
,
(
select
(
i
,
...
)
)
do
2370
t
[
k
]
=
v
2371
end
2372
end
2373
return
t
2374
end
2375
function
table
.
imerge
(
t
,
...
)
2376
local
nt
=
#
t
2377
for
i
=
1
,
select
(
"
#
"
,
...
)
do
2378
local
nst
=
select
(
i
,
...
)
2379
for
j
=
1
,
#
nst
do
2380
nt
=
nt
+
1
2381
t
[
nt
]
=
nst
[
j
]
2382
end
2383
end
2384
return
t
2385
end
2386
function
table
.
imerged
(
...
)
2387
local
tmp
=
{
}
2388
local
ntmp
=
0
2389
for
i
=
1
,
select
(
"
#
"
,
...
)
do
2390
local
nst
=
select
(
i
,
...
)
2391
for
j
=
1
,
#
nst
do
2392
ntmp
=
ntmp
+
1
2393
tmp
[
ntmp
]
=
nst
[
j
]
2394
end
2395
end
2396
return
tmp
2397
end
2398
local
function
fastcopy
(
old
,
metatabletoo
)
2399
if
old
then
2400
local
new
=
{
}
2401
for
k
,
v
in
next
,
old
do
2402
if
type
(
v
)
=
=
"
table
"
then
2403
new
[
k
]
=
fastcopy
(
v
,
metatabletoo
)
2404
else
2405
new
[
k
]
=
v
2406
end
2407
end
2408
if
metatabletoo
then
2409
local
mt
=
getmetatable
(
old
)
2410
if
mt
then
2411
setmetatable
(
new
,
mt
)
2412
end
2413
end
2414
return
new
2415
else
2416
return
{
}
2417
end
2418
end
2419
local
function
copy
(
t
,
tables
)
2420
if
not
tables
then
2421
tables
=
{
}
2422
end
2423
local
tcopy
=
{
}
2424
if
not
tables
[
t
]
then
2425
tables
[
t
]
=
tcopy
2426
end
2427
for
i
,
v
in
next
,
t
do
2428
if
type
(
i
)
=
=
"
table
"
then
2429
if
tables
[
i
]
then
2430
i
=
tables
[
i
]
2431
else
2432
i
=
copy
(
i
,
tables
)
2433
end
2434
end
2435
if
type
(
v
)
~
=
"
table
"
then
2436
tcopy
[
i
]
=
v
2437
elseif
tables
[
v
]
then
2438
tcopy
[
i
]
=
tables
[
v
]
2439
else
2440
tcopy
[
i
]
=
copy
(
v
,
tables
)
2441
end
2442
end
2443
local
mt
=
getmetatable
(
t
)
2444
if
mt
then
2445
setmetatable
(
tcopy
,
mt
)
2446
end
2447
return
tcopy
2448
end
2449
table
.
fastcopy
=
fastcopy
2450
table
.
copy
=
copy
2451
function
table
.
derive
(
parent
)
2452
local
child
=
{
}
2453
if
parent
then
2454
setmetatable
(
child
,
{
__index
=
parent
}
)
2455
end
2456
return
child
2457
end
2458
function
table
.
tohash
(
t
,
value
)
2459
local
h
=
{
}
2460
if
t
then
2461
if
value
=
=
nil
then
value
=
true
end
2462
for
_
,
v
in
next
,
t
do
2463
h
[
v
]
=
value
2464
end
2465
end
2466
return
h
2467
end
2468
function
table
.
fromhash
(
t
)
2469
local
hsh
=
{
}
2470
local
h
=
0
2471
for
k
,
v
in
next
,
t
do
2472
if
v
then
2473
h
=
h
+
1
2474
hsh
[
h
]
=
k
2475
end
2476
end
2477
return
hsh
2478
end
2479
local
noquotes
,
hexify
,
handle
,
compact
,
inline
,
functions
,
metacheck
,
accurate
2480
local
reserved
=
table
.
tohash
{
2481
'
and
'
,
'
break
'
,
'
do
'
,
'
else
'
,
'
elseif
'
,
'
end
'
,
'
false
'
,
'
for
'
,
'
function
'
,
'
if
'
,
2482
'
in
'
,
'
local
'
,
'
nil
'
,
'
not
'
,
'
or
'
,
'
repeat
'
,
'
return
'
,
'
then
'
,
'
true
'
,
'
until
'
,
'
while
'
,
2483
'
NaN
'
,
'
goto
'
,
'
const
'
,
2484
}
2485
local
function
is_simple_table
(
t
,
hexify
,
accurate
)
2486
local
nt
=
#
t
2487
if
nt
>
0
then
2488
local
n
=
0
2489
for
_
,
v
in
next
,
t
do
2490
n
=
n
+
1
2491
if
type
(
v
)
=
=
"
table
"
then
2492
return
nil
2493
end
2494
end
2495
local
haszero
=
rawget
(
t
,
0
)
2496
if
n
=
=
nt
then
2497
local
tt
=
{
}
2498
for
i
=
1
,
nt
do
2499
local
v
=
t
[
i
]
2500
local
tv
=
type
(
v
)
2501
if
tv
=
=
"
number
"
then
2502
if
hexify
then
2503
tt
[
i
]
=
format
(
"
0x%X
"
,
v
)
2504
elseif
accurate
then
2505
tt
[
i
]
=
format
(
"
%q
"
,
v
)
2506
else
2507
tt
[
i
]
=
v
2508
end
2509
elseif
tv
=
=
"
string
"
then
2510
tt
[
i
]
=
format
(
"
%q
"
,
v
)
2511
elseif
tv
=
=
"
boolean
"
then
2512
tt
[
i
]
=
v
and
"
true
"
or
"
false
"
2513
else
2514
return
nil
2515
end
2516
end
2517
return
tt
2518
elseif
haszero
and
(
n
=
=
nt
+
1
)
then
2519
local
tt
=
{
}
2520
for
i
=
0
,
nt
do
2521
local
v
=
t
[
i
]
2522
local
tv
=
type
(
v
)
2523
if
tv
=
=
"
number
"
then
2524
if
hexify
then
2525
tt
[
i
+
1
]
=
format
(
"
0x%X
"
,
v
)
2526
elseif
accurate
then
2527
tt
[
i
+
1
]
=
format
(
"
%q
"
,
v
)
2528
else
2529
tt
[
i
+
1
]
=
v
2530
end
2531
elseif
tv
=
=
"
string
"
then
2532
tt
[
i
+
1
]
=
format
(
"
%q
"
,
v
)
2533
elseif
tv
=
=
"
boolean
"
then
2534
tt
[
i
+
1
]
=
v
and
"
true
"
or
"
false
"
2535
else
2536
return
nil
2537
end
2538
end
2539
tt
[
1
]
=
"
[0] =
"
.
.
tt
[
1
]
2540
return
tt
2541
end
2542
end
2543
return
nil
2544
end
2545
table
.
is_simple_table
=
is_simple_table
2546
local
propername
=
patterns
.
propername
2547
local
function
dummy
(
)
end
2548
local
function
do_serialize
(
root
,
name
,
depth
,
level
,
indexed
)
2549
if
level
>
0
then
2550
depth
=
depth
.
.
"
"
2551
if
indexed
then
2552
handle
(
format
(
"
%s{
"
,
depth
)
)
2553
else
2554
local
tn
=
type
(
name
)
2555
if
tn
=
=
"
number
"
then
2556
if
hexify
then
2557
handle
(
format
(
"
%s[0x%X]={
"
,
depth
,
name
)
)
2558
else
2559
handle
(
format
(
"
%s[%s]={
"
,
depth
,
name
)
)
2560
end
2561
elseif
tn
=
=
"
string
"
then
2562
if
noquotes
and
not
reserved
[
name
]
and
lpegmatch
(
propername
,
name
)
then
2563
handle
(
format
(
"
%s%s={
"
,
depth
,
name
)
)
2564
else
2565
handle
(
format
(
"
%s[%q]={
"
,
depth
,
name
)
)
2566
end
2567
elseif
tn
=
=
"
boolean
"
then
2568
handle
(
format
(
"
%s[%s]={
"
,
depth
,
name
and
"
true
"
or
"
false
"
)
)
2569
else
2570
handle
(
format
(
"
%s{
"
,
depth
)
)
2571
end
2572
end
2573
end
2574
if
root
and
next
(
root
)
~
=
nil
then
2575
local
first
=
nil
2576
local
last
=
0
2577
if
compact
then
2578
last
=
#
root
2579
for
k
=
1
,
last
do
2580
if
rawget
(
root
,
k
)
=
=
nil
then
2581
last
=
k
-1
2582
break
2583
end
2584
end
2585
if
last
>
0
then
2586
first
=
1
2587
end
2588
end
2589
local
sk
=
sortedkeys
(
root
)
2590
for
i
=
1
,
#
sk
do
2591
local
k
=
sk
[
i
]
2592
local
v
=
root
[
k
]
2593
local
tv
=
type
(
v
)
2594
local
tk
=
type
(
k
)
2595
if
compact
and
first
and
tk
=
=
"
number
"
and
k
>
=
first
and
k
<
=
last
then
2596
if
tv
=
=
"
number
"
then
2597
if
hexify
then
2598
handle
(
format
(
"
%s 0x%X,
"
,
depth
,
v
)
)
2599
elseif
accurate
then
2600
handle
(
format
(
"
%s %q,
"
,
depth
,
v
)
)
2601
else
2602
handle
(
format
(
"
%s %s,
"
,
depth
,
v
)
)
2603
end
2604
elseif
tv
=
=
"
string
"
then
2605
handle
(
format
(
"
%s %q,
"
,
depth
,
v
)
)
2606
elseif
tv
=
=
"
table
"
then
2607
if
next
(
v
)
=
=
nil
then
2608
handle
(
format
(
"
%s {},
"
,
depth
)
)
2609
elseif
inline
then
2610
local
st
=
is_simple_table
(
v
,
hexify
,
accurate
)
2611
if
st
then
2612
handle
(
format
(
"
%s { %s },
"
,
depth
,
concat
(
st
,
"
,
"
)
)
)
2613
else
2614
do_serialize
(
v
,
k
,
depth
,
level
+
1
,
true
)
2615
end
2616
else
2617
do_serialize
(
v
,
k
,
depth
,
level
+
1
,
true
)
2618
end
2619
elseif
tv
=
=
"
boolean
"
then
2620
handle
(
format
(
"
%s %s,
"
,
depth
,
v
and
"
true
"
or
"
false
"
)
)
2621
elseif
tv
=
=
"
function
"
then
2622
if
functions
then
2623
handle
(
format
(
'
%s load(%q),
'
,
depth
,
dump
(
v
)
)
)
2624
else
2625
handle
(
format
(
'
%s "function",
'
,
depth
)
)
2626
end
2627
else
2628
handle
(
format
(
"
%s %q,
"
,
depth
,
tostring
(
v
)
)
)
2629
end
2630
elseif
k
=
=
"
__p__
"
then
2631
if
false
then
2632
handle
(
format
(
"
%s __p__=nil,
"
,
depth
)
)
2633
end
2634
elseif
tv
=
=
"
number
"
then
2635
if
tk
=
=
"
number
"
then
2636
if
hexify
then
2637
handle
(
format
(
"
%s [0x%X]=0x%X,
"
,
depth
,
k
,
v
)
)
2638
elseif
accurate
then
2639
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
,
v
)
)
2640
else
2641
handle
(
format
(
"
%s [%s]=%s,
"
,
depth
,
k
,
v
)
)
2642
end
2643
elseif
tk
=
=
"
boolean
"
then
2644
if
hexify
then
2645
handle
(
format
(
"
%s [%s]=0x%X,
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
v
)
)
2646
elseif
accurate
then
2647
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
v
)
)
2648
else
2649
handle
(
format
(
"
%s [%s]=%s,
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
v
)
)
2650
end
2651
elseif
tk
~
=
"
string
"
then
2652
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2653
if
hexify
then
2654
handle
(
format
(
"
%s %s=0x%X,
"
,
depth
,
k
,
v
)
)
2655
elseif
accurate
then
2656
handle
(
format
(
"
%s %s=%q,
"
,
depth
,
k
,
v
)
)
2657
else
2658
handle
(
format
(
"
%s %s=%s,
"
,
depth
,
k
,
v
)
)
2659
end
2660
else
2661
if
hexify
then
2662
handle
(
format
(
"
%s [%q]=0x%X,
"
,
depth
,
k
,
v
)
)
2663
elseif
accurate
then
2664
handle
(
format
(
"
%s [%q]=%q,
"
,
depth
,
k
,
v
)
)
2665
else
2666
handle
(
format
(
"
%s [%q]=%s,
"
,
depth
,
k
,
v
)
)
2667
end
2668
end
2669
elseif
tv
=
=
"
string
"
then
2670
if
tk
=
=
"
number
"
then
2671
if
hexify
then
2672
handle
(
format
(
"
%s [0x%X]=%q,
"
,
depth
,
k
,
v
)
)
2673
elseif
accurate
then
2674
handle
(
format
(
"
%s [%q]=%q,
"
,
depth
,
k
,
v
)
)
2675
else
2676
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
,
v
)
)
2677
end
2678
elseif
tk
=
=
"
boolean
"
then
2679
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
v
)
)
2680
elseif
tk
~
=
"
string
"
then
2681
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2682
handle
(
format
(
"
%s %s=%q,
"
,
depth
,
k
,
v
)
)
2683
else
2684
handle
(
format
(
"
%s [%q]=%q,
"
,
depth
,
k
,
v
)
)
2685
end
2686
elseif
tv
=
=
"
table
"
then
2687
if
next
(
v
)
=
=
nil
then
2688
if
tk
=
=
"
number
"
then
2689
if
hexify
then
2690
handle
(
format
(
"
%s [0x%X]={},
"
,
depth
,
k
)
)
2691
elseif
accurate
then
2692
handle
(
format
(
"
%s [%q]={},
"
,
depth
,
k
)
)
2693
else
2694
handle
(
format
(
"
%s [%s]={},
"
,
depth
,
k
)
)
2695
end
2696
elseif
tk
=
=
"
boolean
"
then
2697
handle
(
format
(
"
%s [%s]={},
"
,
depth
,
k
and
"
true
"
or
"
false
"
)
)
2698
elseif
tk
~
=
"
string
"
then
2699
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2700
handle
(
format
(
"
%s %s={},
"
,
depth
,
k
)
)
2701
else
2702
handle
(
format
(
"
%s [%q]={},
"
,
depth
,
k
)
)
2703
end
2704
elseif
inline
then
2705
local
st
=
is_simple_table
(
v
,
hexify
,
accurate
)
2706
if
st
then
2707
if
tk
=
=
"
number
"
then
2708
if
hexify
then
2709
handle
(
format
(
"
%s [0x%X]={ %s },
"
,
depth
,
k
,
concat
(
st
,
"
,
"
)
)
)
2710
elseif
accurate
then
2711
handle
(
format
(
"
%s [%q]={ %s },
"
,
depth
,
k
,
concat
(
st
,
"
,
"
)
)
)
2712
else
2713
handle
(
format
(
"
%s [%s]={ %s },
"
,
depth
,
k
,
concat
(
st
,
"
,
"
)
)
)
2714
end
2715
elseif
tk
=
=
"
boolean
"
then
2716
handle
(
format
(
"
%s [%s]={ %s },
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
concat
(
st
,
"
,
"
)
)
)
2717
elseif
tk
~
=
"
string
"
then
2718
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2719
handle
(
format
(
"
%s %s={ %s },
"
,
depth
,
k
,
concat
(
st
,
"
,
"
)
)
)
2720
else
2721
handle
(
format
(
"
%s [%q]={ %s },
"
,
depth
,
k
,
concat
(
st
,
"
,
"
)
)
)
2722
end
2723
else
2724
do_serialize
(
v
,
k
,
depth
,
level
+
1
)
2725
end
2726
else
2727
do_serialize
(
v
,
k
,
depth
,
level
+
1
)
2728
end
2729
elseif
tv
=
=
"
boolean
"
then
2730
if
tk
=
=
"
number
"
then
2731
if
hexify
then
2732
handle
(
format
(
"
%s [0x%X]=%s,
"
,
depth
,
k
,
v
and
"
true
"
or
"
false
"
)
)
2733
elseif
accurate
then
2734
handle
(
format
(
"
%s [%q]=%s,
"
,
depth
,
k
,
v
and
"
true
"
or
"
false
"
)
)
2735
else
2736
handle
(
format
(
"
%s [%s]=%s,
"
,
depth
,
k
,
v
and
"
true
"
or
"
false
"
)
)
2737
end
2738
elseif
tk
=
=
"
boolean
"
then
2739
handle
(
format
(
"
%s [%s]=%s,
"
,
depth
,
tostring
(
k
)
,
v
and
"
true
"
or
"
false
"
)
)
2740
elseif
tk
~
=
"
string
"
then
2741
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2742
handle
(
format
(
"
%s %s=%s,
"
,
depth
,
k
,
v
and
"
true
"
or
"
false
"
)
)
2743
else
2744
handle
(
format
(
"
%s [%q]=%s,
"
,
depth
,
k
,
v
and
"
true
"
or
"
false
"
)
)
2745
end
2746
elseif
tv
=
=
"
function
"
then
2747
if
functions
then
2748
local
getinfo
=
debug
and
debug
.
getinfo
2749
if
getinfo
then
2750
local
f
=
getinfo
(
v
)
.
what
=
=
"
C
"
and
dump
(
dummy
)
or
dump
(
v
)
2751
if
tk
=
=
"
number
"
then
2752
if
hexify
then
2753
handle
(
format
(
"
%s [0x%X]=load(%q),
"
,
depth
,
k
,
f
)
)
2754
elseif
accurate
then
2755
handle
(
format
(
"
%s [%q]=load(%q),
"
,
depth
,
k
,
f
)
)
2756
else
2757
handle
(
format
(
"
%s [%s]=load(%q),
"
,
depth
,
k
,
f
)
)
2758
end
2759
elseif
tk
=
=
"
boolean
"
then
2760
handle
(
format
(
"
%s [%s]=load(%q),
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
f
)
)
2761
elseif
tk
~
=
"
string
"
then
2762
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2763
handle
(
format
(
"
%s %s=load(%q),
"
,
depth
,
k
,
f
)
)
2764
else
2765
handle
(
format
(
"
%s [%q]=load(%q),
"
,
depth
,
k
,
f
)
)
2766
end
2767
end
2768
end
2769
else
2770
if
tk
=
=
"
number
"
then
2771
if
hexify
then
2772
handle
(
format
(
"
%s [0x%X]=%q,
"
,
depth
,
k
,
tostring
(
v
)
)
)
2773
elseif
accurate
then
2774
handle
(
format
(
"
%s [%q]=%q,
"
,
depth
,
k
,
tostring
(
v
)
)
)
2775
else
2776
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
,
tostring
(
v
)
)
)
2777
end
2778
elseif
tk
=
=
"
boolean
"
then
2779
handle
(
format
(
"
%s [%s]=%q,
"
,
depth
,
k
and
"
true
"
or
"
false
"
,
tostring
(
v
)
)
)
2780
elseif
tk
~
=
"
string
"
then
2781
elseif
noquotes
and
not
reserved
[
k
]
and
lpegmatch
(
propername
,
k
)
then
2782
handle
(
format
(
"
%s %s=%q,
"
,
depth
,
k
,
tostring
(
v
)
)
)
2783
else
2784
handle
(
format
(
"
%s [%q]=%q,
"
,
depth
,
k
,
tostring
(
v
)
)
)
2785
end
2786
end
2787
end
2788
end
2789
if
level
>
0
then
2790
handle
(
format
(
"
%s},
"
,
depth
)
)
2791
end
2792
end
2793
local
function
serialize
(
_handle
,
root
,
name
,
specification
)
2794
local
tname
=
type
(
name
)
2795
if
type
(
specification
)
=
=
"
table
"
then
2796
noquotes
=
specification
.
noquotes
2797
hexify
=
specification
.
hexify
2798
accurate
=
specification
.
accurate
2799
handle
=
_handle
or
specification
.
handle
or
print
2800
functions
=
specification
.
functions
2801
compact
=
specification
.
compact
2802
inline
=
specification
.
inline
and
compact
2803
metacheck
=
specification
.
metacheck
2804
if
functions
=
=
nil
then
2805
functions
=
true
2806
end
2807
if
compact
=
=
nil
then
2808
compact
=
true
2809
end
2810
if
inline
=
=
nil
then
2811
inline
=
compact
2812
end
2813
if
metacheck
=
=
nil
then
2814
metacheck
=
true
2815
end
2816
else
2817
noquotes
=
false
2818
hexify
=
false
2819
handle
=
_handle
or
print
2820
compact
=
true
2821
inline
=
true
2822
functions
=
true
2823
metacheck
=
true
2824
end
2825
if
tname
=
=
"
string
"
then
2826
if
name
=
=
"
return
"
then
2827
handle
(
"
return {
"
)
2828
else
2829
handle
(
name
.
.
"
={
"
)
2830
end
2831
elseif
tname
=
=
"
number
"
then
2832
if
hexify
then
2833
handle
(
format
(
"
[0x%X]={
"
,
name
)
)
2834
else
2835
handle
(
"
[
"
.
.
name
.
.
"
]={
"
)
2836
end
2837
elseif
tname
=
=
"
boolean
"
then
2838
if
name
then
2839
handle
(
"
return {
"
)
2840
else
2841
handle
(
"
{
"
)
2842
end
2843
else
2844
handle
(
"
t={
"
)
2845
end
2846
if
root
then
2847
if
metacheck
and
getmetatable
(
root
)
then
2848
local
dummy
=
root
.
_w_h_a_t_e_v_e_r_
2849
root
.
_w_h_a_t_e_v_e_r_
=
nil
2850
end
2851
if
next
(
root
)
~
=
nil
then
2852
do_serialize
(
root
,
name
,
"
"
,
0
)
2853
end
2854
end
2855
handle
(
"
}
"
)
2856
end
2857
function
table
.
serialize
(
root
,
name
,
specification
)
2858
local
t
=
{
}
2859
local
n
=
0
2860
local
function
flush
(
s
)
2861
n
=
n
+
1
2862
t
[
n
]
=
s
2863
end
2864
serialize
(
flush
,
root
,
name
,
specification
)
2865
return
concat
(
t
,
"
\n
"
)
2866
end
2867
table
.
tohandle
=
serialize
2868
local
maxtab
=
2
*
1024
2869
function
table
.
tofile
(
filename
,
root
,
name
,
specification
)
2870
local
f
=
io
.
open
(
filename
,
'
w
'
)
2871
if
f
then
2872
if
maxtab
>
1
then
2873
local
t
=
{
}
2874
local
n
=
0
2875
local
function
flush
(
s
)
2876
n
=
n
+
1
2877
t
[
n
]
=
s
2878
if
n
>
maxtab
then
2879
f
:
write
(
concat
(
t
,
"
\n
"
)
,
"
\n
"
)
2880
t
=
{
}
2881
n
=
0
2882
end
2883
end
2884
serialize
(
flush
,
root
,
name
,
specification
)
2885
f
:
write
(
concat
(
t
,
"
\n
"
)
,
"
\n
"
)
2886
else
2887
local
function
flush
(
s
)
2888
f
:
write
(
s
,
"
\n
"
)
2889
end
2890
serialize
(
flush
,
root
,
name
,
specification
)
2891
end
2892
f
:
close
(
)
2893
io
.
flush
(
)
2894
end
2895
end
2896
local
function
flattened
(
t
,
f
,
depth
)
2897
if
f
=
=
nil
then
2898
f
=
{
}
2899
depth
=
0xFFFF
2900
elseif
tonumber
(
f
)
then
2901
depth
=
f
2902
f
=
{
}
2903
elseif
not
depth
then
2904
depth
=
0xFFFF
2905
end
2906
for
k
,
v
in
next
,
t
do
2907
if
type
(
k
)
~
=
"
number
"
then
2908
if
depth
>
0
and
type
(
v
)
=
=
"
table
"
then
2909
flattened
(
v
,
f
,
depth
-1
)
2910
else
2911
f
[
#
f
+
1
]
=
v
2912
end
2913
end
2914
end
2915
for
k
=
1
,
#
t
do
2916
local
v
=
t
[
k
]
2917
if
depth
>
0
and
type
(
v
)
=
=
"
table
"
then
2918
flattened
(
v
,
f
,
depth
-1
)
2919
else
2920
f
[
#
f
+
1
]
=
v
2921
end
2922
end
2923
return
f
2924
end
2925
table
.
flattened
=
flattened
2926
local
function
collapsed
(
t
,
f
,
h
)
2927
if
f
=
=
nil
then
2928
f
=
{
}
2929
h
=
{
}
2930
end
2931
for
k
=
1
,
#
t
do
2932
local
v
=
t
[
k
]
2933
if
type
(
v
)
=
=
"
table
"
then
2934
collapsed
(
v
,
f
,
h
)
2935
elseif
not
h
[
v
]
then
2936
f
[
#
f
+
1
]
=
v
2937
h
[
v
]
=
true
2938
end
2939
end
2940
return
f
2941
end
2942
local
function
collapsedhash
(
t
,
h
)
2943
if
h
=
=
nil
then
2944
h
=
{
}
2945
end
2946
for
k
=
1
,
#
t
do
2947
local
v
=
t
[
k
]
2948
if
type
(
v
)
=
=
"
table
"
then
2949
collapsedhash
(
v
,
h
)
2950
else
2951
h
[
v
]
=
true
2952
end
2953
end
2954
return
h
2955
end
2956
table
.
collapsed
=
collapsed
2957
table
.
collapsedhash
=
collapsedhash
2958
local
function
unnest
(
t
,
f
)
2959
if
not
f
then
2960
f
=
{
}
2961
end
2962
for
i
=
1
,
#
t
do
2963
local
v
=
t
[
i
]
2964
if
type
(
v
)
=
=
"
table
"
then
2965
if
type
(
v
[
1
]
)
=
=
"
table
"
then
2966
unnest
(
v
,
f
)
2967
else
2968
f
[
#
f
+
1
]
=
v
2969
end
2970
else
2971
f
[
#
f
+
1
]
=
v
2972
end
2973
end
2974
return
f
2975
end
2976
function
table
.
unnest
(
t
)
2977
return
unnest
(
t
)
2978
end
2979
local
function
are_equal
(
a
,
b
,
n
,
m
)
2980
if
a
=
=
b
then
2981
return
true
2982
elseif
a
and
b
and
#
a
=
=
#
b
then
2983
if
not
n
then
2984
n
=
1
2985
end
2986
if
not
m
then
2987
m
=
#
a
2988
end
2989
for
i
=
n
,
m
do
2990
local
ai
,
bi
=
a
[
i
]
,
b
[
i
]
2991
if
ai
=
=
bi
then
2992
elseif
type
(
ai
)
=
=
"
table
"
and
type
(
bi
)
=
=
"
table
"
then
2993
if
not
are_equal
(
ai
,
bi
)
then
2994
return
false
2995
end
2996
else
2997
return
false
2998
end
2999
end
3000
return
true
3001
else
3002
return
false
3003
end
3004
end
3005
local
function
identical
(
a
,
b
)
3006
if
a
~
=
b
then
3007
for
ka
,
va
in
next
,
a
do
3008
local
vb
=
b
[
ka
]
3009
if
va
=
=
vb
then
3010
elseif
type
(
va
)
=
=
"
table
"
and
type
(
vb
)
=
=
"
table
"
then
3011
if
not
identical
(
va
,
vb
)
then
3012
return
false
3013
end
3014
else
3015
return
false
3016
end
3017
end
3018
end
3019
return
true
3020
end
3021
table
.
identical
=
identical
3022
table
.
are_equal
=
are_equal
3023
local
function
sparse
(
old
,
nest
,
keeptables
)
3024
local
new
=
{
}
3025
for
k
,
v
in
next
,
old
do
3026
if
not
(
v
=
=
"
"
or
v
=
=
false
)
then
3027
if
nest
and
type
(
v
)
=
=
"
table
"
then
3028
v
=
sparse
(
v
,
nest
)
3029
if
keeptables
or
next
(
v
)
~
=
nil
then
3030
new
[
k
]
=
v
3031
end
3032
else
3033
new
[
k
]
=
v
3034
end
3035
end
3036
end
3037
return
new
3038
end
3039
table
.
sparse
=
sparse
3040
function
table
.
compact
(
t
)
3041
return
sparse
(
t
,
true
,
true
)
3042
end
3043
function
table
.
contains
(
t
,
v
)
3044
if
t
then
3045
for
i
=
1
,
#
t
do
3046
if
t
[
i
]
=
=
v
then
3047
return
i
3048
end
3049
end
3050
end
3051
return
false
3052
end
3053
function
table
.
count
(
t
)
3054
local
n
=
0
3055
for
k
,
v
in
next
,
t
do
3056
n
=
n
+
1
3057
end
3058
return
n
3059
end
3060
function
table
.
swapped
(
t
,
s
)
3061
local
n
=
{
}
3062
if
s
then
3063
for
k
,
v
in
next
,
s
do
3064
n
[
k
]
=
v
3065
end
3066
end
3067
for
k
,
v
in
next
,
t
do
3068
n
[
v
]
=
k
3069
end
3070
return
n
3071
end
3072
function
table
.
hashed
(
t
)
3073
for
i
=
1
,
#
t
do
3074
t
[
t
[
i
]
]
=
i
3075
end
3076
return
t
3077
end
3078
function
table
.
mirrored
(
t
)
3079
local
n
=
{
}
3080
for
k
,
v
in
next
,
t
do
3081
n
[
v
]
=
k
3082
n
[
k
]
=
v
3083
end
3084
return
n
3085
end
3086
function
table
.
reversed
(
t
)
3087
if
t
then
3088
local
tt
=
{
}
3089
local
tn
=
#
t
3090
if
tn
>
0
then
3091
local
ttn
=
0
3092
for
i
=
tn
,
1
,
-1
do
3093
ttn
=
ttn
+
1
3094
tt
[
ttn
]
=
t
[
i
]
3095
end
3096
end
3097
return
tt
3098
end
3099
end
3100
function
table
.
reverse
(
t
)
3101
if
t
then
3102
local
n
=
#
t
3103
local
m
=
n
+
1
3104
for
i
=
1
,
floor
(
n
/
2
)
do
3105
local
j
=
m
-
i
3106
t
[
i
]
,
t
[
j
]
=
t
[
j
]
,
t
[
i
]
3107
end
3108
return
t
3109
end
3110
end
3111
local
function
sequenced
(
t
,
sep
,
simple
)
3112
if
not
t
then
3113
return
"
"
3114
elseif
type
(
t
)
~
=
"
table
"
then
3115
return
t
3116
end
3117
local
n
=
#
t
3118
local
s
=
{
}
3119
if
n
>
0
then
3120
for
i
=
1
,
n
do
3121
local
v
=
t
[
i
]
3122
if
type
(
v
)
=
=
"
table
"
then
3123
s
[
i
]
=
"
{
"
.
.
sequenced
(
v
,
sep
,
simple
)
.
.
"
}
"
3124
else
3125
s
[
i
]
=
tostring
(
t
[
i
]
)
3126
end
3127
end
3128
else
3129
n
=
0
3130
for
k
,
v
in
sortedhash
(
t
)
do
3131
if
simple
then
3132
if
v
=
=
true
then
3133
n
=
n
+
1
3134
s
[
n
]
=
k
3135
elseif
v
and
v
~
=
"
"
then
3136
n
=
n
+
1
3137
if
type
(
v
)
=
=
"
table
"
then
3138
s
[
n
]
=
k
.
.
"
={
"
.
.
sequenced
(
v
,
sep
,
simple
)
.
.
"
}
"
3139
else
3140
s
[
n
]
=
k
.
.
"
=
"
.
.
tostring
(
v
)
3141
end
3142
end
3143
else
3144
n
=
n
+
1
3145
if
type
(
v
)
=
=
"
table
"
then
3146
s
[
n
]
=
k
.
.
"
={
"
.
.
sequenced
(
v
,
sep
,
simple
)
.
.
"
}
"
3147
else
3148
s
[
n
]
=
k
.
.
"
=
"
.
.
tostring
(
v
)
3149
end
3150
end
3151
end
3152
end
3153
if
sep
=
=
true
then
3154
return
"
{
"
.
.
concat
(
s
,
"
,
"
)
.
.
"
}
"
3155
else
3156
return
concat
(
s
,
sep
or
"
|
"
)
3157
end
3158
end
3159
table
.
sequenced
=
sequenced
3160
function
table
.
print
(
t
,
...
)
3161
if
type
(
t
)
~
=
"
table
"
then
3162
print
(
tostring
(
t
)
)
3163
else
3164
serialize
(
print
,
t
,
...
)
3165
end
3166
end
3167
if
setinspector
then
3168
setinspector
(
"
table
"
,
function
(
v
)
if
type
(
v
)
=
=
"
table
"
then
serialize
(
print
,
v
,
"
table
"
)
return
true
end
end
)
3169
end
3170
function
table
.
sub
(
t
,
i
,
j
)
3171
return
{
unpack
(
t
,
i
,
j
)
}
3172
end
3173
function
table
.
is_empty
(
t
)
3174
return
not
t
or
next
(
t
)
=
=
nil
3175
end
3176
function
table
.
has_one_entry
(
t
)
3177
return
t
and
next
(
t
,
next
(
t
)
)
=
=
nil
3178
end
3179
function
table
.
loweredkeys
(
t
)
3180
local
l
=
{
}
3181
for
k
,
v
in
next
,
t
do
3182
l
[
lower
(
k
)
]
=
v
3183
end
3184
return
l
3185
end
3186
function
table
.
unique
(
old
)
3187
local
hash
=
{
}
3188
local
new
=
{
}
3189
local
n
=
0
3190
for
i
=
1
,
#
old
do
3191
local
oi
=
old
[
i
]
3192
if
not
hash
[
oi
]
then
3193
n
=
n
+
1
3194
new
[
n
]
=
oi
3195
hash
[
oi
]
=
true
3196
end
3197
end
3198
return
new
3199
end
3200
function
table
.
sorted
(
t
,
...
)
3201
sort
(
t
,
...
)
3202
return
t
3203
end
3204
function
table
.
values
(
t
,
s
)
3205
if
t
then
3206
local
values
=
{
}
3207
local
keys
=
{
}
3208
local
v
=
0
3209
for
key
,
value
in
next
,
t
do
3210
if
not
keys
[
value
]
then
3211
v
=
v
+
1
3212
values
[
v
]
=
value
3213
keys
[
k
]
=
key
3214
end
3215
end
3216
if
s
then
3217
sort
(
values
)
3218
end
3219
return
values
3220
else
3221
return
{
}
3222
end
3223
end
3224
function
table
.
filtered
(
t
,
pattern
,
sort
,
cmp
)
3225
if
t
and
type
(
pattern
)
=
=
"
string
"
then
3226
if
sort
then
3227
local
s
3228
if
cmp
then
3229
s
=
sortedhashkeys
(
t
,
function
(
a
,
b
)
return
cmp
(
t
,
a
,
b
)
end
)
3230
else
3231
s
=
sortedkeys
(
t
)
3232
end
3233
local
n
=
0
3234
local
m
=
#
s
3235
local
function
kv
(
s
)
3236
while
n
<
m
do
3237
n
=
n
+
1
3238
local
k
=
s
[
n
]
3239
if
find
(
k
,
pattern
)
then
3240
return
k
,
t
[
k
]
3241
end
3242
end
3243
end
3244
return
kv
,
s
3245
else
3246
local
n
=
next
(
t
)
3247
local
function
iterator
(
)
3248
while
n
~
=
nil
do
3249
local
k
=
n
3250
n
=
next
(
t
,
k
)
3251
if
find
(
k
,
pattern
)
then
3252
return
k
,
t
[
k
]
3253
end
3254
end
3255
end
3256
return
iterator
,
t
3257
end
3258
else
3259
return
nothing
3260
end
3261
end
3262
if
not
table
.
move
then
3263
function
table
.
move
(
a1
,
f
,
e
,
t
,
a2
)
3264
if
a2
and
a1
~
=
a2
then
3265
for
i
=
f
,
e
do
3266
a2
[
t
]
=
a1
[
i
]
3267
t
=
t
+
1
3268
end
3269
return
a2
3270
else
3271
t
=
t
+
e
-
f
3272
for
i
=
e
,
f
,
-1
do
3273
a1
[
t
]
=
a1
[
i
]
3274
t
=
t
-1
3275
end
3276
return
a1
3277
end
3278
end
3279
end
3280 3281 3282
end
-- of closure
3283 3284
do
-- create closure to overcome 200 locals limit
3285 3286
package
.
loaded
[
"
l-io
"
]
=
package
.
loaded
[
"
l-io
"
]
or
true
3287 3288
-- original size: 11988, stripped down to: 6430
3289 3290
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-io
'
]
=
{
3291
version
=
1
.
001
,
3292
comment
=
"
companion to luat-lib.mkiv
"
,
3293
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
3294
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
3295
license
=
"
see context related readme files
"
3296
}
3297
local
io
=
io
3298
local
open
,
flush
,
write
,
read
=
io
.
open
,
io
.
flush
,
io
.
write
,
io
.
read
3299
local
byte
,
find
,
gsub
,
format
=
string
.
byte
,
string
.
find
,
string
.
gsub
,
string
.
format
3300
local
concat
=
table
.
concat
3301
local
type
=
type
3302
if
string
.
find
(
os
.
getenv
(
"
PATH
"
)
or
"
"
,
"
;
"
,
1
,
true
)
then
3303
io
.
fileseparator
,
io
.
pathseparator
=
"
\\
"
,
"
;
"
3304
else
3305
io
.
fileseparator
,
io
.
pathseparator
=
"
/
"
,
"
:
"
3306
end
3307
local
large
=
0x01000000
3308
local
medium
=
0x00100000
3309
local
small
=
0x00020000
3310
local
function
readall
(
f
)
3311
local
size
=
f
:
seek
(
"
end
"
)
3312
if
size
>
0
then
3313
f
:
seek
(
"
set
"
,
0
)
3314
return
f
:
read
(
size
)
3315
else
3316
return
"
"
3317
end
3318
end
3319
io
.
readall
=
readall
3320
function
io
.
loaddata
(
filename
,
textmode
)
3321
local
f
=
open
(
filename
,
(
textmode
and
'
r
'
)
or
'
rb
'
)
3322
if
f
then
3323
local
size
=
f
:
seek
(
"
end
"
)
3324
local
data
=
nil
3325
if
size
>
0
then
3326
f
:
seek
(
"
set
"
,
0
)
3327
data
=
f
:
read
(
size
)
3328
end
3329
f
:
close
(
)
3330
return
data
3331
end
3332
end
3333
function
io
.
copydata
(
source
,
target
,
action
)
3334
local
f
=
open
(
source
,
"
rb
"
)
3335
if
f
then
3336
local
g
=
open
(
target
,
"
wb
"
)
3337
if
g
then
3338
local
size
=
f
:
seek
(
"
end
"
)
3339
if
size
>
0
then
3340
f
:
seek
(
"
set
"
,
0
)
3341
local
data
=
f
:
read
(
size
)
3342
if
action
then
3343
data
=
action
(
data
)
3344
end
3345
if
data
then
3346
g
:
write
(
data
)
3347
end
3348
end
3349
g
:
close
(
)
3350
end
3351
f
:
close
(
)
3352
flush
(
)
3353
end
3354
end
3355
function
io
.
savedata
(
filename
,
data
,
joiner
,
append
)
3356
local
f
=
open
(
filename
,
append
and
"
ab
"
or
"
wb
"
)
3357
if
f
then
3358
if
append
and
joiner
and
f
:
seek
(
"
end
"
)
>
0
then
3359
f
:
write
(
joiner
)
3360
end
3361
if
type
(
data
)
=
=
"
table
"
then
3362
f
:
write
(
concat
(
data
,
joiner
or
"
"
)
)
3363
elseif
type
(
data
)
=
=
"
function
"
then
3364
data
(
f
)
3365
else
3366
f
:
write
(
data
or
"
"
)
3367
end
3368
f
:
close
(
)
3369
flush
(
)
3370
return
true
3371
else
3372
return
false
3373
end
3374
end
3375
if
fio
and
fio
.
readline
then
3376
local
readline
=
fio
.
readline
3377
function
io
.
loadlines
(
filename
,
n
)
3378
local
f
=
open
(
filename
,
'
r
'
)
3379
if
not
f
then
3380
elseif
n
then
3381
local
lines
=
{
}
3382
for
i
=
1
,
n
do
3383
local
line
=
readline
(
f
)
3384
if
line
then
3385
lines
[
i
]
=
line
3386
else
3387
break
3388
end
3389
end
3390
f
:
close
(
)
3391
lines
=
concat
(
lines
,
"
\n
"
)
3392
if
#
lines
>
0
then
3393
return
lines
3394
end
3395
else
3396
local
line
=
readline
(
f
)
3397
f
:
close
(
)
3398
if
line
and
#
line
>
0
then
3399
return
line
3400
end
3401
end
3402
end
3403
else
3404
function
io
.
loadlines
(
filename
,
n
)
3405
local
f
=
open
(
filename
,
'
r
'
)
3406
if
not
f
then
3407
elseif
n
then
3408
local
lines
=
{
}
3409
for
i
=
1
,
n
do
3410
local
line
=
f
:
read
(
"
*lines
"
)
3411
if
line
then
3412
lines
[
i
]
=
line
3413
else
3414
break
3415
end
3416
end
3417
f
:
close
(
)
3418
lines
=
concat
(
lines
,
"
\n
"
)
3419
if
#
lines
>
0
then
3420
return
lines
3421
end
3422
else
3423
local
line
=
f
:
read
(
"
*line
"
)
or
"
"
3424
f
:
close
(
)
3425
if
#
line
>
0
then
3426
return
line
3427
end
3428
end
3429
end
3430
end
3431
function
io
.
loadchunk
(
filename
,
n
)
3432
local
f
=
open
(
filename
,
'
rb
'
)
3433
if
f
then
3434
local
data
=
f
:
read
(
n
or
1024
)
3435
f
:
close
(
)
3436
if
#
data
>
0
then
3437
return
data
3438
end
3439
end
3440
end
3441
function
io
.
exists
(
filename
)
3442
local
f
=
open
(
filename
)
3443
if
f
=
=
nil
then
3444
return
false
3445
else
3446
f
:
close
(
)
3447
return
true
3448
end
3449
end
3450
function
io
.
size
(
filename
)
3451
local
f
=
open
(
filename
)
3452
if
f
=
=
nil
then
3453
return
0
3454
else
3455
local
s
=
f
:
seek
(
"
end
"
)
3456
f
:
close
(
)
3457
return
s
3458
end
3459
end
3460
local
function
noflines
(
f
)
3461
if
type
(
f
)
=
=
"
string
"
then
3462
local
f
=
open
(
filename
)
3463
if
f
then
3464
local
n
=
f
and
noflines
(
f
)
or
0
3465
f
:
close
(
)
3466
return
n
3467
else
3468
return
0
3469
end
3470
else
3471
local
n
=
0
3472
for
_
in
f
:
lines
(
)
do
3473
n
=
n
+
1
3474
end
3475
f
:
seek
(
'
set
'
,
0
)
3476
return
n
3477
end
3478
end
3479
io
.
noflines
=
noflines
3480
local
nextchar
=
{
3481
[
4
]
=
function
(
f
)
3482
return
f
:
read
(
1
,
1
,
1
,
1
)
3483
end
,
3484
[
2
]
=
function
(
f
)
3485
return
f
:
read
(
1
,
1
)
3486
end
,
3487
[
1
]
=
function
(
f
)
3488
return
f
:
read
(
1
)
3489
end
,
3490
[
-2
]
=
function
(
f
)
3491
local
a
,
b
=
f
:
read
(
1
,
1
)
3492
return
b
,
a
3493
end
,
3494
[
-4
]
=
function
(
f
)
3495
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
3496
return
d
,
c
,
b
,
a
3497
end
3498
}
3499
function
io
.
characters
(
f
,
n
)
3500
if
f
then
3501
return
nextchar
[
n
or
1
]
,
f
3502
end
3503
end
3504
local
nextbyte
=
{
3505
[
4
]
=
function
(
f
)
3506
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
3507
if
d
then
3508
return
byte
(
a
)
,
byte
(
b
)
,
byte
(
c
)
,
byte
(
d
)
3509
end
3510
end
,
3511
[
3
]
=
function
(
f
)
3512
local
a
,
b
,
c
=
f
:
read
(
1
,
1
,
1
)
3513
if
b
then
3514
return
byte
(
a
)
,
byte
(
b
)
,
byte
(
c
)
3515
end
3516
end
,
3517
[
2
]
=
function
(
f
)
3518
local
a
,
b
=
f
:
read
(
1
,
1
)
3519
if
b
then
3520
return
byte
(
a
)
,
byte
(
b
)
3521
end
3522
end
,
3523
[
1
]
=
function
(
f
)
3524
local
a
=
f
:
read
(
1
)
3525
if
a
then
3526
return
byte
(
a
)
3527
end
3528
end
,
3529
[
-2
]
=
function
(
f
)
3530
local
a
,
b
=
f
:
read
(
1
,
1
)
3531
if
b
then
3532
return
byte
(
b
)
,
byte
(
a
)
3533
end
3534
end
,
3535
[
-3
]
=
function
(
f
)
3536
local
a
,
b
,
c
=
f
:
read
(
1
,
1
,
1
)
3537
if
b
then
3538
return
byte
(
c
)
,
byte
(
b
)
,
byte
(
a
)
3539
end
3540
end
,
3541
[
-4
]
=
function
(
f
)
3542
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
3543
if
d
then
3544
return
byte
(
d
)
,
byte
(
c
)
,
byte
(
b
)
,
byte
(
a
)
3545
end
3546
end
3547
}
3548
function
io
.
bytes
(
f
,
n
)
3549
if
f
then
3550
return
nextbyte
[
n
or
1
]
,
f
3551
else
3552
return
nil
,
nil
3553
end
3554
end
3555
function
io
.
ask
(
question
,
default
,
options
)
3556
while
true
do
3557
write
(
question
)
3558
if
options
then
3559
write
(
format
(
"
[%s]
"
,
concat
(
options
,
"
|
"
)
)
)
3560
end
3561
if
default
then
3562
write
(
format
(
"
[%s]
"
,
default
)
)
3563
end
3564
write
(
format
(
"
"
)
)
3565
flush
(
)
3566
local
answer
=
read
(
)
3567
answer
=
gsub
(
answer
,
"
^%s*(.*)%s*$
"
,
"
%1
"
)
3568
if
answer
=
=
"
"
and
default
then
3569
return
default
3570
elseif
not
options
then
3571
return
answer
3572
else
3573
for
k
=
1
,
#
options
do
3574
if
options
[
k
]
=
=
answer
then
3575
return
answer
3576
end
3577
end
3578
local
pattern
=
"
^
"
.
.
answer
3579
for
k
=
1
,
#
options
do
3580
local
v
=
options
[
k
]
3581
if
find
(
v
,
pattern
)
then
3582
return
v
3583
end
3584
end
3585
end
3586
end
3587
end
3588
local
function
readnumber
(
f
,
n
,
m
)
3589
if
m
then
3590
f
:
seek
(
"
set
"
,
n
)
3591
n
=
m
3592
end
3593
if
n
=
=
1
then
3594
return
byte
(
f
:
read
(
1
)
)
3595
elseif
n
=
=
2
then
3596
local
a
,
b
=
byte
(
f
:
read
(
2
)
,
1
,
2
)
3597
return
0x100
*
a
+
b
3598
elseif
n
=
=
3
then
3599
local
a
,
b
,
c
=
byte
(
f
:
read
(
3
)
,
1
,
3
)
3600
return
0x10000
*
a
+
0x100
*
b
+
c
3601
elseif
n
=
=
4
then
3602
local
a
,
b
,
c
,
d
=
byte
(
f
:
read
(
4
)
,
1
,
4
)
3603
return
0x1000000
*
a
+
0x10000
*
b
+
0x100
*
c
+
d
3604
elseif
n
=
=
8
then
3605
local
a
,
b
=
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
3606
return
0x100
*
a
+
b
3607
elseif
n
=
=
12
then
3608
local
a
,
b
,
c
=
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
3609
return
0x10000
*
a
+
0x100
*
b
+
c
3610
elseif
n
=
=
-2
then
3611
local
b
,
a
=
byte
(
f
:
read
(
2
)
,
1
,
2
)
3612
return
0x100
*
a
+
b
3613
elseif
n
=
=
-3
then
3614
local
c
,
b
,
a
=
byte
(
f
:
read
(
3
)
,
1
,
3
)
3615
return
0x10000
*
a
+
0x100
*
b
+
c
3616
elseif
n
=
=
-4
then
3617
local
d
,
c
,
b
,
a
=
byte
(
f
:
read
(
4
)
,
1
,
4
)
3618
return
0x1000000
*
a
+
0x10000
*
b
+
0x100
*
c
+
d
3619
elseif
n
=
=
-8
then
3620
local
h
,
g
,
f
,
e
,
d
,
c
,
b
,
a
=
byte
(
f
:
read
(
8
)
,
1
,
8
)
3621
return
0x100000000000000
*
a
+
0x1000000000000
*
b
+
0x10000000000
*
c
+
0x100000000
*
d
+
0x1000000
*
e
+
0x10000
*
f
+
0x100
*
g
+
h
3622
else
3623
return
0
3624
end
3625
end
3626
io
.
readnumber
=
readnumber
3627
function
io
.
readstring
(
f
,
n
,
m
)
3628
if
m
then
3629
f
:
seek
(
"
set
"
,
n
)
3630
n
=
m
3631
end
3632
local
str
=
gsub
(
f
:
read
(
n
)
,
"
\000
"
,
"
"
)
3633
return
str
3634
end
3635 3636 3637
end
-- of closure
3638 3639
do
-- create closure to overcome 200 locals limit
3640 3641
package
.
loaded
[
"
l-number
"
]
=
package
.
loaded
[
"
l-number
"
]
or
true
3642 3643
-- original size: 4588, stripped down to: 2159
3644 3645
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-number
'
]
=
{
3646
version
=
1
.
001
,
3647
comment
=
"
companion to luat-lib.mkxl
"
,
3648
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
3649
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
3650
license
=
"
see context related readme files
"
3651
}
3652
local
tostring
,
tonumber
=
tostring
,
tonumber
3653
local
format
,
match
,
rep
=
string
.
format
,
string
.
match
,
string
.
rep
3654
local
concat
,
insert
=
table
.
concat
,
table
.
insert
3655
local
lpegmatch
=
lpeg
.
match
3656
local
floor
=
math
.
floor
3657
number
=
number
or
{
}
3658
local
number
=
number
3659
if
bit32
then
3660
local
bextract
=
bit32
.
extract
3661
local
t
=
{
3662
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
3663
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
3664
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
3665
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
"
0
"
,
3666
}
3667
function
number
.
tobitstring
(
b
,
m
,
w
)
3668
if
not
w
then
3669
w
=
32
3670
end
3671
local
n
=
w
3672
for
i
=
0
,
w
-1
do
3673
local
v
=
bextract
(
b
,
i
)
3674
local
k
=
w
-
i
3675
if
v
=
=
1
then
3676
n
=
k
3677
t
[
k
]
=
"
1
"
3678
else
3679
t
[
k
]
=
"
0
"
3680
end
3681
end
3682
if
w
then
3683
return
concat
(
t
,
"
"
,
1
,
w
)
3684
elseif
m
then
3685
m
=
33
-
m
*
8
3686
if
m
<
1
then
3687
m
=
1
3688
end
3689
return
concat
(
t
,
"
"
,
1
,
m
)
3690
elseif
n
<
8
then
3691
return
concat
(
t
)
3692
elseif
n
<
16
then
3693
return
concat
(
t
,
"
"
,
9
)
3694
elseif
n
<
24
then
3695
return
concat
(
t
,
"
"
,
17
)
3696
else
3697
return
concat
(
t
,
"
"
,
25
)
3698
end
3699
end
3700
else
3701
function
number
.
tobitstring
(
n
,
m
)
3702
if
n
>
0
then
3703
local
t
=
{
}
3704
while
n
>
0
do
3705
insert
(
t
,
1
,
n
%
2
>
0
and
1
or
0
)
3706
n
=
floor
(
n
/
2
)
3707
end
3708
local
nn
=
8
-
#
t
%
8
3709
if
nn
>
0
and
nn
<
8
then
3710
for
i
=
1
,
nn
do
3711
insert
(
t
,
1
,
0
)
3712
end
3713
end
3714
if
m
then
3715
m
=
m
*
8
-
#
t
3716
if
m
>
0
then
3717
insert
(
t
,
1
,
rep
(
"
0
"
,
m
)
)
3718
end
3719
end
3720
return
concat
(
t
)
3721
elseif
m
then
3722
rep
(
"
00000000
"
,
m
)
3723
else
3724
return
"
00000000
"
3725
end
3726
end
3727
end
3728
function
number
.
valid
(
str
,
default
)
3729
return
tonumber
(
str
)
or
default
or
nil
3730
end
3731
function
number
.
toevenhex
(
n
)
3732
local
s
=
format
(
"
%X
"
,
n
)
3733
if
#
s
%
2
=
=
0
then
3734
return
s
3735
else
3736
return
"
0
"
.
.
s
3737
end
3738
end
3739
function
number
.
bytetodecimal
(
b
)
3740
local
d
=
floor
(
b
*
100
/
255
+
0
.
5
)
3741
if
d
>
100
then
3742
return
100
3743
elseif
d
<
-100
then
3744
return
-100
3745
else
3746
return
d
3747
end
3748
end
3749
function
number
.
decimaltobyte
(
d
)
3750
local
b
=
floor
(
d
*
255
/
100
+
0
.
5
)
3751
if
b
>
255
then
3752
return
255
3753
elseif
b
<
-255
then
3754
return
-255
3755
else
3756
return
b
3757
end
3758
end
3759
function
number
.
idiv
(
i
,
d
)
3760
return
floor
(
i
/
d
)
3761
end
3762 3763 3764
end
-- of closure
3765 3766
do
-- create closure to overcome 200 locals limit
3767 3768
package
.
loaded
[
"
l-set
"
]
=
package
.
loaded
[
"
l-set
"
]
or
true
3769 3770
-- original size: 1923, stripped down to: 1044
3771 3772
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-set
'
]
=
{
3773
version
=
1
.
001
,
3774
comment
=
"
companion to luat-lib.mkiv
"
,
3775
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
3776
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
3777
license
=
"
see context related readme files
"
3778
}
3779
set
=
set
or
{
}
3780
local
nums
=
{
}
3781
local
tabs
=
{
}
3782
local
concat
=
table
.
concat
3783
local
next
,
type
=
next
,
type
3784
set
.
create
=
table
.
tohash
3785
function
set
.
tonumber
(
t
)
3786
if
next
(
t
)
then
3787
local
s
=
"
"
3788
for
k
,
v
in
next
,
t
do
3789
if
v
then
3790
s
=
s
.
.
"
"
.
.
k
3791
end
3792
end
3793
local
n
=
nums
[
s
]
3794
if
not
n
then
3795
n
=
#
tabs
+
1
3796
tabs
[
n
]
=
t
3797
nums
[
s
]
=
n
3798
end
3799
return
n
3800
else
3801
return
0
3802
end
3803
end
3804
function
set
.
totable
(
n
)
3805
if
n
=
=
0
then
3806
return
{
}
3807
else
3808
return
tabs
[
n
]
or
{
}
3809
end
3810
end
3811
function
set
.
tolist
(
n
)
3812
if
n
=
=
0
or
not
tabs
[
n
]
then
3813
return
"
"
3814
else
3815
local
t
,
n
=
{
}
,
0
3816
for
k
,
v
in
next
,
tabs
[
n
]
do
3817
if
v
then
3818
n
=
n
+
1
3819
t
[
n
]
=
k
3820
end
3821
end
3822
return
concat
(
t
,
"
"
)
3823
end
3824
end
3825
function
set
.
contains
(
n
,
s
)
3826
if
type
(
n
)
=
=
"
table
"
then
3827
return
n
[
s
]
3828
elseif
n
=
=
0
then
3829
return
false
3830
else
3831
local
t
=
tabs
[
n
]
3832
return
t
and
t
[
s
]
3833
end
3834
end
3835 3836 3837
end
-- of closure
3838 3839
do
-- create closure to overcome 200 locals limit
3840 3841
package
.
loaded
[
"
l-os
"
]
=
package
.
loaded
[
"
l-os
"
]
or
true
3842 3843
-- original size: 20575, stripped down to: 10700
3844 3845
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-os
'
]
=
{
3846
version
=
1
.
001
,
3847
comment
=
"
companion to luat-lib.mkiv
"
,
3848
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
3849
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
3850
license
=
"
see context related readme files
"
3851
}
3852
local
os
=
os
3853
local
date
,
time
,
difftime
=
os
.
date
,
os
.
time
,
os
.
difftime
3854
local
find
,
format
,
gsub
,
upper
,
gmatch
=
string
.
find
,
string
.
format
,
string
.
gsub
,
string
.
upper
,
string
.
gmatch
3855
local
concat
=
table
.
concat
3856
local
random
,
ceil
,
randomseed
,
modf
=
math
.
random
,
math
.
ceil
,
math
.
randomseed
,
math
.
modf
3857
local
type
,
setmetatable
,
tonumber
,
tostring
=
type
,
setmetatable
,
tonumber
,
tostring
3858
do
3859
local
selfdir
=
os
.
selfdir
3860
if
selfdir
=
=
"
"
then
3861
selfdir
=
nil
3862
end
3863
if
not
selfdir
then
3864
if
arg
then
3865
for
i
=
1
,
#
arg
do
3866
local
a
=
arg
[
i
]
3867
if
find
(
a
,
"
^%-%-[c:]*texmfbinpath=
"
)
then
3868
selfdir
=
gsub
(
a
,
"
^.-=
"
,
"
"
)
3869
break
3870
end
3871
end
3872
end
3873
if
not
selfdir
then
3874
selfdir
=
os
.
selfbin
or
"
luatex
"
3875
if
find
(
selfdir
,
"
[/\\]
"
)
then
3876
selfdir
=
gsub
(
selfdir
,
"
[/\\][^/\\]*$
"
,
"
"
)
3877
elseif
os
.
getenv
then
3878
local
path
=
os
.
getenv
(
"
PATH
"
)
3879
local
name
=
gsub
(
selfdir
,
"
^.*[/\\][^/\\]
"
,
"
"
)
3880
local
patt
=
"
[^:]+
"
3881
if
os
.
type
=
=
"
windows
"
then
3882
patt
=
"
[^;]+
"
3883
name
=
name
.
.
"
.exe
"
3884
end
3885
local
isfile
3886
if
lfs
then
3887
local
attributes
=
lfs
.
attributes
3888
isfile
=
function
(
name
)
3889
local
a
=
attributes
(
name
,
"
mode
"
)
3890
return
a
=
=
"
file
"
or
a
=
=
"
link
"
or
nil
3891
end
3892
else
3893
local
open
=
io
.
open
3894
isfile
=
function
(
name
)
3895
local
f
=
open
(
name
)
3896
if
f
then
3897
f
:
close
(
)
3898
return
true
3899
end
3900
end
3901
end
3902
for
p
in
gmatch
(
path
,
patt
)
do
3903
if
isfile
(
p
.
.
"
/
"
.
.
name
)
then
3904
selfdir
=
p
3905
break
3906
end
3907
end
3908
end
3909
end
3910
os
.
selfdir
=
selfdir
or
"
.
"
3911
end
3912
end
3913
math
.
initialseed
=
tonumber
(
string
.
sub
(
string
.
reverse
(
tostring
(
ceil
(
socket
and
socket
.
gettime
(
)
*
10000
or
time
(
)
)
)
)
,
1
,
6
)
)
3914
randomseed
(
math
.
initialseed
)
3915
if
not
os
.
__getenv__
then
3916
os
.
__getenv__
=
os
.
getenv
3917
os
.
__setenv__
=
os
.
setenv
3918
if
os
.
env
then
3919
local
osgetenv
=
os
.
getenv
3920
local
ossetenv
=
os
.
setenv
3921
local
osenv
=
os
.
env
local
_
=
osenv
.
PATH
3922
function
os
.
setenv
(
k
,
v
)
3923
if
v
=
=
nil
then
3924
v
=
"
"
3925
end
3926
local
K
=
upper
(
k
)
3927
osenv
[
K
]
=
v
3928
if
type
(
v
)
=
=
"
table
"
then
3929
v
=
concat
(
v
,
"
;
"
)
3930
end
3931
ossetenv
(
K
,
v
)
3932
end
3933
function
os
.
getenv
(
k
)
3934
local
K
=
upper
(
k
)
3935
local
v
=
osenv
[
K
]
or
osenv
[
k
]
or
osgetenv
(
K
)
or
osgetenv
(
k
)
3936
if
v
=
=
"
"
then
3937
return
nil
3938
else
3939
return
v
3940
end
3941
end
3942
else
3943
local
ossetenv
=
os
.
setenv
3944
local
osgetenv
=
os
.
getenv
3945
local
osenv
=
{
}
3946
function
os
.
setenv
(
k
,
v
)
3947
if
v
=
=
nil
then
3948
v
=
"
"
3949
end
3950
local
K
=
upper
(
k
)
3951
osenv
[
K
]
=
v
3952
end
3953
function
os
.
getenv
(
k
)
3954
local
K
=
upper
(
k
)
3955
local
v
=
osenv
[
K
]
or
osgetenv
(
K
)
or
osgetenv
(
k
)
3956
if
v
=
=
"
"
then
3957
return
nil
3958
else
3959
return
v
3960
end
3961
end
3962
local
function
__index
(
t
,
k
)
3963
return
os
.
getenv
(
k
)
3964
end
3965
local
function
__newindex
(
t
,
k
,
v
)
3966
os
.
setenv
(
k
,
v
)
3967
end
3968
os
.
env
=
{
}
3969
setmetatable
(
os
.
env
,
{
__index
=
__index
,
__newindex
=
__newindex
}
)
3970
end
3971
end
3972
if
not
io
.
fileseparator
then
3973
if
find
(
os
.
getenv
(
"
PATH
"
)
,
"
;
"
,
1
,
true
)
then
3974
io
.
fileseparator
,
io
.
pathseparator
,
os
.
type
=
"
\\
"
,
"
;
"
,
os
.
type
or
"
windows
"
3975
else
3976
io
.
fileseparator
,
io
.
pathseparator
,
os
.
type
=
"
/
"
,
"
:
"
,
os
.
type
or
"
unix
"
3977
end
3978
end
3979
os
.
type
=
os
.
type
or
(
io
.
pathseparator
=
=
"
;
"
and
"
windows
"
)
or
"
unix
"
3980
os
.
name
=
os
.
name
or
(
os
.
type
=
=
"
windows
"
and
"
mswin
"
)
or
"
linux
"
3981
if
os
.
type
=
=
"
windows
"
then
3982
os
.
libsuffix
,
os
.
binsuffix
,
os
.
binsuffixes
=
'
dll
'
,
'
exe
'
,
{
'
exe
'
,
'
cmd
'
,
'
bat
'
}
3983
else
3984
os
.
libsuffix
,
os
.
binsuffix
,
os
.
binsuffixes
=
'
so
'
,
'
'
,
{
'
'
}
3985
end
3986
do
3987
local
execute
=
os
.
execute
3988
local
iopopen
=
io
.
popen
3989
local
ostype
=
os
.
type
3990
local
function
resultof
(
command
)
3991
local
handle
=
iopopen
(
command
,
ostype
=
=
"
windows
"
and
"
rb
"
or
"
r
"
)
3992
if
handle
then
3993
local
result
=
handle
:
read
(
"
*all
"
)
or
"
"
3994
handle
:
close
(
)
3995
return
result
3996
else
3997
return
"
"
3998
end
3999
end
4000
os
.
resultof
=
resultof
4001
function
os
.
pipeto
(
command
)
4002
return
iopopen
(
command
,
"
w
"
)
4003
end
4004
local
launchers
=
{
4005
windows
=
"
start %s
"
,
4006
macosx
=
"
open %s
"
,
4007
unix
=
"
xdg-open %s &> /dev/null &
"
,
4008
}
4009
function
os
.
launch
(
str
)
4010
local
command
=
format
(
launchers
[
os
.
name
]
or
launchers
.
unix
,
str
)
4011
execute
(
command
)
4012
end
4013
end
4014
do
4015
local
gettimeofday
=
os
.
gettimeofday
or
os
.
clock
4016
os
.
gettimeofday
=
gettimeofday
4017
local
startuptime
=
gettimeofday
(
)
4018
function
os
.
runtime
(
)
4019
return
gettimeofday
(
)
-
startuptime
4020
end
4021
end
4022
do
4023
local
name
=
os
.
name
or
"
linux
"
4024
local
platform
=
os
.
getenv
(
"
MTX_PLATFORM
"
)
or
"
"
4025
local
architecture
=
os
.
uname
and
os
.
uname
(
)
.
machine
4026
local
bits
=
os
.
getenv
(
"
MTX_BITS
"
)
or
find
(
platform
,
"
64
"
)
and
64
or
32
4027
if
platform
~
=
"
"
then
4028
elseif
os
.
type
=
=
"
windows
"
then
4029
architecture
=
string
.
lower
(
architecture
or
os
.
getenv
(
"
PROCESSOR_ARCHITECTURE
"
)
or
"
"
)
4030
if
architecture
=
=
"
x86_64
"
then
4031
bits
,
platform
=
64
,
"
win64
"
4032
elseif
find
(
architecture
,
"
amd64
"
)
then
4033
bits
,
platform
=
64
,
"
win64
"
4034
elseif
find
(
architecture
,
"
arm64
"
)
then
4035
bits
,
platform
=
64
,
"
windows-arm64
"
4036
elseif
find
(
architecture
,
"
arm32
"
)
then
4037
bits
,
platform
=
32
,
"
windows-arm32
"
4038
else
4039
bits
,
platform
=
32
,
"
mswin
"
4040
end
4041
elseif
name
=
=
"
linux
"
then
4042
architecture
=
architecture
or
os
.
getenv
(
"
HOSTTYPE
"
)
or
resultof
(
"
uname -m
"
)
or
"
"
4043
local
musl
=
find
(
os
.
selfdir
or
"
"
,
"
linuxmusl
"
)
4044
if
find
(
architecture
,
"
x86_64
"
)
then
4045
bits
,
platform
=
64
,
musl
and
"
linuxmusl
"
or
"
linux-64
"
4046
elseif
find
(
architecture
,
"
ppc
"
)
then
4047
bits
,
platform
=
32
,
"
linux-ppc
"
4048
else
4049
bits
,
platform
=
32
,
musl
and
"
linuxmusl
"
or
"
linux
"
4050
end
4051
elseif
name
=
=
"
macosx
"
then
4052
architecture
=
architecture
or
resultof
(
"
echo $HOSTTYPE
"
)
or
"
"
4053
if
architecture
=
=
"
"
then
4054
bits
,
platform
=
64
,
"
osx-intel
"
4055
elseif
find
(
architecture
,
"
i386
"
)
then
4056
bits
,
platform
=
64
,
"
osx-intel
"
4057
elseif
find
(
architecture
,
"
x86_64
"
)
then
4058
bits
,
platform
=
64
,
"
osx-64
"
4059
elseif
find
(
architecture
,
"
arm64
"
)
then
4060
bits
,
platform
=
64
,
"
osx-arm
"
4061
else
4062
bits
,
platform
=
32
,
"
osx-ppc
"
4063
end
4064
elseif
name
=
=
"
sunos
"
then
4065
architecture
=
architecture
or
resultof
(
"
uname -m
"
)
or
"
"
4066
if
find
(
architecture
,
"
sparc
"
)
then
4067
bits
,
platform
=
32
,
"
solaris-sparc
"
4068
else
4069
bits
,
platform
=
32
,
"
solaris-intel
"
4070
end
4071
elseif
name
=
=
"
freebsd
"
then
4072
architecture
=
architecture
or
os
.
getenv
(
"
MACHTYPE
"
)
or
resultof
(
"
uname -m
"
)
or
"
"
4073
if
find
(
architecture
,
"
amd64
"
)
or
find
(
architecture
,
"
AMD64
"
)
then
4074
bits
,
platform
=
64
,
"
freebsd-amd64
"
4075
else
4076
bits
,
platform
=
32
,
"
freebsd
"
4077
end
4078
elseif
name
=
=
"
kfreebsd
"
then
4079
architecture
=
architecture
or
os
.
getenv
(
"
HOSTTYPE
"
)
or
resultof
(
"
uname -m
"
)
or
"
"
4080
if
architecture
=
=
"
x86_64
"
then
4081
bits
,
platform
=
64
,
"
kfreebsd-amd64
"
4082
else
4083
bits
,
platform
=
32
,
"
kfreebsd-i386
"
4084
end
4085
else
4086
architecture
=
architecture
or
resultof
(
"
uname -m
"
)
or
"
"
4087
if
find
(
architecture
,
"
aarch64
"
)
then
4088
bits
,
platform
=
"
linux-aarch64
"
4089
elseif
find
(
architecture
,
"
armv7l
"
)
then
4090
bits
,
platform
=
32
,
"
linux-armhf
"
4091
elseif
find
(
architecture
,
"
mips64
"
)
or
find
(
architecture
,
"
mips64el
"
)
then
4092
bits
,
platform
=
64
,
"
linux-mipsel
"
4093
elseif
find
(
architecture
,
"
mipsel
"
)
or
find
(
architecture
,
"
mips
"
)
then
4094
bits
,
platform
=
32
,
"
linux-mipsel
"
4095
else
4096
bits
,
platform
=
64
,
"
linux-64
"
4097
end
4098
end
4099
os
.
setenv
(
"
MTX_PLATFORM
"
,
platform
)
4100
os
.
setenv
(
"
MTX_BITS
"
,
bits
)
4101
os
.
platform
=
platform
4102
os
.
bits
=
bits
4103
os
.
newline
=
name
=
=
"
windows
"
and
"
\013\010
"
or
"
\010
"
4104
end
4105
do
4106
local
t
=
{
8
,
9
,
"
a
"
,
"
b
"
}
4107
function
os
.
uuid
(
)
4108
return
format
(
"
%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x
"
,
4109
random
(
0xFFFF
)
,
random
(
0xFFFF
)
,
4110
random
(
0x0FFF
)
,
4111
t
[
ceil
(
random
(
4
)
)
]
or
8
,
random
(
0x0FFF
)
,
4112
random
(
0xFFFF
)
,
4113
random
(
0xFFFF
)
,
random
(
0xFFFF
)
,
random
(
0xFFFF
)
4114
)
4115
end
4116
end
4117
do
4118
local
hour
,
min
4119
function
os
.
timezone
(
difference
)
4120
if
not
hour
then
4121
local
current
=
time
(
)
4122
local
utcdate
=
date
(
"
!*t
"
,
current
)
4123
local
localdate
=
date
(
"
*t
"
,
current
)
4124
localdate
.
isdst
=
false
4125
local
timediff
=
difftime
(
time
(
localdate
)
,
time
(
utcdate
)
)
4126
hour
,
min
=
modf
(
timediff
/
3600
)
4127
min
=
min
*
60
4128
end
4129
if
difference
then
4130
return
hour
,
min
4131
else
4132
return
format
(
"
%+03d:%02d
"
,
hour
,
min
)
4133
end
4134
end
4135
local
timeformat
=
format
(
"
%%s%s
"
,
os
.
timezone
(
)
)
4136
local
dateformat
=
"
%Y-%m-%d %H:%M:%S
"
4137
local
lasttime
=
nil
4138
local
lastdate
=
nil
4139
function
os
.
fulltime
(
t
,
default
)
4140
t
=
t
and
tonumber
(
t
)
or
0
4141
if
t
>
0
then
4142
elseif
default
then
4143
return
default
4144
else
4145
t
=
time
(
)
4146
end
4147
if
t
~
=
lasttime
then
4148
lasttime
=
t
4149
lastdate
=
format
(
timeformat
,
date
(
dateformat
)
)
4150
end
4151
return
lastdate
4152
end
4153
local
dateformat
=
"
%Y-%m-%d %H:%M:%S
"
4154
local
lasttime
=
nil
4155
local
lastdate
=
nil
4156
function
os
.
localtime
(
t
,
default
)
4157
t
=
t
and
tonumber
(
t
)
or
0
4158
if
t
>
0
then
4159
elseif
default
then
4160
return
default
4161
else
4162
t
=
time
(
)
4163
end
4164
if
t
~
=
lasttime
then
4165
lasttime
=
t
4166
lastdate
=
date
(
dateformat
,
t
)
4167
end
4168
return
lastdate
4169
end
4170
function
os
.
converttime
(
t
,
default
)
4171
local
t
=
tonumber
(
t
)
4172
if
t
and
t
>
0
then
4173
return
date
(
dateformat
,
t
)
4174
else
4175
return
default
or
"
-
"
4176
end
4177
end
4178
function
os
.
today
(
)
4179
return
date
(
"
!*t
"
)
4180
end
4181
function
os
.
now
(
)
4182
return
date
(
"
!%Y-%m-%d %H:%M:%S
"
)
4183
end
4184
end
4185
do
4186
local
cache
=
{
}
4187
local
function
which
(
filename
)
4188
local
fullname
=
cache
[
filename
]
4189
if
fullname
=
=
nil
then
4190
local
suffix
=
file
.
suffix
(
filename
)
4191
local
suffixes
=
suffix
=
=
"
"
and
os
.
binsuffixes
or
{
suffix
}
4192
for
directory
in
gmatch
(
os
.
getenv
(
"
PATH
"
)
,
"
[^
"
.
.
io
.
pathseparator
.
.
"
]+
"
)
do
4193
local
df
=
file
.
join
(
directory
,
filename
)
4194
for
i
=
1
,
#
suffixes
do
4195
local
dfs
=
file
.
addsuffix
(
df
,
suffixes
[
i
]
)
4196
if
io
.
exists
(
dfs
)
then
4197
fullname
=
dfs
4198
break
4199
end
4200
end
4201
end
4202
if
not
fullname
then
4203
fullname
=
false
4204
end
4205
cache
[
filename
]
=
fullname
4206
end
4207
return
fullname
4208
end
4209
os
.
which
=
which
4210
os
.
where
=
which
4211
end
4212
if
not
os
.
sleep
then
4213
local
socket
=
socket
4214
function
os
.
sleep
(
n
)
4215
if
not
socket
then
4216
socket
=
require
(
"
socket
"
)
4217
end
4218
socket
.
sleep
(
n
)
4219
end
4220
end
4221
do
4222
local
function
isleapyear
(
year
)
4223
return
(
year
%
4
=
=
0
)
and
(
year
%
100
~
=
0
or
year
%
400
=
=
0
)
4224
end
4225
os
.
isleapyear
=
isleapyear
4226
local
days
=
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
4227
local
function
nofdays
(
year
,
month
,
day
)
4228
if
not
month
then
4229
return
isleapyear
(
year
)
and
365
or
364
4230
elseif
not
day
then
4231
return
month
=
=
2
and
isleapyear
(
year
)
and
29
or
days
[
month
]
4232
else
4233
for
i
=
1
,
month
-1
do
4234
day
=
day
+
days
[
i
]
4235
end
4236
if
month
>
2
and
isleapyear
(
year
)
then
4237
day
=
day
+
1
4238
end
4239
return
day
4240
end
4241
end
4242
os
.
nofdays
=
nofdays
4243
function
os
.
weekday
(
day
,
month
,
year
)
4244
return
date
(
"
%w
"
,
time
{
year
=
year
,
month
=
month
,
day
=
day
}
)
+
1
4245
end
4246
function
os
.
validdate
(
year
,
month
,
day
)
4247
if
month
<
1
then
4248
month
=
1
4249
elseif
month
>
12
then
4250
month
=
12
4251
end
4252
if
day
<
1
then
4253
day
=
1
4254
else
4255
local
max
=
nofdays
(
year
,
month
)
4256
if
day
>
max
then
4257
day
=
max
4258
end
4259
end
4260
return
year
,
month
,
day
4261
end
4262
function
os
.
date
(
fmt
,
...
)
4263
if
not
fmt
then
4264
fmt
=
"
%Y-%m-%d %H:%M
"
4265
end
4266
return
date
(
fmt
,
...
)
4267
end
4268
end
4269
do
4270
local
osexit
=
os
.
exit
4271
local
exitcode
=
nil
4272
function
os
.
setexitcode
(
code
)
4273
exitcode
=
code
4274
end
4275
function
os
.
exit
(
c
)
4276
if
exitcode
~
=
nil
then
4277
return
osexit
(
exitcode
)
4278
end
4279
if
c
~
=
nil
then
4280
return
osexit
(
c
)
4281
end
4282
return
osexit
(
)
4283
end
4284
end
4285 4286 4287
end
-- of closure
4288 4289
do
-- create closure to overcome 200 locals limit
4290 4291
package
.
loaded
[
"
l-file
"
]
=
package
.
loaded
[
"
l-file
"
]
or
true
4292 4293
-- original size: 22186, stripped down to: 10313
4294 4295
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-file
'
]
=
{
4296
version
=
1
.
001
,
4297
comment
=
"
companion to luat-lib.mkiv
"
,
4298
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
4299
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
4300
license
=
"
see context related readme files
"
4301
}
4302
file
=
file
or
{
}
4303
local
file
=
file
4304
if
not
lfs
then
4305
lfs
=
optionalrequire
(
"
lfs
"
)
4306
end
4307
local
insert
,
concat
=
table
.
insert
,
table
.
concat
4308
local
match
,
find
,
gmatch
=
string
.
match
,
string
.
find
,
string
.
gmatch
4309
local
lpegmatch
=
lpeg
.
match
4310
local
getcurrentdir
,
attributes
=
lfs
.
currentdir
,
lfs
.
attributes
4311
local
checkedsplit
=
string
.
checkedsplit
4312
local
P
,
R
,
S
,
C
,
Cs
,
Cp
,
Cc
,
Ct
=
lpeg
.
P
,
lpeg
.
R
,
lpeg
.
S
,
lpeg
.
C
,
lpeg
.
Cs
,
lpeg
.
Cp
,
lpeg
.
Cc
,
lpeg
.
Ct
4313
local
attributes
=
lfs
.
attributes
4314
function
lfs
.
isdir
(
name
)
4315
if
name
then
4316
return
attributes
(
name
,
"
mode
"
)
=
=
"
directory
"
4317
end
4318
end
4319
function
lfs
.
isfile
(
name
)
4320
if
name
then
4321
local
a
=
attributes
(
name
,
"
mode
"
)
4322
return
a
=
=
"
file
"
or
a
=
=
"
link
"
or
nil
4323
end
4324
end
4325
function
lfs
.
isfound
(
name
)
4326
if
name
then
4327
local
a
=
attributes
(
name
,
"
mode
"
)
4328
return
(
a
=
=
"
file
"
or
a
=
=
"
link
"
)
and
name
or
nil
4329
end
4330
end
4331
function
lfs
.
modification
(
name
)
4332
return
name
and
attributes
(
name
,
"
modification
"
)
or
nil
4333
end
4334
if
sandbox
then
4335
sandbox
.
redefine
(
lfs
.
isfile
,
"
lfs.isfile
"
)
4336
sandbox
.
redefine
(
lfs
.
isdir
,
"
lfs.isdir
"
)
4337
sandbox
.
redefine
(
lfs
.
isfound
,
"
lfs.isfound
"
)
4338
end
4339
local
colon
=
P
(
"
:
"
)
4340
local
period
=
P
(
"
.
"
)
4341
local
periods
=
P
(
"
..
"
)
4342
local
fwslash
=
P
(
"
/
"
)
4343
local
bwslash
=
P
(
"
\\
"
)
4344
local
slashes
=
S
(
"
\\/
"
)
4345
local
noperiod
=
1
-
period
4346
local
noslashes
=
1
-
slashes
4347
local
name
=
noperiod
^
1
4348
local
suffix
=
period
/
"
"
*
(
1
-
period
-
slashes
)
^
1
*
-1
4349
local
pattern
=
C
(
(
1
-
(
slashes
^
1
*
noslashes
^
1
*
-1
)
)
^
1
)
*
P
(
1
)
4350
local
function
pathpart
(
name
,
default
)
4351
return
name
and
lpegmatch
(
pattern
,
name
)
or
default
or
"
"
4352
end
4353
local
pattern
=
(
noslashes
^
0
*
slashes
)
^
1
*
C
(
noslashes
^
1
)
*
-1
4354
local
function
basename
(
name
)
4355
return
name
and
lpegmatch
(
pattern
,
name
)
or
name
4356
end
4357
local
pattern
=
(
noslashes
^
0
*
slashes
^
1
)
^
0
*
Cs
(
(
1
-
suffix
)
^
1
)
*
suffix
^
0
4358
local
function
nameonly
(
name
)
4359
return
name
and
lpegmatch
(
pattern
,
name
)
or
name
4360
end
4361
local
pattern
=
(
noslashes
^
0
*
slashes
)
^
0
*
(
noperiod
^
1
*
period
)
^
1
*
C
(
noperiod
^
1
)
*
-1
4362
local
function
suffixonly
(
name
)
4363
return
name
and
lpegmatch
(
pattern
,
name
)
or
"
"
4364
end
4365
local
pattern
=
(
noslashes
^
0
*
slashes
)
^
0
*
noperiod
^
1
*
(
(
period
*
C
(
noperiod
^
1
)
)
^
1
)
*
-1
+
Cc
(
"
"
)
4366
local
function
suffixesonly
(
name
)
4367
if
name
then
4368
return
lpegmatch
(
pattern
,
name
)
4369
else
4370
return
"
"
4371
end
4372
end
4373
file
.
pathpart
=
pathpart
4374
file
.
basename
=
basename
4375
file
.
nameonly
=
nameonly
4376
file
.
suffixonly
=
suffixonly
4377
file
.
suffix
=
suffixonly
4378
file
.
suffixesonly
=
suffixesonly
4379
file
.
suffixes
=
suffixesonly
4380
file
.
dirname
=
pathpart
4381
file
.
extname
=
suffixonly
4382
local
drive
=
C
(
R
(
"
az
"
,
"
AZ
"
)
)
*
colon
4383
local
path
=
C
(
(
noslashes
^
0
*
slashes
)
^
0
)
4384
local
suffix
=
period
*
C
(
P
(
1
-
period
)
^
0
*
P
(
-1
)
)
4385
local
base
=
C
(
(
1
-
suffix
)
^
0
)
4386
local
rest
=
C
(
P
(
1
)
^
0
)
4387
drive
=
drive
+
Cc
(
"
"
)
4388
path
=
path
+
Cc
(
"
"
)
4389
base
=
base
+
Cc
(
"
"
)
4390
suffix
=
suffix
+
Cc
(
"
"
)
4391
local
pattern_a
=
drive
*
path
*
base
*
suffix
4392
local
pattern_b
=
path
*
base
*
suffix
4393
local
pattern_c
=
C
(
drive
*
path
)
*
C
(
base
*
suffix
)
4394
local
pattern_d
=
path
*
rest
4395
function
file
.
splitname
(
str
,
splitdrive
)
4396
if
not
str
then
4397
elseif
splitdrive
then
4398
return
lpegmatch
(
pattern_a
,
str
)
4399
else
4400
return
lpegmatch
(
pattern_b
,
str
)
4401
end
4402
end
4403
function
file
.
splitbase
(
str
)
4404
if
str
then
4405
return
lpegmatch
(
pattern_d
,
str
)
4406
else
4407
return
"
"
,
str
4408
end
4409
end
4410
function
file
.
nametotable
(
str
,
splitdrive
)
4411
if
str
then
4412
local
path
,
drive
,
subpath
,
name
,
base
,
suffix
=
lpegmatch
(
pattern_c
,
str
)
4413
if
splitdrive
then
4414
return
{
4415
path
=
path
,
4416
drive
=
drive
,
4417
subpath
=
subpath
,
4418
name
=
name
,
4419
base
=
base
,
4420
suffix
=
suffix
,
4421
}
4422
else
4423
return
{
4424
path
=
path
,
4425
name
=
name
,
4426
base
=
base
,
4427
suffix
=
suffix
,
4428
}
4429
end
4430
end
4431
end
4432
local
pattern
=
Cs
(
(
(
period
*
(
1
-
period
-
slashes
)
^
1
*
-1
)
/
"
"
+
1
)
^
1
)
4433
function
file
.
removesuffix
(
name
)
4434
return
name
and
lpegmatch
(
pattern
,
name
)
4435
end
4436
local
suffix
=
period
/
"
"
*
(
1
-
period
-
slashes
)
^
1
*
-1
4437
local
pattern
=
Cs
(
(
noslashes
^
0
*
slashes
^
1
)
^
0
*
(
(
1
-
suffix
)
^
1
)
)
*
Cs
(
suffix
)
4438
function
file
.
addsuffix
(
filename
,
suffix
,
criterium
)
4439
if
not
filename
or
not
suffix
or
suffix
=
=
"
"
then
4440
return
filename
4441
elseif
criterium
=
=
true
then
4442
return
filename
.
.
"
.
"
.
.
suffix
4443
elseif
not
criterium
then
4444
local
n
,
s
=
lpegmatch
(
pattern
,
filename
)
4445
if
not
s
or
s
=
=
"
"
then
4446
return
filename
.
.
"
.
"
.
.
suffix
4447
else
4448
return
filename
4449
end
4450
else
4451
local
n
,
s
=
lpegmatch
(
pattern
,
filename
)
4452
if
s
and
s
~
=
"
"
then
4453
local
t
=
type
(
criterium
)
4454
if
t
=
=
"
table
"
then
4455
for
i
=
1
,
#
criterium
do
4456
if
s
=
=
criterium
[
i
]
then
4457
return
filename
4458
end
4459
end
4460
elseif
t
=
=
"
string
"
then
4461
if
s
=
=
criterium
then
4462
return
filename
4463
end
4464
end
4465
end
4466
return
(
n
or
filename
)
.
.
"
.
"
.
.
suffix
4467
end
4468
end
4469
local
suffix
=
period
*
(
1
-
period
-
slashes
)
^
1
*
-1
4470
local
pattern
=
Cs
(
(
1
-
suffix
)
^
0
)
4471
function
file
.
replacesuffix
(
name
,
suffix
)
4472
if
name
and
suffix
and
suffix
~
=
"
"
then
4473
return
lpegmatch
(
pattern
,
name
)
.
.
"
.
"
.
.
suffix
4474
else
4475
return
name
4476
end
4477
end
4478
local
reslasher
=
lpeg
.
replacer
(
P
(
"
\\
"
)
,
"
/
"
)
4479
function
file
.
reslash
(
str
)
4480
return
str
and
lpegmatch
(
reslasher
,
str
)
4481
end
4482
if
lfs
.
isreadablefile
and
lfs
.
iswritablefile
then
4483
file
.
is_readable
=
lfs
.
isreadablefile
4484
file
.
is_writable
=
lfs
.
iswritablefile
4485
else
4486
function
file
.
is_writable
(
name
)
4487
if
not
name</