[latex3-commits] [git/LaTeX3-latex3-lualibs] new-libs: Update merged files (a7c1ddd)

Marcel Fabian Krüger tex at 2krueger.de
Tue Mar 1 15:47:03 CET 2022


Repository : https://github.com/latex3/lualibs
On branch  : new-libs
Link       : https://github.com/latex3/lualibs/commit/a7c1ddd39e819e084d945c897ee1a45b9ab2bdb3

>---------------------------------------------------------------

commit a7c1ddd39e819e084d945c897ee1a45b9ab2bdb3
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Tue Mar 1 15:04:36 2022 +0100

    Update merged files


>---------------------------------------------------------------

a7c1ddd39e819e084d945c897ee1a45b9ab2bdb3
 lualibs-basic-merged.lua    |  629 +++++++++++--------------
 lualibs-extended-merged.lua | 1072 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 1332 insertions(+), 369 deletions(-)

diff --git a/lualibs-basic-merged.lua b/lualibs-basic-merged.lua
index ac98df3..dbcfb66 100644
--- a/lualibs-basic-merged.lua
+++ b/lualibs-basic-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : lualibs-basic-merged.lua
 -- parent file : lualibs-basic.lua
--- merge date  : 2021-05-20 23:14
+-- merge date  : 2022-03-01 15:45
 
 do -- begin closure to overcome local limits and interference
 
@@ -2808,7 +2808,7 @@ if not math.tointeger then
 end
 if not math.ult then
  local floor=math.floor
- function math.tointeger(m,n)
+ function math.ult(m,n)
   return floor(m)<floor(n) 
  end
 end
@@ -2882,9 +2882,12 @@ function io.copydata(source,target,action)
   flush()
  end
 end
-function io.savedata(filename,data,joiner)
- local f=open(filename,"wb")
+function io.savedata(filename,data,joiner,append)
+ local f=open(filename,append and "ab" or "wb")
  if f then
+  if append and joiner and f:seek("end")>0 then
+   f:write(joiner)
+  end
   if type(data)=="table" then
    f:write(concat(data,joiner or ""))
   elseif type(data)=="function" then
@@ -3172,10 +3175,10 @@ if not modules then modules={} end modules ['l-os']={
  license="see context related readme files"
 }
 local os=os
-local date,time=os.date,os.time
+local date,time,difftime=os.date,os.time,os.difftime
 local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch
 local concat=table.concat
-local random,ceil,randomseed=math.random,math.ceil,math.randomseed
+local random,ceil,randomseed,modf=math.random,math.ceil,math.randomseed,math.modf
 local type,setmetatable,tonumber,tostring=type,setmetatable,tonumber,tostring
 do
  local selfdir=os.selfdir
@@ -3291,22 +3294,6 @@ if not os.__getenv__ then
   setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
  end
 end
-local execute=os.execute
-local iopopen=io.popen
-local function resultof(command)
- local handle=iopopen(command,"r") 
- if handle then
-  local result=handle:read("*all") or ""
-  handle:close()
-  return result
- else
-  return ""
- end
-end
-os.resultof=resultof
-function os.pipeto(command)
- return iopopen(command,"w") 
-end
 if not io.fileseparator then
  if find(os.getenv("PATH"),";",1,true) then
   io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "windows"
@@ -3321,228 +3308,231 @@ if os.type=="windows" then
 else
  os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
 end
-local launchers={
- windows="start %s",
- macosx="open %s",
- unix="xdg-open %s &> /dev/null &",
-}
-function os.launch(str)
- local command=format(launchers[os.name] or launchers.unix,str)
- execute(command)
-end
-local gettimeofday=os.gettimeofday or os.clock
-os.gettimeofday=gettimeofday
-local startuptime=gettimeofday()
-function os.runtime()
- return gettimeofday()-startuptime
-end
-local resolvers=os.resolvers or {}
-os.resolvers=resolvers
-setmetatable(os,{ __index=function(t,k)
- local r=resolvers[k]
- return r and r(t,k) or nil 
-end })
-local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or ""
-if platform~="" then
- os.platform=platform
-elseif os.type=="windows" then
- function resolvers.platform(t,k)
-  local architecture=os.getenv("PROCESSOR_ARCHITECTURE") or ""
-  local platform=""
-  if find(architecture,"AMD64",1,true) then
-   platform="win64"
+do
+ local execute=os.execute
+ local iopopen=io.popen
+ local ostype=os.type
+ local function resultof(command)
+  local handle=iopopen(command,ostype=="windows" and "rb" or "r")
+  if handle then
+   local result=handle:read("*all") or ""
+   handle:close()
+   return result
   else
-   platform="mswin"
+   return ""
   end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
  end
-elseif name=="linux" then
- function resolvers.platform(t,k)
-  local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
-  local platform=os.getenv("MTX_PLATFORM") or ""
+ os.resultof=resultof
+ function os.pipeto(command)
+  return iopopen(command,"w") 
+ end
+ local launchers={
+  windows="start %s",
+  macosx="open %s",
+  unix="xdg-open %s &> /dev/null &",
+ }
+ function os.launch(str)
+  local command=format(launchers[os.name] or launchers.unix,str)
+  execute(command)
+ end
+end
+do
+ local gettimeofday=os.gettimeofday or os.clock
+ os.gettimeofday=gettimeofday
+ local startuptime=gettimeofday()
+ function os.runtime()
+  return gettimeofday()-startuptime
+ end
+end
+do
+ local name=os.name or "linux"
+ local platform=os.getenv("MTX_PLATFORM") or ""
+ local architecture=os.uname and os.uname().machine 
+ local bits=os.getenv("MTX_BITS") or find(platform,"64") and 64 or 32
+ if platform~="" then
+ elseif os.type=="windows" then
+  architecture=string.lower(architecture or os.getenv("PROCESSOR_ARCHITECTURE") or "")
+  if architecture=="x86_64" then
+   bits,platform=64,"win64"
+  elseif find(architecture,"amd64") then
+   bits,platform=64,"win64"
+  elseif find(architecture,"arm64") then
+   bits,platform=64,"windows-arm64"
+  elseif find(architecture,"arm32") then
+   bits,platform=32,"windows-arm32"
+  else
+   bits,platform=32,"mswin"
+  end
+ elseif name=="linux" then
+  architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or ""
   local musl=find(os.selfdir or "","linuxmusl")
-  if platform~="" then
-  elseif find(architecture,"x86_64",1,true) then
-   platform=musl and "linuxmusl" or "linux-64"
-  elseif find(architecture,"ppc",1,true) then
-   platform="linux-ppc"
+  if find(architecture,"x86_64") then
+   bits,platform=64,musl and "linuxmusl" or "linux-64"
+  elseif find(architecture,"ppc") then
+   bits,platform=32,"linux-ppc" 
   else
