texlive[67994] Master/texmf-dist: lualibs (20aug23)

commits+karl at tug.org commits+karl at tug.org
Sun Aug 20 21:54:11 CEST 2023


Revision: 67994
          http://tug.org/svn/texlive?view=revision&revision=67994
Author:   karl
Date:     2023-08-20 21:54:11 +0200 (Sun, 20 Aug 2023)
Log Message:
-----------
lualibs (20aug23)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
    trunk/Master/texmf-dist/doc/luatex/lualibs/README.md
    trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
    trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS	2023-08-20 19:54:11 UTC (rev 67994)
@@ -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

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/README.md	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/README.md	2023-08-20 19:54:11 UTC (rev 67994)
@@ -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.
 

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx	2023-08-20 19:54:11 UTC (rev 67994)
@@ -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 @@
 %<*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 @@
 % \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 at telecom-bretagne.eu}\\
 %         Philipp Gesang · \email{phg at phi-gamma.net}\\
 %         The \LaTeX{} Project · \email{https://github.com/latex3/lualibs/}\\
@@ -430,8 +430,8 @@
 
 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 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 @@
 
 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",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -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 @@
  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 @@
 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 @@
  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 @@
 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 @@
  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 @@
    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={}

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -29,8 +29,8 @@
 
 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",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-dir.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -21,7 +21,8 @@
 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 @@
 
 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 @@
         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 @@
 
     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

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -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 @@
  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_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 @@
  ["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 @@
     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 @@
  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 @@
  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 @@
  ["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.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 @@
 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 @@
  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 @@
 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 @@
    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 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
+   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+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
+   z.list=list
+   z.hash=hash
   end
  end
  function getziplist(z)
@@ -5122,7 +5187,10 @@
    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 @@
    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,27 +5425,38 @@
     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
-       elseif verbose then
-        logwriter(n)
+        savedata(p,d)
+        if collect then
+         collect[#collect+1]=p
+        end
        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
@@ -5382,7 +5463,9 @@
      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

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -30,8 +30,8 @@
 
 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",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-file.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -741,8 +741,24 @@
 
 -- not used in context but was in luatex once:
 
-local symlinkattributes = lfs.symlinkattributes
+do
 
-function lfs.readlink(name)
-    return symlinkattributes(name,"target") or nil
+    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
+
 end

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -7,7 +7,7 @@
 }
 
 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 @@
     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

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-unicode.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -32,7 +32,6 @@
 -- dump, find, format, gfind, gmatch, gsub, lower, match, rep, reverse, upper
 
 utf     = utf or { }
--- unicode = nil
 
 if not string.utfcharacters then
 

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-dim.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -6,14 +6,10 @@
     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 @@
     ["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 @@
 --   ["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 @@
     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.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.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,11 +145,8 @@
     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
@@ -163,10 +153,8 @@
     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 @@
 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>
+-- 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:
 
-<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]]--
-
 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 @@
 --     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,21 +261,17 @@
     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>
+-- 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.
 
-<typing>
-local a, b = dimen "10pt", dimen "11pt"
-...
-if a > b then
-    ...
-end
-</typing>
---ldx]]--
-
--- makes no sense: dimensions.__pow and dimensions.__mod
-
 function dimensions.__lt(a, b)
     return a[1] < b[1]
 end
@@ -304,25 +280,18 @@
     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>
+-- Since it does not take much code, we also provide a way to access a few accessors
+--
+--   print(dimen().pt)
+--   print(dimen().sp)
 
-<typing>
-print(dimen().pt)
-print(dimen().sp)
-</typing>
---ldx]]--
-
 function dimensions.__index(tab,key)
     local d = dimenfactors[key]
     if not d then
@@ -332,42 +301,35 @@
     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]]--
+-- 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 * 1/65536 --   4pt
-   dimenfactors["em"] = 10 * 1/65536 --  10pt
--- dimenfactors["%"]  =  4 * 1/65536 -- 400pt/100
+   dimenfactors["ex"] =     4     /65536 --   4pt
+   dimenfactors["em"] =    10     /65536 --  10pt
+-- dimenfactors["%"]  =     4     /65536 -- 400pt/100
+   dimenfactors["eu"] = (9176/129)/65536 --  1es
 
---[[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>
+-- 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:
 
-<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]]--
-
 local known = { } setmetatable(known, { __mode = "v" })
 
 function dimen(a)
@@ -436,15 +398,11 @@
     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]]--
+-- 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:
 
---[[ldx--
-<p>Goodie:s</p>
---ldx]]--
-
 function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out
     d = d or texget("hsize")
     if type(d) == "string" then

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-prs.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -264,8 +264,13 @@
     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 @@
     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  = { }

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-sac.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -551,14 +551,14 @@
     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
 

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -269,6 +269,7 @@
 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 @@
     ["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 @@
     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

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -432,7 +432,7 @@
                 local v = t[0]
                 if v then
                     m = m + 1
-                    r[m] = "[0]='"
+                    r[m] = "[0]="
                     if type(v) == "table" then
                         fastserialize(v)
                     else

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-zip.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -34,11 +34,13 @@
 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 @@
         }
     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 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
+            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 + 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
-                    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 @@
         if not list then
             collect(z)
         end
+     -- inspect(z.list)
         return z.list
     end
 
@@ -193,7 +358,10 @@
             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 @@
         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,27 +643,40 @@
                 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
-                            elseif verbose then
-                                logwriter(n)
+                                savedata(p,d)
+                                if collect then
+                                    collect[#collect+1] = p
+                                end
                             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
@@ -500,7 +683,9 @@
                     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

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua	2023-08-20 14:27:19 UTC (rev 67993)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua	2023-08-20 19:54:11 UTC (rev 67994)
@@ -25,8 +25,8 @@
 
 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",



More information about the tex-live-commits mailing list.