diff options
Diffstat (limited to 'Master')
19 files changed, 738 insertions, 368 deletions
diff --git a/Master/texmf-dist/doc/luatex/lualibs/NEWS b/Master/texmf-dist/doc/luatex/lualibs/NEWS index 889232dc47a..6117812375e 100644 --- a/Master/texmf-dist/doc/luatex/lualibs/NEWS +++ b/Master/texmf-dist/doc/luatex/lualibs/NEWS @@ -1,4 +1,7 @@ History of the lualibs package +2023/07/13 v2.76/ + * sync with Context current as of 2023/07/13. + 2022/10/04 v2.75/ * sync with Context current as of 2022/10/04. * add util-sac diff --git a/Master/texmf-dist/doc/luatex/lualibs/README.md b/Master/texmf-dist/doc/luatex/lualibs/README.md index 09194115ceb..f4f2e7162ce 100644 --- a/Master/texmf-dist/doc/luatex/lualibs/README.md +++ b/Master/texmf-dist/doc/luatex/lualibs/README.md @@ -1,10 +1,10 @@ # The Lualibs Package -VERSION: 2.75 +VERSION: 2.76 -DATE: 2022-10-04 +DATE: 2023-07-13 -FONTLOADERDATE: 2022-10-04 +FONTLOADERDATE: 2023-07-13 Lualibs is a collection of Lua modules useful for general programming. diff --git a/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf b/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf Binary files differindex 175e7e9f017..00ef113d5f8 100644 --- a/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf +++ b/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf diff --git a/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx b/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx index ebdba58424f..d0335005278 100644 --- a/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx +++ b/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx @@ -37,7 +37,7 @@ \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} -\Msg{* Package: lualibs 2022-10-04 v2.75 Lua additional functions.} +\Msg{* Package: lualibs 2023-07-13 v2.76 Lua additional functions.} \Msg{************************************************************************} \keepsilent @@ -107,7 +107,7 @@ and lualibs-extended.lua. %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{lualibs.drv} - [2022/10/04 v2.75 Lua Libraries.] + [2023/07/13 v2.76 Lua Libraries.] \documentclass{ltxdoc} \usepackage{fancyvrb,xspace} \usepackage[x11names]{xcolor} @@ -208,7 +208,7 @@ and lualibs-extended.lua. % \GetFileInfo{lualibs.drv} % % \title{The \identifier{lualibs} package} -% \date{2022/10/04 v2.75} +% \date{2023/07/13 v2.76} % \author{Élie Roux · \email{elie.roux@telecom-bretagne.eu}\\ % Philipp Gesang · \email{phg@phi-gamma.net}\\ % The \LaTeX{} Project · \email{https://github.com/latex3/lualibs/}\\ @@ -430,8 +430,8 @@ lualibs = lualibs or { } lualibs.module_info = { name = "lualibs", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua standard libraries.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -584,8 +584,8 @@ local loadmodule = lualibs.loadmodule local lualibs_basic_module = { name = "lualibs-basic", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua libraries -- basic collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -665,8 +665,8 @@ lualibs = lualibs or { } local lualibs_extended_module = { name = "lualibs-extended", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua libraries -- extended collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua index 690a3160acb..b201cfab041 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-basic-merged.lua -- parent file : lualibs-basic.lua --- merge date : 2022-10-04 17:16 +-- merge date : 2023-07-13 12:55 do -- begin closure to overcome local limits and interference @@ -1274,7 +1274,7 @@ if not modules then modules={} end modules ['l-string']={ license="see context related readme files" } local string=string -local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower +local sub,gmatch,format,char,byte,rep,lower,find=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower,string.find local lpegmatch,patterns=lpeg.match,lpeg.patterns local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote @@ -1284,10 +1284,18 @@ end function string.quoted(str) return format("%q",str) end -function string.count(str,pattern) +function string.count(str,pattern) local n=0 - for _ in gmatch(str,pattern) do - n=n+1 + local i=1 + local l=#pattern + while true do + i=find(str,pattern,i) + if i then + n=n+1 + i=i+l + else + break + end end return n end @@ -4022,9 +4030,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end end -- closure @@ -4136,7 +4158,7 @@ dir=dir or {} local dir=dir local lfs=lfs local attributes=lfs.attributes -local walkdir=lfs.dir +local scandir=lfs.dir local isdir=lfs.isdir local isfile=lfs.isfile local currentdir=lfs.currentdir @@ -4167,6 +4189,15 @@ else lfs.isdir=isdir lfs.isfile=isfile end +local isreadable=file.isreadable +local walkdir=function(p,...) + if isreadable(p.."/.") then + return scandir(p,...) + else + return function() end + end +end +lfs.walkdir=walkdir function dir.current() return (gsub(currentdir(),"\\","/")) end @@ -4582,6 +4613,23 @@ do return str end end + function dir.expandlink(dir,report) + local curdir=currentdir() + local trace=type(report)=="function" + if chdir(dir) then + local newdir=currentdir() + if newdir~=dir and trace then + report("following symlink %a to %a",dir,newdir) + end + chdir(curdir) + return newdir + else + if trace then + report("unable to check path %a",dir) + end + return dir + end + end end file.expandname=dir.expandname local stack={} diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua index d578f70de0b..570a1f4564c 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua @@ -29,8 +29,8 @@ local loadmodule = lualibs.loadmodule local lualibs_basic_module = { name = "lualibs-basic", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua libraries -- basic collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua index ac8e2f4e8e1..3164068505d 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua @@ -21,7 +21,8 @@ local dir = dir local lfs = lfs local attributes = lfs.attributes -local walkdir = lfs.dir +----- walkdir = lfs.dir +local scandir = lfs.dir local isdir = lfs.isdir -- not robust, will be overloaded anyway local isfile = lfs.isfile -- not robust, will be overloaded anyway local currentdir = lfs.currentdir @@ -69,6 +70,20 @@ else end +-- safeguard + +local isreadable = file.isreadable + +local walkdir = function(p,...) + if isreadable(p.."/.") then + return scandir(p,...) + else + return function() end + end +end + +lfs.walkdir = walkdir + -- handy function dir.current() @@ -197,7 +212,7 @@ local function collectpattern(path,patt,recurse,result) if not find(path,"/$") then path = path .. '/' end - for name in scanner, first do -- cna be optimized + for name in scanner, first do -- can be optimized if name == "." then -- skip elseif name == ".." then @@ -596,6 +611,27 @@ do end + -- This go there anc check works okay in tricky situation as we encounter + -- on osx, where tex installations use rather complex chains of links. + + function dir.expandlink(dir,report) + local curdir = currentdir() + local trace = type(report) == "function" + if chdir(dir) then + local newdir = currentdir() + if newdir ~= dir and trace then + report("following symlink %a to %a",dir,newdir) + end + chdir(curdir) + return newdir + else + if trace then + report("unable to check path %a",dir) + end + return dir + end + end + end file.expandname = dir.expandname -- for convenience diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua index 08428c51ac5..ceecbf30132 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-extended-merged.lua -- parent file : lualibs-extended.lua --- merge date : 2022-10-04 17:16 +-- merge date : 2023-07-13 12:55 do -- begin closure to overcome local limits and interference @@ -481,13 +481,13 @@ 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 + function streams.tocardinal2(n) return char(extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,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 + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end if not streams.readcstring then local readchar=streams.readchar @@ -701,6 +701,7 @@ local p_prune_intospace=Cs (noleading*(notrailing+intospace+1 )^0 ) local p_retain_normal=Cs ((normalline+normalempty )^0 ) local p_retain_collapse=Cs ((normalline+doubleempty )^0 ) local p_retain_noempty=Cs ((normalline+singleempty )^0 ) +local p_collapse_all=Cs (stripstart*(stripend+((whitespace+newline)^1/" ")+1)^0 ) local striplinepatterns={ ["prune"]=p_prune_normal, ["prune and collapse"]=p_prune_collapse, @@ -709,6 +710,7 @@ local striplinepatterns={ ["retain"]=p_retain_normal, ["retain and collapse"]=p_retain_collapse, ["retain and no empty"]=p_retain_noempty, + ["collapse all"]=p_collapse_all, ["collapse"]=patterns.collapser, } setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end }) @@ -2090,7 +2092,7 @@ else local v=t[0] if v then m=m+1 - r[m]="[0]='" + r[m]="[0]=" if type(v)=="table" then fastserialize(v) else @@ -2879,7 +2881,9 @@ function parsers.groupedsplitat(symbol,withaction) if not pattern then local symbols=S(symbol) local separator=space^0*symbols*space^0 - local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0) + local value=lbrace*C((nobrace+nestedbraces)^0) +*(rbrace*(#symbols+P(-1))) ++C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0) if withaction then local withvalue=Carg(1)*value/function(f,s) return f(s) end pattern=spaces*withvalue*(separator*withvalue)^0 @@ -2965,7 +2969,17 @@ hashes.settings_to_set=table.setmetatableindex(function(t,k) t[k]=v return v end) -getmetatable(hashes.settings_to_set).__mode="kv" +function parsers.settings_to_set(str) + return str and lpegmatch(pattern,str) or {} +end +local pattern=Ct((C((1-S(", "))^1)*S(", ")^0)^1) +hashes.settings_to_list=table.setmetatableindex(function(t,k) + local v=k and lpegmatch(pattern,k) or {} + t[k]=v + return v +end) +getmetatable(hashes.settings_to_set ).__mode="kv" +getmetatable(hashes.settings_to_list).__mode="kv" function parsers.simple_hash_to_string(h,separator) local t={} local tn=0 @@ -3298,6 +3312,8 @@ local dimenfactors=allocate { ["pc"]=(1/12)/65536, ["dd"]=(1157/1238)/65536, ["cc"]=(1157/14856)/65536, + ["es"]=(9176/129)/65536, + ["ts"]=(4588/645)/65536, } local f_none=formatters["%s%s"] local f_true=formatters["%0.5F%s"] @@ -3323,12 +3339,13 @@ function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end -function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end function number.toscaledpoints(n) return n.."sp" end function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end +function number.toediths (n,fmt) return numbertodimen(n,"es",fmt) end +function number.totoves (n,fmt) return numbertodimen(n,"ts",fmt) end local amount=(S("+-")^0*R("09")^0*P(".")^0*R("09")^0)+Cc("0") local unit=R("az")^1+P("%") local dimenpair=amount/tonumber*(unit^1/dimenfactors+Cc(1)) @@ -3342,7 +3359,7 @@ setmetatableindex(dimenfactors,function(t,s) end) local stringtodimen local amount=S("+-")^0*R("09")^0*S(".,")^0*R("09")^0 -local unit=P("pt")+P("cm")+P("mm")+P("sp")+P("bp")+P("in")+P("pc")+P("dd")+P("cc")+P("nd")+P("nc") +local unit=P("pt")+P("cm")+P("mm")+P("sp")+P("bp")+P("es")+P("ts")+P("pc")+P("dd")+P("cc")+P("in") local validdimen=amount*unit lpeg.patterns.validdimen=validdimen local dimensions={} @@ -3392,8 +3409,9 @@ function dimensions.__index(tab,key) end return 1/d end - dimenfactors["ex"]=4*1/65536 - dimenfactors["em"]=10*1/65536 + dimenfactors["ex"]=4/65536 + dimenfactors["em"]=10/65536 + dimenfactors["eu"]=(9176/129)/65536 local known={} setmetatable(known,{ __mode="v" }) function dimen(a) if a then @@ -4984,11 +5002,13 @@ end local files=utilities.files local openfile=files.open local closefile=files.close +local getsize=files.size local readstring=files.readstring local readcardinal2=files.readcardinal2le local readcardinal4=files.readcardinal4le local setposition=files.setposition local getposition=files.getposition +local skipbytes=files.skip local band=bit32.band local rshift=bit32.rshift local lshift=bit32.lshift @@ -5011,6 +5031,55 @@ local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do handle=openfile(name,0), } end + local function update(handle,data) + position=data.offset + 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) + skipbytes(handle,4) + 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(handle,size) + skipped=skipped+size+2 + skipbytes(8) + skipped=skipped+8 + size=readcardinal2(handle) + skipbytes(handle,size) + skipped=skipped+size+2 + size=readcardinal4(handle) + skipbytes(handle,size) + skipped=skipped+size+4 + size=readcardinal2(handle) + skipbytes(handle,size) + skipped=skipped+size+2 + end + if acceptable then + if filename~=data.filename then + else + position=position+30+namelength+extralength+skipped + data.position=position + return position + end + else + end + end + data.position=false + return false + end local function collect(z) if not z.list then local list={} @@ -5018,72 +5087,68 @@ local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do 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 + local size=getsize(handle) + for i=size-4,size-64*1024,-1 do + setposition(handle,i) + local enddirsignature=readcardinal4(handle) + if enddirsignature==0x06054B50 then + local thisdisknumber=readcardinal2(handle) + local centraldisknumber=readcardinal2(handle) + local thisnofentries=readcardinal2(handle) + local totalnofentries=readcardinal2(handle) + local centralsize=readcardinal4(handle) + local centraloffset=readcardinal4(handle) + local commentlength=readcardinal2(handle) + local comment=readstring(handle,length) + if size-i>=22 then + if thisdisknumber==centraldisknumber then + setposition(handle,centraloffset) + while true do + if readcardinal4(handle)==0x02014B50 then + skipbytes(handle,4) + local flag=readcardinal2(handle) + local method=readcardinal2(handle) + skipbytes(handle,4) + local crc32=readcardinal4(handle) + local compressed=readcardinal4(handle) + local uncompressed=readcardinal4(handle) + local namelength=readcardinal2(handle) + local extralength=readcardinal2(handle) + local commentlength=readcardinal2(handle) + skipbytes(handle,8) + local headeroffset=readcardinal4(handle) + local filename=readstring(handle,namelength) + skipbytes(handle,extralength+commentlength) + local descriptor=band(flag,8)~=0 + local encrypted=band(flag,1)~=0 + local acceptable=method==0 or method==8 + if acceptable then + index=index+1 + local data={ + filename=filename, + index=index, + position=nil, + method=method, + compressed=compressed, + uncompressed=uncompressed, + crc32=crc32, + encrypted=encrypted, + offset=headeroffset, + } + hash[filename]=data + list[index]=data + end + else + break + end + end + end + break end - position=position+compressed - else - break end - z.list=list - z.hash=hash end + z.list=list + z.hash=hash end end function getziplist(z) @@ -5122,7 +5187,10 @@ local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do local handle=z.handle local position=data.position local compressed=data.compressed - if compressed>0 then + if position==nil then + position=update(handle,data) + end + if position and compressed>0 then setposition(handle,position) local result=readstring(handle,compressed) if data.method==8 then @@ -5333,8 +5401,10 @@ if xzip then closezip(zipf) end end - local function unzipdir(zipname,path,verbose) + local function unzipdir(zipname,path,verbose,collect,validate) if type(zipname)=="table" then + validate=zipname.validate + collect=zipname.collect verbose=zipname.verbose path=zipname.path zipname=zipname.zipname @@ -5355,34 +5425,47 @@ if xzip then local done=0 local steps=verbose=="steps" local time=steps and osclock() + if collect then + collect={} + else + collect=false + end 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)) + if not validate or validate(n) then + 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) + if collect then + collect[#collect+1]=p end - elseif verbose then - logwriter(n) end - savedata(p,d) + else + logwriter(format("problem with file %s",n)) 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 + if collect then + return collect + end else closezipfile(z) end diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua index f483fd96e2f..7e8ad6010bf 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua @@ -30,8 +30,8 @@ lualibs = lualibs or { } local lualibs_extended_module = { name = "lualibs-extended", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua libraries -- extended collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua index 9f8fd654833..70f8188dc15 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua @@ -741,8 +741,24 @@ end -- not used in context but was in luatex once: -local symlinkattributes = lfs.symlinkattributes +do + + local symlinktarget = lfs.symlinktarget -- luametatex (always returns string) + local symlinkattributes = lfs.symlinkattributes -- luatex (can return nil) + + if symlinktarget then + function lfs.readlink(name) + local target = symlinktarget(name) + return name ~= target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil end diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua index 1dee85e2894..476820a175b 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua @@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['l-string'] = { } local string = string -local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower +local sub, gmatch, format, char, byte, rep, lower, find = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower, string.find local lpegmatch, patterns = lpeg.match, lpeg.patterns local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs @@ -52,10 +52,26 @@ function string.quoted(str) return format("%q",str) -- always double quote end -function string.count(str,pattern) -- variant 3 +-- function string.count(str,pattern) -- variant 3 +-- local n = 0 +-- for _ in gmatch(str,pattern) do -- not for utf +-- n = n + 1 +-- end +-- return n +-- end + +function string.count(str,pattern) local n = 0 - for _ in gmatch(str,pattern) do -- not for utf - n = n + 1 + local i = 1 + local l = #pattern + while true do + i = find(str,pattern,i) + if i then + n = n + 1 + i = i + l + else + break + end end return n end diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua index 5d9a7149bda..f98686c6b6d 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua @@ -32,7 +32,6 @@ if not modules then modules = { } end modules ['l-unicode'] = { -- dump, find, format, gfind, gmatch, gsub, lower, match, rep, reverse, upper utf = utf or { } --- unicode = nil if not string.utfcharacters then diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua index bb9eca96688..6462f3e4920 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua @@ -6,14 +6,10 @@ if not modules then modules = { } end modules ['util-dim'] = { license = "see context related readme files" } ---[[ldx-- -<p>Internally <l n='luatex'/> work with scaled point, which are -represented by integers. However, in practice, at east at the -<l n='tex'/> end we work with more generic units like points (pt). Going -from scaled points (numbers) to one of those units can be -done by using the conversion factors collected in the following -table.</p> ---ldx]]-- +-- Internally LuaTeX work with scaled point, which are represented by integers. +-- However, in practice, at east at the TeX end we work with more generic units like +-- points (pt). Going from scaled points (numbers) to one of those units can be done +-- by using the conversion factors collected in the following table. local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable local P, S, R, Cc, C, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.C, lpeg.match @@ -45,7 +41,9 @@ local dimenfactors = allocate { ["dd"] = ( 1157/ 1238)/65536, ["cc"] = ( 1157/14856)/65536, -- ["nd"] = (20320/21681)/65536, - -- ["nc"] = ( 5080/65043)/65536 + -- ["nc"] = ( 5080/65043)/65536, + ["es"] = ( 9176/ 129)/65536, + ["ts"] = ( 4588/ 645)/65536, } -- print(table.serialize(dimenfactors)) @@ -86,10 +84,8 @@ local dimenfactors = allocate { -- ["sp"]=1, -- } ---[[ldx-- -<p>A conversion function that takes a number, unit (string) and optional -format (string) is implemented using this table.</p> ---ldx]]-- +-- A conversion function that takes a number, unit (string) and optional format +-- (string) is implemented using this table. local f_none = formatters["%s%s"] local f_true = formatters["%0.5F%s"] @@ -110,9 +106,7 @@ local function numbertodimen(n,unit,fmt) -- will be redefined later ! end end ---[[ldx-- -<p>We collect a bunch of converters in the <type>number</type> namespace.</p> ---ldx]]-- +-- We collect a bunch of converters in the 'number' namespace. number.maxdimen = 1073741823 number.todimen = numbertodimen @@ -122,7 +116,7 @@ function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end -function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end +-------- number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end function number.toscaledpoints(n) return n .. "sp" end function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end @@ -130,14 +124,13 @@ function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end -------- number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end -------- number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end +function number.toediths (n,fmt) return numbertodimen(n,"es",fmt) end +function number.totoves (n,fmt) return numbertodimen(n,"ts",fmt) end ---[[ldx-- -<p>More interesting it to implement a (sort of) dimen datatype, one -that permits calculations too. First we define a function that -converts a string to scaledpoints. We use <l n='lpeg'/>. We capture -a number and optionally a unit. When no unit is given a constant -capture takes place.</p> ---ldx]]-- +-- More interesting it to implement a (sort of) dimen datatype, one that permits +-- calculations too. First we define a function that converts a string to +-- scaledpoints. We use LPEG. We capture a number and optionally a unit. When no +-- unit is given a constant capture takes place. local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0") local unit = R("az")^1 + P("%") @@ -152,21 +145,16 @@ function number.splitdimen(str) return lpegmatch(splitter,str) end ---[[ldx-- -<p>We use a metatable to intercept errors. When no key is found in -the table with factors, the metatable will be consulted for an -alternative index function.</p> ---ldx]]-- +-- We use a metatable to intercept errors. When no key is found in the table with +-- factors, the metatable will be consulted for an alternative index function. setmetatableindex(dimenfactors, function(t,s) -- error("wrong dimension: " .. (s or "?")) -- better a message return false end) ---[[ldx-- -<p>We redefine the following function later on, so we comment it -here (which saves us bytecodes.</p> ---ldx]]-- +-- We redefine the following function later on, so we comment it here (which saves +-- us bytecodes. -- function string.todimen(str) -- if type(str) == "number" then @@ -182,44 +170,38 @@ here (which saves us bytecodes.</p> local stringtodimen -- assigned later (commenting saves bytecode) local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0 -local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") + - P("pc") + P("dd") + P("cc") + P("nd") + P("nc") +local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + + P("es") + P("ts") + P("pc") + P("dd") + P("cc") + + P("in") + -- + P("nd") + P("nc") local validdimen = amount * unit lpeg.patterns.validdimen = validdimen ---[[ldx-- -<p>This converter accepts calls like:</p> - -<typing> -string.todimen("10") -string.todimen(".10") -string.todimen("10.0") -string.todimen("10.0pt") -string.todimen("10pt") -string.todimen("10.0pt") -</typing> - -<p>With this in place, we can now implement a proper datatype for dimensions, one -that permits us to do this:</p> - -<typing> -s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" -</typing> - -<p>We create a local metatable for this new type:</p> ---ldx]]-- +-- This converter accepts calls like: +-- +-- string.todimen("10") +-- string.todimen(".10") +-- string.todimen("10.0") +-- string.todimen("10.0pt") +-- string.todimen("10pt") +-- string.todimen("10.0pt") +-- +-- With this in place, we can now implement a proper datatype for dimensions, one +-- that permits us to do this: +-- +-- s = dimen "10pt" + dimen "20pt" + dimen "200pt" +-- - dimen "100sp" / 10 + "20pt" + "0pt" +-- +-- We create a local metatable for this new type: local dimensions = { } ---[[ldx-- -<p>The main (and globally) visible representation of a dimen is defined next: it is -a one-element table. The unit that is returned from the match is normally a number -(one of the previously defined factors) but we also accept functions. Later we will -see why. This function is redefined later.</p> ---ldx]]-- +-- The main (and globally) visible representation of a dimen is defined next: it is +-- a one-element table. The unit that is returned from the match is normally a +-- number (one of the previously defined factors) but we also accept functions. +-- Later we will see why. This function is redefined later. -- function dimen(a) -- if a then @@ -241,11 +223,9 @@ see why. This function is redefined later.</p> -- end -- end ---[[ldx-- -<p>This function return a small hash with a metatable attached. It is -through this metatable that we can do the calculations. We could have -shared some of the code but for reasons of speed we don't.</p> ---ldx]]-- +-- This function return a small hash with a metatable attached. It is through this +-- metatable that we can do the calculations. We could have shared some of the code +-- but for reasons of speed we don't. function dimensions.__add(a, b) local ta, tb = type(a), type(b) @@ -281,20 +261,16 @@ function dimensions.__unm(a) return setmetatable({ - a }, dimensions) end ---[[ldx-- -<p>It makes no sense to implement the power and modulo function but -the next two do make sense because they permits is code like:</p> - -<typing> -local a, b = dimen "10pt", dimen "11pt" -... -if a > b then - ... -end -</typing> ---ldx]]-- - --- makes no sense: dimensions.__pow and dimensions.__mod +-- It makes no sense to implement the power and modulo function but +-- the next two do make sense because they permits is code like: +-- +-- local a, b = dimen "10pt", dimen "11pt" +-- ... +-- if a > b then +-- ... +-- end +-- +-- This also makes no sense: dimensions.__pow and dimensions.__mod. function dimensions.__lt(a, b) return a[1] < b[1] @@ -304,24 +280,17 @@ function dimensions.__eq(a, b) return a[1] == b[1] end ---[[ldx-- -<p>We also need to provide a function for conversion to string (so that -we can print dimensions). We print them as points, just like <l n='tex'/>.</p> ---ldx]]-- +-- We also need to provide a function for conversion to string (so that we can print +-- dimensions). We print them as points, just like TeX. function dimensions.__tostring(a) return a[1]/65536 .. "pt" -- instead of todimen(a[1]) end ---[[ldx-- -<p>Since it does not take much code, we also provide a way to access -a few accessors</p> - -<typing> -print(dimen().pt) -print(dimen().sp) -</typing> ---ldx]]-- +-- Since it does not take much code, we also provide a way to access a few accessors +-- +-- print(dimen().pt) +-- print(dimen().sp) function dimensions.__index(tab,key) local d = dimenfactors[key] @@ -332,41 +301,34 @@ function dimensions.__index(tab,key) return 1/d end ---[[ldx-- -<p>In the converter from string to dimension we support functions as -factors. This is because in <l n='tex'/> we have a few more units: -<type>ex</type> and <type>em</type>. These are not constant factors but -depend on the current font. They are not defined by default, but need -an explicit function call. This is because at the moment that this code -is loaded, the relevant tables that hold the functions needed may not -yet be available.</p> ---ldx]]-- - - dimenfactors["ex"] = 4 * 1/65536 -- 4pt - dimenfactors["em"] = 10 * 1/65536 -- 10pt --- dimenfactors["%"] = 4 * 1/65536 -- 400pt/100 - ---[[ldx-- -<p>The previous code is rather efficient (also thanks to <l n='lpeg'/>) but we -can speed it up by caching converted dimensions. On my machine (2008) the following -loop takes about 25.5 seconds.</p> - -<typing> -for i=1,1000000 do - local s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" -end -</typing> - -<p>When we cache converted strings this becomes 16.3 seconds. In order not -to waste too much memory on it, we tag the values of the cache as being -week which mean that the garbage collector will collect them in a next -sweep. This means that in most cases the speed up is mostly affecting the -current couple of calculations and as such the speed penalty is small.</p> - -<p>We redefine two previous defined functions that can benefit from -this:</p> ---ldx]]-- +-- In the converter from string to dimension we support functions as factors. This +-- is because in TeX we have a few more units: 'ex' and 'em'. These are not constant +-- factors but depend on the current font. They are not defined by default, but need +-- an explicit function call. This is because at the moment that this code is +-- loaded, the relevant tables that hold the functions needed may not yet be +-- available. + + dimenfactors["ex"] = 4 /65536 -- 4pt + dimenfactors["em"] = 10 /65536 -- 10pt +-- dimenfactors["%"] = 4 /65536 -- 400pt/100 + dimenfactors["eu"] = (9176/129)/65536 -- 1es + +-- The previous code is rather efficient (also thanks to LPEG) but we can speed it +-- up by caching converted dimensions. On my machine (2008) the following loop takes +-- about 25.5 seconds. +-- +-- for i=1,1000000 do +-- local s = dimen "10pt" + dimen "20pt" + dimen "200pt" +-- - dimen "100sp" / 10 + "20pt" + "0pt" +-- end +-- +-- When we cache converted strings this becomes 16.3 seconds. In order not to waste +-- too much memory on it, we tag the values of the cache as being week which mean +-- that the garbage collector will collect them in a next sweep. This means that in +-- most cases the speed up is mostly affecting the current couple of calculations +-- and as such the speed penalty is small. +-- +-- We redefine two previous defined functions that can benefit from this: local known = { } setmetatable(known, { __mode = "v" }) @@ -436,14 +398,10 @@ function number.toscaled(d) return format("%0.5f",d/0x10000) -- 2^16 end ---[[ldx-- -<p>In a similar fashion we can define a glue datatype. In that case we -probably use a hash instead of a one-element table.</p> ---ldx]]-- - ---[[ldx-- -<p>Goodie:s</p> ---ldx]]-- +-- In a similar fashion we can define a glue datatype. In that case we probably use +-- a hash instead of a one-element table. +-- +-- A goodie: function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out d = d or texget("hsize") diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua index 635b610e072..a527555db7e 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua @@ -264,8 +264,13 @@ function parsers.groupedsplitat(symbol,withaction) if not pattern then local symbols = S(symbol) local separator = space^0 * symbols * space^0 - local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace - + C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0) + local value = + lbrace + * C((nobrace + nestedbraces)^0) + -- * rbrace + * (rbrace * (#symbols + P(-1))) -- new per 2023-03-11 + + + C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0) if withaction then local withvalue = Carg(1) * value / function(f,s) return f(s) end pattern = spaces * withvalue * (separator*withvalue)^0 @@ -378,9 +383,25 @@ hashes.settings_to_set = table.setmetatableindex(function(t,k) -- experiment, n return v end) +function parsers.settings_to_set(str) + return str and lpegmatch(pattern,str) or { } +end + +local pattern = Ct((C((1-S(", "))^1) * S(", ")^0)^1) + +hashes.settings_to_list = table.setmetatableindex(function(t,k) -- experiment, not public + local v = k and lpegmatch(pattern,k) or { } + t[k] = v + return v +end) + +-- inspect(hashes.settings_to_set["a,b, c, d"]) +-- inspect(hashes.settings_to_list["a,b, c, d"]) + -- as we use a next, we are not sure when the gc kicks in -getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense) +getmetatable(hashes.settings_to_set ).__mode = "kv" -- could be an option (maybe sharing makes sense) +getmetatable(hashes.settings_to_list).__mode = "kv" -- could be an option (maybe sharing makes sense) function parsers.simple_hash_to_string(h, separator) local t = { } diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua index 36daef81673..9d2e8356da3 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua @@ -551,14 +551,14 @@ if bit32 and not streams.tocardinal1 then 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 + function streams.tocardinal2(n) return char(extract(n, 8,8),extract(n, 0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n, 8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,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 + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua index b5c721a41d2..a9150b886ac 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua @@ -269,6 +269,7 @@ local p_prune_intospace = Cs ( noleading * ( notrailing + intospace + 1 local p_retain_normal = Cs ( ( normalline + normalempty )^0 ) local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 ) local p_retain_noempty = Cs ( ( normalline + singleempty )^0 ) +local p_collapse_all = Cs ( stripstart * ( stripend + ((whitespace+newline)^1/" ") + 1)^0 ) -- function striplines(str,prune,collapse,noempty) -- if prune then @@ -298,6 +299,7 @@ local striplinepatterns = { ["retain"] = p_retain_normal, ["retain and collapse"] = p_retain_collapse, ["retain and no empty"] = p_retain_noempty, + ["collapse all"] = p_collapse_all, ["collapse"] = patterns.collapser, } @@ -313,6 +315,9 @@ function strings.collapse(str) -- maybe also in strings return str and lpegmatch(p_prune_intospace,str) or str end +-- local s = "\naa\n\naa\na a\n\n" +-- print("["..strings.striplines(s,"collapse all").."]") + -- also see: string.collapsespaces strings.striplong = strings.striplines -- for old times sake diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua index 64fa1af4fb3..58ca3bcb10e 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua @@ -432,7 +432,7 @@ else local v = t[0] if v then m = m + 1 - r[m] = "[0]='" + r[m] = "[0]=" if type(v) == "table" then fastserialize(v) else diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua index bd8fdf287f9..194eb56972f 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua @@ -34,11 +34,13 @@ end local files = utilities.files local openfile = files.open local closefile = files.close +local getsize = files.size local readstring = files.readstring local readcardinal2 = files.readcardinal2le local readcardinal4 = files.readcardinal4le local setposition = files.setposition local getposition = files.getposition +local skipbytes = files.skip local band = bit32.band local rshift = bit32.rshift @@ -69,6 +71,158 @@ local openzipfile, closezipfile, unzipfile, foundzipfile, getziphash, getziplist } end + -- https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT + +-- 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 file header 1] +-- -- [encryption header 1] +-- -- [file data 1] +-- -- [data descriptor 1] +-- 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 +-- -- 30 bytes of header including the signature +-- local skipped = 0 +-- local size = 0 +-- if encrypted then +-- size = readcardinal2(handle) +-- skipbytes(handle,size) +-- skipped = skipped + size + 2 +-- skipbytes(8) +-- skipped = skipped + 8 +-- size = readcardinal2(handle) +-- skipbytes(handle,size) +-- skipped = skipped + size + 2 +-- size = readcardinal4(handle) +-- skipbytes(handle,size) +-- skipped = skipped + size + 4 +-- size = readcardinal2(handle) +-- skipbytes(handle,size) +-- skipped = skipped + size + 2 +-- end +-- position = position + 30 + namelength + extralength + skipped +-- -- if descriptor then +-- -- -- where is this one located +-- -- 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 +-- -- maybe a warning when encrypted +-- end +-- position = position + compressed +-- else +-- break +-- end +-- z.list = list +-- z.hash = hash +-- end +-- end +-- end +-- end + +-- end +-- end + + local function update(handle,data) + position = data.offset + setposition(handle,position) + local signature = readstring(handle,4) + if signature == "PK\3\4" then -- 0x04034B50 + -- [local file header 1] + -- [encryption header 1] + -- [file data 1] + -- [data descriptor 1] + local version = readcardinal2(handle) + local flag = readcardinal2(handle) + local method = readcardinal2(handle) + skipbytes(handle,4) + ----- filetime = readcardinal2(handle) + ----- 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 + -- 30 bytes of header including the signature + local skipped = 0 + local size = 0 + if encrypted then + size = readcardinal2(handle) + skipbytes(handle,size) + skipped = skipped + size + 2 + skipbytes(8) + skipped = skipped + 8 + size = readcardinal2(handle) + skipbytes(handle,size) + skipped = skipped + size + 2 + size = readcardinal4(handle) + skipbytes(handle,size) + skipped = skipped + size + 4 + size = readcardinal2(handle) + skipbytes(handle,size) + skipped = skipped + size + 2 + end + if acceptable then + if filename ~= data.filename then + -- elseif method ~= data.method then + -- elseif encrypted ~= data.encrypted then + -- elseif crc32 ~= 0 and crc32 ~= data.crc32 then + -- elseif uncompressed ~= 0 and uncompressed ~= data.uncompressed then + -- elseif compressed ~= 0 and compressed ~= data.compressed then + else + position = position + 30 + namelength + extralength + skipped + data.position = position + return position + end + else + -- maybe a warning when encrypted + end + end + data.position = false + return false + end + local function collect(z) if not z.list then local list = { } @@ -76,78 +230,88 @@ local openzipfile, closezipfile, unzipfile, foundzipfile, getziphash, getziplist 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 file header 1] - -- [encryption header 1] - -- [file data 1] - -- [data descriptor 1] - 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 - -- 30 bytes of header including the signature - 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 - -- maybe a warning when encrypted + local size = getsize(handle) + -- + -- Not all files have the compressed into set so we need to get the directory + -- first. We only handle single disk zip files. + -- + for i=size-4,size-64*1024,-1 do + setposition(handle,i) + local enddirsignature = readcardinal4(handle) + if enddirsignature == 0x06054B50 then + local thisdisknumber = readcardinal2(handle) + local centraldisknumber = readcardinal2(handle) + local thisnofentries = readcardinal2(handle) + local totalnofentries = readcardinal2(handle) + local centralsize = readcardinal4(handle) + local centraloffset = readcardinal4(handle) + local commentlength = readcardinal2(handle) + local comment = readstring(handle,length) + if size - i >= 22 then + if thisdisknumber == centraldisknumber then + setposition(handle,centraloffset) + while true do + if readcardinal4(handle) == 0x02014B50 then + skipbytes(handle,4) + ----- versionmadeby = readcardinal2(handle) + ----- versionneeded = readcardinal2(handle) + local flag = readcardinal2(handle) + local method = readcardinal2(handle) + skipbytes(handle,4) + ----- filetime = readcardinal2(handle) + ----- filedate = readcardinal2(handle) + local crc32 = readcardinal4(handle) + local compressed = readcardinal4(handle) + local uncompressed = readcardinal4(handle) + local namelength = readcardinal2(handle) + local extralength = readcardinal2(handle) + local commentlength = readcardinal2(handle) + skipbytes(handle,8) + ----- disknumber = readcardinal2(handle) + ----- intattributes = readcardinal2(handle) + ----- extattributes = readcardinal4(handle) + local headeroffset = readcardinal4(handle) + local filename = readstring(handle,namelength) + skipbytes(handle,extralength+commentlength) + ----- extradata = readstring(handle,extralength) + ----- comment = readstring(handle,commentlength) + -- + local descriptor = band(flag,8) ~= 0 + local encrypted = band(flag,1) ~= 0 + local acceptable = method == 0 or method == 8 + if acceptable then + index = index + 1 + local data = { + filename = filename, + index = index, + position = nil, + method = method, + compressed = compressed, + uncompressed = uncompressed, + crc32 = crc32, + encrypted = encrypted, + offset = headeroffset, + } + hash[filename] = data + list[index] = data + end + else + break + end + end + end + break end - position = position + compressed - else - break end - z.list = list - z.hash = hash end + -- for i=1,index do -- delayed + -- local data = list[i] + -- if not data.position then + -- update(handle,list[i]) + -- end + -- end + z.list = list + z.hash = hash end end @@ -156,6 +320,7 @@ local openzipfile, closezipfile, unzipfile, foundzipfile, getziphash, getziplist if not list then collect(z) end + -- inspect(z.list) return z.list end @@ -193,7 +358,10 @@ local openzipfile, closezipfile, unzipfile, foundzipfile, getziphash, getziplist local handle = z.handle local position = data.position local compressed = data.compressed - if compressed > 0 then + if position == nil then + position = update(handle,data) + end + if position and compressed > 0 then setposition(handle,position) local result = readstring(handle,compressed) if data.method == 8 then @@ -451,11 +619,13 @@ if xzip then -- flate then do end end - local function unzipdir(zipname,path,verbose) + local function unzipdir(zipname,path,verbose,collect,validate) if type(zipname) == "table" then - verbose = zipname.verbose - path = zipname.path - zipname = zipname.zipname + validate = zipname.validate + collect = zipname.collect + verbose = zipname.verbose + path = zipname.path + zipname = zipname.zipname end if not zipname or zipname == "" then return @@ -473,34 +643,49 @@ if xzip then -- flate then do local done = 0 local steps = verbose == "steps" local time = steps and osclock() + -- local skip = 0 + if collect then + collect = { } + else + collect = false + end for i=1,count do local l = list[i] local n = l.filename - local d = unzipfile(z,n) -- true for check - 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)) + if not validate or validate(n) then + local d = unzipfile(z,n) -- true for check + 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) + if collect then + collect[#collect+1] = p end - elseif verbose then - logwriter(n) end - savedata(p,d) + else + logwriter(format("problem with file %s",n)) end else - logwriter(format("problem with file %s",n)) + -- skip = skip + 1 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 + if collect then + return collect + end else closezipfile(z) end diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua index 9681841d399..2fdf0058e14 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua @@ -25,8 +25,8 @@ lualibs = lualibs or { } lualibs.module_info = { name = "lualibs", - version = "2.75", --TAGVERSION - date = "2022-10-04", --TAGDATE + version = "2.76", --TAGVERSION + date = "2023-07-13", --TAGDATE description = "ConTeXt Lua standard libraries.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", |