-   platform=musl and "linuxmusl" or "linux"
+   bits,platform=32,musl and "linuxmusl" or "linux"
   end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
- end
-elseif name=="macosx" then
- function resolvers.platform(t,k)
-  local architecture=resultof("echo $HOSTTYPE") or ""
-  local platform=""
+ elseif name=="macosx" then
+  architecture=architecture or resultof("echo $HOSTTYPE") or ""
   if architecture=="" then
-   platform="osx-intel"
-  elseif find(architecture,"i386",1,true) then
-   platform="osx-intel"
-  elseif find(architecture,"x86_64",1,true) then
-   platform="osx-64"
-  elseif find(architecture,"arm64",1,true) then
-   platform="osx-arm"
+   bits,platform=64,"osx-intel"
+  elseif find(architecture,"i386") then
+   bits,platform=64,"osx-intel"
+  elseif find(architecture,"x86_64") then
+   bits,platform=64,"osx-64"
+  elseif find(architecture,"arm64") then
+   bits,platform=64,"osx-arm"
   else
-   platform="osx-ppc"
-  end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
- end
-elseif name=="sunos" then
- function resolvers.platform(t,k)
-  local architecture=resultof("uname -m") or ""
-  local platform=""
-  if find(architecture,"sparc",1,true) then
-   platform="solaris-sparc"
+   bits,platform=32,"osx-ppc"
+  end
+ elseif name=="sunos" then
+  architecture=architecture or resultof("uname -m") or ""
+  if find(architecture,"sparc") then
+   bits,platform=32,"solaris-sparc"
   else 
-   platform="solaris-intel"
-  end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
- end
-elseif name=="freebsd" then
- function resolvers.platform(t,k)
-  local architecture=resultof("uname -m") or ""
-  local platform=""
-  if find(architecture,"amd64",1,true) then
-   platform="freebsd-amd64"
+   bits,platform=32,"solaris-intel"
+  end
+ elseif name=="freebsd" then
+  architecture=architecture or os.getenv("MACHTYPE") or resultof("uname -m") or ""
+  if find(architecture,"amd64") or find(architecture,"AMD64") then
+   bits,platform=64,"freebsd-amd64"
   else
-   platform="freebsd"
-  end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
- end
-elseif name=="kfreebsd" then
- function resolvers.platform(t,k)
-  local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
-  local platform=""
-  if find(architecture,"x86_64",1,true) then
-   platform="kfreebsd-amd64"
+   bits,platform=32,"freebsd"
+  end
+ elseif name=="kfreebsd" then
+  architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+  if architecture=="x86_64" then
+   bits,platform=64,"kfreebsd-amd64"
+  else
+   bits,platform=32,"kfreebsd-i386"
+  end
+ else
+  architecture=architecture or resultof("uname -m") or ""
+  if find(architecture,"aarch64") then
+   bits,platform="linux-aarch64"
+  elseif find(architecture,"armv7l") then
+   bits,platform=32,"linux-armhf"
+  elseif find(architecture,"mips64") or find(architecture,"mips64el") then
+   bits,platform=64,"linux-mipsel"
+  elseif find(architecture,"mipsel") or find(architecture,"mips") then
+   bits,platform=32,"linux-mipsel"
   else
-   platform="kfreebsd-i386"
+   bits,platform=64,"linux-64" 
   end
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
  end
-else
- function resolvers.platform(t,k)
-  local platform="linux"
-  os.setenv("MTX_PLATFORM",platform)
-  os.platform=platform
-  return platform
+ os.setenv("MTX_PLATFORM",platform)
+ os.setenv("MTX_BITS",bits)
+ os.platform=platform
+ os.bits=bits
+ os.newline=name=="windows" and "\013\010" or "\010" 
+end
+do
+ local t={ 8,9,"a","b" }
+ function os.uuid()
+  return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+   random(0xFFFF),random(0xFFFF),
+   random(0x0FFF),
+   t[ceil(random(4))] or 8,random(0x0FFF),
+   random(0xFFFF),
+   random(0xFFFF),random(0xFFFF),random(0xFFFF)
+  )
  end
 end
-os.newline=name=="windows" and "\013\010" or "\010" 
-function resolvers.bits(t,k)
- local bits=find(os.platform,"64",1,true) and 64 or 32
- os.bits=bits
- return bits
-end
-local t={ 8,9,"a","b" }
-function os.uuid()
- return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
-  random(0xFFFF),random(0xFFFF),
-  random(0x0FFF),
-  t[ceil(random(4))] or 8,random(0x0FFF),
-  random(0xFFFF),
-  random(0xFFFF),random(0xFFFF),random(0xFFFF)
- )
-end
-local d
-function os.timezone(delta)
- d=d or ((tonumber(date("%H")) or 0)-(tonumber(date("!%H")) or 0))
- if delta then
-  if d>0 then
-   return format("+%02i:00",d)
+do
+ local hour,min
+ function os.timezone(difference)
+  if not hour then
+   local current=time()
+   local utcdate=date("!*t",current)
+   local localdate=date("*t",current)
+   localdate.isdst=false
+   local timediff=difftime(time(localdate),time(utcdate))
+   hour,min=modf(timediff/3600)
+   min=min*60
+  end
+  if difference then
+   return hour,min
   else
-   return format("-%02i:00",-d)
+   return format("%+03d:%02d",hour,min) 
+  end
+ end
+ local timeformat=format("%%s%s",os.timezone())
+ local dateformat="%Y-%m-%d %H:%M:%S"
+ local lasttime=nil
+ local lastdate=nil
+ function os.fulltime(t,default)
+  t=t and tonumber(t) or 0
+  if t>0 then
+  elseif default then
+   return default
+  else
+   t=time()
+  end
+  if t~=lasttime then
+   lasttime=t
+   lastdate=format(timeformat,date(dateformat))
+  end
+  return lastdate
+ end
+ local dateformat="%Y-%m-%d %H:%M:%S"
+ local lasttime=nil
+ local lastdate=nil
+ function os.localtime(t,default)
+  t=t and tonumber(t) or 0
+  if t>0 then
+  elseif default then
+   return default
+  else
+   t=time()
+  end
+  if t~=lasttime then
+   lasttime=t
+   lastdate=date(dateformat,t)
+  end
+  return lastdate
+ end
+ function os.converttime(t,default)
+  local t=tonumber(t)
+  if t and t>0 then
+   return date(dateformat,t)
+  else
+   return default or "-"
   end
