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