summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/lualibs/lualibs-extended-merged.lua')
-rw-r--r--macros/luatex/generic/lualibs/lualibs-extended-merged.lua1173
1 files changed, 1154 insertions, 19 deletions
diff --git a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
index 9cd4487bf2..08428c51ac 100644
--- a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
+++ b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua
@@ -1,6 +1,511 @@
-- merged file : lualibs-extended-merged.lua
-- parent file : lualibs-extended.lua
--- merge date : 2021-05-20 23:14
+-- merge date : 2022-10-04 17:16
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['util-sac']={
+ version=1.001,
+ optimize=true,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local byte,sub=string.byte,string.sub
+local tonumber=tonumber
+utilities=utilities or {}
+local streams={}
+utilities.streams=streams
+function streams.open(filename,zerobased)
+ local f=filename and io.loaddata(filename)
+ if f then
+ return { f,1,#f,zerobased or false }
+ end
+end
+function streams.openstring(f,zerobased)
+ if f then
+ return { f,1,#f,zerobased or false }
+ end
+end
+function streams.getstring(f)
+ if f then
+ return f[1]
+ end
+end
+function streams.close()
+end
+function streams.size(f)
+ return f and f[3] or 0
+end
+streams.getsize=streams.size
+function streams.setposition(f,i)
+ if f[4] then
+ if i<=0 then
+ f[2]=1
+ else
+ f[2]=i+1
+ end
+ else
+ if i<=1 then
+ f[2]=1
+ else
+ f[2]=i
+ end
+ end
+end
+function streams.getposition(f)
+ if f[4] then
+ return f[2]-1
+ else
+ return f[2]
+ end
+end
+function streams.look(f,n,chars)
+ local b=f[2]
+ local e=b+n-1
+ if chars then
+ return sub(f[1],b,e)
+ else
+ return byte(f[1],b,e)
+ end
+end
+function streams.skip(f,n)
+ f[2]=f[2]+n
+end
+function streams.readbyte(f)
+ local i=f[2]
+ f[2]=i+1
+ return byte(f[1],i)
+end
+function streams.readbytes(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return byte(f[1],i,j-1)
+end
+function streams.readbytetable(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return { byte(f[1],i,j-1) }
+end
+function streams.skipbytes(f,n)
+ f[2]=f[2]+n
+end
+function streams.readchar(f)
+ local i=f[2]
+ f[2]=i+1
+ return sub(f[1],i,i)
+end
+function streams.readstring(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return sub(f[1],i,j-1)
+end
+function streams.readinteger1(f)
+ local i=f[2]
+ f[2]=i+1
+ local n=byte(f[1],i)
+ if n>=0x80 then
+ return n-0x100
+ else
+ return n
+ end
+end
+streams.readcardinal1=streams.readbyte
+streams.readcardinal=streams.readcardinal1
+streams.readinteger=streams.readinteger1
+function streams.readcardinal2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local a,b=byte(f[1],i,j)
+ return 0x100*a+b
+end
+function streams.readcardinal2le(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local b,a=byte(f[1],i,j)
+ return 0x100*a+b
+end
+function streams.readinteger2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local a,b=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x100*a+b-0x10000
+ else
+ return 0x100*a+b
+ end
+end
+function streams.readinteger2le(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local b,a=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x100*a+b-0x10000
+ else
+ return 0x100*a+b
+ end
+end
+function streams.readcardinal3(f)
+ local i=f[2]
+ local j=i+2
+ f[2]=j+1
+ local a,b,c=byte(f[1],i,j)
+ return 0x10000*a+0x100*b+c
+end
+function streams.readcardinal3le(f)
+ local i=f[2]
+ local j=i+2
+ f[2]=j+1
+ local c,b,a=byte(f[1],i,j)
+ return 0x10000*a+0x100*b+c
+end
+function streams.readinteger3(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x10000*a+0x100*b+c-0x1000000
+ else
+ return 0x10000*a+0x100*b+c
+ end
+end
+function streams.readinteger3le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local c,b,a=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x10000*a+0x100*b+c-0x1000000
+ else
+ return 0x10000*a+0x100*b+c
+ end
+end
+function streams.readcardinal4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ return 0x1000000*a+0x10000*b+0x100*c+d
+end
+function streams.readcardinal4le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local d,c,b,a=byte(f[1],i,j)
+ return 0x1000000*a+0x10000*b+0x100*c+d
+end
+function streams.readinteger4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
+ else
+ return 0x1000000*a+0x10000*b+0x100*c+d
+ end
+end
+function streams.readinteger4le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local d,c,b,a=byte(f[1],i,j)
+ if a>=0x80 then
+ return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
+ else
+ return 0x1000000*a+0x10000*b+0x100*c+d
+ end
+end
+function streams.readfixed2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local n1,n2=byte(f[1],i,j)
+ if n1>=0x80 then
+ n1=n1-0x100
+ end
+ return n1+n2/0xFF
+end
+function streams.readfixed4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ local n1=0x100*a+b
+ local n2=0x100*c+d
+ if n1>=0x8000 then
+ n1=n1-0x10000
+ end
+ return n1+n2/0xFFFF
+end
+if bit32 then
+ local extract=bit32.extract
+ local band=bit32.band
+ function streams.read2dot14(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local a,b=byte(f[1],i,j)
+ if a>=0x80 then
+ local n=-(0x100*a+b)
+ return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0))
+ else
+ local n=0x100*a+b
+ return (extract(n,14,2)+(band(n,0x3FFF)/16384.0))
+ end
+ end
+end
+function streams.skipshort(f,n)
+ f[2]=f[2]+2*(n or 1)
+end
+function streams.skiplong(f,n)
+ f[2]=f[2]+4*(n or 1)
+end
+if sio and sio.readcardinal2 then
+ local readcardinal1=sio.readcardinal1
+ local readcardinal2=sio.readcardinal2
+ local readcardinal3=sio.readcardinal3
+ local readcardinal4=sio.readcardinal4
+ local readinteger1=sio.readinteger1
+ local readinteger2=sio.readinteger2
+ local readinteger3=sio.readinteger3
+ local readinteger4=sio.readinteger4
+ local readfixed2=sio.readfixed2
+ local readfixed4=sio.readfixed4
+ local read2dot14=sio.read2dot14
+ local readbytes=sio.readbytes
+ local readbytetable=sio.readbytetable
+ function streams.readcardinal1(f)
+ local i=f[2]
+ f[2]=i+1
+ return readcardinal1(f[1],i)
+ end
+ function streams.readcardinal2(f)
+ local i=f[2]
+ f[2]=i+2
+ return readcardinal2(f[1],i)
+ end
+ function streams.readcardinal3(f)
+ local i=f[2]
+ f[2]=i+3
+ return readcardinal3(f[1],i)
+ end
+ function streams.readcardinal4(f)
+ local i=f[2]
+ f[2]=i+4
+ return readcardinal4(f[1],i)
+ end
+ function streams.readinteger1(f)
+ local i=f[2]
+ f[2]=i+1
+ return readinteger1(f[1],i)
+ end
+ function streams.readinteger2(f)
+ local i=f[2]
+ f[2]=i+2
+ return readinteger2(f[1],i)
+ end
+ function streams.readinteger3(f)
+ local i=f[2]
+ f[2]=i+3
+ return readinteger3(f[1],i)
+ end
+ function streams.readinteger4(f)
+ local i=f[2]
+ f[2]=i+4
+ return readinteger4(f[1],i)
+ end
+ function streams.readfixed2(f)
+ local i=f[2]
+ f[2]=i+2
+ return readfixed2(f[1],i)
+ end
+ function streams.readfixed4(f)
+ local i=f[2]
+ f[2]=i+4
+ return readfixed4(f[1],i)
+ end
+ function streams.read2dot14(f)
+ local i=f[2]
+ f[2]=i+2
+ return read2dot14(f[1],i)
+ end
+ function streams.readbytes(f,n)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ return readbytes(f[1],i,n)
+ end
+ function streams.readbytetable(f,n)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ return readbytetable(f[1],i,n)
+ end
+ streams.readbyte=streams.readcardinal1
+ streams.readsignedbyte=streams.readinteger1
+ streams.readcardinal=streams.readcardinal1
+ streams.readinteger=streams.readinteger1
+end
+if sio and sio.readcardinaltable then
+ local readcardinaltable=sio.readcardinaltable
+ local readintegertable=sio.readintegertable
+ function utilities.streams.readcardinaltable(f,n,b)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n*b
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ return readcardinaltable(f[1],i,n,b)
+ end
+ function utilities.streams.readintegertable(f,n,b)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n*b
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ return readintegertable(f[1],i,n,b)
+ end
+else
+ local readcardinal1=streams.readcardinal1
+ local readcardinal2=streams.readcardinal2
+ local readcardinal3=streams.readcardinal3
+ local readcardinal4=streams.readcardinal4
+ function streams.readcardinaltable(f,n,b)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n*b
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ local t={}
+ if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end
+ elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end
+ elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end
+ elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end
+ return t
+ end
+ local readinteger1=streams.readinteger1
+ local readinteger2=streams.readinteger2
+ local readinteger3=streams.readinteger3
+ local readinteger4=streams.readinteger4
+ function streams.readintegertable(f,n,b)
+ local i=f[2]
+ local s=f[3]
+ local p=i+n*b
+ if p>s then
+ f[2]=s+1
+ else
+ f[2]=p
+ end
+ local t={}
+ if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end
+ elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end
+ elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end
+ elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end
+ return t
+ end
+end
+do
+ local files=utilities.files
+ if files then
+ local openfile=files.open
+ local openstream=streams.open
+ local openstring=streams.openstring
+ local setmetatable=setmetatable
+ function io.newreader(str,method)
+ local f,m
+ if method=="string" then
+ f=openstring(str,true)
+ m=streams
+ elseif method=="stream" then
+ f=openstream(str,true)
+ m=streams
+ else
+ f=openfile(str,"rb")
+ m=files
+ end
+ if f then
+ local t={}
+ setmetatable(t,{
+ __index=function(t,k)
+ local r=m[k]
+ if k=="close" then
+ if f then
+ m.close(f)
+ f=nil
+ end
+ return function() end
+ elseif r then
+ local v=function(_,a,b) return r(f,a,b) end
+ t[k]=v
+ return v
+ else
+ print("unknown key",k)
+ end
+ end
+ } )
+ return t
+ end
+ end
+ end
+end
+if bit32 and not streams.tocardinal1 then
+ local extract=bit32.extract
+ local char=string.char
+ streams.tocardinal1=char
+ function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end
+ function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end
+ function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end
+ streams.tocardinal1le=char
+ function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end
+ function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end
+ function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end
+end
+if not streams.readcstring then
+ local readchar=streams.readchar
+ local concat=table.concat
+ function streams.readcstring(f)
+ local t={}
+ while true do
+ local c=readchar(f)
+ if c and c~="\0" then
+ t[#t+1]=c
+ else
+ return concat(t)
+ end
+ end
+ end
+end
+
+end -- closure
do -- begin closure to overcome local limits and interference
@@ -14,12 +519,13 @@ if not modules then modules={} end modules ['util-str']={
utilities=utilities or {}
utilities.strings=utilities.strings or {}
local strings=utilities.strings
-local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find
+local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char
local load,dump=load,string.dump
local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable
local unpack,concat=table.unpack,table.concat
local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local tsplitat=lpeg.tsplitat
local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
local loadstripped=function(str,shortcuts)
if shortcuts then
@@ -373,6 +879,14 @@ patterns.escapedquotes=pattern
function string.escapedquotes(s)
return lpegmatch(pattern,s)
end
+local pattern=(1-P("\\"))^1;pattern=Cs (
+ pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1
+)
+patterns.unescapedquotes=pattern
+function string.unescapedquotes(s)
+ return lpegmatch(pattern,s) or s
+end
+string.texnewlines=lpeg.replacer(patterns.newline,"\r",true)
local preamble=""
local environment={
global=global or _G,
@@ -908,7 +1422,6 @@ function number.to16dot16(n)
return f_16_16(n/65536.0)
end
if not string.explode then
- local tsplitat=lpeg.tsplitat
local p_utf=patterns.utf8character
local p_check=C(p_utf)*(P("+")*Cc(true))^0
local p_split=Ct(C(p_utf)^0)
@@ -928,6 +1441,20 @@ if not string.explode then
end
end
end
+do
+ local p_whitespace=patterns.whitespace^1
+ local cache=setmetatable({},{ __index=function(t,k)
+ local p=tsplitat(p_whitespace*P(k)*p_whitespace)
+ local v=function(s)
+ return lpegmatch(p,s)
+ end
+ t[k]=v
+ return v
+ end })
+ function string.wordsplitter(s)
+ return cache[s]
+ end
+end
end -- closure
@@ -1552,9 +2079,6 @@ if JITSUPPORTED then
return concat(fastserialize(t,true))
end
else
- local f_v=formatters["[%q]=%q,"]
- local f_t=formatters["[%q]="]
- local f_q=formatters["%q,"]
function table.fastserialize(t,prefix)
local r={ type(prefix)=="string" and prefix or "return" }
local m=1
@@ -1963,6 +2487,21 @@ function table.ordered(t)
return function() end
end
end
+function combine(target,source)
+ if target then
+ for k,v in next,source do
+ if type(v)=="table" then
+ target[k]=combine(target[k],source[k])
+ else
+ target[k]=v
+ end
+ end
+ return target
+ else
+ return source
+ end
+end
+table.combine=combine
end -- closure
@@ -2181,8 +2720,8 @@ local noparent=1-(lparent+rparent)
local nobracket=1-(lbracket+rbracket)
local escape,left,right=P("\\"),P('{'),P('}')
lpegpatterns.balanced=P {
- [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
- [2]=left*V(1)*right
+ ((escape*(left+right))+(1-(left+right))+V(2))^0,
+ left*V(1)*right
}
local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
@@ -2190,11 +2729,12 @@ local nestedbrackets=P { lbracket*(nobracket+V(1))^0*rbracket }
local spaces=space^0
local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
local content=(1-endofstring)^0
-lpegpatterns.nestedbraces=nestedbraces
-lpegpatterns.nestedparents=nestedparents
-lpegpatterns.nested=nestedbraces
-lpegpatterns.argument=argument
-lpegpatterns.content=content
+lpegpatterns.nestedbraces=nestedbraces
+lpegpatterns.nestedparents=nestedparents
+lpegpatterns.nestedbrackets=nestedbrackets
+lpegpatterns.nested=nestedbraces
+lpegpatterns.argument=argument
+lpegpatterns.content=content
local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0)
local key=C((1-equal-comma)^1)
local pattern_a=(space+comma)^0*(key*equal*value+key*C(""))
@@ -2600,15 +3140,24 @@ local function ranger(first,last,n,action)
action(first)
end
end
-local cardinal=lpegpatterns.cardinal/tonumber
+local cardinal=(lpegpatterns.hexadecimal+lpegpatterns.cardinal)/tonumber
local spacers=lpegpatterns.spacer^0
local endofstring=lpegpatterns.endofstring
local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring
function parsers.stepper(str,n,action)
+ local ts=type(str)
if type(n)=="function" then
- lpegmatch(stepper,str,1,false,n or print)
- else
+ if ts=="number" then
+ n(str)
+ elseif ts=="table" then
+ for i=1,#str do
+ n(str[i])
+ end
+ else
+ lpegmatch(stepper,str,1,false,n or print)
+ end
+ elseif ts=="string" then
lpegmatch(stepper,str,1,n,action or print)
end
end
@@ -2626,7 +3175,7 @@ local cache={}
local spaces=lpegpatterns.space^0
local dummy=function() end
setmetatableindex(cache,function(t,k)
- local separator=P(k)
+ local separator=S(k)
local value=(1-separator)^0
local pattern=spaces*C(value)*separator^0*Cp()
t[k]=pattern
@@ -2706,8 +3255,11 @@ local p_year=lpegpatterns.digit^4/tonumber
local pattern=Cf(Ct("")*(
(Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("day")*cardinal)
)+(Cg(Cc("day")*cardinal)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year)
+ )+(Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal)
+ )+(Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year)
)
- )*P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1
+ )*(
+ P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1+P(-1) )
,rawset)
lpegpatterns.splittime=pattern
function parsers.totime(str)
@@ -2914,6 +3466,9 @@ if not modules then modules={} end modules ['util-jsn']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+if utilities and utilities.json then
+ return json
+end
local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg
local lpegmatch=lpeg.match
local format,gsub=string.format,string.gsub
@@ -3118,6 +3673,8 @@ do
k=lpegmatch(escaper,k) or k
v=lpegmatch(escaper,v) or v
n=n+1 t[n]=f_key_val_str(depth,k,v)
+ elseif i>1 then
+ n=n-1
end
elseif tv=="table" then
local l=#v
@@ -3133,6 +3690,8 @@ do
end
elseif next(v) then
tojsonpp(v,k,depth,level+1,0)
+ elseif i>1 then
+ n=n-1
end
elseif tv=="boolean" then
if tk=="number" then
@@ -3150,6 +3709,8 @@ do
else
t[n]=f_key_val_nop(depth,k)
end
+ elseif i>1 then
+ n=n-1
end
else
if tk=="number" then
@@ -3159,6 +3720,8 @@ do
k=lpegmatch(escaper,k) or k
n=n+1
t[n]=f_key_val_null(depth,k)
+ elseif i>1 then
+ n=n-1
end
end
end
@@ -3260,7 +3823,6 @@ do
return jsontostring(value,true)
end
end
-return json
end -- closure
@@ -3990,6 +4552,22 @@ local function showtraceback(rep)
end
end
debugger.showtraceback=showtraceback
+if luac then
+ local show,dump=luac.print,string.dump
+ function luac.inspect(v)
+ if type(v)=="function" then
+ local ok,str=xpcall(dump,function() end,v)
+ if ok then
+ v=str
+ end
+ end
+ if type(v)=="string" then
+ show(v,true)
+ else
+ print(v)
+ end
+ end
+end
end -- closure
@@ -4379,3 +4957,560 @@ function stacker.new(name)
end
end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['util-zip']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tostring,tonumber=type,tostring,tonumber
+local sort,concat=table.sort,table.concat
+local find,format,sub,gsub=string.find,string.format,string.sub,string.gsub
+local osdate,ostime,osclock=os.date,os.time,os.clock
+local ioopen=io.open
+local loaddata,savedata=io.loaddata,io.savedata
+local filejoin,isdir,dirname,mkdirs=file.join,lfs.isdir,file.dirname,dir.mkdirs
+local suffix,suffixes=file.suffix,file.suffixes
+local openfile=io.open
+gzip=gzip or {}
+if not zlib then
+ zlib=xzip
+elseif not xzip then
+ xzip=zlib
+end
+local files=utilities.files
+local openfile=files.open
+local closefile=files.close
+local readstring=files.readstring
+local readcardinal2=files.readcardinal2le
+local readcardinal4=files.readcardinal4le
+local setposition=files.setposition
+local getposition=files.getposition
+local band=bit32.band
+local rshift=bit32.rshift
+local lshift=bit32.lshift
+local zlibdecompress=zlib.decompress
+local zlibdecompresssize=zlib.decompresssize
+local zlibchecksum=zlib.crc32
+if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then
+ local cs=zlibchecksum
+ zlibchecksum=function(str,n) return cs(n or 0,str) end
+end
+local decompress=function(source) return zlibdecompress (source,-15) end
+local decompresssize=function(source,targetsize) return zlibdecompresssize(source,targetsize,-15) end
+local calculatecrc=function(buffer,initial) return zlibchecksum (initial or 0,buffer) end
+local zipfiles={}
+utilities.zipfiles=zipfiles
+local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do
+ function openzipfile(name)
+ return {
+ name=name,
+ handle=openfile(name,0),
+ }
+ end
+ local function collect(z)
+ if not z.list then
+ local list={}
+ local hash={}
+ local position=0
+ local index=0
+ local handle=z.handle
+ while true do
+ setposition(handle,position)
+ local signature=readstring(handle,4)
+ if signature=="PK\3\4" then
+ local version=readcardinal2(handle)
+ local flag=readcardinal2(handle)
+ local method=readcardinal2(handle)
+ local filetime=readcardinal2(handle)
+ local filedate=readcardinal2(handle)
+ local crc32=readcardinal4(handle)
+ local compressed=readcardinal4(handle)
+ local uncompressed=readcardinal4(handle)
+ local namelength=readcardinal2(handle)
+ local extralength=readcardinal2(handle)
+ local filename=readstring(handle,namelength)
+ local descriptor=band(flag,8)~=0
+ local encrypted=band(flag,1)~=0
+ local acceptable=method==0 or method==8
+ local skipped=0
+ local size=0
+ if encrypted then
+ size=readcardinal2(handle)
+ skipbytes(size)
+ skipped=skipped+size+2
+ skipbytes(8)
+ skipped=skipped+8
+ size=readcardinal2(handle)
+ skipbytes(size)
+ skipped=skipped+size+2
+ size=readcardinal4(handle)
+ skipbytes(size)
+ skipped=skipped+size+4
+ size=readcardinal2(handle)
+ skipbytes(size)
+ skipped=skipped+size+2
+ end
+ position=position+30+namelength+extralength+skipped
+ if descriptor then
+ setposition(handle,position+compressed)
+ crc32=readcardinal4(handle)
+ compressed=readcardinal4(handle)
+ uncompressed=readcardinal4(handle)
+ end
+ if acceptable then
+ index=index+1
+ local data={
+ filename=filename,
+ index=index,
+ position=position,
+ method=method,
+ compressed=compressed,
+ uncompressed=uncompressed,
+ crc32=crc32,
+ encrypted=encrypted,
+ }
+ hash[filename]=data
+ list[index]=data
+ else
+ end
+ position=position+compressed
+ else
+ break
+ end
+ z.list=list
+ z.hash=hash
+ end
+ end
+ end
+ function getziplist(z)
+ local list=z.list
+ if not list then
+ collect(z)
+ end
+ return z.list
+ end
+ function getziphash(z)
+ local hash=z.hash
+ if not hash then
+ collect(z)
+ end
+ return z.hash
+ end
+ function foundzipfile(z,name)
+ return getziphash(z)[name]
+ end
+ function closezipfile(z)
+ local f=z.handle
+ if f then
+ closefile(f)
+ z.handle=nil
+ end
+ end
+ function unzipfile(z,filename,check)
+ local hash=z.hash
+ if not hash then
+ hash=zipfiles.hash(z)
+ end
+ local data=hash[filename]
+ if not data then
+ end
+ if data then
+ local handle=z.handle
+ local position=data.position
+ local compressed=data.compressed
+ if compressed>0 then
+ setposition(handle,position)
+ local result=readstring(handle,compressed)
+ if data.method==8 then
+ if decompresssize then
+ result=decompresssize(result,data.uncompressed)
+ else
+ result=decompress(result)
+ end
+ end
+ if check and data.crc32~=calculatecrc(result) then
+ print("checksum mismatch")
+ return ""
+ end
+ return result
+ else
+ return ""
+ end
+ end
+ end
+ zipfiles.open=openzipfile
+ zipfiles.close=closezipfile
+ zipfiles.unzip=unzipfile
+ zipfiles.hash=getziphash
+ zipfiles.list=getziplist
+ zipfiles.found=foundzipfile
+end
+if xzip then
+ local writecardinal1=files.writebyte
+ local writecardinal2=files.writecardinal2le
+ local writecardinal4=files.writecardinal4le
+ local logwriter=logs.writer
+ local globpattern=dir.globpattern
+ local compress=xzip.compress
+ local checksum=xzip.crc32
+ local function fromdostime(dostime,dosdate)
+ return ostime {
+ year=rshift(dosdate,9)+1980,
+ month=band(rshift(dosdate,5),0x0F),
+ day=band((dosdate ),0x1F),
+ hour=band(rshift(dostime,11) ),
+ min=band(rshift(dostime,5),0x3F),
+ sec=band((dostime ),0x1F),
+ }
+ end
+ local function todostime(time)
+ local t=osdate("*t",time)
+ return
+ lshift(t.year-1980,9)+lshift(t.month,5)+t.day,
+ lshift(t.hour,11)+lshift(t.min,5)+rshift(t.sec,1)
+ end
+ local function openzip(filename,level,comment,verbose)
+ local f=ioopen(filename,"wb")
+ if f then
+ return {
+ filename=filename,
+ handle=f,
+ list={},
+ level=tonumber(level) or 3,
+ comment=tostring(comment),
+ verbose=verbose,
+ uncompressed=0,
+ compressed=0,
+ }
+ end
+ end
+ local function writezip(z,name,data,level,time)
+ local f=z.handle
+ local list=z.list
+ local level=tonumber(level) or z.level or 3
+ local method=8
+ local zipped=compress(data,level)
+ local checksum=checksum(data)
+ local verbose=z.verbose
+ if not zipped then
+ method=0
+ zipped=data
+ end
+ local start=f:seek()
+ local compressed=#zipped
+ local uncompressed=#data
+ z.compressed=z.compressed+compressed
+ z.uncompressed=z.uncompressed+uncompressed
+ if verbose then
+ local pct=100*compressed/uncompressed
+ if pct>=100 then
+ logwriter(format("%10i %s",uncompressed,name))
+ else
+ logwriter(format("%10i %02.1f %s",uncompressed,pct,name))
+ end
+ end
+ f:write("\x50\x4b\x03\x04")
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,method)
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal4(f,checksum)
+ writecardinal4(f,compressed)
+ writecardinal4(f,uncompressed)
+ writecardinal2(f,#name)
+ writecardinal2(f,0)
+ f:write(name)
+ f:write(zipped)
+ list[#list+1]={ #zipped,#data,name,checksum,start,time or 0 }
+ end
+ local function closezip(z)
+ local f=z.handle
+ local list=z.list
+ local comment=z.comment
+ local verbose=z.verbose
+ local count=#list
+ local start=f:seek()
+ for i=1,count do
+ local l=list[i]
+ local compressed=l[1]
+ local uncompressed=l[2]
+ local name=l[3]
+ local checksum=l[4]
+ local start=l[5]
+ local time=l[6]
+ local date,time=todostime(time)
+ f:write('\x50\x4b\x01\x02')
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,8)
+ writecardinal2(f,time)
+ writecardinal2(f,date)
+ writecardinal4(f,checksum)
+ writecardinal4(f,compressed)
+ writecardinal4(f,uncompressed)
+ writecardinal2(f,#name)
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal4(f,0)
+ writecardinal4(f,start)
+ f:write(name)
+ end
+ local stop=f:seek()
+ local size=stop-start
+ f:write('\x50\x4b\x05\x06')
+ writecardinal2(f,0)
+ writecardinal2(f,0)
+ writecardinal2(f,count)
+ writecardinal2(f,count)
+ writecardinal4(f,size)
+ writecardinal4(f,start)
+ if type(comment)=="string" and comment~="" then
+ writecardinal2(f,#comment)
+ f:write(comment)
+ else
+ writecardinal2(f,0)
+ end
+ if verbose then
+ local compressed=z.compressed
+ local uncompressed=z.uncompressed
+ local filename=z.filename
+ local pct=100*compressed/uncompressed
+ logwriter("")
+ if pct>=100 then
+ logwriter(format("%10i %s",uncompressed,filename))
+ else
+ logwriter(format("%10i %02.1f %s",uncompressed,pct,filename))
+ end
+ end
+ f:close()
+ end
+ local function zipdir(zipname,path,level,verbose)
+ if type(zipname)=="table" then
+ verbose=zipname.verbose
+ level=zipname.level
+ path=zipname.path
+ zipname=zipname.zipname
+ end
+ if not zipname or zipname=="" then
+ return
+ end
+ if not path or path=="" then
+ path="."
+ end
+ if not isdir(path) then
+ return
+ end
+ path=gsub(path,"\\+","/")
+ path=gsub(path,"/+","/")
+ local list={}
+ local count=0
+ globpattern(path,"",true,function(name,size,time)
+ count=count+1
+ list[count]={ name,time }
+ end)
+ sort(list,function(a,b)
+ return a[1]<b[1]
+ end)
+ local zipf=openzip(zipname,level,comment,verbose)
+ if zipf then
+ local p=#path+2
+ for i=1,count do
+ local li=list[i]
+ local name=li[1]
+ local time=li[2]
+ local data=loaddata(name)
+ local name=sub(name,p,#name)
+ writezip(zipf,name,data,level,time,verbose)
+ end
+ closezip(zipf)
+ end
+ end
+ local function unzipdir(zipname,path,verbose)
+ if type(zipname)=="table" then
+ verbose=zipname.verbose
+ path=zipname.path
+ zipname=zipname.zipname
+ end
+ if not zipname or zipname=="" then
+ return
+ end
+ if not path or path=="" then
+ path="."
+ end
+ local z=openzipfile(zipname)
+ if z then
+ local list=getziplist(z)
+ if list then
+ local total=0
+ local count=#list
+ local step=number.idiv(count,10)
+ local done=0
+ local steps=verbose=="steps"
+ local time=steps and osclock()
+ for i=1,count do
+ local l=list[i]
+ local n=l.filename
+ local d=unzipfile(z,n)
+ if d then
+ local p=filejoin(path,n)
+ if mkdirs(dirname(p)) then
+ if steps then
+ total=total+#d
+ done=done+1
+ if done>=step then
+ done=0
+ logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",i,count,total,osclock()-time))
+ end
+ elseif verbose then
+ logwriter(n)
+ end
+ savedata(p,d)
+ end
+ else
+ logwriter(format("problem with file %s",n))
+ end
+ end
+ if steps then
+ logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",count,count,total,osclock()-time))
+ end
+ closezipfile(z)
+ return true
+ else
+ closezipfile(z)
+ end
+ end
+ end
+ zipfiles.zipdir=zipdir
+ zipfiles.unzipdir=unzipdir
+end
+local pattern="^\x1F\x8B\x08"
+local gziplevel=3
+function gzip.suffix(filename)
+ local suffix,extra=suffixes(filename)
+ local gzipped=extra=="gz"
+ return suffix,gzipped
+end
+function gzip.compressed(s)
+ return s and find(s,pattern)
+end
+local getdecompressed
+local putcompressed
+if gzip.compress then
+ local gzipwindow=15+16
+ local compress=zlib.compress
+ local decompress=zlib.decompress
+ getdecompressed=function(str)
+ return decompress(str,gzipwindow)
+ end
+ putcompressed=function(str,level)
+ return compress(str,level or gziplevel,nil,gzipwindow)
+ end
+else
+ local gzipwindow=-15
+ local identifier="\x1F\x8B"
+ local compress=zlib.compress
+ local decompress=zlib.decompress
+ local zlibchecksum=zlib.crc32
+ if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then
+ local cs=zlibchecksum
+ zlibchecksum=function(str,n) return cs(n or 0,str) end
+ end
+ local streams=utilities.streams
+ local openstream=streams.openstring
+ local closestream=streams.close
+ local getposition=streams.getposition
+ local readbyte=streams.readbyte
+ local readcardinal4=streams.readcardinal4le
+ local readcardinal2=streams.readcardinal2le
+ local readstring=streams.readstring
+ local readcstring=streams.readcstring
+ local skipbytes=streams.skip
+ local tocardinal1=streams.tocardinal1
+ local tocardinal4=streams.tocardinal4le
+ getdecompressed=function(str)
+ local s=openstream(str)
+ local identifier=readstring(s,2)
+ local method=readbyte(s,1)
+ local flags=readbyte(s,1)
+ local timestamp=readcardinal4(s)
+ local compression=readbyte(s,1)
+ local operating=readbyte(s,1)
+ local isjusttext=band(flags,0x01)~=0 and true or false
+ local extrasize=band(flags,0x04)~=0 and readcardinal2(s) or 0
+ local filename=band(flags,0x08)~=0 and readcstring(s) or ""
+ local comment=band(flags,0x10)~=0 and readcstring(s) or ""
+ local checksum=band(flags,0x02)~=0 and readcardinal2(s) or 0
+ local compressed=readstring(s,#str)
+ local data=decompress(compressed,gzipwindow)
+ return data
+ end
+ putcompressed=function(str,level,originalname)
+ return concat {
+ identifier,
+ tocardinal1(0x08),
+ tocardinal1(0x08),
+ tocardinal4(os.time()),
+ tocardinal1(0x02),
+ tocardinal1(0xFF),
+ (originalname or "unknownname").."\0",
+ compress(str,level,nil,gzipwindow),
+ tocardinal4(zlibchecksum(str)),
+ tocardinal4(#str),
+ }
+ end
+end
+function gzip.load(filename)
+ local f=openfile(filename,"rb")
+ if not f then
+ else
+ local data=f:read("*all")
+ f:close()
+ if data and data~="" then
+ if suffix(filename)=="gz" then
+ data=getdecompressed(data)
+ end
+ return data
+ end
+ end
+end
+function gzip.save(filename,data,level,originalname)
+ if suffix(filename)~="gz" then
+ filename=filename..".gz"
+ end
+ local f=openfile(filename,"wb")
+ if f then
+ data=putcompressed(data or "",level or gziplevel,originalname)
+ f:write(data)
+ f:close()
+ return #data
+ end
+end
+function gzip.compress(s,level)
+ if s and not find(s,pattern) then
+ if not level then
+ level=gziplevel
+ elseif level<=0 then
+ return s
+ elseif level>9 then
+ level=9
+ end
+ return putcompressed(s,level or gziplevel) or s
+ end
+end
+function gzip.decompress(s)
+ if s and find(s,pattern) then
+ return getdecompressed(s)
+ else
+ return s
+ end
+end
+
+end -- closure