- else
-  return 1
- end
-end
-local timeformat=format("%%s%s",os.timezone(true))
-local dateformat="!%Y-%m-%d %H:%M:%S"
-local lasttime=nil
-local lastdate=nil
-function os.fulltime(t,default)
- t=t and tonumber(t) or 0
- if t>0 then
- elseif default then
-  return default
- else
-  t=time()
- end
- if t~=lasttime then
-  lasttime=t
-  lastdate=format(timeformat,date(dateformat))
- end
- return lastdate
-end
-local dateformat="%Y-%m-%d %H:%M:%S"
-local lasttime=nil
-local lastdate=nil
-function os.localtime(t,default)
- t=t and tonumber(t) or 0
- if t>0 then
- elseif default then
-  return default
- else
-  t=time()
  end
- if t~=lasttime then
-  lasttime=t
-  lastdate=date(dateformat,t)
+ function os.today()
+  return date("!*t")
+ end
+ function os.now()
+  return date("!%Y-%m-%d %H:%M:%S")
  end
- return lastdate
 end
-function os.converttime(t,default)
- local t=tonumber(t)
- if t and t>0 then
-  return date(dateformat,t)
- else
-  return default or "-"
- end
-end
-local memory={}
-local function which(filename)
- local fullname=memory[filename]
- if fullname==nil then
-  local suffix=file.suffix(filename)
-  local suffixes=suffix=="" and os.binsuffixes or { suffix }
-  for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
-   local df=file.join(directory,filename)
-   for i=1,#suffixes do
-    local dfs=file.addsuffix(df,suffixes[i])
-    if io.exists(dfs) then
-     fullname=dfs
-     break
+do
+ local cache={}
+ local function which(filename)
+  local fullname=cache[filename]
+  if fullname==nil then
+   local suffix=file.suffix(filename)
+   local suffixes=suffix=="" and os.binsuffixes or { suffix }
+   for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+    local df=file.join(directory,filename)
+    for i=1,#suffixes do
+     local dfs=file.addsuffix(df,suffixes[i])
+     if io.exists(dfs) then
+      fullname=dfs
+      break
+     end
     end
    end
+   if not fullname then
+    fullname=false
+   end
+   cache[filename]=fullname
   end
-  if not fullname then
-   fullname=false
-  end
-  memory[filename]=fullname
+  return fullname
  end
- return fullname
-end
-os.which=which
-os.where=which
-function os.today()
- return date("!*t") 
-end
-function os.now()
- return date("!%Y-%m-%d %H:%M:%S") 
+ os.which=which
+ os.where=which
 end
 if not os.sleep then
  local socket=socket
@@ -3553,65 +3543,69 @@ if not os.sleep then
   socket.sleep(n)
  end
 end
-local function isleapyear(year)
- return (year%4==0) and (year%100~=0 or year%400==0)
-end
-os.isleapyear=isleapyear
-local days={ 31,28,31,30,31,30,31,31,30,31,30,31 }
-local function nofdays(year,month,day)
- if not month then
-  return isleapyear(year) and 365 or 364
- elseif not day then
-  return month==2 and isleapyear(year) and 29 or days[month]
- else
-  for i=1,month-1 do
-   day=day+days[i]
-  end
-  if month>2 and isleapyear(year) then
-   day=day+1
+do
+ local function isleapyear(year)
+  return (year%4==0) and (year%100~=0 or year%400==0)
+ end
+ os.isleapyear=isleapyear
+ local days={ 31,28,31,30,31,30,31,31,30,31,30,31 }
+ local function nofdays(year,month,day)
+  if not month then
+   return isleapyear(year) and 365 or 364
+  elseif not day then
+   return month==2 and isleapyear(year) and 29 or days[month]
+  else
+   for i=1,month-1 do
+    day=day+days[i]
+   end
+   if month>2 and isleapyear(year) then
+    day=day+1
+   end
+   return day
   end
-  return day
  end
-end
-os.nofdays=nofdays
-function os.weekday(day,month,year)
- return date("%w",time { year=year,month=month,day=day })+1
-end
-function os.validdate(year,month,day)
- if month<1 then
-  month=1
- elseif month>12 then
-  month=12
+ os.nofdays=nofdays
+ function os.weekday(day,month,year)
+  return date("%w",time { year=year,month=month,day=day })+1
  end
- if day<1 then
-  day=1
- else
-  local max=nofdays(year,month)
-  if day>max then
-   day=max
+ function os.validdate(year,month,day)
+  if month<1 then
+   month=1
+  elseif month>12 then
+   month=12
+  end
+  if day<1 then
+   day=1
+  else
+   local max=nofdays(year,month)
+   if day>max then
+    day=max
+   end
   end
+  return year,month,day
  end
- return year,month,day
-end
-function os.date(fmt,...)
- if not fmt then
-  fmt="%Y-%m-%d %H:%M"
+ function os.date(fmt,...)
+  if not fmt then
+   fmt="%Y-%m-%d %H:%M"
+  end
+  return date(fmt,...)
  end
- return date(fmt,...)
-end
-local osexit=os.exit
-local exitcode=nil
-function os.setexitcode(code)
- exitcode=code
 end
-function os.exit(c)
- if exitcode~=nil then
-  return osexit(exitcode)
+do
+ local osexit=os.exit
+ local exitcode=nil
+ function os.setexitcode(code)
+  exitcode=code
  end
- if c~=nil then
-  return osexit(c)
+ function os.exit(c)
+  if exitcode~=nil then
+   return osexit(exitcode)
+  end
+  if c~=nil then
+   return osexit(c)
+  end
+  return osexit()
  end
- return osexit()
 end
 
 end -- closure
@@ -3872,7 +3866,7 @@ function file.join(one,two,three,...)
  if not two then
   return one=="" and one or lpegmatch(reslasher,one)
  end
- if one=="" then
+ if not one or one=="" then
   return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
  end
  if lpegmatch(isnetwork,one) then
@@ -4031,87 +4025,6 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['l-gzip']={
- version=1.001,
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-gzip=gzip or {} 
-if not zlib then
- zlib=xzip 
-elseif not xzip then
- xzip=zlib
-end
-if zlib then
- local suffix=file.suffix
- local suffixes=file.suffixes
- local find=string.find
- local openfile=io.open
- local gzipwindow=15+16 
- local gziplevel=3
- local identifier="^\x1F\x8B\x08"
- local compress=zlib.compress
- local decompress=zlib.decompress
- function gzip.load(filename)
-  local f=openfile(filename,"rb")
-  if not f then
-  else
-   local data=f:read("*all")
-   f:close()
-   if data and data~="" then
-    if suffix(filename)=="gz" then
-     data=decompress(data,gzipwindow)
-    end
-    return data
-   end
-  end
- end
- function gzip.save(filename,data,level)
-  if suffix(filename)~="gz" then
-   filename=filename..".gz"
-  end
-  local f=openfile(filename,"wb")
-  if f then
-   data=compress(data or "",level or gziplevel,nil,gzipwindow)
-   f:write(data)
-   f:close()
-   return #data
-  end
- end
- function gzip.suffix(filename)
-  local suffix,extra=suffixes(filename)
-  local gzipped=extra=="gz"
-  return suffix,gzipped
- end
- function gzip.compressed(s)
-  return s and find(s,identifier)
- end
- function gzip.compress(s,level)
-  if s and not find(s,identifier) then 
-   if not level then
-    level=gziplevel
-   elseif level<=0 then
-    return s
-   elseif level>9 then
-    level=9
-   end
-   return compress(s,level or gziplevel,nil,gzipwindow) or s
-  end
- end
- function gzip.decompress(s)
-  if s and find(s,identifier) then
-   return decompress(s,gzipwindow)
-  else
-   return s
-  end
- end
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
 if not modules then modules={} end modules ['l-md5']={
  version=1.001,
  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -4389,15 +4302,15 @@ local separator,pattern
 if onwindows then 
  local slash=S("/\\")/"/"
  pattern={
-  [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
-  [2]=Cs(((1-S("*?/\\"))^0*slash)^0),
-  [3]=Cs(P(1)^0)
+  (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
+  Cs(((1-S("*?/\\"))^0*slash)^0),
+  Cs(P(1)^0)
  }
 else
  pattern={
-  [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
-  [2]=C(((1-S("*?/"))^0*P("/"))^0),
-  [3]=C(P(1)^0)
+  (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
+  C(((1-S("*?/"))^0*P("/"))^0),
+  C(P(1)^0)
  }
 end
 local filter=Cs ((
diff --git a/lualibs-extended-merged.lua b/lualibs-extended-merged.lua
index 9cd4487..4b4c811 100644
--- a/lualibs-extended-merged.lua
+++ b/lualibs-extended-merged.lua
@@ -1,6 +1,484 @@
 -- merged file : lualibs-extended-merged.lua
 -- parent file : lualibs-extended.lua
--- merge date  : 2021-05-20 23:14
+-- merge date  : 2022-03-01 15:45
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['util-sac']={
+ version=1.001,
+ optimize=true,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local byte,sub=string.byte,string.sub
+local tonumber=tonumber
+utilities=utilities or {}
+local streams={}
+utilities.streams=streams
+function streams.open(filename,zerobased)
+ local f=filename and io.loaddata(filename)
+ if f then
+  return { f,1,#f,zerobased or false }
+ end
+end
+function streams.openstring(f,zerobased)
+ if f then
+  return { f,1,#f,zerobased or false }
+ end
+end
+function streams.getstring(f)
+ if f then
+  return f[1]
+ end
+end
+function streams.close()
+end
+function streams.size(f)
+ return f and f[3] or 0
+end
+streams.getsize=streams.size
+function streams.setposition(f,i)
+ if f[4] then
+  if i<=0 then
+   f[2]=1
+  else
+   f[2]=i+1
+  end
+ else
+  if i<=1 then
+   f[2]=1
+  else
+   f[2]=i
+  end
+ end
+end
+function streams.getposition(f)
+ if f[4] then
+  return f[2]-1
+ else
+  return f[2]
+ end
+end
+function streams.look(f,n,chars)
+ local b=f[2]
+ local e=b+n-1
+ if chars then
+  return sub(f[1],b,e)
+ else
+  return byte(f[1],b,e)
+ end
+end
+function streams.skip(f,n)
+ f[2]=f[2]+n
+end
+function streams.readbyte(f)
+ local i=f[2]
+ f[2]=i+1
+ return byte(f[1],i)
+end
+function streams.readbytes(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return byte(f[1],i,j-1)
+end
+function streams.readbytetable(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return { byte(f[1],i,j-1) }
+end
+function streams.skipbytes(f,n)
+ f[2]=f[2]+n
+end
+function streams.readchar(f)
+ local i=f[2]
+ f[2]=i+1
+ return sub(f[1],i,i)
+end
+function streams.readstring(f,n)
+ local i=f[2]
+ local j=i+n
+ f[2]=j
+ return sub(f[1],i,j-1)
+end
+function streams.readinteger1(f)  
+ local i=f[2]
+ f[2]=i+1
+ local n=byte(f[1],i)
+ if n>=0x80 then
+  return n-0x100
+ else
+  return n
+ end
+end
+streams.readcardinal1=streams.readbyte  
+streams.readcardinal=streams.readcardinal1
+streams.readinteger=streams.readinteger1
+function streams.readcardinal2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local a,b=byte(f[1],i,j)
+ return 0x100*a+b
+end
+function streams.readcardinal2le(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local b,a=byte(f[1],i,j)
+ return 0x100*a+b
+end
+function streams.readinteger2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local a,b=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x100*a+b-0x10000
+ else
+  return 0x100*a+b
+ end
+end
+function streams.readinteger2le(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local b,a=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x100*a+b-0x10000
+ else
+  return 0x100*a+b
+ end
+end
+function streams.readcardinal3(f)
+ local i=f[2]
+ local j=i+2
+ f[2]=j+1
+ local a,b,c=byte(f[1],i,j)
+ return 0x10000*a+0x100*b+c
+end
+function streams.readcardinal3le(f)
+ local i=f[2]
+ local j=i+2
+ f[2]=j+1
+ local c,b,a=byte(f[1],i,j)
+ return 0x10000*a+0x100*b+c
+end
+function streams.readinteger3(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x10000*a+0x100*b+c-0x1000000
+ else
+  return 0x10000*a+0x100*b+c
+ end
+end
+function streams.readinteger3le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local c,b,a=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x10000*a+0x100*b+c-0x1000000
+ else
+  return 0x10000*a+0x100*b+c
+ end
+end
+function streams.readcardinal4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ return 0x1000000*a+0x10000*b+0x100*c+d
+end
+function streams.readcardinal4le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local d,c,b,a=byte(f[1],i,j)
+ return 0x1000000*a+0x10000*b+0x100*c+d
+end
+function streams.readinteger4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
+ else
+  return 0x1000000*a+0x10000*b+0x100*c+d
+ end
+end
+function streams.readinteger4le(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local d,c,b,a=byte(f[1],i,j)
+ if a>=0x80 then
+  return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
+ else
+  return 0x1000000*a+0x10000*b+0x100*c+d
+ end
+end
+function streams.readfixed2(f)
+ local i=f[2]
+ local j=i+1
+ f[2]=j+1
+ local n1,n2=byte(f[1],i,j)
+ if n1>=0x80 then
+  n1=n1-0x100
+ end
+ return n1+n2/0xFF
+end
+function streams.readfixed4(f)
+ local i=f[2]
+ local j=i+3
+ f[2]=j+1
+ local a,b,c,d=byte(f[1],i,j)
+ local n1=0x100*a+b
+ local n2=0x100*c+d
+ if n1>=0x8000 then
+  n1=n1-0x10000
+ end
+ return n1+n2/0xFFFF
+end
+if bit32 then
+ local extract=bit32.extract
+ local band=bit32.band
+ function streams.read2dot14(f)
+  local i=f[2]
+  local j=i+1
+  f[2]=j+1
+  local a,b=byte(f[1],i,j)
+  if a>=0x80 then
+   local n=-(0x100*a+b)
+   return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0))
+  else
+   local n=0x100*a+b
+   return   (extract(n,14,2)+(band(n,0x3FFF)/16384.0))
+  end
+ end
+end
+function streams.skipshort(f,n)
+ f[2]=f[2]+2*(n or 1)
+end
+function streams.skiplong(f,n)
+ f[2]=f[2]+4*(n or 1)
+end
+if sio and sio.readcardinal2 then
+ local readcardinal1=sio.readcardinal1
+ local readcardinal2=sio.readcardinal2
+ local readcardinal3=sio.readcardinal3
+ local readcardinal4=sio.readcardinal4
+ local readinteger1=sio.readinteger1
+ local readinteger2=sio.readinteger2
+ local readinteger3=sio.readinteger3
+ local readinteger4=sio.readinteger4
+ local readfixed2=sio.readfixed2
+ local readfixed4=sio.readfixed4
+ local read2dot14=sio.read2dot14
+ local readbytes=sio.readbytes
+ local readbytetable=sio.readbytetable
+ function streams.readcardinal1(f)
+  local i=f[2]
+  f[2]=i+1
+  return readcardinal1(f[1],i)
+ end
+ function streams.readcardinal2(f)
+  local i=f[2]
+  f[2]=i+2
+  return readcardinal2(f[1],i)
+ end
+ function streams.readcardinal3(f)
+  local i=f[2]
+  f[2]=i+3
+  return readcardinal3(f[1],i)
+ end
+ function streams.readcardinal4(f)
+  local i=f[2]
+  f[2]=i+4
+  return readcardinal4(f[1],i)
+ end
+ function streams.readinteger1(f)
+  local i=f[2]
+  f[2]=i+1
+  return readinteger1(f[1],i)
+ end
+ function streams.readinteger2(f)
+  local i=f[2]
+  f[2]=i+2
+  return readinteger2(f[1],i)
+ end
+ function streams.readinteger3(f)
+  local i=f[2]
+  f[2]=i+3
+  return readinteger3(f[1],i)
+ end
+ function streams.readinteger4(f)
+  local i=f[2]
+  f[2]=i+4
+  return readinteger4(f[1],i)
+ end
+ function streams.readfixed2(f) 
+  local i=f[2]
+  f[2]=i+2
+  return readfixed2(f[1],i)
+ end
+ function streams.readfixed4(f) 
+  local i=f[2]
+  f[2]=i+4
+  return readfixed4(f[1],i)
+ end
+ function streams.read2dot14(f)
+  local i=f[2]
+  f[2]=i+2
+  return read2dot14(f[1],i)
+ end
+ function streams.readbytes(f,n)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  return readbytes(f[1],i,n)
+ end
+ function streams.readbytetable(f,n)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  return readbytetable(f[1],i,n)
+ end
+ streams.readbyte=streams.readcardinal1
+ streams.readsignedbyte=streams.readinteger1
+ streams.readcardinal=streams.readcardinal1
+ streams.readinteger=streams.readinteger1
+end
+if sio and sio.readcardinaltable then
+ local readcardinaltable=sio.readcardinaltable
+ local readintegertable=sio.readintegertable
+ function utilities.streams.readcardinaltable(f,n,b)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n*b
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  return readcardinaltable(f[1],i,n,b)
+ end
+ function utilities.streams.readintegertable(f,n,b)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n*b
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  return readintegertable(f[1],i,n,b)
+ end
+else
+ local readcardinal1=streams.readcardinal1
+ local readcardinal2=streams.readcardinal2
+ local readcardinal3=streams.readcardinal3
+ local readcardinal4=streams.readcardinal4
+ function streams.readcardinaltable(f,n,b)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n*b
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  local t={}
+   if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end
+  elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end
+  elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end
+  elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end
+  return t
+ end
+ local readinteger1=streams.readinteger1
+ local readinteger2=streams.readinteger2
+ local readinteger3=streams.readinteger3
+ local readinteger4=streams.readinteger4
+ function streams.readintegertable(f,n,b)
+  local i=f[2]
+  local s=f[3]
+  local p=i+n*b
+  if p>s then
+   f[2]=s+1
+  else
+   f[2]=p
+  end
+  local t={}
+   if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end
+  elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end
+  elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end
+  elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end
+  return t
+ end
+end
+do
+ local files=utilities.files
+ if files then
+  local openfile=files.open
+  local openstream=streams.open
+  local openstring=streams.openstring
+  local setmetatable=setmetatable
+  function io.newreader(str,method)
+   local f,m
+   if method=="string" then
+    f=openstring(str,true)
+    m=streams
+   elseif method=="stream" then
+    f=openstream(str,true)
+    m=streams
+   else
+    f=openfile(str,"rb")
+    m=files
+   end
+   if f then
+    local t={}
+    setmetatable(t,{
+     __index=function(t,k)
+      local r=m[k]
+      if k=="close" then
+       if f then
+        m.close(f)
+        f=nil
+       end
+       return function() end
+      elseif r then
+       local v=function(_,a,b) return r(f,a,b) end
+       t[k]=v
+       return v
+      else
+       print("unknown key",k)
+      end
+     end
+    } )
+    return t
+   end
+  end
+ end
+end
+
+end -- closure
 
 do -- begin closure to overcome local limits and interference
 
@@ -14,12 +492,13 @@ if not modules then modules={} end modules ['util-str']={
 utilities=utilities or {}
 utilities.strings=utilities.strings or {}
 local strings=utilities.strings
-local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find
+local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char
 local load,dump=load,string.dump
 local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable
 local unpack,concat=table.unpack,table.concat
 local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
 local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local tsplitat=lpeg.tsplitat
 local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
 local loadstripped=function(str,shortcuts)
  if shortcuts then
@@ -373,6 +852,14 @@ patterns.escapedquotes=pattern
 function string.escapedquotes(s)
  return lpegmatch(pattern,s)
 end
+local pattern=(1-P("\\"))^1;pattern=Cs (
+ pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1
+)
+patterns.unescapedquotes=pattern
+function string.unescapedquotes(s)
+ return lpegmatch(pattern,s) or s
+end
+string.texnewlines=lpeg.replacer(patterns.newline,"\r",true)
 local preamble=""
 local environment={
  global=global or _G,
@@ -908,7 +1395,6 @@ function number.to16dot16(n)
  return f_16_16(n/65536.0)
 end
 if not string.explode then
- local tsplitat=lpeg.tsplitat
  local p_utf=patterns.utf8character
  local p_check=C(p_utf)*(P("+")*Cc(true))^0
  local p_split=Ct(C(p_utf)^0)
@@ -928,6 +1414,20 @@ if not string.explode then
   end
  end
 end
+do
+ local p_whitespace=patterns.whitespace^1
+ local cache=setmetatable({},{ __index=function(t,k)
+  local p=tsplitat(p_whitespace*P(k)*p_whitespace)
+  local v=function(s)
+   return lpegmatch(p,s)
+  end
+  t[k]=v
+  return v
+ end })
+ function string.wordsplitter(s)
+  return cache[s]
+ end
+end
 
 end -- closure
 
@@ -1552,9 +2052,6 @@ if JITSUPPORTED then
   return concat(fastserialize(t,true))
  end
 else
- local f_v=formatters["[%q]=%q,"]
- local f_t=formatters["[%q]="]
- local f_q=formatters["%q,"]
  function table.fastserialize(t,prefix) 
   local r={ type(prefix)=="string" and prefix or "return" }
   local m=1
@@ -2181,8 +2678,8 @@ local noparent=1-(lparent+rparent)
 local nobracket=1-(lbracket+rbracket)
 local escape,left,right=P("\\"),P('{'),P('}')
 lpegpatterns.balanced=P {
- [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
- [2]=left*V(1)*right
+ ((escape*(left+right))+(1-(left+right))+V(2))^0,
+ left*V(1)*right
 }
 local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
 local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
@@ -2192,6 +2689,7 @@ local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
 local content=(1-endofstring)^0
 lpegpatterns.nestedbraces=nestedbraces   
 lpegpatterns.nestedparents=nestedparents  
+lpegpatterns.nestedbrackets=nestedbrackets 
 lpegpatterns.nested=nestedbraces   
 lpegpatterns.argument=argument    
 lpegpatterns.content=content  
@@ -2600,7 +3098,7 @@ local function ranger(first,last,n,action)
   action(first)
  end
 end
-local cardinal=lpegpatterns.cardinal/tonumber
+local cardinal=(lpegpatterns.hexadecimal+lpegpatterns.cardinal)/tonumber
 local spacers=lpegpatterns.spacer^0
 local endofstring=lpegpatterns.endofstring
 local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
@@ -2626,7 +3124,7 @@ local cache={}
 local spaces=lpegpatterns.space^0
 local dummy=function() end
 setmetatableindex(cache,function(t,k)
- local separator=P(k)
+ local separator=S(k) 
  local value=(1-separator)^0
  local pattern=spaces*C(value)*separator^0*Cp()
  t[k]=pattern
@@ -2914,6 +3412,9 @@ if not modules then modules={} end modules ['util-jsn']={
  copyright="PRAGMA ADE / ConTeXt Development Team",
  license="see context related readme files"
 }
+if utilities and utilities.json then
+ return json
+end
 local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg
 local lpegmatch=lpeg.match
 local format,gsub=string.format,string.gsub
@@ -3260,7 +3761,6 @@ do
   return jsontostring(value,true)
  end
 end
-return json
 
 end -- closure
 
@@ -4379,3 +4879,553 @@ function stacker.new(name)
 end
 
 end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['util-zip']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tostring,tonumber=type,tostring,tonumber
+local sort,concat=table.sort,table.concat
+local find,format,sub,gsub=string.find,string.format,string.sub,string.gsub
+local osdate,ostime,osclock=os.date,os.time,os.clock
+local ioopen=io.open
+local loaddata,savedata=io.loaddata,io.savedata
+local filejoin,isdir,dirname,mkdirs=file.join,lfs.isdir,file.dirname,dir.mkdirs
+local suffix,suffixes=file.suffix,file.suffixes
+local openfile=io.open
+gzip=gzip or {} 
+if not zlib then
+ zlib=xzip 
+elseif not xzip then
+ xzip=zlib
+end
+local files=utilities.files
+local openfile=files.open
+local closefile=files.close
+local readstring=files.readstring
+local readcardinal2=files.readcardinal2le
+local readcardinal4=files.readcardinal4le
+local setposition=files.setposition
+local getposition=files.getposition
+local band=bit32.band
+local rshift=bit32.rshift
+local lshift=bit32.lshift
+local zlibdecompress=zlib.decompress
+local zlibdecompresssize=zlib.decompresssize
+local zlibchecksum=zlib.crc32
+local decompress=function(source)   return zlibdecompress (source,-15)   end 
+local decompresssize=function(source,targetsize) return zlibdecompresssize(source,targetsize,-15) end 
+local calculatecrc=function(buffer,initial) return zlibchecksum   (initial or 0,buffer)   end
+local zipfiles={}
+utilities.zipfiles=zipfiles
+local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist  do
+ function openzipfile(name)
+  return {
+   name=name,
+   handle=openfile(name,0),
+  }
+ end
+ local function collect(z)
+  if not z.list then
+   local list={}
+   local hash={}
+   local position=0
+   local index=0
+   local handle=z.handle
+   while true do
+    setposition(handle,position)
+    local signature=readstring(handle,4)
+    if signature=="PK\3\4" then
+     local version=readcardinal2(handle)
+     local flag=readcardinal2(handle)
+     local method=readcardinal2(handle)
+     local filetime=readcardinal2(handle)
+     local filedate=readcardinal2(handle)
+     local crc32=readcardinal4(handle)
+     local compressed=readcardinal4(handle)
+     local uncompressed=readcardinal4(handle)
+     local namelength=readcardinal2(handle)
+     local extralength=readcardinal2(handle)
+     local filename=readstring(handle,namelength)
+     local descriptor=band(flag,8)~=0
+     local encrypted=band(flag,1)~=0
+     local acceptable=method==0 or method==8
+     local skipped=0
+     local size=0
+     if encrypted then
+      size=readcardinal2(handle)
+      skipbytes(size)
+      skipped=skipped+size+2
+      skipbytes(8)
+      skipped=skipped+8
+      size=readcardinal2(handle)
+      skipbytes(size)
+      skipped=skipped+size+2
+      size=readcardinal4(handle)
+      skipbytes(size)
+      skipped=skipped+size+4
+      size=readcardinal2(handle)
+      skipbytes(size)
+      skipped=skipped+size+2
+     end
+     position=position+30+namelength+extralength+skipped
+     if descriptor then
+      setposition(handle,position+compressed)
+      crc32=readcardinal4(handle)
+      compressed=readcardinal4(handle)
+      uncompressed=readcardinal4(handle)
+     end
+     if acceptable then
+      index=index+1
+      local data={
+       filename=filename,
+       index=index,
+       position=position,
+       method=method,
+       compressed=compressed,
+       uncompressed=uncompressed,
+       crc32=crc32,
+       encrypted=encrypted,
+      }
+      hash[filename]=data
+      list[index]=data
+     else
+     end
+     position=position+compressed
+    else
+     break
+    end
+    z.list=list
+    z.hash=hash
+   end
+  end
+ end
+ function getziplist(z)
+  local list=z.list
+  if not list then
+   collect(z)
+  end
+  return z.list
+ end
+ function getziphash(z)
+  local hash=z.hash
+  if not hash then
+   collect(z)
+  end
+  return z.hash
+ end
+ function foundzipfile(z,name)
+  return getziphash(z)[name]
+ end
+ function closezipfile(z)
+  local f=z.handle
+  if f then
+   closefile(f)
+   z.handle=nil
+  end
+ end
+ function unzipfile(z,filename,check)
+  local hash=z.hash
+  if not hash then
+   hash=zipfiles.hash(z)
+  end
+  local data=hash[filename] 
+  if not data then
+  end
+  if data then
+   local handle=z.handle
+   local position=data.position
+   local compressed=data.compressed
+   if compressed>0 then
+    setposition(handle,position)
+    local result=readstring(handle,compressed)
+    if data.method==8 then
+     if decompresssize then
+      result=decompresssize(result,data.uncompressed)
+     else
+      result=decompress(result)
+     end
+    end
+    if check and data.crc32~=calculatecrc(result) then
+     print("checksum mismatch")
+     return ""
+    end
+    return result
+   else
+    return ""
+   end
+  end
+ end
+ zipfiles.open=openzipfile
+ zipfiles.close=closezipfile
+ zipfiles.unzip=unzipfile
+ zipfiles.hash=getziphash
+ zipfiles.list=getziplist
+ zipfiles.found=foundzipfile
+end
+if xzip then 
+ local writecardinal1=files.writebyte
+ local writecardinal2=files.writecardinal2le
+ local writecardinal4=files.writecardinal4le
+ local logwriter=logs.writer
+ local globpattern=dir.globpattern
+ local compress=xzip.compress
+ local checksum=xzip.crc32
+ local function fromdostime(dostime,dosdate)
+  return ostime {
+   year=rshift(dosdate,9)+1980,
+   month=band(rshift(dosdate,5),0x0F),
+   day=band((dosdate   ),0x1F),
+   hour=band(rshift(dostime,11)    ),
+   min=band(rshift(dostime,5),0x3F),
+   sec=band((dostime   ),0x1F),
+  }
+ end
+ local function todostime(time)
+  local t=osdate("*t",time)
+  return
+   lshift(t.year-1980,9)+lshift(t.month,5)+t.day,
+   lshift(t.hour,11)+lshift(t.min,5)+rshift(t.sec,1)
+ end
+ local function openzip(filename,level,comment,verbose)
+  local f=ioopen(filename,"wb")
+  if f then
+   return {
+    filename=filename,
+    handle=f,
+    list={},
+    level=tonumber(level) or 3,
+    comment=tostring(comment),
+    verbose=verbose,
+    uncompressed=0,
+    compressed=0,
+   }
+  end
+ end
+ local function writezip(z,name,data,level,time)
+  local f=z.handle
+  local list=z.list
+  local level=tonumber(level) or z.level or 3
+  local method=8
+  local zipped=compress(data,level)
+  local checksum=checksum(data)
+  local verbose=z.verbose
+  if not zipped then
+   method=0
+   zipped=data
+  end
+  local start=f:seek()
+  local compressed=#zipped
+  local uncompressed=#data
+  z.compressed=z.compressed+compressed
+  z.uncompressed=z.uncompressed+uncompressed
+  if verbose then
+   local pct=100*compressed/uncompressed
+   if pct>=100 then
+    logwriter(format("%10i        %s",uncompressed,name))
+   else
+    logwriter(format("%10i  %02.1f  %s",uncompressed,pct,name))
+   end
+  end
+  f:write("\x50\x4b\x03\x04")
+  writecardinal2(f,0)   
+  writecardinal2(f,0)   
+  writecardinal2(f,method)    
+  writecardinal2(f,0)   
+  writecardinal2(f,0)   
+  writecardinal4(f,checksum)  
+  writecardinal4(f,compressed)   
+  writecardinal4(f,uncompressed) 
+  writecardinal2(f,#name)  
+  writecardinal2(f,0)
+  f:write(name)      
+  f:write(zipped)
+  list[#list+1]={ #zipped,#data,name,checksum,start,time or 0 }
+ end
+ local function closezip(z)
+  local f=z.handle
+  local list=z.list
+  local comment=z.comment
+  local verbose=z.verbose
+  local count=#list
+  local start=f:seek()
+  for i=1,count do
+   local l=list[i]
+   local compressed=l[1]
+   local uncompressed=l[2]
+   local name=l[3]
+   local checksum=l[4]
+   local start=l[5]
+   local time=l[6]
+   local date,time=todostime(time)
+   f:write('\x50\x4b\x01\x02')
+   writecardinal2(f,0)   
+   writecardinal2(f,0)   
+   writecardinal2(f,0)   
+   writecardinal2(f,8)   
+   writecardinal2(f,time)   
+   writecardinal2(f,date)   
+   writecardinal4(f,checksum)  
+   writecardinal4(f,compressed)   
+   writecardinal4(f,uncompressed) 
+   writecardinal2(f,#name)  
+   writecardinal2(f,0)   
+   writecardinal2(f,0)   
+   writecardinal2(f,0)   
+   writecardinal2(f,0)   
+   writecardinal4(f,0)   
+   writecardinal4(f,start)  
+   f:write(name)      
+  end
+  local stop=f:seek()
+  local size=stop-start
+  f:write('\x50\x4b\x05\x06')
+  writecardinal2(f,0)   
+  writecardinal2(f,0)   
+  writecardinal2(f,count)  
+  writecardinal2(f,count)  
+  writecardinal4(f,size)   
+  writecardinal4(f,start)  
+  if type(comment)=="string" and comment~="" then
+   writecardinal2(f,#comment) 
+   f:write(comment)     
+  else
+   writecardinal2(f,0)
+  end
+  if verbose then
+   local compressed=z.compressed
+   local uncompressed=z.uncompressed
+   local filename=z.filename
+   local pct=100*compressed/uncompressed
+   logwriter("")
+   if pct>=100 then
+    logwriter(format("%10i        %s",uncompressed,filename))
+   else
+    logwriter(format("%10i  %02.1f  %s",uncompressed,pct,filename))
+   end
+  end
+  f:close()
+ end
+ local function zipdir(zipname,path,level,verbose)
+  if type(zipname)=="table" then
+   verbose=zipname.verbose
+   level=zipname.level
+   path=zipname.path
+   zipname=zipname.zipname
+  end
+  if not zipname or zipname=="" then
+   return
+  end
+  if not path or path=="" then
+   path="."
+  end
+  if not isdir(path) then
+   return
+  end
+  path=gsub(path,"\\+","/")
+  path=gsub(path,"/+","/")
+  local list={}
+  local count=0
+  globpattern(path,"",true,function(name,size,time)
+   count=count+1
+   list[count]={ name,time }
+  end)
+  sort(list,function(a,b)
+   return a[1]<b[1]
+  end)
+  local zipf=openzip(zipname,level,comment,verbose)
+  if zipf then
+   local p=#path+2
+   for i=1,count do
+    local li=list[i]
+    local name=li[1]
+    local time=li[2]
+    local data=loaddata(name)
+    local name=sub(name,p,#name)
+    writezip(zipf,name,data,level,time,verbose)
+   end
+   closezip(zipf)
+  end
+ end
+ local function unzipdir(zipname,path,verbose)
+  if type(zipname)=="table" then
+   verbose=zipname.verbose
+   path=zipname.path
+   zipname=zipname.zipname
+  end
+  if not zipname or zipname=="" then
+   return
+  end
+  if not path or path=="" then
+   path="."
+  end
+  local z=openzipfile(zipname)
+  if z then
+   local list=getziplist(z)
+   if list then
+    local total=0
+    local count=#list
+    local step=number.idiv(count,10)
+    local done=0
+    local steps=verbose=="steps"
+    local time=steps and osclock()
+    for i=1,count do
+     local l=list[i]
+     local n=l.filename
+     local d=unzipfile(z,n) 
+     if d then
+      local p=filejoin(path,n)
+      if mkdirs(dirname(p)) then
+       if steps then
+        total=total+#d
+        done=done+1
+        if done>=step then
+         done=0
+         logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",i,count,total,osclock()-time))
+        end
+       elseif verbose then
+        logwriter(n)
+       end
+       savedata(p,d)
+      end
+     else
+      logwriter(format("problem with file %s",n))
+     end
+    end
+    if steps then
+     logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",count,count,total,osclock()-time))
+    end
+    closezipfile(z)
+    return true
+   else
+    closezipfile(z)
+   end
+  end
+ end
+ zipfiles.zipdir=zipdir
+ zipfiles.unzipdir=unzipdir
+end
+local pattern="^\x1F\x8B\x08"
+local gziplevel=3
+function gzip.suffix(filename)
+ local suffix,extra=suffixes(filename)
+ local gzipped=extra=="gz"
+ return suffix,gzipped
+end
+function gzip.compressed(s)
+ return s and find(s,pattern)
+end
+local getdecompressed
+local putcompressed
+if gzip.compress then
+ local gzipwindow=15+16 
+ local compress=zlib.compress
+ local decompress=zlib.decompress
+ getdecompressed=function(str)
+  return decompress(str,gzipwindow) 
+ end
+ putcompressed=function(str,level)
+  return compress(str,level or gziplevel,nil,gzipwindow)
+ end
+else
+ local gzipwindow=-15 
+ local identifier="\x1F\x8B"
+ local compress=zlib.compress
+ local decompress=zlib.decompress
+ local crc32=zlib.crc32
+ local streams=utilities.streams
+ local openstream=streams.openstring
+ local closestream=streams.close
+ local getposition=streams.getposition
+ local readbyte=streams.readbyte
+ local readcardinal4=streams.readcardinal4le
+ local readcardinal2=streams.readcardinal2le
+ local readstring=streams.readstring
+ local readcstring=streams.readcstring
+ local skipbytes=streams.skip
+ local tocardinal1=streams.tocardinal1
+ local tocardinal4=streams.tocardinal4le
+ getdecompressed=function(str)
+  local s=openstream(str)
+  local identifier=readstring(s,2)
+  local method=readbyte(s,1)
+  local flags=readbyte(s,1)
+  local timestamp=readcardinal4(s)
+  local compression=readbyte(s,1)
+  local operating=readbyte(s,1)
+  local isjusttext=band(flags,0x01)~=0 and true    or false
+  local extrasize=band(flags,0x04)~=0 and readcardinal2(s) or 0
+  local filename=band(flags,0x08)~=0 and readcstring(s)   or ""
+  local comment=band(flags,0x10)~=0 and readcstring(s)   or ""
+  local checksum=band(flags,0x02)~=0 and readcardinal2(s) or 0
+  local compressed=readstring(s,#str)
+  local data=decompress(compressed,gzipwindow) 
+  return data
+ end
+ putcompressed=function(str,level,originalname)
+  return concat {
+   identifier,
+   tocardinal1(0x08),
+   tocardinal1(0x08),
+   tocardinal4(os.time()),
+   tocardinal1(0x02),
+   tocardinal1(0xFF),
+   (originalname or "unknownname").."\0",
+   compress(str,level,nil,gzipwindow),
+   tocardinal4(crc32(str)),
+   tocardinal4(#str),
+  }
+ end
+end
+function gzip.load(filename)
+ local f=openfile(filename,"rb")
+ if not f then
+ else
+  local data=f:read("*all")
+  f:close()
+  if data and data~="" then
+   if suffix(filename)=="gz" then
+    data=getdecompressed(data)
+   end
+   return data
+  end
+ end
+end
+function gzip.save(filename,data,level,originalname)
+ if suffix(filename)~="gz" then
+  filename=filename..".gz"
+ end
+ local f=openfile(filename,"wb")
+ if f then
+  data=putcompressed(data or "",level or gziplevel,originalname)
+  f:write(data)
+  f:close()
+  return #data
+ end
+end
+function gzip.compress(s,level)
+ if s and not find(s,pattern) then
+  if not level then
+   level=gziplevel
+  elseif level<=0 then
+   return s
+  elseif level>9 then
+   level=9
+  end
+  return putcompressed(s,level or gziplevel) or s
+ end
+end
+function gzip.decompress(s)
+ if s and find(s,pattern) then
+  return getdecompressed(s)
+ else
+  return s
+ end
+end
+zipfiles.gunzipfile=gzip.load
+
+end -- closure





More information about the latex3-commits mailing list.