texlive[50118] trunk: lwarp (24feb19)

commits+karl at tug.org commits+karl at tug.org
Sun Feb 24 23:54:37 CET 2019


Revision: 50118
          http://tug.org/svn/texlive?view=revision&revision=50118
Author:   karl
Date:     2019-02-24 23:54:37 +0100 (Sun, 24 Feb 2019)
Log Message:
-----------
lwarp (24feb19)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/context/perl/mptopdf.pl
    trunk/Build/source/texk/texlive/linked_scripts/context/stubs/unix/mtxrun
    trunk/Build/source/texk/texlive/linked_scripts/lwarp/lwarpmk.lua
    trunk/Master/texmf-dist/doc/latex/lwarp/README.txt
    trunk/Master/texmf-dist/doc/latex/lwarp/lwarp.pdf
    trunk/Master/texmf-dist/scripts/lwarp/lwarpmk.lua
    trunk/Master/texmf-dist/source/latex/lwarp/lwarp.dtx
    trunk/Master/texmf-dist/source/latex/lwarp/lwarp.ins
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-amsmath.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-amsthm.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-color.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-easy-todo.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fancybox.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fancyvrb.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fixme.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-floatrow.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-graphics.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-hyperref.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-keyfloat.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-ntheorem.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-parnotes.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-realscripts.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-textcomp.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-todo.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-wrapfig.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-xcolor.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-xunicode.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp.sty

Added Paths:
-----------
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-academicons.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-bbding.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-changes.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-dingbat.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-eurosym.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fitbox.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fontawesome.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-fontawesome5.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-foreign.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-gloss.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-karnaugh-map.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-marvosym.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-multicap.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-nomencl.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-notes.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-pifont.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-struktex.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-typicons.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-umoline.sty
    trunk/Master/texmf-dist/tex/latex/lwarp/lwarp-xfakebold.sty

Modified: trunk/Build/source/texk/texlive/linked_scripts/context/perl/mptopdf.pl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/context/perl/mptopdf.pl	2019-02-24 22:53:38 UTC (rev 50117)
+++ trunk/Build/source/texk/texlive/linked_scripts/context/perl/mptopdf.pl	2019-02-24 22:54:37 UTC (rev 50118)
@@ -118,9 +118,14 @@
     @files = glob "$pattern" ;
 }
 
+# this patch was send via debian but is not tested by me
+
 foreach my $file (@files) {
     $_ = $file ;
-    if (s/\.(\d+|mps)$// && -e $file) {
+  # if (s/\.(\d+|mps)$// && -e $file) {
+    if (s/\.(\d+|mps|ps)$// && -e $file) {
+        my $suffix = $1 ;
+        my $pdf = basename($_).".pdf" ;
         if ($miktex) {
             $command = "pdftex -undump=mptopdf" ;
         } else {
@@ -136,15 +141,22 @@
             print "\n$program : error while processing tex file\n" ;
             exit 1 ;
         }
-        my $pdfsrc = basename($_).".pdf";
-        rename ($pdfsrc, "$_-$1.pdf") ;
-        if (-e $pdfsrc) {
-            CopyFile ($pdfsrc, "$_-$1.pdf") ;
+      # my $pdfsrc = basename($_).".pdf";
+      # rename ($pdfsrc, "$_-$1.pdf") ;
+      # if (-e $pdfsrc) {
+      #     CopyFile ($pdfsrc, "$_-$1.pdf") ;
+        if ($suffix =~ m/\.\d+$/) {
+            rename ($pdf, "$_-$suffix.pdf") ;
+            if (-e $pdf) {
+                CopyFile ($pdf, "$_-$suffix.pdf") ;
+            }
+            $pdf = "$_-$suffix.pdf" ;
         }
         if ($done) {
             $report .= " +" ;
         }
-        $report .= " $_-$1.pdf" ;
+      # $report .= " $_-$1.pdf" ;
+        $report .= " $pdf" ;
         ++$done  ;
     }
 }

Modified: trunk/Build/source/texk/texlive/linked_scripts/context/stubs/unix/mtxrun
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/context/stubs/unix/mtxrun	2019-02-24 22:53:38 UTC (rev 50117)
+++ trunk/Build/source/texk/texlive/linked_scripts/context/stubs/unix/mtxrun	2019-02-24 22:54:37 UTC (rev 50118)
@@ -1,16 +1,5 @@
 #!/usr/bin/env texlua
 
--- for k, v in next, _G.string do
---     local tv = type(v)
---     if tv == "table" then
---         for kk, vv in next, v do
---             print(k,kk,vv)
---         end
---     else
---         print(tv,k,v)
---     end
--- end
-
 if not modules then modules = { } end modules ['mtxrun'] = {
     version   = 1.001,
     comment   = "runner, lua replacement for texmfstart.rb",
@@ -20,10 +9,16 @@
 }
 
 -- one can make a stub:
+
+-- mtxrun :
 --
 -- #!/bin/sh
 -- env LUATEXDIR=/....../texmf/scripts/context/lua luatex --luaonly mtxrun.lua "$@"
 
+-- mtxrun.cmd :
+--
+-- @luatex --luaonly %~d0%~p0mtxrun.lua %*
+
 -- filename : mtxrun.lua
 -- comment  : companion to context.tex
 -- author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
@@ -30,15 +25,27 @@
 -- copyright: PRAGMA ADE / ConTeXt Development Team
 -- license  : see context related readme files
 
--- This script is based on texmfstart.rb but does not use kpsewhich to
--- locate files. Although kpse is a library it never came to opening up
--- its interface to other programs (esp scripting languages) and so we
--- do it ourselves. The lua variant evolved out of an experimental ruby
--- one. Interesting is that using a scripting language instead of c does
--- not have a speed penalty. Actually the lua variant is more efficient,
--- especially when multiple calls to kpsewhich are involved. The lua
+-- This script is based on texmfstart.rb but does not use kpsewhich to locate files.
+-- Although kpse is a library it never came to opening up its interface to other
+-- programs (esp scripting languages) and so we do it ourselves. The lua variant
+-- evolved out of an experimental ruby one. Interesting is that using a scripting
+-- language instead of c does not have a speed penalty. Actually the lua variant is
+-- more efficient, especially when multiple calls to kpsewhich are involved. The lua
 -- library also gives way more control.
 
+-- When libraries used here are updates you can run
+--
+--   mtxrun --selfmerge
+--
+-- to update the embedded code. After that you might need to run
+--
+--   mtxrun --selfupdate
+--
+-- to copy the new script (from scripts/context/lua) to location where
+-- binaries are expected. If you want to remove the embedded code you can run
+--
+--   mtxxun --selfclean
+
 -- to be done / considered
 --
 -- support for --exec or make it default
@@ -54,16 +61,147 @@
 
 do -- create closure to overcome 200 locals limit
 
+package.loaded["l-bit32"] = package.loaded["l-bit32"] or true
+
+-- original size: 3607, stripped down to: 3009
+
+if not modules then modules={} end modules ['l-bit32']={
+ version=1.001,
+ license="the same as regular Lua",
+ source="bitwise.lua, v 1.24 2014/12/26 17:20:53 roberto",
+ comment="drop-in for bit32, adapted a bit by Hans Hagen",
+}
+if bit32 then
+elseif utf8 then
+ load ([[
+local select = select -- instead of: arg = { ... }
+bit32 = {
+  bnot = function (a)
+    return ~a & 0xFFFFFFFF
+  end,
+  band = function (x, y, z, ...)
+    if not z then
+      return ((x or -1) & (y or -1)) & 0xFFFFFFFF
+    else
+      local res = x & y & z
+      for i=1,select("#",...) do
+        res = res & select(i,...)
+      end
+      return res & 0xFFFFFFFF
+    end
+  end,
+  bor = function (x, y, z, ...)
+    if not z then
+      return ((x or 0) | (y or 0)) & 0xFFFFFFFF
+    else
+      local res = x | y | z
+      for i=1,select("#",...) do
+        res = res | select(i,...)
+      end
+      return res & 0xFFFFFFFF
+    end
+  end,
+  bxor = function (x, y, z, ...)
+    if not z then
+      return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF
+    else
+      local res = x ~ y ~ z
+      for i=1,select("#",...) do
+        res = res ~ select(i,...)
+      end
+      return res & 0xFFFFFFFF
+    end
+  end,
+  btest = function (x, y, z, ...)
+    if not z then
+      return (((x or -1) & (y or -1)) & 0xFFFFFFFF) ~= 0
+    else
+      local res = x & y & z
+      for i=1,select("#",...) do
+          res = res & select(i,...)
+      end
+      return (res & 0xFFFFFFFF) ~= 0
+    end
+  end,
+  lshift = function (a, b)
+    return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF
+  end,
+  rshift = function (a, b)
+    return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF
+  end,
+  arshift = function (a, b)
+    a = a & 0xFFFFFFFF
+    if b <= 0 or (a & 0x80000000) == 0 then
+      return (a >> b) & 0xFFFFFFFF
+    else
+      return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF
+    end
+  end,
+  lrotate = function (a ,b)
+    b = b & 31
+    a = a & 0xFFFFFFFF
+    a = (a << b) | (a >> (32 - b))
+    return a & 0xFFFFFFFF
+  end,
+  rrotate = function (a, b)
+    b = -b & 31
+    a = a & 0xFFFFFFFF
+    a = (a << b) | (a >> (32 - b))
+    return a & 0xFFFFFFFF
+  end,
+  extract = function (a, f, w)
+    return (a >> f) & ~(-1 << (w or 1))
+  end,
+  replace = function (a, v, f, w)
+    local mask = ~(-1 << (w or 1))
+    return ((a & ~(mask << f)) | ((v & mask) << f)) & 0xFFFFFFFF
+  end,
+}
+        ]] ) ()
+elseif bit then
+ load ([[
+local band, bnot, rshift, lshift = bit.band, bit.bnot, bit.rshift, bit.lshift
+bit32 = {
+  arshift = bit.arshift,
+  band    = band,
+  bnot    = bnot,
+  bor     = bit.bor,
+  bxor    = bit.bxor,
+  btest   = function(...)
+    return band(...) ~= 0
+  end,
+  extract = function(a,f,w)
+    return band(rshift(a,f),2^(w or 1)-1)
+  end,
+  lrotate = bit.rol,
+  lshift  = lshift,
+  replace = function(a,v,f,w)
+    local mask = 2^(w or 1)-1
+    return band(a,bnot(lshift(mask,f)))+lshift(band(v,mask),f)
+  end,
+  rrotate = bit.ror,
+  rshift  = rshift,
+}
+        ]] ) ()
+else
+ xpcall(function() local _,t=require("bit32") if t then bit32=t end return end,function() end)
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
 package.loaded["l-lua"] = package.loaded["l-lua"] or true
 
--- original size: 6230, stripped down to: 3662
+-- original size: 6281, stripped down to: 2863
 
 if not modules then modules={} end modules ['l-lua']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 next,type,tonumber=next,type,tonumber
 LUAMAJORVERSION,LUAMINORVERSION=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
@@ -71,122 +209,111 @@
 LUAMINORVERSION=tonumber(LUAMINORVERSION) or 1
 LUAVERSION=LUAMAJORVERSION+LUAMINORVERSION/10
 if LUAVERSION<5.2 and jit then
-  MINORVERSION=2
-  LUAVERSION=5.2
+ MINORVERSION=2
+ LUAVERSION=5.2
 end
-_LUAVERSION=LUAVERSION
 if not lpeg then
-  lpeg=require("lpeg")
+ lpeg=require("lpeg")
 end
 if loadstring then
-  local loadnormal=load
-  function load(first,...)
-    if type(first)=="string" then
-      return loadstring(first,...)
-    else
-      return loadnormal(first,...)
-    end
+ local loadnormal=load
+ function load(first,...)
+  if type(first)=="string" then
+   return loadstring(first,...)
+  else
+   return loadnormal(first,...)
   end
+ end
 else
-  loadstring=load
+ loadstring=load
 end
 if not ipairs then
-  local function iterate(a,i)
-    i=i+1
-    local v=a[i]
-    if v~=nil then
-      return i,v 
-    end
+ local function iterate(a,i)
+  i=i+1
+  local v=a[i]
+  if v~=nil then
+   return i,v 
   end
-  function ipairs(a)
-    return iterate,a,0
-  end
+ end
+ function ipairs(a)
+  return iterate,a,0
+ end
 end
 if not pairs then
-  function pairs(t)
-    return next,t 
-  end
+ function pairs(t)
+  return next,t 
+ end
 end
 if not table.unpack then
-  table.unpack=_G.unpack
+ table.unpack=_G.unpack
 elseif not unpack then
-  _G.unpack=table.unpack
+ _G.unpack=table.unpack
 end
 if not package.loaders then 
-  package.loaders=package.searchers
+ package.loaders=package.searchers
 end
 local print,select,tostring=print,select,tostring
 local inspectors={}
 function setinspector(kind,inspector) 
-  inspectors[kind]=inspector
+ inspectors[kind]=inspector
 end
 function inspect(...) 
-  for s=1,select("#",...) do
-    local value=select(s,...)
-    if value==nil then
-      print("nil")
-    else
-      local done=false
-      local kind=type(value)
-      local inspector=inspectors[kind]
-      if inspector then
-        done=inspector(value)
-        if done then
-          break
-        end
-      end
-      for kind,inspector in next,inspectors do
-        done=inspector(value)
-        if done then
-          break
-        end
-      end
-      if not done then
-        print(tostring(value))
-      end
+ for s=1,select("#",...) do
+  local value=select(s,...)
+  if value==nil then
+   print("nil")
+  else
+   local done=false
+   local kind=type(value)
+   local inspector=inspectors[kind]
+   if inspector then
+    done=inspector(value)
+    if done then
+     break
     end
+   end
+   for kind,inspector in next,inspectors do
+    done=inspector(value)
+    if done then
+     break
+    end
+   end
+   if not done then
+    print(tostring(value))
+   end
   end
+ end
 end
 local dummy=function() end
 function optionalrequire(...)
-  local ok,result=xpcall(require,dummy,...)
-  if ok then
-    return result
-  end
+ local ok,result=xpcall(require,dummy,...)
+ if ok then
+  return result
+ end
 end
 if lua then
-  lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
+ lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
 end
 local flush=io.flush
 if flush then
-  local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
-  local exec=os.exec  if exec  then function os.exec  (...) flush() return exec  (...) end end
-  local spawn=os.spawn  if spawn  then function os.spawn (...) flush() return spawn (...) end end
-  local popen=io.popen  if popen  then function io.popen (...) flush() return popen (...) end end
+ local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
+ local exec=os.exec if exec then function os.exec   (...) flush() return exec   (...) end end
+ local spawn=os.spawn   if spawn   then function os.spawn  (...) flush() return spawn  (...) end end
+ local popen=io.popen   if popen   then function io.popen  (...) flush() return popen  (...) end end
 end
 FFISUPPORTED=type(ffi)=="table" and ffi.os~="" and ffi.arch~="" and ffi.load
 if not FFISUPPORTED then
-  local okay;okay,ffi=pcall(require,"ffi")
-  FFISUPPORTED=type(ffi)=="table" and ffi.os~="" and ffi.arch~="" and ffi.load
+ local okay;okay,ffi=pcall(require,"ffi")
+ FFISUPPORTED=type(ffi)=="table" and ffi.os~="" and ffi.arch~="" and ffi.load
 end
 if not FFISUPPORTED then
-  ffi=nil
+ ffi=nil
 elseif not ffi.number then
-  ffi.number=tonumber
+ ffi.number=tonumber
 end
-if not bit32 then
-  bit32=require("l-bit32")
+if LUAVERSION>5.3 then
+ collectgarbage("generational")
 end
-local loaded=package.loaded
-if not loaded["socket"] then loaded["socket"]=loaded["socket.core"] end
-if not loaded["mime"]  then loaded["mime"]=loaded["mime.core"]  end
-if not socket.mime then socket.mime=package.loaded["mime"] end
-if not loaded["socket.mime"] then loaded["socket.mime"]=socket.mime end
-if not loaded["socket.http"] then loaded["socket.http"]=socket.http end
-if not loaded["socket.ftp"] then loaded["socket.ftp"]=socket.ftp end
-if not loaded["socket.smtp"] then loaded["socket.smtp"]=socket.smtp end
-if not loaded["socket.tp"]  then loaded["socket.tp"]=socket.tp  end
-if not loaded["socket.url"] then loaded["socket.url"]=socket.url end
 
 
 end -- of closure
@@ -195,25 +322,27 @@
 
 package.loaded["l-macro"] = package.loaded["l-macro"] or true
 
--- original size: 8260, stripped down to: 5213
+-- original size: 10131, stripped down to: 5991
 
 if not modules then modules={} end modules ['l-macros']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 S,P,R,V,C,Cs,Cc,Ct,Carg=lpeg.S,lpeg.P,lpeg.R,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg
 local lpegmatch=lpeg.match
 local concat=table.concat
-local format,sub=string.format,string.sub
+local format,sub,match=string.format,string.sub,string.match
 local next,load,type=next,load,type
 local newline=S("\n\r")^1
 local continue=P("\\")*newline
+local whitespace=S(" \t\n\r")
 local spaces=S(" \t")+continue
-local name=R("az","AZ","__","09")^1
-local body=((1+continue/"")-newline)^1
+local nametoken=R("az","AZ","__","09")
+local name=nametoken^1
+local body=((continue/""+1)-newline)^1
 local lparent=P("(")
 local rparent=P(")")
 local noparent=1-(lparent+rparent)
@@ -230,172 +359,214 @@
 local resolve
 local subparser
 local report_lua=function(...)
-  if logs and logs.reporter then
-    report_lua=logs.reporter("system","lua")
-    report_lua(...)
-  else
-    print(format(...))
-  end
+ if logs and logs.reporter then
+  report_lua=logs.reporter("system","lua")
+  report_lua(...)
+ else
+  print(format(...))
+ end
 end
-resolve=C(C(name)*arguments^-1)/function(raw,s,a)
-  local d=definitions[s]
-  if d then
-    if a then
-      local n=#a
-      local p=patterns[s][n]
-      if p then
-        local d=d[n]
-        for i=1,n do
-          a[i]=lpegmatch(subparser,a[i]) or a[i]
-        end
-        return lpegmatch(p,d,1,a) or d
-      else
-        return raw
-      end
-    else
-      return d[0] or raw
+local safeguard=P("local")*whitespace^1*name*(whitespace+P("="))
+resolve=safeguard+C(C(name)*(arguments^-1))/function(raw,s,a)
+ local d=definitions[s]
+ if d then
+  if a then
+   local n=#a
+   local p=patterns[s][n]
+   if p then
+    local d=d[n]
+    for i=1,n do
+     a[i]=lpegmatch(subparser,a[i]) or a[i]
     end
-  elseif a then
-    for i=1,#a do
-      a[i]=lpegmatch(subparser,a[i]) or a[i]
-    end
-    return s.."("..concat(a,",")..")"
+    return lpegmatch(p,d,1,a) or d
+   else
+    return raw
+   end
   else
-    return raw
+   return d[0] or raw
   end
+ elseif a then
+  for i=1,#a do
+   a[i]=lpegmatch(subparser,a[i]) or a[i]
+  end
+  return s.."("..concat(a,",")..")"
+ else
+  return raw
+ end
 end
 subparser=Cs((resolve+P(1))^1)
 local enddefine=P("#enddefine")/""
-local beginregister=(C(name)*spaces^0*(arguments+Cc(false))*C((1-enddefine)^1)*enddefine)/function(k,a,v)
-  local n=0
-  if a then
-    n=#a
-    local pattern=P(false)
-    for i=1,n do
-      pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end
-    end
-    pattern=Cs((pattern+P(1))^1)
-    local p=patterns[k]
-    if not p then
-      p={ [0]=false,false,false,false,false,false,false,false,false }
-      patterns[k]=p
-    end
-    p[n]=pattern
+local beginregister=(C(name)*(arguments+Cc(false))*C((1-enddefine)^1)*enddefine)/function(k,a,v)
+ local n=0
+ if a then
+  n=#a
+  local pattern=P(false)
+  for i=1,n do
+   pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end
   end
-  local d=definitions[k]
-  if not d then
-    d={ [0]=false,false,false,false,false,false,false,false,false }
-    definitions[k]=d
+  pattern=Cs((pattern+P(1))^1)
+  local p=patterns[k]
+  if not p then
+   p={ [0]=false,false,false,false,false,false,false,false,false }
+   patterns[k]=p
   end
-  d[n]=lpegmatch(subparser,v) or v
-  return ""
+  p[n]=pattern
+ end
+ local d=definitions[k]
+ if not d then
+  d={ a=a,[0]=false,false,false,false,false,false,false,false,false }
+  definitions[k]=d
+ end
+ d[n]=lpegmatch(subparser,v) or v
+ return ""
 end
-local register=(C(name)*spaces^0*(arguments+Cc(false))*spaces^0*C(body))/function(k,a,v)
-  local n=0
-  if a then
-    n=#a
-    local pattern=P(false)
-    for i=1,n do
-      pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end
-    end
-    pattern=Cs((pattern+P(1))^1)
-    local p=patterns[k]
-    if not p then
-      p={ [0]=false,false,false,false,false,false,false,false,false }
-      patterns[k]=p
-    end
-    p[n]=pattern
+local register=(Cs(name)*(arguments+Cc(false))*spaces^0*Cs(body))/function(k,a,v)
+ local n=0
+ if a then
+  n=#a
+  local pattern=P(false)
+  for i=1,n do
+   pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end
   end
-  local d=definitions[k]
-  if not d then
-    d={ [0]=false,false,false,false,false,false,false,false,false }
-    definitions[k]=d
+  pattern=Cs((pattern+P(1))^1)
+  local p=patterns[k]
+  if not p then
+   p={ [0]=false,false,false,false,false,false,false,false,false }
+   patterns[k]=p
   end
-  d[n]=lpegmatch(subparser,v) or v
-  return ""
+  p[n]=pattern
+ end
+ local d=definitions[k]
+ if not d then
+  d={ a=a,[0]=false,false,false,false,false,false,false,false,false }
+  definitions[k]=d
+ end
+ d[n]=lpegmatch(subparser,v) or v
+ return ""
 end
 local unregister=(C(name)*spaces^0*(arguments+Cc(false)))/function(k,a)
-  local n=0
-  if a then
-    n=#a
-    local p=patterns[k]
-    if p then
-      p[n]=false
-    end
+ local n=0
+ if a then
+  n=#a
+  local p=patterns[k]
+  if p then
+   p[n]=false
   end
-  local d=definitions[k]
-  if d then
-    d[n]=false
-  end
-  return ""
+ end
+ local d=definitions[k]
+ if d then
+  d[n]=false
+ end
+ return ""
 end
 local begindefine=(P("begindefine")*spaces^0/"")*beginregister
-local define=(P("define"   )*spaces^0/"")*register
-local undefine=(P("undefine"  )*spaces^0/"")*unregister
+local define=(P("define"  )*spaces^0/"")*register
+local undefine=(P("undefine"   )*spaces^0/"")*unregister
 local parser=Cs((((P("#")/"")*(define+begindefine+undefine)*(newline^0/"") )+resolve+P(1) )^0 )
 function macros.reset()
-  definitions={}
-  patterns={}
+ definitions={}
+ patterns={}
 end
+function macros.showdefinitions()
+ for name,list in table.sortedhash(definitions) do
+  local arguments=list.a
+  if arguments then
+   arguments="("..concat(arguments,",")..")"
+  else
+   arguments=""
+  end
+  print("macro: "..name..arguments)
+  for i=0,#list do
+   local l=list[i]
+   if l then
+    print("  "..l)
+   end
+  end
+ end
+end
 function macros.resolvestring(str)
-  return lpegmatch(parser,str) or str
+ return lpegmatch(parser,str) or str
 end
 function macros.resolving()
-  return next(patterns)
+ return next(patterns)
 end
-local function loaded(name,trace,detail)
-  local f=io.open(name,"rb")
-  if not f then
-    return false,format("file '%s' not found",name)
-  end
-  local c=f:read("*a")
-  if not c then
-    return false,format("file '%s' is invalid",name)
-  end
+local function reload(path,name,data)
+ local only=match(name,".-([^/]+)%.lua")
+ if only and only~="" then
+  local name=path.."/"..only
+  local f=io.open(name,"wb")
+  f:write(data)
   f:close()
-  local n=lpegmatch(parser,c)
-  if trace then
-    if #n~=#c then
-      report_lua("macros expanded in '%s' (%i => %i bytes)",name,#c,#n)
-      if detail then
-        report_lua()
-        report_lua(n)
-        report_lua()
-      end
-    elseif detail then
-      report_lua("no macros expanded in '%s'",name)
-    end
+  local f=loadfile(name)
+  os.remove(name)
+  return f
+ end
+end
+local function reload(path,name,data)
+ if path and path~="" then
+  local only=string.match(name,".-([^/]+)%.lua")
+  if only and only~="" then
+   local name=path.."/"..only.."-macro.lua"
+   local f=io.open(name,"wb")
+   if f then
+    f:write(data)
+    f:close()
+    local l=loadfile(name)
+    os.remove(name)
+    return l
+   end
   end
-  if #name>30 then
-    n="--[["..sub(name,-30).."]] "..n
-  else
-    n="--[["..name.."]] "..n
+ end
+ return load(data,name)
+end
+local function loaded(name,trace,detail)
+ local f=io.open(name,"rb")
+ if not f then
+  return false,format("file '%s' not found",name)
+ end
+ local c=f:read("*a")
+ if not c then
+  return false,format("file '%s' is invalid",name)
+ end
+ f:close()
+ local n=lpegmatch(parser,c)
+ if trace then
+  if #n~=#c then
+   report_lua("macros expanded in '%s' (%i => %i bytes)",name,#c,#n)
+   if detail then
+    report_lua()
+    report_lua(n)
+    report_lua()
+   end
+  elseif detail then
+   report_lua("no macros expanded in '%s'",name)
   end
-  return load(n)
+ end
+ return reload(lfs and lfs.currentdir(),name,n)
 end
 macros.loaded=loaded
 function required(name,trace)
-  local filename=file.addsuffix(name,"lua")
-  local fullname=resolvers and resolvers.find_file(filename) or filename
-  if not fullname or fullname=="" then
-    return false
-  end
-  local codeblob=package.loaded[fullname]
-  if codeblob then
-    return codeblob
-  end
-  local code,message=loaded(fullname,macros,trace,trace)
-  if type(code)=="function" then
-    code=code()
-  else
-    report_lua("error when loading '%s'",fullname)
-    return false,message
-  end
-  if code==nil then
-    code=false
-  end
-  package.loaded[fullname]=code
-  return code
+ local filename=file.addsuffix(name,"lua")
+ local fullname=resolvers and resolvers.find_file(filename) or filename
+ if not fullname or fullname=="" then
+  return false
+ end
+ local codeblob=package.loaded[fullname]
+ if codeblob then
+  return codeblob
+ end
+ local code,message=loaded(fullname,macros,trace,trace)
+ if type(code)=="function" then
+  code=code()
+ else
+  report_lua("error when loading '%s'",fullname)
+  return false,message
+ end
+ if code==nil then
+  code=false
+ end
+ package.loaded[fullname]=code
+ return code
 end
 macros.required=required
 
@@ -406,14 +577,14 @@
 
 package.loaded["l-sandbox"] = package.loaded["l-sandbox"] or true
 
--- original size: 9678, stripped down to: 6688
+-- original size: 9747, stripped down to: 6313
 
 if not modules then modules={} end modules ['l-sandbox']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 global=_G
 local next=next
@@ -439,192 +610,195 @@
 local logger=false
 local blocked={}
 local function report(...)
-  tprint("sandbox         ! "..format(...)) 
+ tprint("sandbox         ! "..format(...)) 
 end
 sandbox.report=report
 function sandbox.setreporter(r)
-  report=r
-  sandbox.report=r
+ report=r
+ sandbox.report=r
 end
 function sandbox.settrace(v)
-  trace=v
+ trace=v
 end
 function sandbox.setlogger(l)
-  logger=type(l)=="function" and l or false
+ logger=type(l)=="function" and l or false
 end
 local function register(func,overload,comment)
-  if type(func)=="function" then
-    if type(overload)=="string" then
-      comment=overload
-      overload=nil
+ if type(func)=="function" then
+  if type(overload)=="string" then
+   comment=overload
+   overload=nil
+  end
+  local function f(...)
+   if sandboxed then
+    local overload=overloads[f]
+    if overload then
+     if logger then
+      local result={ overload(func,...) }
+      logger {
+       comment=comments[f] or tostring(f),
+       arguments={... },
+       result=result[1] and true or false,
+      }
+      return unpack(result)
+     else
+      return overload(func,...)
+     end
+    else
     end
-    local function f(...)
-      if sandboxed then
-        local overload=overloads[f]
-        if overload then
-          if logger then
-            local result={ overload(func,...) }
-            logger {
-              comment=comments[f] or tostring(f),
-              arguments={... },
-              result=result[1] and true or false,
-            }
-            return unpack(result)
-          else
-            return overload(func,...)
-          end
-        else
-        end
-      else
-        return func(...)
-      end
-    end
-    if comment then
-      comments[f]=comment
-      if trace then
-        report("registering function: %s",comment)
-      end
-    end
-    overloads[f]=overload or false
-    originals[f]=func
-    return f
+   else
+    return func(...)
+   end
   end
+  if comment then
+   comments[f]=comment
+   if trace then
+    report("registering function: %s",comment)
+   end
+  end
+  overloads[f]=overload or false
+  originals[f]=func
+  return f
+ end
 end
 local function redefine(func,comment)
-  if type(func)=="function" then
-    skiploads[func]=comment or comments[func] or "unknown"
-    if overloads[func]==false then
-      overloads[func]=nil 
-    end
+ if type(func)=="function" then
+  skiploads[func]=comment or comments[func] or "unknown"
+  if overloads[func]==false then
+   overloads[func]=nil 
   end
+ end
 end
 sandbox.register=register
 sandbox.redefine=redefine
 function sandbox.original(func)
-  return originals and originals[func] or func
+ return originals and originals[func] or func
 end
 function sandbox.overload(func,overload,comment)
-  comment=comment or comments[func] or "?"
-  if type(func)~="function" then
-    if trace then
-      report("overloading unknown function: %s",comment)
-    end
-  elseif type(overload)~="function" then
-    if trace then
-      report("overloading function with bad overload: %s",comment)
-    end
-  elseif overloads[func]==nil then
-    if trace then
-      report("function is not registered: %s",comment)
-    end
-  elseif skiploads[func] then
-    if trace then
-      report("function is not skipped: %s",comment)
-    end
-  else
-    if trace then
-      report("overloading function: %s",comment)
-    end
-    overloads[func]=overload
+ comment=comment or comments[func] or "?"
+ if type(func)~="function" then
+  if trace then
+   report("overloading unknown function: %s",comment)
   end
-  return func
+ elseif type(overload)~="function" then
+  if trace then
+   report("overloading function with bad overload: %s",comment)
+  end
+ elseif overloads[func]==nil then
+  if trace then
+   report("function is not registered: %s",comment)
+  end
+ elseif skiploads[func] then
+  if trace then
+   report("function is not skipped: %s",comment)
+  end
+ else
+  if trace then
+   report("overloading function: %s",comment)
+  end
+  overloads[func]=overload
+ end
+ return func
 end
 local function whatever(specification,what,target)
-  if type(specification)~="table" then
-    report("%s needs a specification",what)
-  elseif type(specification.category)~="string" or type(specification.action)~="function" then
-    report("%s needs a category and action",what)
-  elseif not sandboxed then
-    target[#target+1]=specification
-  elseif trace then
-    report("already enabled, discarding %s",what)
-  end
+ if type(specification)~="table" then
+  report("%s needs a specification",what)
+ elseif type(specification.category)~="string" or type(specification.action)~="function" then
+  report("%s needs a category and action",what)
+ elseif not sandboxed then
+  target[#target+1]=specification
+ elseif trace then
+  report("already enabled, discarding %s",what)
+ end
 end
 function sandbox.initializer(specification)
-  whatever(specification,"initializer",initializers)
+ whatever(specification,"initializer",initializers)
 end
 function sandbox.finalizer(specification)
-  whatever(specification,"finalizer",finalizers)
+ whatever(specification,"finalizer",finalizers)
 end
 function require(name)
-  local n=gsub(name,"^.*[\\/]","")
-  local n=gsub(n,"[%.].*$","")
-  local b=blocked[n]
-  if b==false then
-    return nil 
-  elseif b then
-    if trace then
-      report("using blocked: %s",n)
-    end
-    return b
-  else
-    if trace then
-      report("requiring: %s",name)
-    end
-    return requiem(name)
+ local n=gsub(name,"^.*[\\/]","")
+ local n=gsub(n,"[%.].*$","")
+ local b=blocked[n]
+ if b==false then
+  return nil 
+ elseif b then
+  if trace then
+   report("using blocked: %s",n)
   end
-end
-function blockrequire(name,lib)
+  return b
+ else
   if trace then
-    report("preventing reload of: %s",name)
+   report("requiring: %s",name)
   end
-  blocked[name]=lib or _G[name] or false
+  return requiem(name)
+ end
 end
+function blockrequire(name,lib)
+ if trace then
+  report("preventing reload of: %s",name)
+ end
+ blocked[name]=lib or _G[name] or false
+end
 function sandbox.enable()
-  if not sandboxed then
-    for i=1,#initializers do
-      initializers[i].action()
+ if not sandboxed then
+  debug={
+   traceback=debug.traceback,
+  }
+  for i=1,#initializers do
+   initializers[i].action()
+  end
+  for i=1,#finalizers do
+   finalizers[i].action()
+  end
+  local nnot=0
+  local nyes=0
+  local cnot={}
+  local cyes={}
+  local skip={}
+  for k,v in next,overloads do
+   local c=comments[k]
+   if v then
+    if c then
+     cyes[#cyes+1]=c
+    else 
+     nyes=nyes+1
     end
-    for i=1,#finalizers do
-      finalizers[i].action()
+   else
+    if c then
+     cnot[#cnot+1]=c
+    else 
+     nnot=nnot+1
     end
-    local nnot=0
-    local nyes=0
-    local cnot={}
-    local cyes={}
-    local skip={}
-    for k,v in next,overloads do
-      local c=comments[k]
-      if v then
-        if c then
-          cyes[#cyes+1]=c
-        else 
-          nyes=nyes+1
-        end
-      else
-        if c then
-          cnot[#cnot+1]=c
-        else 
-          nnot=nnot+1
-        end
-      end
-    end
-    for k,v in next,skiploads do
-      skip[#skip+1]=v
-    end
-    if #cyes>0 then
-      sort(cyes)
-      report("overloaded known: %s",concat(cyes," | "))
-    end
-    if nyes>0 then
-      report("overloaded unknown: %s",nyes)
-    end
-    if #cnot>0 then
-      sort(cnot)
-      report("not overloaded known: %s",concat(cnot," | "))
-    end
-    if nnot>0 then
-      report("not overloaded unknown: %s",nnot)
-    end
-    if #skip>0 then
-      sort(skip)
-      report("not overloaded redefined: %s",concat(skip," | "))
-    end
-    initializers=nil
-    finalizers=nil
-    originals=nil
-    sandboxed=true
+   end
   end
+  for k,v in next,skiploads do
+   skip[#skip+1]=v
+  end
+  if #cyes>0 then
+   sort(cyes)
+   report("overloaded known: %s",concat(cyes," | "))
+  end
+  if nyes>0 then
+   report("overloaded unknown: %s",nyes)
+  end
+  if #cnot>0 then
+   sort(cnot)
+   report("not overloaded known: %s",concat(cnot," | "))
+  end
+  if nnot>0 then
+   report("not overloaded unknown: %s",nnot)
+  end
+  if #skip>0 then
+   sort(skip)
+   report("not overloaded redefined: %s",concat(skip," | "))
+  end
+  initializers=nil
+  finalizers=nil
+  originals=nil
+  sandboxed=true
+ end
 end
 blockrequire("lfs",lfs)
 blockrequire("io",io)
@@ -631,39 +805,39 @@
 blockrequire("os",os)
 blockrequire("ffi",ffi)
 local function supported(library)
-  local l=_G[library]
-  return l
+ local l=_G[library]
+ return l
 end
 loadfile=register(loadfile,"loadfile")
 if supported("io") then
-  io.open=register(io.open,"io.open")
-  io.popen=register(io.popen,"io.popen") 
-  io.lines=register(io.lines,"io.lines")
-  io.output=register(io.output,"io.output")
-  io.input=register(io.input,"io.input")
+ io.open=register(io.open,"io.open")
+ io.popen=register(io.popen,"io.popen") 
+ io.lines=register(io.lines,"io.lines")
+ io.output=register(io.output,"io.output")
+ io.input=register(io.input,"io.input")
 end
 if supported("os") then
-  os.execute=register(os.execute,"os.execute")
-  os.spawn=register(os.spawn,"os.spawn")
-  os.exec=register(os.exec,"os.exec")
-  os.rename=register(os.rename,"os.rename")
-  os.remove=register(os.remove,"os.remove")
+ os.execute=register(os.execute,"os.execute")
+ os.spawn=register(os.spawn,"os.spawn")
+ os.exec=register(os.exec,"os.exec")
+ os.rename=register(os.rename,"os.rename")
+ os.remove=register(os.remove,"os.remove")
 end
 if supported("lfs") then
-  lfs.chdir=register(lfs.chdir,"lfs.chdir")
-  lfs.mkdir=register(lfs.mkdir,"lfs.mkdir")
-  lfs.rmdir=register(lfs.rmdir,"lfs.rmdir")
-  lfs.isfile=register(lfs.isfile,"lfs.isfile")
-  lfs.isdir=register(lfs.isdir,"lfs.isdir")
-  lfs.attributes=register(lfs.attributes,"lfs.attributes")
-  lfs.dir=register(lfs.dir,"lfs.dir")
-  lfs.lock_dir=register(lfs.lock_dir,"lfs.lock_dir")
-  lfs.touch=register(lfs.touch,"lfs.touch")
-  lfs.link=register(lfs.link,"lfs.link")
-  lfs.setmode=register(lfs.setmode,"lfs.setmode")
-  lfs.readlink=register(lfs.readlink,"lfs.readlink")
-  lfs.shortname=register(lfs.shortname,"lfs.shortname")
-  lfs.symlinkattributes=register(lfs.symlinkattributes,"lfs.symlinkattributes")
+ lfs.chdir=register(lfs.chdir,"lfs.chdir")
+ lfs.mkdir=register(lfs.mkdir,"lfs.mkdir")
+ lfs.rmdir=register(lfs.rmdir,"lfs.rmdir")
+ lfs.isfile=register(lfs.isfile,"lfs.isfile")
+ lfs.isdir=register(lfs.isdir,"lfs.isdir")
+ lfs.attributes=register(lfs.attributes,"lfs.attributes")
+ lfs.dir=register(lfs.dir,"lfs.dir")
+ lfs.lock_dir=register(lfs.lock_dir,"lfs.lock_dir")
+ lfs.touch=register(lfs.touch,"lfs.touch")
+ lfs.link=register(lfs.link,"lfs.link")
+ lfs.setmode=register(lfs.setmode,"lfs.setmode")
+ lfs.readlink=register(lfs.readlink,"lfs.readlink")
+ lfs.shortname=register(lfs.shortname,"lfs.shortname")
+ lfs.symlinkattributes=register(lfs.symlinkattributes,"lfs.symlinkattributes")
 end
 
 
@@ -673,14 +847,14 @@
 
 package.loaded["l-package"] = package.loaded["l-package"] or true
 
--- original size: 11562, stripped down to: 8625
+-- original size: 11605, stripped down to: 8299
 
 if not modules then modules={} end modules ['l-package']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 type=type
 local gsub,format,find=string.gsub,string.format,string.find
@@ -688,40 +862,40 @@
 local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match
 local package=package
 local searchers=package.searchers or package.loaders
-local filejoin=file and file.join    or function(path,name)  return path.."/"..name end
-local isreadable=file and file.is_readable or function(name)    local f=io.open(name) if f then f:close() return true end end
-local addsuffix=file and file.addsuffix  or function(name,suffix) return name.."."..suffix end
+local filejoin=file and file.join  or function(path,name)   return path.."/"..name end
+local isreadable=file and file.is_readable or function(name)  local f=io.open(name) if f then f:close() return true end end
+local addsuffix=file and file.addsuffix   or function(name,suffix) return name.."."..suffix end
 local function cleanpath(path) 
-  return path
+ return path
 end
 local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1)
 local function lualibfile(name)
-  return lpegmatch(pattern,name) or name
+ return lpegmatch(pattern,name) or name
 end
 local offset=luarocks and 1 or 0 
 local helpers=package.helpers or {
-  cleanpath=cleanpath,
-  lualibfile=lualibfile,
-  trace=false,
-  report=function(...) print(format(...)) end,
-  builtin={
-    ["preload table"]=searchers[1+offset],
-    ["path specification"]=searchers[2+offset],
-    ["cpath specification"]=searchers[3+offset],
-    ["all in one fallback"]=searchers[4+offset],
-  },
-  methods={},
-  sequence={
-    "already loaded",
-    "preload table",
-    "qualified path",
-    "lua extra list",
-    "lib extra list",
-    "path specification",
-    "cpath specification",
-    "all in one fallback",
-    "not loaded",
-  }
+ cleanpath=cleanpath,
+ lualibfile=lualibfile,
+ trace=false,
+ report=function(...) print(format(...)) end,
+ builtin={
+  ["preload table"]=searchers[1+offset],
+  ["path specification"]=searchers[2+offset],
+  ["cpath specification"]=searchers[3+offset],
+  ["all in one fallback"]=searchers[4+offset],
+ },
+ methods={},
+ sequence={
+  "already loaded",
+  "preload table",
+  "qualified path",
+  "lua extra list",
+  "lib extra list",
+  "path specification",
+  "cpath specification",
+  "all in one fallback",
+  "not loaded",
+ }
 }
 package.helpers=helpers
 local methods=helpers.methods
@@ -737,51 +911,51 @@
 local nofpathlua=-1
 local nofpathlib=-1
 local function listpaths(what,paths)
-  local nofpaths=#paths
-  if nofpaths>0 then
-    for i=1,nofpaths do
-      helpers.report("using %s path %i: %s",what,i,paths[i])
-    end
-  else
-    helpers.report("no %s paths defined",what)
+ local nofpaths=#paths
+ if nofpaths>0 then
+  for i=1,nofpaths do
+   helpers.report("using %s path %i: %s",what,i,paths[i])
   end
-  return nofpaths
+ else
+  helpers.report("no %s paths defined",what)
+ end
+ return nofpaths
 end
 local function getextraluapaths()
-  if helpers.trace and #extraluapaths~=nofextralua then
-    nofextralua=listpaths("extra lua",extraluapaths)
-  end
-  return extraluapaths
+ if helpers.trace and #extraluapaths~=nofextralua then
+  nofextralua=listpaths("extra lua",extraluapaths)
+ end
+ return extraluapaths
 end
 local function getextralibpaths()
-  if helpers.trace and #extralibpaths~=nofextralib then
-    nofextralib=listpaths("extra lib",extralibpaths)
-  end
-  return extralibpaths
+ if helpers.trace and #extralibpaths~=nofextralib then
+  nofextralib=listpaths("extra lib",extralibpaths)
+ end
+ return extralibpaths
 end
 local function getluapaths()
-  local luapath=package.path or ""
-  if oldluapath~=luapath then
-    luapaths=file.splitpath(luapath,";")
-    oldluapath=luapath
-    nofpathlua=-1
-  end
-  if helpers.trace and #luapaths~=nofpathlua then
-    nofpathlua=listpaths("builtin lua",luapaths)
-  end
-  return luapaths
+ local luapath=package.path or ""
+ if oldluapath~=luapath then
+  luapaths=file.splitpath(luapath,";")
+  oldluapath=luapath
+  nofpathlua=-1
+ end
+ if helpers.trace and #luapaths~=nofpathlua then
+  nofpathlua=listpaths("builtin lua",luapaths)
+ end
+ return luapaths
 end
 local function getlibpaths()
-  local libpath=package.cpath or ""
-  if oldlibpath~=libpath then
-    libpaths=file.splitpath(libpath,";")
-    oldlibpath=libpath
-    nofpathlib=-1
-  end
-  if helpers.trace and #libpaths~=nofpathlib then
-    nofpathlib=listpaths("builtin lib",libpaths)
-  end
-  return libpaths
+ local libpath=package.cpath or ""
+ if oldlibpath~=libpath then
+  libpaths=file.splitpath(libpath,";")
+  oldlibpath=libpath
+  nofpathlib=-1
+ end
+ if helpers.trace and #libpaths~=nofpathlib then
+  nofpathlib=listpaths("builtin lib",libpaths)
+ end
+ return libpaths
 end
 package.luapaths=getluapaths
 package.libpaths=getlibpaths
@@ -788,202 +962,205 @@
 package.extraluapaths=getextraluapaths
 package.extralibpaths=getextralibpaths
 local hashes={
-  lua={},
-  lib={},
+ lua={},
+ lib={},
 }
 local function registerpath(tag,what,target,...)
-  local pathlist={... }
-  local cleanpath=helpers.cleanpath
-  local trace=helpers.trace
-  local report=helpers.report
-  local hash=hashes[what]
-  local function add(path)
-    local path=cleanpath(path)
-    if not hash[path] then
-      target[#target+1]=path
-      hash[path]=true
-      if trace then
-        report("registered %s path %s: %s",tag,#target,path)
-      end
-    else
-      if trace then
-        report("duplicate %s path: %s",tag,path)
-      end
-    end
+ local pathlist={... }
+ local cleanpath=helpers.cleanpath
+ local trace=helpers.trace
+ local report=helpers.report
+ local hash=hashes[what]
+ local function add(path)
+  local path=cleanpath(path)
+  if not hash[path] then
+   target[#target+1]=path
+   hash[path]=true
+   if trace then
+    report("registered %s path %s: %s",tag,#target,path)
+   end
+  else
+   if trace then
+    report("duplicate %s path: %s",tag,path)
+   end
   end
-  for p=1,#pathlist do
-    local path=pathlist[p]
-    if type(path)=="table" then
-      for i=1,#path do
-        add(path[i])
-      end
-    else
-      add(path)
-    end
+ end
+ for p=1,#pathlist do
+  local path=pathlist[p]
+  if type(path)=="table" then
+   for i=1,#path do
+    add(path[i])
+   end
+  else
+   add(path)
   end
+ end
 end
 local function pushpath(tag,what,target,path)
-  local path=helpers.cleanpath(path)
-  insert(target,1,path)
-  if helpers.trace then
-    helpers.report("pushing %s path in front: %s",tag,path)
-  end
+ local path=helpers.cleanpath(path)
+ insert(target,1,path)
+ if helpers.trace then
+  helpers.report("pushing %s path in front: %s",tag,path)
+ end
 end
 local function poppath(tag,what,target)
-  local path=remove(target,1)
-  if helpers.trace then
-    if path then
-      helpers.report("popping %s path from front: %s",tag,path)
-    else
-      helpers.report("no %s path to pop",tag)
-    end
+ local path=remove(target,1)
+ if helpers.trace then
+  if path then
+   helpers.report("popping %s path from front: %s",tag,path)
+  else
+   helpers.report("no %s path to pop",tag)
   end
+ end
 end
 helpers.registerpath=registerpath
 function package.extraluapath(...)
-  registerpath("extra lua","lua",extraluapaths,...)
+ registerpath("extra lua","lua",extraluapaths,...)
 end
 function package.pushluapath(path)
-  pushpath("extra lua","lua",extraluapaths,path)
+ pushpath("extra lua","lua",extraluapaths,path)
 end
 function package.popluapath()
-  poppath("extra lua","lua",extraluapaths)
+ poppath("extra lua","lua",extraluapaths)
 end
 function package.extralibpath(...)
-  registerpath("extra lib","lib",extralibpaths,...)
+ registerpath("extra lib","lib",extralibpaths,...)
 end
 function package.pushlibpath(path)
-  pushpath("extra lib","lib",extralibpaths,path)
+ pushpath("extra lib","lib",extralibpaths,path)
 end
 function package.poplibpath()
-  poppath("extra lib","lua",extralibpaths)
+ poppath("extra lib","lua",extralibpaths)
 end
 local function loadedaslib(resolved,rawname) 
-  local base=gsub(rawname,"%.","_")
-  local init="luaopen_"..gsub(base,"%.","_")
-  if helpers.trace then
-    helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
-  end
-  return package.loadlib(resolved,init)
+ local base=gsub(rawname,"%.","_")
+ local init="luaopen_"..gsub(base,"%.","_")
+ if helpers.trace then
+  helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
 end
 helpers.loadedaslib=loadedaslib
 local function loadedbypath(name,rawname,paths,islib,what)
-  local trace=helpers.trace
-  for p=1,#paths do
-    local path=paths[p]
-    local resolved=filejoin(path,name)
-    if trace then
-      helpers.report("%s path, identifying '%s' on '%s'",what,name,path)
-    end
-    if isreadable(resolved) then
-      if trace then
-        helpers.report("%s path, '%s' found on '%s'",what,name,resolved)
-      end
-      if islib then
-        return loadedaslib(resolved,rawname)
-      else
-        return loadfile(resolved)
-      end
-    end
+ local trace=helpers.trace
+ for p=1,#paths do
+  local path=paths[p]
+  local resolved=filejoin(path,name)
+  if trace then
+   helpers.report("%s path, identifying '%s' on '%s'",what,name,path)
   end
+  if isreadable(resolved) then
+   if trace then
+    helpers.report("%s path, '%s' found on '%s'",what,name,resolved)
+   end
+   if islib then
+    return loadedaslib(resolved,rawname)
+   else
+    return loadfile(resolved)
+   end
+  end
+ end
 end
 helpers.loadedbypath=loadedbypath
 local function loadedbyname(name,rawname)
-  if find(name,"^/") or find(name,"^[a-zA-Z]:/") then
-    local trace=helpers.trace
-    if trace then
-      helpers.report("qualified name, identifying '%s'",what,name)
-    end
-    if isreadable(name) then
-      if trace then
-        helpers.report("qualified name, '%s' found",what,name)
-      end
-      return loadfile(name)
-    end
+ if find(name,"^/") or find(name,"^[a-zA-Z]:/") then
+  local trace=helpers.trace
+  if trace then
+   helpers.report("qualified name, identifying '%s'",what,name)
   end
+  if isreadable(name) then
+   if trace then
+    helpers.report("qualified name, '%s' found",what,name)
+   end
+   return loadfile(name)
+  end
+ end
 end
 helpers.loadedbyname=loadedbyname
 methods["already loaded"]=function(name)
-  return package.loaded[name]
+ return package.loaded[name]
 end
 methods["preload table"]=function(name)
-  return builtin["preload table"](name)
+ return builtin["preload table"](name)
 end
 methods["qualified path"]=function(name)
- return loadedbyname(addsuffix(lualibfile(name),"lua"),name)
+  return loadedbyname(addsuffix(lualibfile(name),"lua"),name)
 end
 methods["lua extra list"]=function(name)
-  return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua")
+ return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua")
 end
 methods["lib extra list"]=function(name)
-  return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib")
+ return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib")
 end
 methods["path specification"]=function(name)
-  getluapaths() 
-  return builtin["path specification"](name)
+ getluapaths() 
+ return builtin["path specification"](name)
 end
 methods["cpath specification"]=function(name)
-  getlibpaths() 
-  return builtin["cpath specification"](name)
+ getlibpaths() 
+ return builtin["cpath specification"](name)
 end
 methods["all in one fallback"]=function(name)
-  return builtin["all in one fallback"](name)
+ return builtin["all in one fallback"](name)
 end
 methods["not loaded"]=function(name)
-  if helpers.trace then
-    helpers.report("unable to locate '%s'",name or "?")
-  end
-  return nil
+ if helpers.trace then
+  helpers.report("unable to locate '%s'",name or "?")
+ end
+ return nil
 end
 local level=0
 local used={}
 helpers.traceused=false
 function helpers.loaded(name)
-  local sequence=helpers.sequence
-  level=level+1
-  for i=1,#sequence do
-    local method=sequence[i]
-    if helpers.trace then
-      helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name)
-    end
-    local result,rest=methods[method](name)
-    if type(result)=="function" then
-      if helpers.trace then
-        helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name)
-      end
-      if helpers.traceused then
-        used[#used+1]={ level=level,name=name }
-      end
-      level=level-1
-      return result,rest
-    end
+ local sequence=helpers.sequence
+ level=level+1
+ for i=1,#sequence do
+  local method=sequence[i]
+  if helpers.trace then
+   helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name)
   end
-  level=level-1
-  return nil
+  local result,rest=methods[method](name)
+  if type(result)=="function" then
+   if helpers.trace then
+    helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name)
+   end
+   if helpers.traceused then
+    used[#used+1]={ level=level,name=name }
+   end
+   level=level-1
+   return result,rest
+  end
+ end
+ level=level-1
+ return nil
 end
 function helpers.showused()
-  local n=#used
-  if n>0 then
-    helpers.report("%s libraries loaded:",n)
-    helpers.report()
-    for i=1,n do
-      local u=used[i]
-      helpers.report("%i %a",u.level,u.name)
-    end
-    helpers.report()
-   end
+ local n=#used
+ if n>0 then
+  helpers.report("%s libraries loaded:",n)
+  helpers.report()
+  for i=1,n do
+   local u=used[i]
+   helpers.report("%i %a",u.level,u.name)
+  end
+  helpers.report()
+  end
 end
 function helpers.unload(name)
-  if helpers.trace then
-    if package.loaded[name] then
-      helpers.report("unloading, name '%s', %s",name,"done")
-    else
-      helpers.report("unloading, name '%s', %s",name,"not loaded")
-    end
+ if helpers.trace then
+  if package.loaded[name] then
+   helpers.report("unloading, name '%s', %s",name,"done")
+  else
+   helpers.report("unloading, name '%s', %s",name,"not loaded")
   end
-  package.loaded[name]=nil
+ end
+ package.loaded[name]=nil
 end
 table.insert(searchers,1,helpers.loaded)
+if context then
+ package.path=""
+end
 
 
 end -- of closure
@@ -992,14 +1169,14 @@
 
 package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
 
--- original size: 38582, stripped down to: 20518
+-- original size: 38434, stripped down to: 19310
 
 if not modules then modules={} end modules ['l-lpeg']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 lpeg=require("lpeg") 
 local lpeg=lpeg
@@ -1010,7 +1187,7 @@
 local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
 local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
 if setinspector then
-  setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
+ setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
 end
 lpeg.patterns=lpeg.patterns or {} 
 local patterns=lpeg.patterns
@@ -1033,7 +1210,7 @@
 local hexdigit=digit+lowercase+uppercase
 local hexdigits=hexdigit^1
 local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
-local newline=P("\r")*(P("\n")+P(true))+P("\n") 
+local newline=P("\r")*(P("\n")+P(true))+P("\n")  
 local escaped=P("\\")*anything
 local squote=P("'")
 local dquote=P('"')
@@ -1042,9 +1219,9 @@
 local comma=P(",")
 local utfbom_32_be=P('\000\000\254\255') 
 local utfbom_32_le=P('\255\254\000\000') 
-local utfbom_16_be=P('\254\255')     
-local utfbom_16_le=P('\255\254')     
-local utfbom_8=P('\239\187\191')   
+local utfbom_16_be=P('\254\255')   
+local utfbom_16_le=P('\255\254')   
+local utfbom_8=P('\239\187\191')  
 local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
 local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8") 
 local utfstricttype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")
@@ -1076,7 +1253,7 @@
 patterns.validutf8=validutf8char
 patterns.validutf8char=validutf8char
 local eol=S("\n\r")
-local spacer=S(" \t\f\v") 
+local spacer=S(" \t\f\v")  
 local whitespace=eol+spacer
 local nonspacer=1-spacer
 local nonwhitespace=1-whitespace
@@ -1085,15 +1262,15 @@
 patterns.whitespace=whitespace
 patterns.nonspacer=nonspacer
 patterns.nonwhitespace=nonwhitespace
-local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)   
+local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)  
 local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0)
 local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
 local nospacer=Cs((whitespace^1/""+nonwhitespace^1)^0)
 local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0)
-local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0)
+local e_collapser=Cs((whitespace^1*endofstring/""+nonwhitespace^1+whitespace^1/" ")^0)
 local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0)
 local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0)
-local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0)
+local e_stripper=Cs((spacer^1*endofstring/""+nonspacer^1+spacer^1/" ")^0)
 local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0)
 patterns.stripper=stripper
 patterns.fullstripper=fullstripper
@@ -1150,7 +1327,7 @@
 patterns.number=patterns.float+patterns.integer
 patterns.cnumber=patterns.cfloat+patterns.integer
 patterns.cpnumber=patterns.cpfloat+patterns.integer
-patterns.oct=zero*octdigits
+patterns.oct=zero*octdigits 
 patterns.octal=patterns.oct
 patterns.HEX=zero*P("X")*(digit+uppercase)^1
 patterns.hex=zero*P("x")*(digit+lowercase)^1
@@ -1160,77 +1337,85 @@
 patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring
 patterns.somecontent=(anything-newline-space)^1 
 patterns.beginline=#(1-newline)
-patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0))
-local function anywhere(pattern) 
-  return P { P(pattern)+1*V(1) }
+patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0))
+function anywhere(pattern) 
+ return (1-P(pattern))^0*P(pattern)
 end
 lpeg.anywhere=anywhere
 function lpeg.instringchecker(p)
-  p=anywhere(p)
-  return function(str)
-    return lpegmatch(p,str) and true or false
-  end
+ p=anywhere(p)
+ return function(str)
+  return lpegmatch(p,str) and true or false
+ end
 end
 function lpeg.splitter(pattern,action)
+ if action then
   return (((1-P(pattern))^1)/action+1)^0
+ else
+  return (Cs((1-P(pattern))^1)+1)^0
+ end
 end
 function lpeg.tsplitter(pattern,action)
+ if action then
   return Ct((((1-P(pattern))^1)/action+1)^0)
+ else
+  return Ct((Cs((1-P(pattern))^1)+1)^0)
+ end
 end
 local splitters_s,splitters_m,splitters_t={},{},{}
 local function splitat(separator,single)
-  local splitter=(single and splitters_s[separator]) or splitters_m[separator]
-  if not splitter then
-    separator=P(separator)
-    local other=C((1-separator)^0)
-    if single then
-      local any=anything
-      splitter=other*(separator*C(any^0)+"") 
-      splitters_s[separator]=splitter
-    else
-      splitter=other*(separator*other)^0
-      splitters_m[separator]=splitter
-    end
+ local splitter=(single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+  separator=P(separator)
+  local other=C((1-separator)^0)
+  if single then
+   local any=anything
+   splitter=other*(separator*C(any^0)+"") 
+   splitters_s[separator]=splitter
+  else
+   splitter=other*(separator*other)^0
+   splitters_m[separator]=splitter
   end
-  return splitter
+ end
+ return splitter
 end
 local function tsplitat(separator)
-  local splitter=splitters_t[separator]
-  if not splitter then
-    splitter=Ct(splitat(separator))
-    splitters_t[separator]=splitter
-  end
-  return splitter
+ local splitter=splitters_t[separator]
+ if not splitter then
+  splitter=Ct(splitat(separator))
+  splitters_t[separator]=splitter
+ end
+ return splitter
 end
 lpeg.splitat=splitat
 lpeg.tsplitat=tsplitat
 function string.splitup(str,separator)
-  if not separator then
-    separator=","
-  end
-  return lpegmatch(splitters_m[separator] or splitat(separator),str)
+ if not separator then
+  separator=","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
 end
 local cache={}
 function lpeg.split(separator,str)
+ local c=cache[separator]
+ if not c then
+  c=tsplitat(separator)
+  cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+function string.split(str,separator)
+ if separator then
   local c=cache[separator]
   if not c then
-    c=tsplitat(separator)
-    cache[separator]=c
+   c=tsplitat(separator)
+   cache[separator]=c
   end
   return lpegmatch(c,str)
+ else
+  return { str }
+ end
 end
-function string.split(str,separator)
-  if separator then
-    local c=cache[separator]
-    if not c then
-      c=tsplitat(separator)
-      cache[separator]=c
-    end
-    return lpegmatch(c,str)
-  else
-    return { str }
-  end
-end
 local spacing=patterns.spacer^0*newline 
 local empty=spacing*Cc("")
 local nonempty=Cs((1-spacing)^1)*spacing^-1
@@ -1239,334 +1424,276 @@
 local linesplitter=tsplitat(newline)
 patterns.linesplitter=linesplitter
 function string.splitlines(str)
-  return lpegmatch(linesplitter,str)
+ return lpegmatch(linesplitter,str)
 end
 local cache={}
 function lpeg.checkedsplit(separator,str)
-  local c=cache[separator]
-  if not c then
-    separator=P(separator)
-    local other=C((1-separator)^1)
-    c=Ct(separator^0*other*(separator^1*other)^0)
-    cache[separator]=c
-  end
-  return lpegmatch(c,str)
+ local c=cache[separator]
+ if not c then
+  separator=P(separator)
+  local other=C((1-separator)^1)
+  c=Ct(separator^0*other*(separator^1*other)^0)
+  cache[separator]=c
+ end
+ return lpegmatch(c,str)
 end
 function string.checkedsplit(str,separator)
-  local c=cache[separator]
-  if not c then
-    separator=P(separator)
-    local other=C((1-separator)^1)
-    c=Ct(separator^0*other*(separator^1*other)^0)
-    cache[separator]=c
-  end
-  return lpegmatch(c,str)
+ local c=cache[separator]
+ if not c then
+  separator=P(separator)
+  local other=C((1-separator)^1)
+  c=Ct(separator^0*other*(separator^1*other)^0)
+  cache[separator]=c
+ end
+ return lpegmatch(c,str)
 end
-local function f2(s) local c1,c2=byte(s,1,2) return  c1*64+c2-12416 end
-local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end
+local function f2(s) local c1,c2=byte(s,1,2) return   c1*64+c2-12416 end
+local function f3(s) local c1,c2,c3=byte(s,1,3) return  (c1*64+c2)*64+c3-925824 end
 local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end
 local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4
 patterns.utf8byte=utf8byte
 local cache={}
 function lpeg.stripper(str)
-  if type(str)=="string" then
-    local s=cache[str]
-    if not s then
-      s=Cs(((S(str)^1)/""+1)^0)
-      cache[str]=s
-    end
-    return s
-  else
-    return Cs(((str^1)/""+1)^0)
+ if type(str)=="string" then
+  local s=cache[str]
+  if not s then
+   s=Cs(((S(str)^1)/""+1)^0)
+   cache[str]=s
   end
+  return s
+ else
+  return Cs(((str^1)/""+1)^0)
+ end
 end
 local cache={}
 function lpeg.keeper(str)
-  if type(str)=="string" then
-    local s=cache[str]
-    if not s then
-      s=Cs((((1-S(str))^1)/""+1)^0)
-      cache[str]=s
-    end
-    return s
-  else
-    return Cs((((1-str)^1)/""+1)^0)
+ if type(str)=="string" then
+  local s=cache[str]
+  if not s then
+   s=Cs((((1-S(str))^1)/""+1)^0)
+   cache[str]=s
   end
+  return s
+ else
+  return Cs((((1-str)^1)/""+1)^0)
+ end
 end
 function lpeg.frontstripper(str) 
-  return (P(str)+P(true))*Cs(anything^0)
+ return (P(str)+P(true))*Cs(anything^0)
 end
 function lpeg.endstripper(str) 
-  return Cs((1-P(str)*endofstring)^0)
+ return Cs((1-P(str)*endofstring)^0)
 end
 function lpeg.replacer(one,two,makefunction,isutf) 
-  local pattern
-  local u=isutf and utf8char or 1
-  if type(one)=="table" then
-    local no=#one
-    local p=P(false)
-    if no==0 then
-      for k,v in next,one do
-        p=p+P(k)/v
-      end
-      pattern=Cs((p+u)^0)
-    elseif no==1 then
-      local o=one[1]
-      one,two=P(o[1]),o[2]
-      pattern=Cs((one/two+u)^0)
-    else
-      for i=1,no do
-        local o=one[i]
-        p=p+P(o[1])/o[2]
-      end
-      pattern=Cs((p+u)^0)
-    end
+ local pattern
+ local u=isutf and utf8char or 1
+ if type(one)=="table" then
+  local no=#one
+  local p=P(false)
+  if no==0 then
+   for k,v in next,one do
+    p=p+P(k)/v
+   end
+   pattern=Cs((p+u)^0)
+  elseif no==1 then
+   local o=one[1]
+   one,two=P(o[1]),o[2]
+   pattern=Cs((one/two+u)^0)
   else
-    pattern=Cs((P(one)/(two or "")+u)^0)
+   for i=1,no do
+    local o=one[i]
+    p=p+P(o[1])/o[2]
+   end
+   pattern=Cs((p+u)^0)
   end
-  if makefunction then
-    return function(str)
-      return lpegmatch(pattern,str)
-    end
-  else
-    return pattern
+ else
+  pattern=Cs((P(one)/(two or "")+u)^0)
+ end
+ if makefunction then
+  return function(str)
+   return lpegmatch(pattern,str)
   end
+ else
+  return pattern
+ end
 end
 function lpeg.finder(lst,makefunction,isutf) 
-  local pattern
-  if type(lst)=="table" then
-    pattern=P(false)
-    if #lst==0 then
-      for k,v in next,lst do
-        pattern=pattern+P(k) 
-      end
-    else
-      for i=1,#lst do
-        pattern=pattern+P(lst[i])
-      end
-    end
+ local pattern
+ if type(lst)=="table" then
+  pattern=P(false)
+  if #lst==0 then
+   for k,v in next,lst do
+    pattern=pattern+P(k) 
+   end
   else
-    pattern=P(lst)
+   for i=1,#lst do
+    pattern=pattern+P(lst[i])
+   end
   end
-  if isutf then
-    pattern=((utf8char or 1)-pattern)^0*pattern
-  else
-    pattern=(1-pattern)^0*pattern
+ else
+  pattern=P(lst)
+ end
+ if isutf then
+  pattern=((utf8char or 1)-pattern)^0*pattern
+ else
+  pattern=(1-pattern)^0*pattern
+ end
+ if makefunction then
+  return function(str)
+   return lpegmatch(pattern,str)
   end
-  if makefunction then
-    return function(str)
-      return lpegmatch(pattern,str)
-    end
-  else
-    return pattern
-  end
+ else
+  return pattern
+ end
 end
 local splitters_f,splitters_s={},{}
 function lpeg.firstofsplit(separator) 
-  local splitter=splitters_f[separator]
-  if not splitter then
-    local pattern=P(separator)
-    splitter=C((1-pattern)^0)
-    splitters_f[separator]=splitter
-  end
-  return splitter
+ local splitter=splitters_f[separator]
+ if not splitter then
+  local pattern=P(separator)
+  splitter=C((1-pattern)^0)
+  splitters_f[separator]=splitter
+ end
+ return splitter
 end
 function lpeg.secondofsplit(separator) 
-  local splitter=splitters_s[separator]
-  if not splitter then
-    local pattern=P(separator)
-    splitter=(1-pattern)^0*pattern*C(anything^0)
-    splitters_s[separator]=splitter
-  end
-  return splitter
+ local splitter=splitters_s[separator]
+ if not splitter then
+  local pattern=P(separator)
+  splitter=(1-pattern)^0*pattern*C(anything^0)
+  splitters_s[separator]=splitter
+ end
+ return splitter
 end
 local splitters_s,splitters_p={},{}
 function lpeg.beforesuffix(separator) 
-  local splitter=splitters_s[separator]
-  if not splitter then
-    local pattern=P(separator)
-    splitter=C((1-pattern)^0)*pattern*endofstring
-    splitters_s[separator]=splitter
-  end
-  return splitter
+ local splitter=splitters_s[separator]
+ if not splitter then
+  local pattern=P(separator)
+  splitter=C((1-pattern)^0)*pattern*endofstring
+  splitters_s[separator]=splitter
+ end
+ return splitter
 end
 function lpeg.afterprefix(separator) 
-  local splitter=splitters_p[separator]
-  if not splitter then
-    local pattern=P(separator)
-    splitter=pattern*C(anything^0)
-    splitters_p[separator]=splitter
-  end
-  return splitter
+ local splitter=splitters_p[separator]
+ if not splitter then
+  local pattern=P(separator)
+  splitter=pattern*C(anything^0)
+  splitters_p[separator]=splitter
+ end
+ return splitter
 end
 function lpeg.balancer(left,right)
-  left,right=P(left),P(right)
-  return P { left*((1-left-right)+V(1))^0*right }
+ left,right=P(left),P(right)
+ return P { left*((1-left-right)+V(1))^0*right }
 end
 function lpeg.counter(pattern,action)
-  local n=0
-  local pattern=(P(pattern)/function() n=n+1 end+anything)^0
-  if action then
-    return function(str) n=0;lpegmatch(pattern,str);action(n) end
-  else
-    return function(str) n=0;lpegmatch(pattern,str);return n end
-  end
+ local n=0
+ local pattern=(P(pattern)/function() n=n+1 end+anything)^0
+ if action then
+  return function(str) n=0;lpegmatch(pattern,str);action(n) end
+ else
+  return function(str) n=0;lpegmatch(pattern,str);return n end
+ end
 end
-utf=utf or (unicode and unicode.utf8) or {}
-local utfcharacters=utf and utf.characters or string.utfcharacters
-local utfgmatch=utf and utf.gmatch
-local utfchar=utf and utf.char
-lpeg.UP=lpeg.P
-if utfcharacters then
-  function lpeg.US(str)
-    local p=P(false)
-    for uc in utfcharacters(str) do
-      p=p+P(uc)
-    end
-    return p
-  end
-elseif utfgmatch then
-  function lpeg.US(str)
-    local p=P(false)
-    for uc in utfgmatch(str,".") do
-      p=p+P(uc)
-    end
-    return p
-  end
-else
-  function lpeg.US(str)
-    local p=P(false)
-    local f=function(uc)
-      p=p+P(uc)
-    end
-    lpegmatch((utf8char/f)^0,str)
-    return p
-  end
-end
-local range=utf8byte*utf8byte+Cc(false) 
-function lpeg.UR(str,more)
-  local first,last
-  if type(str)=="number" then
-    first=str
-    last=more or first
-  else
-    first,last=lpegmatch(range,str)
-    if not last then
-      return P(str)
-    end
-  end
-  if first==last then
-    return P(str)
-  elseif utfchar and (last-first<8) then 
-    local p=P(false)
-    for i=first,last do
-      p=p+P(utfchar(i))
-    end
-    return p 
-  else
-    local f=function(b)
-      return b>=first and b<=last
-    end
-    return utf8byte/f 
-  end
-end
 function lpeg.is_lpeg(p)
-  return p and lpegtype(p)=="pattern"
+ return p and lpegtype(p)=="pattern"
 end
 function lpeg.oneof(list,...) 
-  if type(list)~="table" then
-    list={ list,... }
-  end
-  local p=P(list[1])
-  for l=2,#list do
-    p=p+P(list[l])
-  end
-  return p
+ if type(list)~="table" then
+  list={ list,... }
+ end
+ local p=P(list[1])
+ for l=2,#list do
+  p=p+P(list[l])
+ end
+ return p
 end
 local sort=table.sort
 local function copyindexed(old)
-  local new={}
-  for i=1,#old do
-    new[i]=old
-  end
-  return new
+ local new={}
+ for i=1,#old do
+  new[i]=old
+ end
+ return new
 end
 local function sortedkeys(tab)
-  local keys,s={},0
-  for key,_ in next,tab do
-    s=s+1
-    keys[s]=key
-  end
-  sort(keys)
-  return keys
+ local keys,s={},0
+ for key,_ in next,tab do
+  s=s+1
+  keys[s]=key
+ end
+ sort(keys)
+ return keys
 end
 function lpeg.append(list,pp,delayed,checked)
-  local p=pp
-  if #list>0 then
-    local keys=copyindexed(list)
-    sort(keys)
-    for i=#keys,1,-1 do
-      local k=keys[i]
-      if p then
-        p=P(k)+p
-      else
-        p=P(k)
-      end
-    end
-  elseif delayed then 
-    local keys=sortedkeys(list)
+ local p=pp
+ if #list>0 then
+  local keys=copyindexed(list)
+  sort(keys)
+  for i=#keys,1,-1 do
+   local k=keys[i]
+   if p then
+    p=P(k)+p
+   else
+    p=P(k)
+   end
+  end
+ elseif delayed then 
+  local keys=sortedkeys(list)
+  if p then
+   for i=1,#keys,1 do
+    local k=keys[i]
+    local v=list[k]
+    p=P(k)/list+p
+   end
+  else
+   for i=1,#keys do
+    local k=keys[i]
+    local v=list[k]
     if p then
-      for i=1,#keys,1 do
-        local k=keys[i]
-        local v=list[k]
-        p=P(k)/list+p
-      end
+     p=P(k)+p
     else
-      for i=1,#keys do
-        local k=keys[i]
-        local v=list[k]
-        if p then
-          p=P(k)+p
-        else
-          p=P(k)
-        end
-      end
-      if p then
-        p=p/list
-      end
+     p=P(k)
     end
-  elseif checked then
-    local keys=sortedkeys(list)
-    for i=1,#keys do
-      local k=keys[i]
-      local v=list[k]
-      if p then
-        if k==v then
-          p=P(k)+p
-        else
-          p=P(k)/v+p
-        end
-      else
-        if k==v then
-          p=P(k)
-        else
-          p=P(k)/v
-        end
-      end
+   end
+   if p then
+    p=p/list
+   end
+  end
+ elseif checked then
+  local keys=sortedkeys(list)
+  for i=1,#keys do
+   local k=keys[i]
+   local v=list[k]
+   if p then
+    if k==v then
+     p=P(k)+p
+    else
+     p=P(k)/v+p
     end
-  else
-    local keys=sortedkeys(list)
-    for i=1,#keys do
-      local k=keys[i]
-      local v=list[k]
-      if p then
-        p=P(k)/v+p
-      else
-        p=P(k)/v
-      end
+   else
+    if k==v then
+     p=P(k)
+    else
+     p=P(k)/v
     end
+   end
   end
-  return p
+ else
+  local keys=sortedkeys(list)
+  for i=1,#keys do
+   local k=keys[i]
+   local v=list[k]
+   if p then
+    p=P(k)/v+p
+   else
+    p=P(k)/v
+   end
+  end
+ end
+ return p
 end
 local p_false=P(false)
 local p_true=P(true)
@@ -1573,171 +1700,187 @@
 local lower=utf and utf.lower or string.lower
 local upper=utf and utf.upper or string.upper
 function lpeg.setutfcasers(l,u)
-  lower=l or lower
-  upper=u or upper
+ lower=l or lower
+ upper=u or upper
 end
 local function make1(t,rest)
-  local p=p_false
-  local keys=sortedkeys(t)
-  for i=1,#keys do
-    local k=keys[i]
-    if k~="" then
-      local v=t[k]
-      if v==true then
-        p=p+P(k)*p_true
-      elseif v==false then
-      else
-        p=p+P(k)*make1(v,v[""])
-      end
-    end
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+  local k=keys[i]
+  if k~="" then
+   local v=t[k]
+   if v==true then
+    p=p+P(k)*p_true
+   elseif v==false then
+   else
+    p=p+P(k)*make1(v,v[""])
+   end
   end
-  if rest then
-    p=p+p_true
-  end
-  return p
+ end
+ if rest then
+  p=p+p_true
+ end
+ return p
 end
 local function make2(t,rest) 
-  local p=p_false
-  local keys=sortedkeys(t)
-  for i=1,#keys do
-    local k=keys[i]
-    if k~="" then
-      local v=t[k]
-      if v==true then
-        p=p+(P(lower(k))+P(upper(k)))*p_true
-      elseif v==false then
-      else
-        p=p+(P(lower(k))+P(upper(k)))*make2(v,v[""])
-      end
-    end
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+  local k=keys[i]
+  if k~="" then
+   local v=t[k]
+   if v==true then
+    p=p+(P(lower(k))+P(upper(k)))*p_true
+   elseif v==false then
+   else
+    p=p+(P(lower(k))+P(upper(k)))*make2(v,v[""])
+   end
   end
-  if rest then
-    p=p+p_true
-  end
-  return p
+ end
+ if rest then
+  p=p+p_true
+ end
+ return p
 end
-function lpeg.utfchartabletopattern(list,insensitive) 
-  local tree={}
-  local n=#list
-  if n==0 then
-    for s in next,list do
-      local t=tree
-      local p,pk
-      for c in gmatch(s,".") do
-        if t==true then
-          t={ [c]=true,[""]=true }
-          p[pk]=t
-          p=t
-          t=false
-        elseif t==false then
-          t={ [c]=false }
-          p[pk]=t
-          p=t
-          t=false
-        else
-          local tc=t[c]
-          if not tc then
-            tc=false
-            t[c]=false
-          end
-          p=t
-          t=tc
-        end
-        pk=c
-      end
-      if t==false then
-        p[pk]=true
-      elseif t==true then
-      else
-        t[""]=true
-      end
+local function utfchartabletopattern(list,insensitive) 
+ local tree={}
+ local n=#list
+ if n==0 then
+  for s in next,list do
+   local t=tree
+   local p,pk
+   for c in gmatch(s,".") do
+    if t==true then
+     t={ [c]=true,[""]=true }
+     p[pk]=t
+     p=t
+     t=false
+    elseif t==false then
+     t={ [c]=false }
+     p[pk]=t
+     p=t
+     t=false
+    else
+     local tc=t[c]
+     if not tc then
+      tc=false
+      t[c]=false
+     end
+     p=t
+     t=tc
     end
-  else
-    for i=1,n do
-      local s=list[i]
-      local t=tree
-      local p,pk
-      for c in gmatch(s,".") do
-        if t==true then
-          t={ [c]=true,[""]=true }
-          p[pk]=t
-          p=t
-          t=false
-        elseif t==false then
-          t={ [c]=false }
-          p[pk]=t
-          p=t
-          t=false
-        else
-          local tc=t[c]
-          if not tc then
-            tc=false
-            t[c]=false
-          end
-          p=t
-          t=tc
-        end
-        pk=c
-      end
-      if t==false then
-        p[pk]=true
-      elseif t==true then
-      else
-        t[""]=true
-      end
+    pk=c
+   end
+   if t==false then
+    p[pk]=true
+   elseif t==true then
+   else
+    t[""]=true
+   end
+  end
+ else
+  for i=1,n do
+   local s=list[i]
+   local t=tree
+   local p,pk
+   for c in gmatch(s,".") do
+    if t==true then
+     t={ [c]=true,[""]=true }
+     p[pk]=t
+     p=t
+     t=false
+    elseif t==false then
+     t={ [c]=false }
+     p[pk]=t
+     p=t
+     t=false
+    else
+     local tc=t[c]
+     if not tc then
+      tc=false
+      t[c]=false
+     end
+     p=t
+     t=tc
     end
+    pk=c
+   end
+   if t==false then
+    p[pk]=true
+   elseif t==true then
+   else
+    t[""]=true
+   end
   end
-  return (insensitive and make2 or make1)(tree)
+ end
+ return (insensitive and make2 or make1)(tree)
 end
+lpeg.utfchartabletopattern=utfchartabletopattern
+function lpeg.utfreplacer(list,insensitive)
+ local pattern=Cs((utfchartabletopattern(list,insensitive)/list+utf8character)^0)
+ return function(str)
+  return lpegmatch(pattern,str) or str
+ end
+end
 patterns.containseol=lpeg.finder(eol)
 local function nextstep(n,step,result)
-  local m=n%step   
-  local d=floor(n/step) 
-  if d>0 then
-    local v=V(tostring(step))
-    local s=result.start
-    for i=1,d do
-      if s then
-        s=v*s
-      else
-        s=v
-      end
-    end
-    result.start=s
+ local m=n%step   
+ local d=floor(n/step) 
+ if d>0 then
+  local v=V(tostring(step))
+  local s=result.start
+  for i=1,d do
+   if s then
+    s=v*s
+   else
+    s=v
+   end
   end
-  if step>1 and result.start then
-    local v=V(tostring(step/2))
-    result[tostring(step)]=v*v
-  end
-  if step>0 then
-    return nextstep(m,step/2,result)
-  else
-    return result
-  end
+  result.start=s
+ end
+ if step>1 and result.start then
+  local v=V(tostring(step/2))
+  result[tostring(step)]=v*v
+ end
+ if step>0 then
+  return nextstep(m,step/2,result)
+ else
+  return result
+ end
 end
 function lpeg.times(pattern,n)
-  return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
+ return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
 end
-local trailingzeros=zero^0*-digit 
-local case_1=period*trailingzeros/""
-local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
-local number=digits*(case_1+case_2)
-local stripper=Cs((number+1)^0)
-lpeg.patterns.stripzeros=stripper
+do
+ local trailingzeros=zero^0*-digit 
+ local stripper=Cs((
+  digits*(
+   period*trailingzeros/""+period*(digit-trailingzeros)^1*(trailingzeros/"")
+  )+1
+ )^0)
+ lpeg.patterns.stripzeros=stripper 
+ local nonzero=digit-zero
+ local trailingzeros=zero^1*endofstring
+ local stripper=Cs((1-period)^0*(
+  period*trailingzeros/""+period*(nonzero^1+(trailingzeros/"")+zero^1)^0+endofstring
+ ))
+ lpeg.patterns.stripzero=stripper
+end
 local byte_to_HEX={}
 local byte_to_hex={}
 local byte_to_dec={} 
 local hex_to_byte={}
 for i=0,255 do
-  local H=format("%02X",i)
-  local h=format("%02x",i)
-  local d=format("%03i",i)
-  local c=char(i)
-  byte_to_HEX[c]=H
-  byte_to_hex[c]=h
-  byte_to_dec[c]=d
-  hex_to_byte[h]=c
-  hex_to_byte[H]=c
+ local H=format("%02X",i)
+ local h=format("%02x",i)
+ local d=format("%03i",i)
+ local c=char(i)
+ byte_to_HEX[c]=H
+ byte_to_hex[c]=h
+ byte_to_dec[c]=d
+ hex_to_byte[h]=c
+ hex_to_byte[H]=c
 end
 local hextobyte=P(2)/hex_to_byte
 local bytetoHEX=P(1)/byte_to_HEX
@@ -1756,33 +1899,48 @@
 patterns.bytestohex=bytestohex
 patterns.bytestodec=bytestodec
 function string.toHEX(s)
-  if not s or s=="" then
-    return s
-  else
-    return lpegmatch(bytestoHEX,s)
-  end
+ if not s or s=="" then
+  return s
+ else
+  return lpegmatch(bytestoHEX,s)
+ end
 end
 function string.tohex(s)
-  if not s or s=="" then
-    return s
-  else
-    return lpegmatch(bytestohex,s)
-  end
+ if not s or s=="" then
+  return s
+ else
+  return lpegmatch(bytestohex,s)
+ end
 end
 function string.todec(s)
-  if not s or s=="" then
-    return s
-  else
-    return lpegmatch(bytestodec,s)
-  end
+ if not s or s=="" then
+  return s
+ else
+  return lpegmatch(bytestodec,s)
+ end
 end
 function string.tobytes(s)
-  if not s or s=="" then
-    return s
-  else
-    return lpegmatch(hextobytes,s)
-  end
+ if not s or s=="" then
+  return s
+ else
+  return lpegmatch(hextobytes,s)
+ end
 end
+local patterns={} 
+local function containsws(what)
+ local p=patterns[what]
+ if not p then
+  local p1=P(what)*(whitespace+endofstring)*Cc(true)
+  local p2=whitespace*P(p1)
+  p=P(p1)+P(1-p2)^0*p2+Cc(false)
+  patterns[what]=p
+ end
+ return p
+end
+lpeg.containsws=containsws
+function string.containsws(str,what)
+ return lpegmatch(patterns[what] or containsws(what),str)
+end
 
 
 end -- of closure
@@ -1791,14 +1949,14 @@
 
 package.loaded["l-function"] = package.loaded["l-function"] or true
 
--- original size: 361, stripped down to: 322
+-- original size: 361, stripped down to: 317
 
 if not modules then modules={} end modules ['l-functions']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 functions=functions or {}
 function functions.dummy() end
@@ -1810,14 +1968,14 @@
 
 package.loaded["l-string"] = package.loaded["l-string"] or true
 
--- original size: 6461, stripped down to: 3341
+-- original size: 6461, stripped down to: 3255
 
 if not modules then modules={} end modules ['l-string']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 string=string
 local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
@@ -1825,25 +1983,25 @@
 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
 function string.unquoted(str)
-  return lpegmatch(unquoted,str) or str
+ return lpegmatch(unquoted,str) or str
 end
 function string.quoted(str)
-  return format("%q",str) 
+ return format("%q",str) 
 end
 function string.count(str,pattern) 
-  local n=0
-  for _ in gmatch(str,pattern) do 
-    n=n+1
-  end
-  return n
+ local n=0
+ for _ in gmatch(str,pattern) do 
+  n=n+1
+ end
+ return n
 end
 function string.limit(str,n,sentinel) 
-  if #str>n then
-    sentinel=sentinel or "..."
-    return sub(str,1,(n-#sentinel))..sentinel
-  else
-    return str
-  end
+ if #str>n then
+  sentinel=sentinel or "..."
+  return sub(str,1,(n-#sentinel))..sentinel
+ else
+  return str
+ end
 end
 local stripper=patterns.stripper
 local fullstripper=patterns.fullstripper
@@ -1851,81 +2009,81 @@
 local nospacer=patterns.nospacer
 local longtostring=patterns.longtostring
 function string.strip(str)
-  return str and lpegmatch(stripper,str) or ""
+ return str and lpegmatch(stripper,str) or ""
 end
 function string.fullstrip(str)
-  return str and lpegmatch(fullstripper,str) or ""
+ return str and lpegmatch(fullstripper,str) or ""
 end
 function string.collapsespaces(str)
-  return str and lpegmatch(collapser,str) or ""
+ return str and lpegmatch(collapser,str) or ""
 end
 function string.nospaces(str)
-  return str and lpegmatch(nospacer,str) or ""
+ return str and lpegmatch(nospacer,str) or ""
 end
 function string.longtostring(str)
-  return str and lpegmatch(longtostring,str) or ""
+ return str and lpegmatch(longtostring,str) or ""
 end
 local pattern=P(" ")^0*P(-1)
 function string.is_empty(str)
-  if not str or str=="" then
-    return true
-  else
-    return lpegmatch(pattern,str) and true or false
-  end
+ if not str or str=="" then
+  return true
+ else
+  return lpegmatch(pattern,str) and true or false
+ end
 end
 local anything=patterns.anything
 local allescapes=Cc("%")*S(".-+%?()[]*") 
-local someescapes=Cc("%")*S(".-+%()[]")  
-local matchescapes=Cc(".")*S("*?")     
+local someescapes=Cc("%")*S(".-+%()[]")   
+local matchescapes=Cc(".")*S("*?")   
 local pattern_a=Cs ((allescapes+anything )^0 )
 local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
 local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
 function string.escapedpattern(str,simple)
-  return lpegmatch(simple and pattern_b or pattern_a,str)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
 end
 function string.topattern(str,lowercase,strict)
-  if str=="" or type(str)~="string" then
-    return ".*"
-  elseif strict then
-    str=lpegmatch(pattern_c,str)
-  else
-    str=lpegmatch(pattern_b,str)
-  end
-  if lowercase then
-    return lower(str)
-  else
-    return str
-  end
+ if str=="" or type(str)~="string" then
+  return ".*"
+ elseif strict then
+  str=lpegmatch(pattern_c,str)
+ else
+  str=lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+  return lower(str)
+ else
+  return str
+ end
 end
 function string.valid(str,default)
-  return (type(str)=="string" and str~="" and str) or default or nil
+ return (type(str)=="string" and str~="" and str) or default or nil
 end
 string.itself=function(s) return s end
 local pattern_c=Ct(C(1)^0) 
 local pattern_b=Ct((C(1)/byte)^0)
 function string.totable(str,bytes)
-  return lpegmatch(bytes and pattern_b or pattern_c,str)
+ return lpegmatch(bytes and pattern_b or pattern_c,str)
 end
 local replacer=lpeg.replacer("@","%%") 
 function string.tformat(fmt,...)
-  return format(lpegmatch(replacer,fmt),...)
+ return format(lpegmatch(replacer,fmt),...)
 end
 string.quote=string.quoted
 string.unquote=string.unquoted
 if not string.bytetable then 
-  local limit=5000 
-  function string.bytetable(str) 
-    local n=#str
-    if n>limit then
-      local t={ byte(str,1,limit) }
-      for i=limit+1,n do
-        t[i]=byte(str,i)
-      end
-      return t
-    else
-      return { byte(str,1,n) }
-    end
+ local limit=5000 
+ function string.bytetable(str) 
+  local n=#str
+  if n>limit then
+   local t={ byte(str,1,limit) }
+   for i=limit+1,n do
+    t[i]=byte(str,i)
+   end
+   return t
+  else
+   return { byte(str,1,n) }
   end
+ end
 end
 
 
@@ -1935,166 +2093,172 @@
 
 package.loaded["l-table"] = package.loaded["l-table"] or true
 
--- original size: 40197, stripped down to: 23561
+-- original size: 41298, stripped down to: 21498
 
 if not modules then modules={} end modules ['l-table']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 type,next,tostring,tonumber,select=type,next,tostring,tonumber,select
 local table,string=table,string
-local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+local concat,sort=table.concat,table.sort
 local format,lower,dump=string.format,string.lower,string.dump
 local getmetatable,setmetatable=getmetatable,setmetatable
-local getinfo=debug.getinfo
 local lpegmatch,patterns=lpeg.match,lpeg.patterns
 local floor=math.floor
 local stripper=patterns.stripper
 function table.getn(t)
-  return t and #t 
+ return t and #t 
 end
 function table.strip(tab)
-  local lst,l={},0
-  for i=1,#tab do
-    local s=lpegmatch(stripper,tab[i]) or ""
-    if s=="" then
-    else
-      l=l+1
-      lst[l]=s
-    end
+ local lst={}
+ local l=0
+ for i=1,#tab do
+  local s=lpegmatch(stripper,tab[i]) or ""
+  if s=="" then
+  else
+   l=l+1
+   lst[l]=s
   end
-  return lst
+ end
+ return lst
 end
 function table.keys(t)
-  if t then
-    local keys,k={},0
-    for key in next,t do
-      k=k+1
-      keys[k]=key
-    end
-    return keys
-  else
-    return {}
+ if t then
+  local keys={}
+  local k=0
+  for key in next,t do
+   k=k+1
+   keys[k]=key
   end
+  return keys
+ else
+  return {}
+ end
 end
 local function compare(a,b)
-  local ta=type(a) 
-  if ta=="number" then
-    local tb=type(b) 
-    if ta==tb then
-      return a<b
-    elseif tb=="string" then
-      return tostring(a)<b
-    end
-  elseif ta=="string" then
-    local tb=type(b) 
-    if ta==tb then
-      return a<b
-    else
-      return a<tostring(b)
-    end
+ local ta=type(a) 
+ if ta=="number" then
+  local tb=type(b) 
+  if ta==tb then
+   return a<b
+  elseif tb=="string" then
+   return tostring(a)<b
   end
-  return tostring(a)<tostring(b) 
+ elseif ta=="string" then
+  local tb=type(b) 
+  if ta==tb then
+   return a<b
+  else
+   return a<tostring(b)
+  end
+ end
+ return tostring(a)<tostring(b) 
 end
 local function sortedkeys(tab)
-  if tab then
-    local srt,category,s={},0,0 
-    for key in next,tab do
-      s=s+1
-      srt[s]=key
-      if category==3 then
-      elseif category==1 then
-        if type(key)~="string" then
-          category=3
-        end
-      elseif category==2 then
-        if type(key)~="number" then
-          category=3
-        end
-      else
-        local tkey=type(key)
-        if tkey=="string" then
-          category=1
-        elseif tkey=="number" then
-          category=2
-        else
-          category=3
-        end
-      end
+ if tab then
+  local srt={}
+  local category=0 
+  local s=0
+  for key in next,tab do
+   s=s+1
+   srt[s]=key
+   if category==3 then
+   elseif category==1 then
+    if type(key)~="string" then
+     category=3
     end
-    if s<2 then
-    elseif category==3 then
-      sort(srt,compare)
+   elseif category==2 then
+    if type(key)~="number" then
+     category=3
+    end
+   else
+    local tkey=type(key)
+    if tkey=="string" then
+     category=1
+    elseif tkey=="number" then
+     category=2
     else
-      sort(srt)
+     category=3
     end
-    return srt
+   end
+  end
+  if s<2 then
+  elseif category==3 then
+   sort(srt,compare)
   else
-    return {}
+   sort(srt)
   end
+  return srt
+ else
+  return {}
+ end
 end
 local function sortedhashonly(tab)
-  if tab then
-    local srt,s={},0
-    for key in next,tab do
-      if type(key)=="string" then
-        s=s+1
-        srt[s]=key
-      end
-    end
-    if s>1 then
-      sort(srt)
-    end
-    return srt
-  else
-    return {}
+ if tab then
+  local srt={}
+  local s=0
+  for key in next,tab do
+   if type(key)=="string" then
+    s=s+1
+    srt[s]=key
+   end
   end
+  if s>1 then
+   sort(srt)
+  end
+  return srt
+ else
+  return {}
+ end
 end
 local function sortedindexonly(tab)
-  if tab then
-    local srt,s={},0
-    for key in next,tab do
-      if type(key)=="number" then
-        s=s+1
-        srt[s]=key
-      end
-    end
-    if s>1 then
-      sort(srt)
-    end
-    return srt
-  else
-    return {}
+ if tab then
+  local srt={}
+  local s=0
+  for key in next,tab do
+   if type(key)=="number" then
+    s=s+1
+    srt[s]=key
+   end
   end
+  if s>1 then
+   sort(srt)
+  end
+  return srt
+ else
+  return {}
+ end
 end
 local function sortedhashkeys(tab,cmp) 
-  if tab then
-    local srt,s={},0
-    for key in next,tab do
-      if key then
-        s=s+1
-        srt[s]=key
-      end
-    end
-    if s>1 then
-      sort(srt,cmp)
-    end
-    return srt
-  else
-    return {}
+ if tab then
+  local srt={}
+  local s=0
+  for key in next,tab do
+   if key then
+    s=s+1
+    srt[s]=key
+   end
   end
+  if s>1 then
+   sort(srt,cmp)
+  end
+  return srt
+ else
+  return {}
+ end
 end
 function table.allkeys(t)
-  local keys={}
-  for k,v in next,t do
-    for k in next,v do
-      keys[k]=true
-    end
+ local keys={}
+ for k,v in next,t do
+  for k in next,v do
+   keys[k]=true
   end
-  return sortedkeys(keys)
+ end
+ return sortedkeys(keys)
 end
 table.sortedkeys=sortedkeys
 table.sortedhashonly=sortedhashonly
@@ -2102,907 +2266,944 @@
 table.sortedhashkeys=sortedhashkeys
 local function nothing() end
 local function sortedhash(t,cmp)
-  if t then
-    local s
-    if cmp then
-      s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
-    else
-      s=sortedkeys(t) 
+ if t then
+  local s
+  if cmp then
+   s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+  else
+   s=sortedkeys(t) 
+  end
+  local m=#s
+  if m==1 then
+   return next,t
+  elseif m>0 then
+   local n=0
+   return function()
+    if n<m then
+     n=n+1
+     local k=s[n]
+     return k,t[k]
     end
-    local m=#s
-    if m==1 then
-      return next,t
-    elseif m>0 then
-      local n=0
-      return function()
-        if n<m then
-          n=n+1
-          local k=s[n]
-          return k,t[k]
-        end
-      end
-    end
+   end
   end
-  return nothing
+ end
+ return nothing
 end
 table.sortedhash=sortedhash
 table.sortedpairs=sortedhash 
 function table.append(t,list)
-  local n=#t
-  for i=1,#list do
-    n=n+1
-    t[n]=list[i]
-  end
-  return t
+ local n=#t
+ for i=1,#list do
+  n=n+1
+  t[n]=list[i]
+ end
+ return t
 end
 function table.prepend(t,list)
-  local nl=#list
-  local nt=nl+#t
-  for i=#t,1,-1 do
-    t[nt]=t[i]
-    nt=nt-1
-  end
-  for i=1,#list do
-    t[i]=list[i]
-  end
-  return t
+ local nl=#list
+ local nt=nl+#t
+ for i=#t,1,-1 do
+  t[nt]=t[i]
+  nt=nt-1
+ end
+ for i=1,#list do
+  t[i]=list[i]
+ end
+ return t
 end
 function table.merge(t,...) 
-  t=t or {}
-  for i=1,select("#",...) do
-    for k,v in next,(select(i,...)) do
-      t[k]=v
-    end
+ if not t then
+  t={}
+ end
+ for i=1,select("#",...) do
+  for k,v in next,(select(i,...)) do
+   t[k]=v
   end
-  return t
+ end
+ return t
 end
 function table.merged(...)
-  local t={}
-  for i=1,select("#",...) do
-    for k,v in next,(select(i,...)) do
-      t[k]=v
-    end
+ local t={}
+ for i=1,select("#",...) do
+  for k,v in next,(select(i,...)) do
+   t[k]=v
   end
-  return t
+ end
+ return t
 end
 function table.imerge(t,...)
-  local nt=#t
-  for i=1,select("#",...) do
-    local nst=select(i,...)
-    for j=1,#nst do
-      nt=nt+1
-      t[nt]=nst[j]
-    end
+ local nt=#t
+ for i=1,select("#",...) do
+  local nst=select(i,...)
+  for j=1,#nst do
+   nt=nt+1
+   t[nt]=nst[j]
   end
-  return t
+ end
+ return t
 end
 function table.imerged(...)
-  local tmp,ntmp={},0
-  for i=1,select("#",...) do
-    local nst=select(i,...)
-    for j=1,#nst do
-      ntmp=ntmp+1
-      tmp[ntmp]=nst[j]
-    end
+ local tmp={}
+ local ntmp=0
+ for i=1,select("#",...) do
+  local nst=select(i,...)
+  for j=1,#nst do
+   ntmp=ntmp+1
+   tmp[ntmp]=nst[j]
   end
-  return tmp
+ end
+ return tmp
 end
 local function fastcopy(old,metatabletoo) 
-  if old then
-    local new={}
-    for k,v in next,old do
-      if type(v)=="table" then
-        new[k]=fastcopy(v,metatabletoo) 
-      else
-        new[k]=v
-      end
-    end
-    if metatabletoo then
-      local mt=getmetatable(old)
-      if mt then
-        setmetatable(new,mt)
-      end
-    end
-    return new
-  else
-    return {}
+ if old then
+  local new={}
+  for k,v in next,old do
+   if type(v)=="table" then
+    new[k]=fastcopy(v,metatabletoo) 
+   else
+    new[k]=v
+   end
   end
+  if metatabletoo then
+   local mt=getmetatable(old)
+   if mt then
+    setmetatable(new,mt)
+   end
+  end
+  return new
+ else
+  return {}
+ end
 end
 local function copy(t,tables) 
-  tables=tables or {}
-  local tcopy={}
-  if not tables[t] then
-    tables[t]=tcopy
+ if not tables then
+  tables={}
+ end
+ local tcopy={}
+ if not tables[t] then
+  tables[t]=tcopy
+ end
+ for i,v in next,t do 
+  if type(i)=="table" then
+   if tables[i] then
+    i=tables[i]
+   else
+    i=copy(i,tables)
+   end
   end
-  for i,v in next,t do 
-    if type(i)=="table" then
-      if tables[i] then
-        i=tables[i]
-      else
-        i=copy(i,tables)
-      end
-    end
-    if type(v)~="table" then
-      tcopy[i]=v
-    elseif tables[v] then
-      tcopy[i]=tables[v]
-    else
-      tcopy[i]=copy(v,tables)
-    end
+  if type(v)~="table" then
+   tcopy[i]=v
+  elseif tables[v] then
+   tcopy[i]=tables[v]
+  else
+   tcopy[i]=copy(v,tables)
   end
-  local mt=getmetatable(t)
-  if mt then
-    setmetatable(tcopy,mt)
-  end
-  return tcopy
+ end
+ local mt=getmetatable(t)
+ if mt then
+  setmetatable(tcopy,mt)
+ end
+ return tcopy
 end
 table.fastcopy=fastcopy
 table.copy=copy
 function table.derive(parent) 
-  local child={}
-  if parent then
-    setmetatable(child,{ __index=parent })
-  end
-  return child
+ local child={}
+ if parent then
+  setmetatable(child,{ __index=parent })
+ end
+ return child
 end
 function table.tohash(t,value)
-  local h={}
-  if t then
-    if value==nil then value=true end
-    for _,v in next,t do
-      h[v]=value
-    end
+ local h={}
+ if t then
+  if value==nil then value=true end
+  for _,v in next,t do
+   h[v]=value
   end
-  return h
+ end
+ return h
 end
 function table.fromhash(t)
-  local hsh,h={},0
-  for k,v in next,t do
-    if v then
-      h=h+1
-      hsh[h]=k
-    end
+ local hsh={}
+ local h=0
+ for k,v in next,t do
+  if v then
+   h=h+1
+   hsh[h]=k
   end
-  return hsh
+ end
+ return hsh
 end
 local noquotes,hexify,handle,compact,inline,functions,metacheck
 local reserved=table.tohash { 
-  'and','break','do','else','elseif','end','false','for','function','if',
-  'in','local','nil','not','or','repeat','return','then','true','until','while',
-  'NaN','goto',
+ 'and','break','do','else','elseif','end','false','for','function','if',
+ 'in','local','nil','not','or','repeat','return','then','true','until','while',
+ 'NaN','goto',
 }
 local function is_simple_table(t,hexify) 
-  local nt=#t
-  if nt>0 then
-    local n=0
-    for _,v in next,t do
-      n=n+1
-      if type(v)=="table" then
-        return nil
-      end
+ local nt=#t
+ if nt>0 then
+  local n=0
+  for _,v in next,t do
+   n=n+1
+   if type(v)=="table" then
+    return nil
+   end
+  end
+  local haszero=rawget(t,0) 
+  if n==nt then
+   local tt={}
+   for i=1,nt do
+    local v=t[i]
+    local tv=type(v)
+    if tv=="number" then
+     if hexify then
+      tt[i]=format("0x%X",v)
+     else
+      tt[i]=v 
+     end
+    elseif tv=="string" then
+     tt[i]=format("%q",v) 
+    elseif tv=="boolean" then
+     tt[i]=v and "true" or "false"
+    else
+     return nil
     end
-    local haszero=rawget(t,0) 
-    if n==nt then
-      local tt={}
-      for i=1,nt do
-        local v=t[i]
-        local tv=type(v)
-        if tv=="number" then
-          if hexify then
-            tt[i]=format("0x%X",v)
-          else
-            tt[i]=v 
-          end
-        elseif tv=="string" then
-          tt[i]=format("%q",v) 
-        elseif tv=="boolean" then
-          tt[i]=v and "true" or "false"
-        else
-          return nil
-        end
-      end
-      return tt
-    elseif haszero and (n==nt+1) then
-      local tt={}
-      for i=0,nt do
-        local v=t[i]
-        local tv=type(v)
-        if tv=="number" then
-          if hexify then
-            tt[i+1]=format("0x%X",v)
-          else
-            tt[i+1]=v 
-          end
-        elseif tv=="string" then
-          tt[i+1]=format("%q",v) 
-        elseif tv=="boolean" then
-          tt[i+1]=v and "true" or "false"
-        else
-          return nil
-        end
-      end
-      tt[1]="[0] = "..tt[1]
-      return tt
+   end
+   return tt
+  elseif haszero and (n==nt+1) then
+   local tt={}
+   for i=0,nt do
+    local v=t[i]
+    local tv=type(v)
+    if tv=="number" then
+     if hexify then
+      tt[i+1]=format("0x%X",v)
+     else
+      tt[i+1]=v 
+     end
+    elseif tv=="string" then
+     tt[i+1]=format("%q",v) 
+    elseif tv=="boolean" then
+     tt[i+1]=v and "true" or "false"
+    else
+     return nil
     end
+   end
+   tt[1]="[0] = "..tt[1]
+   return tt
   end
-  return nil
+ end
+ return nil
 end
 table.is_simple_table=is_simple_table
 local propername=patterns.propername 
 local function dummy() end
 local function do_serialize(root,name,depth,level,indexed)
-  if level>0 then
-    depth=depth.." "
-    if indexed then
-      handle(format("%s{",depth))
+ if level>0 then
+  depth=depth.." "
+  if indexed then
+   handle(format("%s{",depth))
+  else
+   local tn=type(name)
+   if tn=="number" then
+    if hexify then
+     handle(format("%s[0x%X]={",depth,name))
     else
-      local tn=type(name)
-      if tn=="number" then
-        if hexify then
-          handle(format("%s[0x%X]={",depth,name))
-        else
-          handle(format("%s[%s]={",depth,name))
-        end
-      elseif tn=="string" then
-        if noquotes and not reserved[name] and lpegmatch(propername,name) then
-          handle(format("%s%s={",depth,name))
-        else
-          handle(format("%s[%q]={",depth,name))
-        end
-      elseif tn=="boolean" then
-        handle(format("%s[%s]={",depth,name and "true" or "false"))
-      else
-        handle(format("%s{",depth))
-      end
+     handle(format("%s[%s]={",depth,name))
     end
+   elseif tn=="string" then
+    if noquotes and not reserved[name] and lpegmatch(propername,name) then
+     handle(format("%s%s={",depth,name))
+    else
+     handle(format("%s[%q]={",depth,name))
+    end
+   elseif tn=="boolean" then
+    handle(format("%s[%s]={",depth,name and "true" or "false"))
+   else
+    handle(format("%s{",depth))
+   end
   end
-  if root and next(root)~=nil then
-    local first,last=nil,0
-    if compact then
-      last=#root
-      for k=1,last do
-        if rawget(root,k)==nil then
-          last=k-1
-          break
-        end
-      end
-      if last>0 then
-        first=1
-      end
+ end
+ if root and next(root)~=nil then
+  local first=nil
+  local last=0
+  if compact then
+   last=#root
+   for k=1,last do
+    if rawget(root,k)==nil then
+     last=k-1
+     break
     end
-    local sk=sortedkeys(root)
-    for i=1,#sk do
-      local k=sk[i]
-      local v=root[k]
-      local tv=type(v)
-      local tk=type(k)
-      if compact and first and tk=="number" and k>=first and k<=last then
-        if tv=="number" then
-          if hexify then
-            handle(format("%s 0x%X,",depth,v))
-          else
-            handle(format("%s %s,",depth,v)) 
-          end
-        elseif tv=="string" then
-          handle(format("%s %q,",depth,v))
-        elseif tv=="table" then
-          if next(v)==nil then
-            handle(format("%s {},",depth))
-          elseif inline then 
-            local st=is_simple_table(v,hexify)
-            if st then
-              handle(format("%s { %s },",depth,concat(st,", ")))
-            else
-              do_serialize(v,k,depth,level+1,true)
-            end
-          else
-            do_serialize(v,k,depth,level+1,true)
-          end
-        elseif tv=="boolean" then
-          handle(format("%s %s,",depth,v and "true" or "false"))
-        elseif tv=="function" then
-          if functions then
-            handle(format('%s load(%q),',depth,dump(v))) 
-          else
-            handle(format('%s "function",',depth))
-          end
-        else
-          handle(format("%s %q,",depth,tostring(v)))
-        end
-      elseif k=="__p__" then 
-        if false then
-          handle(format("%s __p__=nil,",depth))
-        end
-      elseif tv=="number" then
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%X]=0x%X,",depth,k,v))
-          else
-            handle(format("%s [%s]=%s,",depth,k,v)) 
-          end
-        elseif tk=="boolean" then
-          if hexify then
-            handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
-          else
-            handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) 
-          end
-        elseif tk~="string" then
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          if hexify then
-            handle(format("%s %s=0x%X,",depth,k,v))
-          else
-            handle(format("%s %s=%s,",depth,k,v)) 
-          end
-        else
-          if hexify then
-            handle(format("%s [%q]=0x%X,",depth,k,v))
-          else
-            handle(format("%s [%q]=%s,",depth,k,v)) 
-          end
-        end
-      elseif tv=="string" then
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%X]=%q,",depth,k,v))
-          else
-            handle(format("%s [%s]=%q,",depth,k,v))
-          end
-        elseif tk=="boolean" then
-          handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
-        elseif tk~="string" then
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          handle(format("%s %s=%q,",depth,k,v))
-        else
-          handle(format("%s [%q]=%q,",depth,k,v))
-        end
-      elseif tv=="table" then
-        if next(v)==nil then
-          if tk=="number" then
-            if hexify then
-              handle(format("%s [0x%X]={},",depth,k))
-            else
-              handle(format("%s [%s]={},",depth,k))
-            end
-          elseif tk=="boolean" then
-            handle(format("%s [%s]={},",depth,k and "true" or "false"))
-          elseif tk~="string" then
-          elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-            handle(format("%s %s={},",depth,k))
-          else
-            handle(format("%s [%q]={},",depth,k))
-          end
-        elseif inline then
-          local st=is_simple_table(v,hexify)
-          if st then
-            if tk=="number" then
-              if hexify then
-                handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
-              else
-                handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
-              end
-            elseif tk=="boolean" then
-              handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
-            elseif tk~="string" then
-            elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-              handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
-            else
-              handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
-            end
-          else
-            do_serialize(v,k,depth,level+1)
-          end
-        else
-          do_serialize(v,k,depth,level+1)
-        end
-      elseif tv=="boolean" then
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
-          else
-            handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
-          end
-        elseif tk=="boolean" then
-          handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
-        elseif tk~="string" then
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
-        else
-          handle(format("%s [%q]=%s,",depth,k,v and "true" or "false"))
-        end
-      elseif tv=="function" then
-        if functions then
-          local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
-          if tk=="number" then
-            if hexify then
-              handle(format("%s [0x%X]=load(%q),",depth,k,f))
-            else
-              handle(format("%s [%s]=load(%q),",depth,k,f))
-            end
-          elseif tk=="boolean" then
-            handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
-          elseif tk~="string" then
-          elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-            handle(format("%s %s=load(%q),",depth,k,f))
-          else
-            handle(format("%s [%q]=load(%q),",depth,k,f))
-          end
-        end
+   end
+   if last>0 then
+    first=1
+   end
+  end
+  local sk=sortedkeys(root)
+  for i=1,#sk do
+   local k=sk[i]
+   local v=root[k]
+   local tv=type(v)
+   local tk=type(k)
+   if compact and first and tk=="number" and k>=first and k<=last then
+    if tv=="number" then
+     if hexify then
+      handle(format("%s 0x%X,",depth,v))
+     else
+      handle(format("%s %s,",depth,v)) 
+     end
+    elseif tv=="string" then
+     handle(format("%s %q,",depth,v))
+    elseif tv=="table" then
+     if next(v)==nil then
+      handle(format("%s {},",depth))
+     elseif inline then 
+      local st=is_simple_table(v,hexify)
+      if st then
+       handle(format("%s { %s },",depth,concat(st,", ")))
       else
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
-          else
-            handle(format("%s [%s]=%q,",depth,k,tostring(v)))
-          end
-        elseif tk=="boolean" then
-          handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
-        elseif tk~="string" then
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          handle(format("%s %s=%q,",depth,k,tostring(v)))
-        else
-          handle(format("%s [%q]=%q,",depth,k,tostring(v)))
-        end
+       do_serialize(v,k,depth,level+1,true)
       end
+     else
+      do_serialize(v,k,depth,level+1,true)
+     end
+    elseif tv=="boolean" then
+     handle(format("%s %s,",depth,v and "true" or "false"))
+    elseif tv=="function" then
+     if functions then
+      handle(format('%s load(%q),',depth,dump(v))) 
+     else
+      handle(format('%s "function",',depth))
+     end
+    else
+     handle(format("%s %q,",depth,tostring(v)))
     end
-  end
-  if level>0 then
-    handle(format("%s},",depth))
-  end
-end
-local function serialize(_handle,root,name,specification) 
-  local tname=type(name)
-  if type(specification)=="table" then
-    noquotes=specification.noquotes
-    hexify=specification.hexify
-    handle=_handle or specification.handle or print
-    functions=specification.functions
-    compact=specification.compact
-    inline=specification.inline and compact
-    metacheck=specification.metacheck
-    if functions==nil then
-      functions=true
+   elseif k=="__p__" then 
+    if false then
+     handle(format("%s __p__=nil,",depth))
     end
-    if compact==nil then
-      compact=true
+   elseif tv=="number" then
+    if tk=="number" then
+     if hexify then
+      handle(format("%s [0x%X]=0x%X,",depth,k,v))
+     else
+      handle(format("%s [%s]=%s,",depth,k,v)) 
+     end
+    elseif tk=="boolean" then
+     if hexify then
+      handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
+     else
+      handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) 
+     end
+    elseif tk~="string" then
+    elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+     if hexify then
+      handle(format("%s %s=0x%X,",depth,k,v))
+     else
+      handle(format("%s %s=%s,",depth,k,v)) 
+     end
+    else
+     if hexify then
+      handle(format("%s [%q]=0x%X,",depth,k,v))
+     else
+      handle(format("%s [%q]=%s,",depth,k,v)) 
+     end
     end
-    if inline==nil then
-      inline=compact
+   elseif tv=="string" then
+    if tk=="number" then
+     if hexify then
+      handle(format("%s [0x%X]=%q,",depth,k,v))
+     else
+      handle(format("%s [%s]=%q,",depth,k,v))
+     end
+    elseif tk=="boolean" then
+     handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+    elseif tk~="string" then
+    elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+     handle(format("%s %s=%q,",depth,k,v))
+    else
+     handle(format("%s [%q]=%q,",depth,k,v))
     end
-    if metacheck==nil then
-      metacheck=true
-    end
-  else
-    noquotes=false
-    hexify=false
-    handle=_handle or print
-    compact=true
-    inline=true
-    functions=true
-    metacheck=true
-  end
-  if tname=="string" then
-    if name=="return" then
-      handle("return {")
+   elseif tv=="table" then
+    if next(v)==nil then
+     if tk=="number" then
+      if hexify then
+       handle(format("%s [0x%X]={},",depth,k))
+      else
+       handle(format("%s [%s]={},",depth,k))
+      end
+     elseif tk=="boolean" then
+      handle(format("%s [%s]={},",depth,k and "true" or "false"))
+     elseif tk~="string" then
+     elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+      handle(format("%s %s={},",depth,k))
+     else
+      handle(format("%s [%q]={},",depth,k))
+     end
+    elseif inline then
+     local st=is_simple_table(v,hexify)
+     if st then
+      if tk=="number" then
+       if hexify then
+        handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
+       else
+        handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+       end
+      elseif tk=="boolean" then
+       handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+      elseif tk~="string" then
+      elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+       handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+      else
+       handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
+      end
+     else
+      do_serialize(v,k,depth,level+1)
+     end
     else
-      handle(name.."={")
+     do_serialize(v,k,depth,level+1)
     end
-  elseif tname=="number" then
-    if hexify then
-      handle(format("[0x%X]={",name))
+   elseif tv=="boolean" then
+    if tk=="number" then
+     if hexify then
+      handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
+     else
+      handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
+     end
+    elseif tk=="boolean" then
+     handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+    elseif tk~="string" then
+    elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+     handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
     else
-      handle("["..name.."]={")
+     handle(format("%s [%q]=%s,",depth,k,v and "true" or "false"))
     end
-  elseif tname=="boolean" then
-    if name then
-      handle("return {")
+   elseif tv=="function" then
+    if functions then
+     local getinfo=debug and debug.getinfo
+     if getinfo then
+      local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
+      if tk=="number" then
+       if hexify then
+        handle(format("%s [0x%X]=load(%q),",depth,k,f))
+       else
+        handle(format("%s [%s]=load(%q),",depth,k,f))
+       end
+      elseif tk=="boolean" then
+       handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+      elseif tk~="string" then
+      elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+       handle(format("%s %s=load(%q),",depth,k,f))
+      else
+       handle(format("%s [%q]=load(%q),",depth,k,f))
+      end
+     end
+    end
+   else
+    if tk=="number" then
+     if hexify then
+      handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
+     else
+      handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+     end
+    elseif tk=="boolean" then
+     handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+    elseif tk~="string" then
+    elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+     handle(format("%s %s=%q,",depth,k,tostring(v)))
     else
-      handle("{")
+     handle(format("%s [%q]=%q,",depth,k,tostring(v)))
     end
+   end
+  end
+ end
+ if level>0 then
+  handle(format("%s},",depth))
+ end
+end
+local function serialize(_handle,root,name,specification) 
+ local tname=type(name)
+ if type(specification)=="table" then
+  noquotes=specification.noquotes
+  hexify=specification.hexify
+  handle=_handle or specification.handle or print
+  functions=specification.functions
+  compact=specification.compact
+  inline=specification.inline and compact
+  metacheck=specification.metacheck
+  if functions==nil then
+   functions=true
+  end
+  if compact==nil then
+   compact=true
+  end
+  if inline==nil then
+   inline=compact
+  end
+  if metacheck==nil then
+   metacheck=true
+  end
+ else
+  noquotes=false
+  hexify=false
+  handle=_handle or print
+  compact=true
+  inline=true
+  functions=true
+  metacheck=true
+ end
+ if tname=="string" then
+  if name=="return" then
+   handle("return {")
   else
-    handle("t={")
+   handle(name.."={")
   end
-  if root then
-    if metacheck and getmetatable(root) then
-      local dummy=root._w_h_a_t_e_v_e_r_
-      root._w_h_a_t_e_v_e_r_=nil
-    end
-    if next(root)~=nil then
-      do_serialize(root,name,"",0)
-    end
+ elseif tname=="number" then
+  if hexify then
+   handle(format("[0x%X]={",name))
+  else
+   handle("["..name.."]={")
   end
-  handle("}")
+ elseif tname=="boolean" then
+  if name then
+   handle("return {")
+  else
+   handle("{")
+  end
+ else
+  handle("t={")
+ end
+ if root then
+  if metacheck and getmetatable(root) then
+   local dummy=root._w_h_a_t_e_v_e_r_
+   root._w_h_a_t_e_v_e_r_=nil
+  end
+  if next(root)~=nil then
+   do_serialize(root,name,"",0)
+  end
+ end
+ handle("}")
 end
 function table.serialize(root,name,specification)
-  local t,n={},0
-  local function flush(s)
-    n=n+1
-    t[n]=s
-  end
-  serialize(flush,root,name,specification)
-  return concat(t,"\n")
+ local t={}
+ local n=0
+ local function flush(s)
+  n=n+1
+  t[n]=s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
 end
 table.tohandle=serialize
 local maxtab=2*1024
 function table.tofile(filename,root,name,specification)
-  local f=io.open(filename,'w')
-  if f then
-    if maxtab>1 then
-      local t,n={},0
-      local function flush(s)
-        n=n+1
-        t[n]=s
-        if n>maxtab then
-          f:write(concat(t,"\n"),"\n") 
-          t,n={},0 
-        end
-      end
-      serialize(flush,root,name,specification)
-      f:write(concat(t,"\n"),"\n")
-    else
-      local function flush(s)
-        f:write(s,"\n")
-      end
-      serialize(flush,root,name,specification)
+ local f=io.open(filename,'w')
+ if f then
+  if maxtab>1 then
+   local t={}
+   local n=0
+   local function flush(s)
+    n=n+1
+    t[n]=s
+    if n>maxtab then
+     f:write(concat(t,"\n"),"\n") 
+     t={} 
+     n=0
     end
-    f:close()
-    io.flush()
+   end
+   serialize(flush,root,name,specification)
+   f:write(concat(t,"\n"),"\n")
+  else
+   local function flush(s)
+    f:write(s,"\n")
+   end
+   serialize(flush,root,name,specification)
   end
+  f:close()
+  io.flush()
+ end
 end
 local function flattened(t,f,depth) 
-  if f==nil then
-    f={}
-    depth=0xFFFF
-  elseif tonumber(f) then
-    depth=f
-    f={}
-  elseif not depth then
-    depth=0xFFFF
+ if f==nil then
+  f={}
+  depth=0xFFFF
+ elseif tonumber(f) then
+  depth=f
+  f={}
+ elseif not depth then
+  depth=0xFFFF
+ end
+ for k,v in next,t do
+  if type(k)~="number" then
+   if depth>0 and type(v)=="table" then
+    flattened(v,f,depth-1)
+   else
+    f[#f+1]=v
+   end
   end
-  for k,v in next,t do
-    if type(k)~="number" then
-      if depth>0 and type(v)=="table" then
-        flattened(v,f,depth-1)
-      else
-        f[#f+1]=v
-      end
-    end
+ end
+ for k=1,#t do
+  local v=t[k]
+  if depth>0 and type(v)=="table" then
+   flattened(v,f,depth-1)
+  else
+   f[#f+1]=v
   end
-  for k=1,#t do
-    local v=t[k]
-    if depth>0 and type(v)=="table" then
-      flattened(v,f,depth-1)
-    else
-      f[#f+1]=v
-    end
-  end
-  return f
+ end
+ return f
 end
 table.flattened=flattened
 local function collapsed(t,f,h)
-  if f==nil then
-    f={}
-    h={}
+ if f==nil then
+  f={}
+  h={}
+ end
+ for k=1,#t do
+  local v=t[k]
+  if type(v)=="table" then
+   collapsed(v,f,h)
+  elseif not h[v] then
+   f[#f+1]=v
+   h[v]=true
   end
-  for k=1,#t do
-    local v=t[k]
-    if type(v)=="table" then
-      collapsed(v,f,h)
-    elseif not h[v] then
-      f[#f+1]=v
-      h[v]=true
-    end
-  end
-  return f
+ end
+ return f
 end
 local function collapsedhash(t,h)
-  if h==nil then
-    h={}
+ if h==nil then
+  h={}
+ end
+ for k=1,#t do
+  local v=t[k]
+  if type(v)=="table" then
+   collapsedhash(v,h)
+  else
+   h[v]=true
   end
-  for k=1,#t do
-    local v=t[k]
-    if type(v)=="table" then
-      collapsedhash(v,h)
-    else
-      h[v]=true
-    end
-  end
-  return h
+ end
+ return h
 end
-table.collapsed=collapsed   
+table.collapsed=collapsed  
 table.collapsedhash=collapsedhash
 local function unnest(t,f) 
-  if not f then     
-    f={}      
+ if not f then    
+  f={}   
+ end
+ for i=1,#t do
+  local v=t[i]
+  if type(v)=="table" then
+   if type(v[1])=="table" then
+    unnest(v,f)
+   else
+    f[#f+1]=v
+   end
+  else
+   f[#f+1]=v
   end
-  for i=1,#t do
-    local v=t[i]
-    if type(v)=="table" then
-      if type(v[1])=="table" then
-        unnest(v,f)
-      else
-        f[#f+1]=v
-      end
-    else
-      f[#f+1]=v
-    end
-  end
-  return f
+ end
+ return f
 end
 function table.unnest(t) 
-  return unnest(t)
+ return unnest(t)
 end
 local function are_equal(a,b,n,m) 
-  if a==b then
-    return true
-  elseif a and b and #a==#b then
-    n=n or 1
-    m=m or #a
-    for i=n,m do
-      local ai,bi=a[i],b[i]
-      if ai==bi then
-      elseif type(ai)=="table" and type(bi)=="table" then
-        if not are_equal(ai,bi) then
-          return false
-        end
-      else
-        return false
-      end
+ if a==b then
+  return true
+ elseif a and b and #a==#b then
+  if not n then
+   n=1
+  end
+  if not m then
+   m=#a
+  end
+  for i=n,m do
+   local ai,bi=a[i],b[i]
+   if ai==bi then
+   elseif type(ai)=="table" and type(bi)=="table" then
+    if not are_equal(ai,bi) then
+     return false
     end
-    return true
-  else
+   else
     return false
+   end
   end
+  return true
+ else
+  return false
+ end
 end
 local function identical(a,b) 
-  if a~=b then
-    for ka,va in next,a do
-      local vb=b[ka]
-      if va==vb then
-      elseif type(va)=="table" and type(vb)=="table" then
-        if not identical(va,vb) then
-          return false
-        end
-      else
-        return false
-      end
+ if a~=b then
+  for ka,va in next,a do
+   local vb=b[ka]
+   if va==vb then
+   elseif type(va)=="table" and  type(vb)=="table" then
+    if not identical(va,vb) then
+     return false
     end
+   else
+    return false
+   end
   end
-  return true
+ end
+ return true
 end
 table.identical=identical
 table.are_equal=are_equal
 local function sparse(old,nest,keeptables)
-  local new={}
-  for k,v in next,old do
-    if not (v=="" or v==false) then
-      if nest and type(v)=="table" then
-        v=sparse(v,nest)
-        if keeptables or next(v)~=nil then
-          new[k]=v
-        end
-      else
-        new[k]=v
-      end
+ local new={}
+ for k,v in next,old do
+  if not (v=="" or v==false) then
+   if nest and type(v)=="table" then
+    v=sparse(v,nest)
+    if keeptables or next(v)~=nil then
+     new[k]=v
     end
+   else
+    new[k]=v
+   end
   end
-  return new
+ end
+ return new
 end
 table.sparse=sparse
 function table.compact(t)
-  return sparse(t,true,true)
+ return sparse(t,true,true)
 end
 function table.contains(t,v)
-  if t then
-    for i=1,#t do
-      if t[i]==v then
-        return i
-      end
-    end
+ if t then
+  for i=1,#t do
+   if t[i]==v then
+    return i
+   end
   end
-  return false
+ end
+ return false
 end
 function table.count(t)
-  local n=0
-  for k,v in next,t do
-    n=n+1
-  end
-  return n
+ local n=0
+ for k,v in next,t do
+  n=n+1
+ end
+ return n
 end
 function table.swapped(t,s) 
-  local n={}
-  if s then
-    for k,v in next,s do
-      n[k]=v
-    end
+ local n={}
+ if s then
+  for k,v in next,s do
+   n[k]=v
   end
-  for k,v in next,t do
-    n[v]=k
-  end
-  return n
+ end
+ for k,v in next,t do
+  n[v]=k
+ end
+ return n
 end
 function table.hashed(t) 
-  for i=1,#t do
-    t[t[i]]=i
-  end
-  return t
+ for i=1,#t do
+  t[t[i]]=i
+ end
+ return t
 end
 function table.mirrored(t) 
-  local n={}
-  for k,v in next,t do
-    n[v]=k
-    n[k]=v
-  end
-  return n
+ local n={}
+ for k,v in next,t do
+  n[v]=k
+  n[k]=v
+ end
+ return n
 end
 function table.reversed(t)
-  if t then
-    local tt,tn={},#t
-    if tn>0 then
-      local ttn=0
-      for i=tn,1,-1 do
-        ttn=ttn+1
-        tt[ttn]=t[i]
-      end
-    end
-    return tt
+ if t then
+  local tt={}
+  local tn=#t
+  if tn>0 then
+   local ttn=0
+   for i=tn,1,-1 do
+    ttn=ttn+1
+    tt[ttn]=t[i]
+   end
   end
+  return tt
+ end
 end
 function table.reverse(t) 
-  if t then
-    local n=#t
-    for i=1,floor(n/2) do 
-      local j=n-i+1
-      t[i],t[j]=t[j],t[i]
-    end
-    return t
+ if t then
+  local n=#t
+  local m=n+1
+  for i=1,floor(n/2) do 
+   local j=m-i
+   t[i],t[j]=t[j],t[i]
   end
+  return t
+ end
 end
-function table.sequenced(t,sep,simple) 
-  if not t then
-    return ""
+local function sequenced(t,sep,simple)
+ if not t then
+  return ""
+ elseif type(t)=="string" then
+  return t 
+ end
+ local n=#t
+ local s={}
+ if n>0 then
+  for i=1,n do
+   local v=t[i]
+   if type(v)=="table" then
+    s[i]="{"..sequenced(v,sep,simple).."}"
+   else
+    s[i]=tostring(t[i])
+   end
   end
-  local n=#t
-  local s={}
-  if n>0 then
-    for i=1,n do
-      s[i]=tostring(t[i])
+ else
+  n=0
+  for k,v in sortedhash(t) do
+   if simple then
+    if v==true then
+     n=n+1
+     s[n]=k
+    elseif v and v~="" then
+     n=n+1
+     if type(v)=="table" then
+      s[n]=k.."={"..sequenced(v,sep,simple).."}"
+     else
+      s[n]=k.."="..tostring(v)
+     end
     end
-  else
-    n=0
-    for k,v in sortedhash(t) do
-      if simple then
-        if v==true then
-          n=n+1
-          s[n]=k
-        elseif v and v~="" then
-          n=n+1
-          s[n]=k.."="..tostring(v)
-        end
-      else
-        n=n+1
-        s[n]=k.."="..tostring(v)
-      end
+   else
+    n=n+1
+    if type(v)=="table" then
+     s[n]=k.."={"..sequenced(v,sep,simple).."}"
+    else
+     s[n]=k.."="..tostring(v)
     end
+   end
   end
-  return concat(s,sep or " | ")
+ end
+ return concat(s,sep or " | ")
 end
+table.sequenced=sequenced
 function table.print(t,...)
-  if type(t)~="table" then
-    print(tostring(t))
-  else
-    serialize(print,t,...)
-  end
+ if type(t)~="table" then
+  print(tostring(t))
+ else
+  serialize(print,t,...)
+ end
 end
 if setinspector then
-  setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
+ setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
 end
 function table.sub(t,i,j)
-  return { unpack(t,i,j) }
+ return { unpack(t,i,j) }
 end
 function table.is_empty(t)
-  return not t or next(t)==nil
+ return not t or next(t)==nil
 end
 function table.has_one_entry(t)
-  return t and next(t,next(t))==nil
+ return t and next(t,next(t))==nil
 end
 function table.loweredkeys(t) 
-  local l={}
-  for k,v in next,t do
-    l[lower(k)]=v
-  end
-  return l
+ local l={}
+ for k,v in next,t do
+  l[lower(k)]=v
+ end
+ return l
 end
 function table.unique(old)
-  local hash={}
-  local new={}
-  local n=0
-  for i=1,#old do
-    local oi=old[i]
-    if not hash[oi] then
-      n=n+1
-      new[n]=oi
-      hash[oi]=true
-    end
+ local hash={}
+ local new={}
+ local n=0
+ for i=1,#old do
+  local oi=old[i]
+  if not hash[oi] then
+   n=n+1
+   new[n]=oi
+   hash[oi]=true
   end
-  return new
+ end
+ return new
 end
 function table.sorted(t,...)
-  sort(t,...)
-  return t 
+ sort(t,...)
+ return t 
 end
 function table.values(t,s) 
-  if t then
-    local values,keys,v={},{},0
-    for key,value in next,t do
-      if not keys[value] then
-        v=v+1
-        values[v]=value
-        keys[k]=key
-      end
-    end
-    if s then
-      sort(values)
-    end
-    return values
-  else
-    return {}
+ if t then
+  local values={}
+  local keys={}
+  local v=0
+  for key,value in next,t do
+   if not keys[value] then
+    v=v+1
+    values[v]=value
+    keys[k]=key
+   end
   end
+  if s then
+   sort(values)
+  end
+  return values
+ else
+  return {}
+ end
 end
 function table.filtered(t,pattern,sort,cmp)
-  if t and type(pattern)=="string" then
-    if sort then
-      local s
-      if cmp then
-        s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
-      else
-        s=sortedkeys(t) 
-      end
-      local n=0
-      local m=#s
-      local function kv(s)
-        while n<m do
-          n=n+1
-          local k=s[n]
-          if find(k,pattern) then
-            return k,t[k]
-          end
-        end
-      end
-      return kv,s
-    else
-      local n=next(t)
-      local function iterator()
-        while n~=nil do
-          local k=n
-          n=next(t,k)
-          if find(k,pattern) then
-            return k,t[k]
-          end
-        end
-      end
-      return iterator,t
+ if t and type(pattern)=="string" then
+  if sort then
+   local s
+   if cmp then
+    s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+   else
+    s=sortedkeys(t) 
+   end
+   local n=0
+   local m=#s
+   local function kv(s)
+    while n<m do
+     n=n+1
+     local k=s[n]
+     if find(k,pattern) then
+      return k,t[k]
+     end
     end
+   end
+   return kv,s
   else
-    return nothing
+   local n=next(t)
+   local function iterator()
+    while n~=nil do
+     local k=n
+     n=next(t,k)
+     if find(k,pattern) then
+      return k,t[k]
+     end
+    end
+   end
+   return iterator,t
   end
+ else
+  return nothing
+ end
 end
 if not table.move then
-  function table.move(a1,f,e,t,a2)
-    if a2 and a1~=a2 then
-      for i=f,e do
-        a2[t]=a1[i]
-        t=t+1
-      end
-      return a2
-    else
-      t=t+e-f
-      for i=e,f,-1 do
-        a1[t]=a1[i]
-        t=t-1
-      end
-      return a1
-    end
+ function table.move(a1,f,e,t,a2)
+  if a2 and a1~=a2 then
+   for i=f,e do
+    a2[t]=a1[i]
+    t=t+1
+   end
+   return a2
+  else
+   t=t+e-f
+   for i=e,f,-1 do
+    a1[t]=a1[i]
+    t=t-1
+   end
+   return a1
   end
+ end
 end
 
 
@@ -3012,14 +3213,14 @@
 
 package.loaded["l-io"] = package.loaded["l-io"] or true
 
--- original size: 11823, stripped down to: 6945
+-- original size: 11823, stripped down to: 6325
 
 if not modules then modules={} end modules ['l-io']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 io=io
 local open,flush,write,read=io.open,io.flush,io.write,io.read
@@ -3027,334 +3228,334 @@
 local concat=table.concat
 local type=type
 if string.find(os.getenv("PATH"),";",1,true) then
-  io.fileseparator,io.pathseparator="\\",";"
+ io.fileseparator,io.pathseparator="\\",";"
 else
-  io.fileseparator,io.pathseparator="/",":"
+ io.fileseparator,io.pathseparator="/",":"
 end
 local large=0x01000000 
 local medium=0x00100000 
 local small=0x00020000
 local function readall(f)
-  local size=f:seek("end")
-  if size>0 then
-    f:seek("set",0)
-    return f:read(size)
-  else
-    return ""
-  end
+ local size=f:seek("end")
+ if size>0 then
+  f:seek("set",0)
+  return f:read(size)
+ else
+  return ""
+ end
 end
 io.readall=readall
 function io.loaddata(filename,textmode) 
-  local f=open(filename,(textmode and 'r') or 'rb')
-  if f then
-    local size=f:seek("end")
-    local data=nil
-    if size>0 then
-      f:seek("set",0)
-      data=f:read(size)
-    end
-    f:close()
-    return data
+ local f=open(filename,(textmode and 'r') or 'rb')
+ if f then
+  local size=f:seek("end")
+  local data=nil
+  if size>0 then
+   f:seek("set",0)
+   data=f:read(size)
   end
+  f:close()
+  return data
+ end
 end
 function io.copydata(source,target,action)
-  local f=open(source,"rb")
-  if f then
-    local g=open(target,"wb")
-    if g then
-      local size=f:seek("end")
-      if size>0 then
-        f:seek("set",0)
-        local data=f:read(size)
-        if action then
-          data=action(data)
-        end
-        if data then
-          g:write(data)
-        end
-      end
-      g:close()
+ local f=open(source,"rb")
+ if f then
+  local g=open(target,"wb")
+  if g then
+   local size=f:seek("end")
+   if size>0 then
+    f:seek("set",0)
+    local data=f:read(size)
+    if action then
+     data=action(data)
     end
-    f:close()
-    flush()
+    if data then
+     g:write(data)
+    end
+   end
+   g:close()
   end
+  f:close()
+  flush()
+ end
 end
 function io.savedata(filename,data,joiner)
-  local f=open(filename,"wb")
-  if f then
-    if type(data)=="table" then
-      f:write(concat(data,joiner or ""))
-    elseif type(data)=="function" then
-      data(f)
-    else
-      f:write(data or "")
-    end
-    f:close()
-    flush()
-    return true
+ local f=open(filename,"wb")
+ if f then
+  if type(data)=="table" then
+   f:write(concat(data,joiner or ""))
+  elseif type(data)=="function" then
+   data(f)
   else
-    return false
+   f:write(data or "")
   end
+  f:close()
+  flush()
+  return true
+ else
+  return false
+ end
 end
 if fio and fio.readline then
-  local readline=fio.readline
-  function io.loadlines(filename,n) 
-    local f=open(filename,'r')
-    if not f then
-    elseif n then
-      local lines={}
-      for i=1,n do
-        local line=readline(f)
-        if line then
-          lines[i]=line
-        else
-          break
-        end
-      end
-      f:close()
-      lines=concat(lines,"\n")
-      if #lines>0 then
-        return lines
-      end
+ local readline=fio.readline
+ function io.loadlines(filename,n) 
+  local f=open(filename,'r')
+  if not f then
+  elseif n then
+   local lines={}
+   for i=1,n do
+    local line=readline(f)
+    if line then
+     lines[i]=line
     else
-      local line=readline(f)
-      f:close()
-      if line and #line>0 then
-        return line
-      end
+     break
     end
+   end
+   f:close()
+   lines=concat(lines,"\n")
+   if #lines>0 then
+    return lines
+   end
+  else
+   local line=readline(f)
+   f:close()
+   if line and #line>0 then
+    return line
+   end
   end
+ end
 else
-  function io.loadlines(filename,n) 
-    local f=open(filename,'r')
-    if not f then
-    elseif n then
-      local lines={}
-      for i=1,n do
-        local line=f:read("*lines")
-        if line then
-          lines[i]=line
-        else
-          break
-        end
-      end
-      f:close()
-      lines=concat(lines,"\n")
-      if #lines>0 then
-        return lines
-      end
+ function io.loadlines(filename,n) 
+  local f=open(filename,'r')
+  if not f then
+  elseif n then
+   local lines={}
+   for i=1,n do
+    local line=f:read("*lines")
+    if line then
+     lines[i]=line
     else
-      local line=f:read("*line") or ""
-      f:close()
-      if #line>0 then
-        return line
-      end
+     break
     end
+   end
+   f:close()
+   lines=concat(lines,"\n")
+   if #lines>0 then
+    return lines
+   end
+  else
+   local line=f:read("*line") or ""
+   f:close()
+   if #line>0 then
+    return line
+   end
   end
+ end
 end
 function io.loadchunk(filename,n)
-  local f=open(filename,'rb')
-  if f then
-    local data=f:read(n or 1024)
-    f:close()
-    if #data>0 then
-      return data
-    end
+ local f=open(filename,'rb')
+ if f then
+  local data=f:read(n or 1024)
+  f:close()
+  if #data>0 then
+   return data
   end
+ end
 end
 function io.exists(filename)
-  local f=open(filename)
-  if f==nil then
-    return false
-  else
-    f:close()
-    return true
-  end
+ local f=open(filename)
+ if f==nil then
+  return false
+ else
+  f:close()
+  return true
+ end
 end
 function io.size(filename)
-  local f=open(filename)
-  if f==nil then
-    return 0
-  else
-    local s=f:seek("end")
-    f:close()
-    return s
-  end
+ local f=open(filename)
+ if f==nil then
+  return 0
+ else
+  local s=f:seek("end")
+  f:close()
+  return s
+ end
 end
 local function noflines(f)
-  if type(f)=="string" then
-    local f=open(filename)
-    if f then
-      local n=f and noflines(f) or 0
-      f:close()
-      return n
-    else
-      return 0
-    end
+ if type(f)=="string" then
+  local f=open(filename)
+  if f then
+   local n=f and noflines(f) or 0
+   f:close()
+   return n
   else
-    local n=0
-    for _ in f:lines() do
-      n=n+1
-    end
-    f:seek('set',0)
-    return n
+   return 0
   end
+ else
+  local n=0
+  for _ in f:lines() do
+   n=n+1
+  end
+  f:seek('set',0)
+  return n
+ end
 end
 io.noflines=noflines
 local nextchar={
-  [ 4]=function(f)
-    return f:read(1,1,1,1)
-  end,
-  [ 2]=function(f)
-    return f:read(1,1)
-  end,
-  [ 1]=function(f)
-    return f:read(1)
-  end,
-  [-2]=function(f)
-    local a,b=f:read(1,1)
-    return b,a
-  end,
-  [-4]=function(f)
-    local a,b,c,d=f:read(1,1,1,1)
-    return d,c,b,a
-  end
+ [ 4]=function(f)
+  return f:read(1,1,1,1)
+ end,
+ [ 2]=function(f)
+  return f:read(1,1)
+ end,
+ [ 1]=function(f)
+  return f:read(1)
+ end,
+ [-2]=function(f)
+  local a,b=f:read(1,1)
+  return b,a
+ end,
+ [-4]=function(f)
+  local a,b,c,d=f:read(1,1,1,1)
+  return d,c,b,a
+ end
 }
 function io.characters(f,n)
-  if f then
-    return nextchar[n or 1],f
-  end
+ if f then
+  return nextchar[n or 1],f
+ end
 end
 local nextbyte={
-  [4]=function(f)
-    local a,b,c,d=f:read(1,1,1,1)
-    if d then
-      return byte(a),byte(b),byte(c),byte(d)
-    end
-  end,
-  [3]=function(f)
-    local a,b,c=f:read(1,1,1)
-    if b then
-      return byte(a),byte(b),byte(c)
-    end
-  end,
-  [2]=function(f)
-    local a,b=f:read(1,1)
-    if b then
-      return byte(a),byte(b)
-    end
-  end,
-  [1]=function (f)
-    local a=f:read(1)
-    if a then
-      return byte(a)
-    end
-  end,
-  [-2]=function (f)
-    local a,b=f:read(1,1)
-    if b then
-      return byte(b),byte(a)
-    end
-  end,
-  [-3]=function(f)
-    local a,b,c=f:read(1,1,1)
-    if b then
-      return byte(c),byte(b),byte(a)
-    end
-  end,
-  [-4]=function(f)
-    local a,b,c,d=f:read(1,1,1,1)
-    if d then
-      return byte(d),byte(c),byte(b),byte(a)
-    end
+ [4]=function(f)
+  local a,b,c,d=f:read(1,1,1,1)
+  if d then
+   return byte(a),byte(b),byte(c),byte(d)
   end
+ end,
+ [3]=function(f)
+  local a,b,c=f:read(1,1,1)
+  if b then
+   return byte(a),byte(b),byte(c)
+  end
+ end,
+ [2]=function(f)
+  local a,b=f:read(1,1)
+  if b then
+   return byte(a),byte(b)
+  end
+ end,
+ [1]=function (f)
+  local a=f:read(1)
+  if a then
+   return byte(a)
+  end
+ end,
+ [-2]=function (f)
+  local a,b=f:read(1,1)
+  if b then
+   return byte(b),byte(a)
+  end
+ end,
+ [-3]=function(f)
+  local a,b,c=f:read(1,1,1)
+  if b then
+   return byte(c),byte(b),byte(a)
+  end
+ end,
+ [-4]=function(f)
+  local a,b,c,d=f:read(1,1,1,1)
+  if d then
+   return byte(d),byte(c),byte(b),byte(a)
+  end
+ end
 }
 function io.bytes(f,n)
-  if f then
-    return nextbyte[n or 1],f
-  else
-    return nil,nil
-  end
+ if f then
+  return nextbyte[n or 1],f
+ else
+  return nil,nil
+ end
 end
 function io.ask(question,default,options)
-  while true do
-    write(question)
-    if options then
-      write(format(" [%s]",concat(options,"|")))
+ while true do
+  write(question)
+  if options then
+   write(format(" [%s]",concat(options,"|")))
+  end
+  if default then
+   write(format(" [%s]",default))
+  end
+  write(format(" "))
+  flush()
+  local answer=read()
+  answer=gsub(answer,"^%s*(.*)%s*$","%1")
+  if answer=="" and default then
+   return default
+  elseif not options then
+   return answer
+  else
+   for k=1,#options do
+    if options[k]==answer then
+     return answer
     end
-    if default then
-      write(format(" [%s]",default))
+   end
+   local pattern="^"..answer
+   for k=1,#options do
+    local v=options[k]
+    if find(v,pattern) then
+     return v
     end
-    write(format(" "))
-    flush()
-    local answer=read()
-    answer=gsub(answer,"^%s*(.*)%s*$","%1")
-    if answer=="" and default then
-      return default
-    elseif not options then
-      return answer
-    else
-      for k=1,#options do
-        if options[k]==answer then
-          return answer
-        end
-      end
-      local pattern="^"..answer
-      for k=1,#options do
-        local v=options[k]
-        if find(v,pattern) then
-          return v
-        end
-      end
-    end
+   end
   end
+ end
 end
 local function readnumber(f,n,m) 
-  if m then
-    f:seek("set",n)
-    n=m
-  end
-  if n==1 then
-    return byte(f:read(1))
-  elseif n==2 then
-    local a,b=byte(f:read(2),1,2)
-    return 0x100*a+b
-  elseif n==3 then
-    local a,b,c=byte(f:read(3),1,3)
-    return 0x10000*a+0x100*b+c
-  elseif n==4 then
-    local a,b,c,d=byte(f:read(4),1,4)
-    return 0x1000000*a+0x10000*b+0x100*c+d
-  elseif n==8 then
-    local a,b=readnumber(f,4),readnumber(f,4)
-    return 0x100*a+b
-  elseif n==12 then
-    local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
-    return 0x10000*a+0x100*b+c
-  elseif n==-2 then
-    local b,a=byte(f:read(2),1,2)
-    return 0x100*a+b
-  elseif n==-3 then
-    local c,b,a=byte(f:read(3),1,3)
-    return 0x10000*a+0x100*b+c
-  elseif n==-4 then
-    local d,c,b,a=byte(f:read(4),1,4)
-    return 0x1000000*a+0x10000*b+0x100*c+d
-  elseif n==-8 then
-    local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
-    return 0x100000000000000*a+0x1000000000000*b+0x10000000000*c+0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
-  else
-    return 0
-  end
+ if m then
+  f:seek("set",n)
+  n=m
+ end
+ if n==1 then
+  return byte(f:read(1))
+ elseif n==2 then
+  local a,b=byte(f:read(2),1,2)
+  return 0x100*a+b
+ elseif n==3 then
+  local a,b,c=byte(f:read(3),1,3)
+  return 0x10000*a+0x100*b+c
+ elseif n==4 then
+  local a,b,c,d=byte(f:read(4),1,4)
+  return 0x1000000*a+0x10000*b+0x100*c+d
+ elseif n==8 then
+  local a,b=readnumber(f,4),readnumber(f,4)
+  return 0x100*a+b
+ elseif n==12 then
+  local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
+  return 0x10000*a+0x100*b+c
+ elseif n==-2 then
+  local b,a=byte(f:read(2),1,2)
+  return 0x100*a+b
+ elseif n==-3 then
+  local c,b,a=byte(f:read(3),1,3)
+  return 0x10000*a+0x100*b+c
+ elseif n==-4 then
+  local d,c,b,a=byte(f:read(4),1,4)
+  return 0x1000000*a+0x10000*b+0x100*c+d
+ elseif n==-8 then
+  local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
+  return 0x100000000000000*a+0x1000000000000*b+0x10000000000*c+0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
+ else
+  return 0
+ end
 end
 io.readnumber=readnumber
 function io.readstring(f,n,m)
-  if m then
-    f:seek("set",n)
-    n=m
-  end
-  local str=gsub(f:read(n),"\000","")
-  return str
+ if m then
+  f:seek("set",n)
+  n=m
+ end
+ local str=gsub(f:read(n),"\000","")
+ return str
 end
 
 
@@ -3364,14 +3565,14 @@
 
 package.loaded["l-number"] = package.loaded["l-number"] or true
 
--- original size: 5645, stripped down to: 2253
+-- original size: 5720, stripped down to: 2176
 
 if not modules then modules={} end modules ['l-number']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 tostring,tonumber=tostring,tonumber
 local format,floor,match,rep=string.format,math.floor,string.match,string.rep
@@ -3381,100 +3582,108 @@
 number=number or {}
 local number=number
 if bit32 then
-  local bextract=bit32.extract
-  local t={
-    "0","0","0","0","0","0","0","0",
-    "0","0","0","0","0","0","0","0",
-    "0","0","0","0","0","0","0","0",
-    "0","0","0","0","0","0","0","0",
-  }
-  function number.tobitstring(b,m)
-    local n=32
-    for i=0,31 do
-      local v=bextract(b,i)
-      local k=32-i
-      if v==1 then
-        n=k
-        t[k]="1"
-      else
-        t[k]="0"
-      end
-    end
-    if m then
-      m=33-m*8
-      if m<1 then
-        m=1
-      end
-      return concat(t,"",m)
-    elseif n<8 then
-      return concat(t)
-    elseif n<16 then
-      return concat(t,"",9)
-    elseif n<24 then
-      return concat(t,"",17)
-    else
-      return concat(t,"",25)
-    end
+ local bextract=bit32.extract
+ local t={
+  "0","0","0","0","0","0","0","0",
+  "0","0","0","0","0","0","0","0",
+  "0","0","0","0","0","0","0","0",
+  "0","0","0","0","0","0","0","0",
+ }
+ function number.tobitstring(b,m,w)
+  if not w then
+   w=32
   end
+  local n=w
+  for i=0,w-1 do
+   local v=bextract(b,i)
+   local k=w-i
+   if v==1 then
+    n=k
+    t[k]="1"
+   else
+    t[k]="0"
+   end
+  end
+  if w then
+   return concat(t,"",1,w)
+  elseif m then
+   m=33-m*8
+   if m<1 then
+    m=1
+   end
+   return concat(t,"",1,m)
+  elseif n<8 then
+   return concat(t)
+  elseif n<16 then
+   return concat(t,"",9)
+  elseif n<24 then
+   return concat(t,"",17)
+  else
+   return concat(t,"",25)
+  end
+ end
 else
-  function number.tobitstring(n,m)
-    if n>0 then
-      local t={}
-      while n>0 do
-        insert(t,1,n%2>0 and 1 or 0)
-        n=floor(n/2)
-      end
-      local nn=8-#t%8
-      if nn>0 and nn<8 then
-        for i=1,nn do
-          insert(t,1,0)
-        end
-      end
-      if m then
-        m=m*8-#t
-        if m>0 then
-          insert(t,1,rep("0",m))
-        end
-      end
-      return concat(t)
-    elseif m then
-      rep("00000000",m)
-    else
-      return "00000000"
+ function number.tobitstring(n,m)
+  if n>0 then
+   local t={}
+   while n>0 do
+    insert(t,1,n%2>0 and 1 or 0)
+    n=floor(n/2)
+   end
+   local nn=8-#t%8
+   if nn>0 and nn<8 then
+    for i=1,nn do
+     insert(t,1,0)
     end
+   end
+   if m then
+    m=m*8-#t
+    if m>0 then
+     insert(t,1,rep("0",m))
+    end
+   end
+   return concat(t)
+  elseif m then
+   rep("00000000",m)
+  else
+   return "00000000"
   end
+ end
 end
 function number.valid(str,default)
-  return tonumber(str) or default or nil
+ return tonumber(str) or default or nil
 end
 function number.toevenhex(n)
-  local s=format("%X",n)
-  if #s%2==0 then
-    return s
-  else
-    return "0"..s
-  end
+ local s=format("%X",n)
+ if #s%2==0 then
+  return s
+ else
+  return "0"..s
+ end
 end
 function number.bytetodecimal(b)
-  local d=floor(b*100/255+0.5)
-  if d>100 then
-    return 100
-  elseif d<-100 then
-    return -100
-  else
-    return d
-  end
+ local d=floor(b*100/255+0.5)
+ if d>100 then
+  return 100
+ elseif d<-100 then
+  return -100
+ else
+  return d
+ end
 end
 function number.decimaltobyte(d)
-  local b=floor(d*255/100+0.5)
-  if b>255 then
-    return 255
-  elseif b<-255 then
-    return -255
-  else
-    return b
-  end
+ local b=floor(d*255/100+0.5)
+ if b>255 then
+  return 255
+ elseif b<-255 then
+  return -255
+ else
+  return b
+ end
 end
+function number.idiv(i,d)
+ return floor(i/d) 
+end
 
 
 end -- of closure
@@ -3483,14 +3692,14 @@
 
 package.loaded["l-set"] = package.loaded["l-set"] or true
 
--- original size: 1923, stripped down to: 1133
+-- original size: 1923, stripped down to: 1044
 
 if not modules then modules={} end modules ['l-set']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 set=set or {}
 local nums={}
@@ -3499,54 +3708,54 @@
 local next,type=next,type
 set.create=table.tohash
 function set.tonumber(t)
-  if next(t) then
-    local s=""
-    for k,v in next,t do
-      if v then
-        s=s.." "..k
-      end
-    end
-    local n=nums[s]
-    if not n then
-      n=#tabs+1
-      tabs[n]=t
-      nums[s]=n
-    end
-    return n
-  else
-    return 0
+ if next(t) then
+  local s=""
+  for k,v in next,t do
+   if v then
+    s=s.." "..k
+   end
   end
+  local n=nums[s]
+  if not n then
+   n=#tabs+1
+   tabs[n]=t
+   nums[s]=n
+  end
+  return n
+ else
+  return 0
+ end
 end
 function set.totable(n)
-  if n==0 then
-    return {}
-  else
-    return tabs[n] or {}
-  end
+ if n==0 then
+  return {}
+ else
+  return tabs[n] or {}
+ end
 end
 function set.tolist(n)
-  if n==0 or not tabs[n] then
-    return ""
-  else
-    local t,n={},0
-    for k,v in next,tabs[n] do
-      if v then
-        n=n+1
-        t[n]=k
-      end
-    end
-    return concat(t," ")
+ if n==0 or not tabs[n] then
+  return ""
+ else
+  local t,n={},0
+  for k,v in next,tabs[n] do
+   if v then
+    n=n+1
+    t[n]=k
+   end
   end
+  return concat(t," ")
+ end
 end
 function set.contains(n,s)
-  if type(n)=="table" then
-    return n[s]
-  elseif n==0 then
-    return false
-  else
-    local t=tabs[n]
-    return t and t[s]
-  end
+ if type(n)=="table" then
+  return n[s]
+ elseif n==0 then
+  return false
+ else
+  local t=tabs[n]
+  return t and t[s]
+ end
 end
 
 
@@ -3556,14 +3765,14 @@
 
 package.loaded["l-os"] = package.loaded["l-os"] or true
 
--- original size: 16268, stripped down to: 9246
+-- original size: 19347, stripped down to: 10258
 
 if not modules then modules={} end modules ['l-os']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 os=os
 local date,time=os.date,os.time
@@ -3571,242 +3780,305 @@
 local concat=table.concat
 local random,ceil,randomseed=math.random,math.ceil,math.randomseed
 local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring
-math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
-randomseed(math.initialseed)
-if not os.__getenv__ then
-  os.__getenv__=os.getenv
-  os.__setenv__=os.setenv
-  if os.env then
-    local osgetenv=os.getenv
-    local ossetenv=os.setenv
-    local osenv=os.env   local _=osenv.PATH 
-    function os.setenv(k,v)
-      if v==nil then
-        v=""
-      end
-      local K=upper(k)
-      osenv[K]=v
-      if type(v)=="table" then
-        v=concat(v,";") 
-      end
-      ossetenv(K,v)
+do
+ local selfdir=os.selfdir
+ if selfdir=="" then
+  selfdir=nil
+ end
+ if not selfdir then
+  if arg then
+   for i=1,#arg do
+    local a=arg[i]
+    if find(a,"^%-%-[c:]*texmfbinpath=") then
+     selfdir=gsub(a,"^.-=","")
+     break
     end
-    function os.getenv(k)
-      local K=upper(k)
-      local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
-      if v=="" then
-        return nil
-      else
-        return v
-      end
+   end
+  end
+  if not selfdir then
+   selfdir=os.selfbin or "luatex"
+   if find(selfdir,"[/\\]") then
+    selfdir=gsub(selfdir,"[/\\][^/\\]*$","")
+   elseif os.getenv then
+    local path=os.getenv("PATH")
+    local name=gsub(selfdir,"^.*[/\\][^/\\]","")
+    local patt="[^:]+"
+    if os.type=="windows" then
+     patt="[^;]+"
+     name=name..".exe"
     end
-  else
-    local ossetenv=os.setenv
-    local osgetenv=os.getenv
-    local osenv={}
-    function os.setenv(k,v)
-      if v==nil then
-        v=""
+    local isfile
+    if lfs then
+     local attributes=lfs.attributes
+     isfile=function(name)
+      local a=attributes(name,"mode")
+      return a=="file" or a=="link" or nil
+     end
+    else
+     local open=io.open
+     isfile=function(name)
+      local f=open(name)
+      if f then
+       f:close()
+       return true
       end
-      local K=upper(k)
-      osenv[K]=v
+     end
     end
-    function os.getenv(k)
-      local K=upper(k)
-      local v=osenv[K] or osgetenv(K) or osgetenv(k)
-      if v=="" then
-        return nil
-      else
-        return v
-      end
+    for p in gmatch(path,patt) do
+     if isfile(p.."/"..name) then
+      selfdir=p
+      break
+     end
     end
-    local function __index(t,k)
-      return os.getenv(k)
-    end
-    local function __newindex(t,k,v)
-      os.setenv(k,v)
-    end
-    os.env={}
-    setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
+   end
   end
+  os.selfdir=selfdir or "."
+ end
 end
+math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+randomseed(math.initialseed)
+if not os.__getenv__ then
+ os.__getenv__=os.getenv
+ os.__setenv__=os.setenv
+ if os.env then
+  local osgetenv=os.getenv
+  local ossetenv=os.setenv
+  local osenv=os.env   local _=osenv.PATH 
+  function os.setenv(k,v)
+   if v==nil then
+    v=""
+   end
+   local K=upper(k)
+   osenv[K]=v
+   if type(v)=="table" then
+    v=concat(v,";") 
+   end
+   ossetenv(K,v)
+  end
+  function os.getenv(k)
+   local K=upper(k)
+   local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
+   if v=="" then
+    return nil
+   else
+    return v
+   end
+  end
+ else
+  local ossetenv=os.setenv
+  local osgetenv=os.getenv
+  local osenv={}
+  function os.setenv(k,v)
+   if v==nil then
+    v=""
+   end
+   local K=upper(k)
+   osenv[K]=v
+  end
+  function os.getenv(k)
+   local K=upper(k)
+   local v=osenv[K] or osgetenv(K) or osgetenv(k)
+   if v=="" then
+    return nil
+   else
+    return v
+   end
+  end
+  local function __index(t,k)
+   return os.getenv(k)
+  end
+  local function __newindex(t,k,v)
+   os.setenv(k,v)
+  end
+  os.env={}
+  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
+ 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") 
+ 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"
-  else
-    io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix"
-  end
+ if find(os.getenv("PATH"),";",1,true) then
+  io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "windows"
+ else
+  io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix"
+ end
 end
 os.type=os.type or (io.pathseparator==";"    and "windows") or "unix"
-os.name=os.name or (os.type=="windows" and "mswin" ) or "linux"
+os.name=os.name or (os.type=="windows" and "mswin"  ) or "linux"
 if os.type=="windows" then
-  os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
+ os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
 else
-  os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
+ os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
 end
 local launchers={
-  windows="start %s",
-  macosx="open %s",
-  unix="$BROWSER %s &> /dev/null &",
+ windows="start %s",
+ macosx="open %s",
+ unix="xdg-open %s &> /dev/null &",
 }
 function os.launch(str)
-  execute(format(launchers[os.name] or launchers.unix,str))
+ execute(format(launchers[os.name] or launchers.unix,str))
 end
 if not os.times then
-  function os.times()
-    return {
-      utime=os.gettimeofday(),
-      stime=0,
-      cutime=0,
-      cstime=0,
-    }
-  end
+ function os.times()
+  return {
+   utime=os.gettimeofday(),
+   stime=0,
+   cutime=0,
+   cstime=0,
+  }
+ end
 end
 local gettimeofday=os.gettimeofday or os.clock
 os.gettimeofday=gettimeofday
 local startuptime=gettimeofday()
 function os.runtime()
-  return gettimeofday()-startuptime
+ 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 
+ 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
+ os.platform=platform
 elseif os.type=="windows" then
-  function resolvers.platform(t,k)
-    local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or ""
-    if find(architecture,"AMD64",1,true) then
-      platform="win64"
-    else
-      platform="mswin"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ function resolvers.platform(t,k)
+  local architecture=os.getenv("PROCESSOR_ARCHITECTURE") or ""
+  local platform=""
+  if find(architecture,"AMD64",1,true) then
+   platform="win64"
+  else
+   platform="mswin"
   end
+  os.setenv("MTX_PLATFORM",platform)
+  os.platform=platform
+  return platform
+ end
 elseif name=="linux" then
-  function resolvers.platform(t,k)
-    local platform,architecture="",os.getenv("HOSTTYPE") or resultof("uname -m") or ""
-    if find(architecture,"x86_64",1,true) then
-      platform="linux-64"
-    elseif find(architecture,"ppc",1,true) then
-      platform="linux-ppc"
-    else
-      platform="linux"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ function resolvers.platform(t,k)
+  local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+  local platform=os.getenv("MTX_PLATFORM") 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"
+  else
+   platform=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 platform,architecture="",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"
-    else
-      platform="osx-ppc"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ function resolvers.platform(t,k)
+  local architecture=resultof("echo $HOSTTYPE") or ""
+  local platform=""
+  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"
+  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 platform,architecture="",resultof("uname -m") or ""
-    if find(architecture,"sparc",1,true) then
-      platform="solaris-sparc"
-    else 
-      platform="solaris-intel"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ function resolvers.platform(t,k)
+  local architecture=resultof("uname -m") or ""
+  local platform=""
+  if find(architecture,"sparc",1,true) then
+   platform="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 platform,architecture="",resultof("uname -m") or ""
-    if find(architecture,"amd64",1,true) then
-      platform="freebsd-amd64"
-    else
-      platform="freebsd"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ function resolvers.platform(t,k)
+  local architecture=resultof("uname -m") or ""
+  local platform=""
+  if find(architecture,"amd64",1,true) then
+   platform="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 platform,architecture="",os.getenv("HOSTTYPE") or resultof("uname -m") or ""
-    if find(architecture,"x86_64",1,true) then
-      platform="kfreebsd-amd64"
-    else
-      platform="kfreebsd-i386"
-    end
-    os.setenv("MTX_PLATFORM",platform)
-    os.platform=platform
-    return platform
+ 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"
+  else
+   platform="kfreebsd-i386"
   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
-  end
+ function resolvers.platform(t,k)
+  local platform="linux"
+  os.setenv("MTX_PLATFORM",platform)
+  os.platform=platform
+  return platform
+ 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
+ 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)
-  )
+ 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(tonumber(date("%H")-date("!%H")))
-  if delta then
-    if d>0 then
-      return format("+%02i:00",d)
-    else
-      return format("-%02i:00",-d)
-    end
+ d=d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+  if d>0 then
+   return format("+%02i:00",d)
   else
-    return 1
+   return format("-%02i:00",-d)
   end
+ else
+  return 1
+ end
 end
 local timeformat=format("%%s%s",os.timezone(true))
 local dateformat="!%Y-%m-%d %H:%M:%S"
@@ -3813,116 +4085,130 @@
 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
+ 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
+ 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
+ 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
-        end
-      end
+ 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
     end
-    if not fullname then
-      fullname=false
-    end
-    memory[filename]=fullname
+   end
   end
-  return fullname
+  if not fullname then
+   fullname=false
+  end
+  memory[filename]=fullname
+ end
+ return fullname
 end
 os.which=which
 os.where=which
 function os.today()
-  return date("!*t") 
+ return date("!*t") 
 end
 function os.now()
-  return date("!%Y-%m-%d %H:%M:%S") 
+ return date("!%Y-%m-%d %H:%M:%S") 
 end
 if not os.sleep then
-  local socket=socket
-  function os.sleep(n)
-    if not socket then
-      socket=require("socket")
-    end
-    socket.sleep(n)
+ local socket=socket
+ function os.sleep(n)
+  if not socket then
+   socket=require("socket")
   end
+  socket.sleep(n)
+ end
 end
 local function isleapyear(year)
-  return (year%4==0) and (year%100~=0 or year%400==0)
+ 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)
-  if not month then
-    return isleapyear(year) and 365 or 364
-  else
-    return month==2 and isleapyear(year) and 29 or days[month]
-  end
+ if not month then
+  return isleapyear(year) and 365 or 364
+ else
+  return month==2 and isleapyear(year) and 29 or days[month]
+ end
 end
 os.nofdays=nofdays
 function os.weekday(day,month,year)
-  return date("%w",time { year=year,month=month,day=day })+1
+ 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
+ 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
-  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
+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)
+ end
+ if c~=nil then
+  return osexit(c)
+ end
+ return osexit()
+end
 
 
 end -- of closure
@@ -3931,19 +4217,19 @@
 
 package.loaded["l-file"] = package.loaded["l-file"] or true
 
--- original size: 21616, stripped down to: 10359
+-- original size: 21804, stripped down to: 9980
 
 if not modules then modules={} end modules ['l-file']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 file=file or {}
 local file=file
 if not lfs then
-  lfs=optionalrequire("lfs")
+ lfs=optionalrequire("lfs")
 end
 local insert,concat=table.insert,table.concat
 local match,find,gmatch=string.match,string.find,string.gmatch
@@ -3951,25 +4237,23 @@
 local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
 local checkedsplit=string.checkedsplit
 local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
-local tricky=S("/\\")*P(-1)
 local attributes=lfs.attributes
-if sandbox then
-  sandbox.redefine(lfs.isfile,"lfs.isfile")
-  sandbox.redefine(lfs.isdir,"lfs.isdir")
-end
 function lfs.isdir(name)
-  if lpegmatch(tricky,name) then
-    return attributes(name,"mode")=="directory"
-  else
-    return attributes(name.."/.","mode")=="directory"
-  end
+ return attributes(name,"mode")=="directory"
 end
 function lfs.isfile(name)
-  return attributes(name,"mode")=="file"
+ local a=attributes(name,"mode")
+ return a=="file" or a=="link" or nil
 end
 function lfs.isfound(name)
-  return attributes(name,"mode")=="file" and name or nil
+ local a=attributes(name,"mode")
+ return (a=="file" or a=="link") and name or nil
 end
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir,"lfs.isdir")
+ sandbox.redefine(lfs.isfound,"lfs.isfound")
+end
 local colon=P(":")
 local period=P(".")
 local periods=P("..")
@@ -3982,27 +4266,27 @@
 local suffix=period/""*(1-period-slashes)^1*-1
 local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1) 
 local function pathpart(name,default)
-  return name and lpegmatch(pattern,name) or default or ""
+ return name and lpegmatch(pattern,name) or default or ""
 end
 local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1
 local function basename(name)
-  return name and lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
 end
 local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0
 local function nameonly(name)
-  return name and lpegmatch(pattern,name) or name
+ return name and lpegmatch(pattern,name) or name
 end
 local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1
 local function suffixonly(name)
-  return name and lpegmatch(pattern,name) or ""
+ return name and lpegmatch(pattern,name) or ""
 end
 local pattern=(noslashes^0*slashes)^0*noperiod^1*((period*C(noperiod^1))^1)*-1+Cc("")
 local function suffixesonly(name)
-  if name then
-    return lpegmatch(pattern,name)
-  else
-    return ""
-  end
+ if name then
+  return lpegmatch(pattern,name)
+ else
+  return ""
+ end
 end
 file.pathpart=pathpart
 file.basename=basename
@@ -4011,7 +4295,7 @@
 file.suffix=suffixonly
 file.suffixesonly=suffixesonly
 file.suffixes=suffixesonly
-file.dirname=pathpart  
+file.dirname=pathpart   
 file.extname=suffixonly
 local drive=C(R("az","AZ"))*colon
 local path=C((noslashes^0*slashes)^0)
@@ -4027,142 +4311,142 @@
 local pattern_c=C(drive*path)*C(base*suffix) 
 local pattern_d=path*rest
 function file.splitname(str,splitdrive)
-  if not str then
-  elseif splitdrive then
-    return lpegmatch(pattern_a,str) 
-  else
-    return lpegmatch(pattern_b,str) 
-  end
+ if not str then
+ elseif splitdrive then
+  return lpegmatch(pattern_a,str) 
+ else
+  return lpegmatch(pattern_b,str) 
+ end
 end
 function file.splitbase(str)
-  if str then
-    return lpegmatch(pattern_d,str) 
-  else
-    return "",str 
-  end
+ if str then
+  return lpegmatch(pattern_d,str) 
+ else
+  return "",str 
+ end
 end
 function file.nametotable(str,splitdrive)
-  if str then
-    local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
-    if splitdrive then
-      return {
-        path=path,
-        drive=drive,
-        subpath=subpath,
-        name=name,
-        base=base,
-        suffix=suffix,
-      }
-    else
-      return {
-        path=path,
-        name=name,
-        base=base,
-        suffix=suffix,
-      }
-    end
+ if str then
+  local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
+  if splitdrive then
+   return {
+    path=path,
+    drive=drive,
+    subpath=subpath,
+    name=name,
+    base=base,
+    suffix=suffix,
+   }
+  else
+   return {
+    path=path,
+    name=name,
+    base=base,
+    suffix=suffix,
+   }
   end
+ end
 end
 local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1)
 function file.removesuffix(name)
-  return name and lpegmatch(pattern,name)
+ return name and lpegmatch(pattern,name)
 end
 local suffix=period/""*(1-period-slashes)^1*-1
 local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix)
 function file.addsuffix(filename,suffix,criterium)
-  if not filename or not suffix or suffix=="" then
-    return filename
-  elseif criterium==true then
-    return filename.."."..suffix
-  elseif not criterium then
-    local n,s=lpegmatch(pattern,filename)
-    if not s or s=="" then
-      return filename.."."..suffix
-    else
+ if not filename or not suffix or suffix=="" then
+  return filename
+ elseif criterium==true then
+  return filename.."."..suffix
+ elseif not criterium then
+  local n,s=lpegmatch(pattern,filename)
+  if not s or s=="" then
+   return filename.."."..suffix
+  else
+   return filename
+  end
+ else
+  local n,s=lpegmatch(pattern,filename)
+  if s and s~="" then
+   local t=type(criterium)
+   if t=="table" then
+    for i=1,#criterium do
+     if s==criterium[i] then
       return filename
+     end
     end
-  else
-    local n,s=lpegmatch(pattern,filename)
-    if s and s~="" then
-      local t=type(criterium)
-      if t=="table" then
-        for i=1,#criterium do
-          if s==criterium[i] then
-            return filename
-          end
-        end
-      elseif t=="string" then
-        if s==criterium then
-          return filename
-        end
-      end
+   elseif t=="string" then
+    if s==criterium then
+     return filename
     end
-    return (n or filename).."."..suffix
+   end
   end
+  return (n or filename).."."..suffix
+ end
 end
 local suffix=period*(1-period-slashes)^1*-1
 local pattern=Cs((1-suffix)^0)
 function file.replacesuffix(name,suffix)
-  if name and suffix and suffix~="" then
-    return lpegmatch(pattern,name).."."..suffix
-  else
-    return name
-  end
+ if name and suffix and suffix~="" then
+  return lpegmatch(pattern,name).."."..suffix
+ else
+  return name
+ end
 end
 local reslasher=lpeg.replacer(P("\\"),"/")
 function file.reslash(str)
-  return str and lpegmatch(reslasher,str)
+ return str and lpegmatch(reslasher,str)
 end
 function file.is_writable(name)
-  if not name then
-  elseif lfs.isdir(name) then
-    name=name.."/m_t_x_t_e_s_t.tmp"
-    local f=io.open(name,"wb")
-    if f then
-      f:close()
-      os.remove(name)
-      return true
-    end
-  elseif lfs.isfile(name) then
-    local f=io.open(name,"ab")
-    if f then
-      f:close()
-      return true
-    end
-  else
-    local f=io.open(name,"ab")
-    if f then
-      f:close()
-      os.remove(name)
-      return true
-    end
+ if not name then
+ elseif lfs.isdir(name) then
+  name=name.."/m_t_x_t_e_s_t.tmp"
+  local f=io.open(name,"wb")
+  if f then
+   f:close()
+   os.remove(name)
+   return true
   end
-  return false
+ elseif lfs.isfile(name) then
+  local f=io.open(name,"ab")
+  if f then
+   f:close()
+   return true
+  end
+ else
+  local f=io.open(name,"ab")
+  if f then
+   f:close()
+   os.remove(name)
+   return true
+  end
+ end
+ return false
 end
 local readable=P("r")*Cc(true)
 function file.is_readable(name)
-  if name then
-    local a=attributes(name)
-    return a and lpegmatch(readable,a.permissions) or false
-  else
-    return false
-  end
+ if name then
+  local a=attributes(name)
+  return a and lpegmatch(readable,a.permissions) or false
+ else
+  return false
+ end
 end
 file.isreadable=file.is_readable 
 file.iswritable=file.is_writable 
 function file.size(name)
-  if name then
-    local a=attributes(name)
-    return a and a.size or 0
-  else
-    return 0
-  end
+ if name then
+  local a=attributes(name)
+  return a and a.size or 0
+ else
+  return 0
+ end
 end
 function file.splitpath(str,separator) 
-  return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
 end
 function file.joinpath(tab,separator) 
-  return tab and concat(tab,separator or io.pathseparator) 
+ return tab and concat(tab,separator or io.pathseparator) 
 end
 local someslash=S("\\/")
 local stripper=Cs(P(fwslash)^0/""*reslasher)
@@ -4172,30 +4456,30 @@
 local reslasher=lpeg.replacer(S("\\/"),"/")
 local deslasher=lpeg.replacer(S("\\/")^1,"/")
 function file.join(one,two,three,...)
-  if not two then
-    return one=="" and one or lpegmatch(reslasher,one)
+ if not two then
+  return one=="" and one or lpegmatch(reslasher,one)
+ end
+ if one=="" then
+  return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
+ end
+ if lpegmatch(isnetwork,one) then
+  local one=lpegmatch(reslasher,one)
+  local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
+  if lpegmatch(hasroot,two) then
+   return one..two
+  else
+   return one.."/"..two
   end
-  if one=="" then
-    return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
-  end
-  if lpegmatch(isnetwork,one) then
-    local one=lpegmatch(reslasher,one)
-    local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
-    if lpegmatch(hasroot,two) then
-      return one..two
-    else
-      return one.."/"..two
-    end
-  elseif lpegmatch(isroot,one) then
-    local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
-    if lpegmatch(hasroot,two) then
-      return two
-    else
-      return "/"..two
-    end
+ elseif lpegmatch(isroot,one) then
+  local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
+  if lpegmatch(hasroot,two) then
+   return two
   else
-    return lpegmatch(deslasher,concat({ one,two,three,... },"/"))
+   return "/"..two
   end
+ else
+  return lpegmatch(deslasher,concat({  one,two,three,... },"/"))
+ end
 end
 local drivespec=R("az","AZ")^1*colon
 local anchors=fwslash+drivespec
@@ -4205,56 +4489,56 @@
 local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
 local absolute=fwslash
 function file.collapsepath(str,anchor) 
-  if not str then
-    return
-  end
-  if anchor==true and not lpegmatch(anchors,str) then
-    str=getcurrentdir().."/"..str
-  end
-  if str=="" or str=="." then
-    return "."
-  elseif lpegmatch(untouched,str) then
-    return lpegmatch(reslasher,str)
-  end
-  local starter,oldelements=lpegmatch(splitstarter,str)
-  local newelements={}
-  local i=#oldelements
-  while i>0 do
-    local element=oldelements[i]
-    if element=='.' then
-    elseif element=='..' then
-      local n=i-1
-      while n>0 do
-        local element=oldelements[n]
-        if element~='..' and element~='.' then
-          oldelements[n]='.'
-          break
-        else
-          n=n-1
-        end
-       end
-      if n<1 then
-        insert(newelements,1,'..')
-      end
-    elseif element~="" then
-      insert(newelements,1,element)
+ if not str then
+  return
+ end
+ if anchor==true and not lpegmatch(anchors,str) then
+  str=getcurrentdir().."/"..str
+ end
+ if str=="" or str=="." then
+  return "."
+ elseif lpegmatch(untouched,str) then
+  return lpegmatch(reslasher,str)
+ end
+ local starter,oldelements=lpegmatch(splitstarter,str)
+ local newelements={}
+ local i=#oldelements
+ while i>0 do
+  local element=oldelements[i]
+  if element=='.' then
+  elseif element=='..' then
+   local n=i-1
+   while n>0 do
+    local element=oldelements[n]
+    if element~='..' and element~='.' then
+     oldelements[n]='.'
+     break
+    else
+     n=n-1
     end
-    i=i-1
+    end
+   if n<1 then
+      insert(newelements,1,'..')
+   end
+  elseif element~="" then
+   insert(newelements,1,element)
   end
-  if #newelements==0 then
-    return starter or "."
-  elseif starter then
-    return starter..concat(newelements,'/')
-  elseif lpegmatch(absolute,str) then
-    return "/"..concat(newelements,'/')
+  i=i-1
+ end
+ if #newelements==0 then
+  return starter or "."
+ elseif starter then
+  return starter..concat(newelements,'/')
+ elseif lpegmatch(absolute,str) then
+  return "/"..concat(newelements,'/')
+ else
+  newelements=concat(newelements,'/')
+  if anchor=="." and find(str,"^%./") then
+   return "./"..newelements
   else
-    newelements=concat(newelements,'/')
-    if anchor=="." and find(str,"^%./") then
-      return "./"..newelements
-    else
-      return newelements
-    end
+   return newelements
   end
+ end
 end
 local validchars=R("az","09","AZ","--","..")
 local pattern_a=lpeg.replacer(1-validchars)
@@ -4262,14 +4546,14 @@
 local whatever=P("-")^0/""
 local pattern_b=Cs(whatever*(1-whatever*-1)^1)
 function file.robustname(str,strict)
-  if str then
-    str=lpegmatch(pattern_a,str) or str
-    if strict then
-      return lpegmatch(pattern_b,str) or str 
-    else
-      return str
-    end
+ if str then
+  str=lpegmatch(pattern_a,str) or str
+  if strict then
+   return lpegmatch(pattern_b,str) or str 
+  else
+   return str
   end
+ end
 end
 local loaddata=io.loaddata
 local savedata=io.savedata
@@ -4276,12 +4560,12 @@
 file.readdata=loaddata
 file.savedata=savedata
 function file.copy(oldname,newname)
-  if oldname and newname then
-    local data=loaddata(oldname)
-    if data and data~="" then
-      savedata(newname,data)
-    end
+ if oldname and newname then
+  local data=loaddata(oldname)
+  if data and data~="" then
+   savedata(newname,data)
   end
+ end
 end
 local letter=R("az","AZ")+S("_-+")
 local separator=P("://")
@@ -4290,41 +4574,45 @@
 lpeg.patterns.qualified=qualified
 lpeg.patterns.rootbased=rootbased
 function file.is_qualified_path(filename)
-  return filename and lpegmatch(qualified,filename)~=nil
+ return filename and lpegmatch(qualified,filename)~=nil
 end
 function file.is_rootbased_path(filename)
-  return filename and lpegmatch(rootbased,filename)~=nil
+ return filename and lpegmatch(rootbased,filename)~=nil
 end
 function file.strip(name,dir)
-  if name then
-    local b,a=match(name,"^(.-)"..dir.."(.*)$")
-    return a~="" and a or name
-  end
+ if name then
+  local b,a=match(name,"^(.-)"..dir.."(.*)$")
+  return a~="" and a or name
+ end
 end
 function lfs.mkdirs(path)
-  local full=""
-  for sub in gmatch(path,"(/*[^\\/]+)") do 
-    full=full..sub
-    lfs.mkdir(full)
-  end
+ local full=""
+ for sub in gmatch(path,"(/*[^\\/]+)") do 
+  full=full..sub
+  lfs.mkdir(full)
+ end
 end
 function file.withinbase(path) 
-  local l=0
-  if not find(path,"^/") then
-    path="/"..path
+ local l=0
+ if not find(path,"^/") then
+  path="/"..path
+ end
+ for dir in gmatch(path,"/([^/]+)") do
+  if dir==".." then
+   l=l-1
+  elseif dir~="." then
+   l=l+1
   end
-  for dir in gmatch(path,"/([^/]+)") do
-    if dir==".." then
-      l=l-1
-    elseif dir~="." then
-      l=l+1
-    end
-    if l<0 then
-      return false
-    end
+  if l<0 then
+   return false
   end
-  return true
+ end
+ return true
 end
+local symlinkattributes=lfs.symlinkattributes
+function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+end
 
 
 end -- of closure
@@ -4333,51 +4621,51 @@
 
 package.loaded["l-gzip"] = package.loaded["l-gzip"] or true
 
--- original size: 1211, stripped down to: 1002
+-- original size: 1211, stripped down to: 951
 
 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"
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 if not gzip then
-  return
+ return
 end
 local suffix,suffixes=file.suffix,file.suffixes
 function gzip.load(filename)
-  local f=io.open(filename,"rb")
-  if not f then
-  elseif suffix(filename)=="gz" then
-    f:close()
-    local g=gzip.open(filename,"rb")
-    if g then
-      local str=g:read("*all")
-      g:close()
-      return str
-    end
-  else
-    local str=f:read("*all")
-    f:close()
-    return str
+ local f=io.open(filename,"rb")
+ if not f then
+ elseif suffix(filename)=="gz" then
+  f:close()
+  local g=gzip.open(filename,"rb")
+  if g then
+   local str=g:read("*all")
+   g:close()
+   return str
   end
+ else
+  local str=f:read("*all")
+  f:close()
+  return str
+ end
 end
 function gzip.save(filename,data)
-  if suffix(filename)~="gz" then
-    filename=filename..".gz"
-  end
-  local f=io.open(filename,"wb")
-  if f then
-    local s=zlib.compress(data or "",9,nil,15+16)
-    f:write(s)
-    f:close()
-    return #s
-  end
+ if suffix(filename)~="gz" then
+  filename=filename..".gz"
+ end
+ local f=io.open(filename,"wb")
+ if f then
+  local s=zlib.compress(data or "",9,nil,15+16)
+  f:write(s)
+  f:close()
+  return #s
+ end
 end
 function gzip.suffix(filename)
-  local suffix,extra=suffixes(filename)
-  local gzipped=extra=="gz"
-  return suffix,gzipped
+ local suffix,extra=suffixes(filename)
+ local gzipped=extra=="gz"
+ return suffix,gzipped
 end
 
 
@@ -4387,87 +4675,87 @@
 
 package.loaded["l-md5"] = package.loaded["l-md5"] or true
 
--- original size: 3309, stripped down to: 2314
+-- original size: 3309, stripped down to: 2218
 
 if not modules then modules={} end modules ['l-md5']={
-  version=1.001,
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 if not md5 then
-  md5=optionalrequire("md5")
+ md5=optionalrequire("md5")
 end
 if not md5 then
-  md5={
-    sum=function(str) print("error: md5 is not loaded (sum     ignored)") return str end,
-    sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
-  }
+ md5={
+  sum=function(str) print("error: md5 is not loaded (sum     ignored)") return str end,
+  sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
+ }
 end
 local md5,file=md5,file
 local gsub=string.gsub
 do
-  local patterns=lpeg and lpeg.patterns
-  if patterns then
-    local bytestoHEX=patterns.bytestoHEX
-    local bytestohex=patterns.bytestohex
-    local bytestodec=patterns.bytestodec
-    local lpegmatch=lpeg.match
-    local md5sum=md5.sum
-    if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
-    if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
-    if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
-    md5.sumhexa=md5.hex
-    md5.sumHEXA=md5.HEX
-  end
+ local patterns=lpeg and lpeg.patterns
+ if patterns then
+  local bytestoHEX=patterns.bytestoHEX
+  local bytestohex=patterns.bytestohex
+  local bytestodec=patterns.bytestodec
+  local lpegmatch=lpeg.match
+  local md5sum=md5.sum
+  if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
+  if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
+  if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
+  md5.sumhexa=md5.hex
+  md5.sumHEXA=md5.HEX
+ end
 end
 function file.needsupdating(oldname,newname,threshold) 
-  local oldtime=lfs.attributes(oldname,"modification")
-  if oldtime then
-    local newtime=lfs.attributes(newname,"modification")
-    if not newtime then
-      return true 
-    elseif newtime>=oldtime then
-      return false 
-    elseif oldtime-newtime<(threshold or 1) then
-      return false 
-    else
-      return true 
-    end
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime then
+  local newtime=lfs.attributes(newname,"modification")
+  if not newtime then
+   return true 
+  elseif newtime>=oldtime then
+   return false 
+  elseif oldtime-newtime<(threshold or 1) then
+   return false 
   else
-    return false 
+   return true 
   end
+ else
+  return false 
+ end
 end
 file.needs_updating=file.needsupdating
 function file.syncmtimes(oldname,newname)
-  local oldtime=lfs.attributes(oldname,"modification")
-  if oldtime and lfs.isfile(newname) then
-    lfs.touch(newname,oldtime,oldtime)
-  end
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+  lfs.touch(newname,oldtime,oldtime)
+ end
 end
 function file.checksum(name)
-  if md5 then
-    local data=io.loaddata(name)
-    if data then
-      return md5.HEX(data)
-    end
+ if md5 then
+  local data=io.loaddata(name)
+  if data then
+   return md5.HEX(data)
   end
-  return nil
+ end
+ return nil
 end
 function file.loadchecksum(name)
-  if md5 then
-    local data=io.loaddata(name..".md5")
-    return data and (gsub(data,"%s",""))
-  end
-  return nil
+ if md5 then
+  local data=io.loaddata(name..".md5")
+  return data and (gsub(data,"%s",""))
+ end
+ return nil
 end
 function file.savechecksum(name,checksum)
-  if not checksum then checksum=file.checksum(name) end
-  if checksum then
-    io.savedata(name..".md5",checksum)
-    return checksum
-  end
-  return nil
+ if not checksum then checksum=file.checksum(name) end
+ if checksum then
+  io.savedata(name..".md5",checksum)
+  return checksum
+ end
+ return nil
 end
 
 
@@ -4475,16 +4763,48 @@
 
 do -- create closure to overcome 200 locals limit
 
+package.loaded["l-sha"] = package.loaded["l-sha"] or true
+
+-- original size: 1085, stripped down to: 969
+
+if not modules then modules={} end modules ['l-sha']={
+ version=1.001,
+ 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"
+}
+if sha2 then
+ local lpegmatch=lpeg.match
+ local lpegpatterns=lpeg.patterns
+ local bytestohex=lpegpatterns.bytestohex
+ local bytestoHEX=lpegpatterns.bytestoHEX
+ local digest256=sha2.digest256
+ local digest384=sha2.digest384
+ local digest512=sha2.digest512
+ sha2.hash256=function(str) return lpegmatch(bytestohex,digest256(str)) end
+ sha2.hash384=function(str) return lpegmatch(bytestohex,digest384(str)) end
+ sha2.hash512=function(str) return lpegmatch(bytestohex,digest512(str)) end
+ sha2.HASH256=function(str) return lpegmatch(bytestoHEX,digest256(str)) end
+ sha2.HASH384=function(str) return lpegmatch(bytestoHEX,digest384(str)) end
+ sha2.HASH512=function(str) return lpegmatch(bytestoHEX,digest512(str)) end
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
 package.loaded["l-url"] = package.loaded["l-url"] or true
 
--- original size: 14755, stripped down to: 7236
+-- original size: 14755, stripped down to: 6981
 
 if not modules then modules={} end modules ['l-url']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 char,format,byte=string.char,string.format,string.byte
 local concat=table.concat
@@ -4497,14 +4817,14 @@
 local unescapes={}
 local escapes={}
 setmetatable(unescapes,{ __index=function(t,k)
-  local v=char(tonumber(k,16))
-  t[k]=v
-  return v
+ local v=char(tonumber(k,16))
+ t[k]=v
+ return v
 end })
 setmetatable(escapes,{ __index=function(t,k)
-  local v=format("%%%02X",byte(k))
-  t[k]=v
-  return v
+ local v=format("%%%02X",byte(k))
+ t[k]=v
+ return v
 end })
 local colon=P(":")
 local qmark=P("?")
@@ -4523,21 +4843,21 @@
 local noslash=P("/")/""
 local plustospace=P("+")/" "
 local decoder=Cs((
-          plustospace+escapedchar+P("\r\n")/"\n"+P(1)
-        )^0 )
+     plustospace+escapedchar+P("\r\n")/"\n"+P(1)
+    )^0 )
 local encoder=Cs((
-          R("09","AZ","az")^1+S("-./_")^1+P(" ")/"+"+P("\n")/"\r\n"+unescapedchar
-        )^0 )
+     R("09","AZ","az")^1+S("-./_")^1+P(" ")/"+"+P("\n")/"\r\n"+unescapedchar
+    )^0 )
 lpegpatterns.urldecoder=decoder
 lpegpatterns.urlencoder=encoder
-function url.decode (str) return str and lpegmatch(decoder,str) or str end
-function url.encode (str) return str and lpegmatch(encoder,str) or str end
+function url.decode  (str) return str and lpegmatch(decoder,str) or str end
+function url.encode  (str) return str and lpegmatch(encoder,str) or str end
 function url.unescape(str) return str and lpegmatch(unescaper,str) or str end
 local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2)
 local authoritystr=Cs((escaped+(1-   slash-qmark-hash))^0)
-local pathstr=Cs((escaped+(1-      qmark-hash))^0)
-local querystr=Cs(((1-         hash))^0)
-local fragmentstr=Cs((escaped+(1-      endofstring))^0)
+local pathstr=Cs((escaped+(1-   qmark-hash))^0)
+local querystr=Cs(((1-      hash))^0)
+local fragmentstr=Cs((escaped+(1-     endofstring))^0)
 local scheme=schemestr*colon+nothing
 local authority=slash*slash*authoritystr+nothing
 local path=slash*pathstr+nothing
@@ -4555,19 +4875,19 @@
 lpegpatterns.urlunescaper=unescaper
 lpegpatterns.urlgetcleaner=getcleaner
 function url.unescapeget(str)
-  return lpegmatch(getcleaner,str)
+ return lpegmatch(getcleaner,str)
 end
 local function split(str)
-  return (type(str)=="string" and lpegmatch(parser,str)) or str
+ return (type(str)=="string" and lpegmatch(parser,str)) or str
 end
 local isscheme=schemestr*colon*slash*slash 
 local function hasscheme(str)
-  if str then
-    local scheme=lpegmatch(isscheme,str) 
-    return scheme~="" and scheme or false
-  else
-    return false
-  end
+ if str then
+  local scheme=lpegmatch(isscheme,str) 
+  return scheme~="" and scheme or false
+ else
+  return false
+ end
 end
 local rootletter=R("az","AZ")+S("_-+")
 local separator=P("://")
@@ -4577,161 +4897,161 @@
 local backslashswapper=replacer("\\","/")
 local equal=P("=")
 local amp=P("&")
-local key=Cs(((plustospace+escapedchar+1)-equal       )^0)
+local key=Cs(((plustospace+escapedchar+1)-equal     )^0)
 local value=Cs(((plustospace+escapedchar+1)-amp-endofstring)^0)
 local splitquery=Cf (Ct("")*P { "sequence",
-  sequence=V("pair")*(amp*V("pair"))^0,
-  pair=Cg(key*equal*value),
+ sequence=V("pair")*(amp*V("pair"))^0,
+ pair=Cg(key*equal*value),
 },rawset)
 local userpart=(1-atsign-colon)^1
 local serverpart=(1-colon)^1
 local splitauthority=((Cs(userpart)*colon*Cs(userpart)+Cs(userpart)*Cc(nil))*atsign+Cc(nil)*Cc(nil))*Cs(serverpart)*(colon*(serverpart/tonumber)+Cc(nil))
 local function hashed(str) 
-  if not str or str=="" then
-    return {
-      scheme="invalid",
-      original=str,
-    }
-  end
-  local detailed=split(str)
-  local rawscheme=""
-  local rawquery=""
-  local somescheme=false
-  local somequery=false
-  if detailed then
-    rawscheme=detailed[1]
-    rawquery=detailed[4]
-    somescheme=rawscheme~=""
-    somequery=rawquery~=""
-  end
-  if not somescheme and not somequery then
-    return {
-      scheme="file",
-      authority="",
-      path=str,
-      query="",
-      fragment="",
-      original=str,
-      noscheme=true,
-      filename=str,
-    }
-  end
-  local authority=detailed[2]
-  local path=detailed[3]
-  local filename 
-  local username 
-  local password 
-  local host   
-  local port   
-  if authority~="" then
-    username,password,host,port=lpegmatch(splitauthority,authority)
-  end
-  if authority=="" then
-    filename=path
-  elseif path=="" then
-    filename=""
-  else
-    filename=authority.."/"..path
-  end
+ if not str or str=="" then
   return {
-    scheme=rawscheme,
-    authority=authority,
-    path=path,
-    query=lpegmatch(unescaper,rawquery),
-    queries=lpegmatch(splitquery,rawquery),
-    fragment=detailed[5],
-    original=str,
-    noscheme=false,
-    filename=filename,
-    host=host,
-    port=port,
+   scheme="invalid",
+   original=str,
   }
+ end
+ local detailed=split(str)
+ local rawscheme=""
+ local rawquery=""
+ local somescheme=false
+ local somequery=false
+ if detailed then
+  rawscheme=detailed[1]
+  rawquery=detailed[4]
+  somescheme=rawscheme~=""
+  somequery=rawquery~=""
+ end
+ if not somescheme and not somequery then
+  return {
+   scheme="file",
+   authority="",
+   path=str,
+   query="",
+   fragment="",
+   original=str,
+   noscheme=true,
+   filename=str,
+  }
+ end
+ local authority=detailed[2]
+ local path=detailed[3]
+ local filename  
+ local username  
+ local password  
+ local host   
+ local port   
+ if authority~="" then
+  username,password,host,port=lpegmatch(splitauthority,authority)
+ end
+ if authority=="" then
+  filename=path
+ elseif path=="" then
+  filename=""
+ else
+  filename=authority.."/"..path
+ end
+ return {
+  scheme=rawscheme,
+  authority=authority,
+  path=path,
+  query=lpegmatch(unescaper,rawquery),
+  queries=lpegmatch(splitquery,rawquery),
+  fragment=detailed[5],
+  original=str,
+  noscheme=false,
+  filename=filename,
+  host=host,
+  port=port,
+ }
 end
 url.split=split
 url.hasscheme=hasscheme
 url.hashed=hashed
 function url.addscheme(str,scheme) 
-  if hasscheme(str) then
-    return str
-  elseif not scheme then
-    return "file:///"..str
-  else
-    return scheme..":///"..str
-  end
+ if hasscheme(str) then
+  return str
+ elseif not scheme then
+  return "file:///"..str
+ else
+  return scheme..":///"..str
+ end
 end
 function url.construct(hash) 
-  local result,r={},0
-  local scheme=hash.scheme
-  local authority=hash.authority
-  local path=hash.path
-  local queries=hash.queries
-  local fragment=hash.fragment
-  if scheme and scheme~="" then
-    r=r+1;result[r]=lpegmatch(escaper,scheme)
-    r=r+1;result[r]="://"
+ local result,r={},0
+ local scheme=hash.scheme
+ local authority=hash.authority
+ local path=hash.path
+ local queries=hash.queries
+ local fragment=hash.fragment
+ if scheme and scheme~="" then
+  r=r+1;result[r]=lpegmatch(escaper,scheme)
+  r=r+1;result[r]="://"
+ end
+ if authority and authority~="" then
+  r=r+1;result[r]=lpegmatch(escaper,authority)
+ end
+ if path and path~="" then
+  r=r+1;result[r]="/"
+  r=r+1;result[r]=lpegmatch(escaper,path)
+ end
+ if queries then
+  local done=false
+  for k,v in sortedhash(queries) do
+   r=r+1;result[r]=done and "&" or "?"
+   r=r+1;result[r]=lpegmatch(escaper,k) 
+   r=r+1;result[r]="="
+   r=r+1;result[r]=lpegmatch(escaper,v) 
+   done=true
   end
-  if authority and authority~="" then
-    r=r+1;result[r]=lpegmatch(escaper,authority)
-  end
-  if path and path~="" then
-    r=r+1;result[r]="/"
-    r=r+1;result[r]=lpegmatch(escaper,path)
-  end
-  if queries then
-    local done=false
-    for k,v in sortedhash(queries) do
-      r=r+1;result[r]=done and "&" or "?"
-      r=r+1;result[r]=lpegmatch(escaper,k) 
-      r=r+1;result[r]="="
-      r=r+1;result[r]=lpegmatch(escaper,v) 
-      done=true
-    end
-  end
-  if fragment and fragment~="" then
-    r=r+1;result[r]="#"
-    r=r+1;result[r]=lpegmatch(escaper,fragment)
-  end
-  return concat(result)
+ end
+ if fragment and fragment~="" then
+  r=r+1;result[r]="#"
+  r=r+1;result[r]=lpegmatch(escaper,fragment)
+ end
+ return concat(result)
 end
 local pattern=Cs(slash^-1/""*R("az","AZ")*((S(":|")/":")+P(":"))*slash*P(1)^0)
 function url.filename(filename)
-  local spec=hashed(filename)
-  local path=spec.path
-  return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename
+ local spec=hashed(filename)
+ local path=spec.path
+ return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename
 end
 local function escapestring(str)
-  return lpegmatch(escaper,str)
+ return lpegmatch(escaper,str)
 end
 url.escape=escapestring
 function url.query(str)
-  if type(str)=="string" then
-    return lpegmatch(splitquery,str) or ""
-  else
-    return str
-  end
+ if type(str)=="string" then
+  return lpegmatch(splitquery,str) or ""
+ else
+  return str
+ end
 end
 function url.toquery(data)
-  local td=type(data)
-  if td=="string" then
-    return #str and escape(data) or nil 
-  elseif td=="table" then
-    if next(data) then
-      local t={}
-      for k,v in next,data do
-        t[#t+1]=format("%s=%s",k,escapestring(v))
-      end
-      return concat(t,"&")
-    end
-  else
+ local td=type(data)
+ if td=="string" then
+  return #str and escape(data) or nil 
+ elseif td=="table" then
+  if next(data) then
+   local t={}
+   for k,v in next,data do
+    t[#t+1]=format("%s=%s",k,escapestring(v))
+   end
+   return concat(t,"&")
   end
+ else
+ end
 end
 local pattern=Cs(noslash^0*(1-noslash*P(-1))^0)
 function url.barepath(path)
-  if not path or path=="" then
-    return ""
-  else
-    return lpegmatch(pattern,path)
-  end
+ if not path or path=="" then
+  return ""
+ else
+  return lpegmatch(pattern,path)
+ end
 end
 
 
@@ -4741,14 +5061,14 @@
 
 package.loaded["l-dir"] = package.loaded["l-dir"] or true
 
--- original size: 17703, stripped down to: 11691
+-- original size: 18002, stripped down to: 10681
 
 if not modules then modules={} end modules ['l-dir']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 type,select=type,select
 local find,gmatch,match,gsub,sub=string.find,string.gmatch,string.match,string.gsub,string.sub
@@ -4760,7 +5080,7 @@
 local lfs=lfs
 local attributes=lfs.attributes
 local walkdir=lfs.dir
-local isdir=lfs.isdir 
+local isdir=lfs.isdir  
 local isfile=lfs.isfile 
 local currentdir=lfs.currentdir
 local chdir=lfs.chdir
@@ -4767,464 +5087,471 @@
 local mkdir=lfs.mkdir
 local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true)
 if onwindows then
-  local tricky=S("/\\")*P(-1)
-  isdir=function(name)
-    if lpegmatch(tricky,name) then
-      return attributes(name,"mode")=="directory"
-    else
-      return attributes(name.."/.","mode")=="directory"
-    end
+ local tricky=S("/\\")*P(-1)
+ isdir=function(name)
+  if lpegmatch(tricky,name) then
+   return attributes(name,"mode")=="directory"
+  else
+   return attributes(name.."/.","mode")=="directory"
   end
-  isfile=function(name)
-    return attributes(name,"mode")=="file"
-  end
-  lfs.isdir=isdir
-  lfs.isfile=isfile
+ end
+ isfile=function(name)
+  return attributes(name,"mode")=="file"
+ end
+ lfs.isdir=isdir
+ lfs.isfile=isfile
 else
-  isdir=function(name)
-    return attributes(name,"mode")=="directory"
-  end
-  isfile=function(name)
-    return attributes(name,"mode")=="file"
-  end
-  lfs.isdir=isdir
-  lfs.isfile=isfile
+ isdir=function(name)
+  return attributes(name,"mode")=="directory"
+ end
+ isfile=function(name)
+  return attributes(name,"mode")=="file"
+ end
+ lfs.isdir=isdir
+ lfs.isfile=isfile
 end
 function dir.current()
-  return (gsub(currentdir(),"\\","/"))
+ return (gsub(currentdir(),"\\","/"))
 end
 local function glob_pattern_function(path,patt,recurse,action)
-  if isdir(path) then
-    local usedpath
-    if path=="/" then
-      usedpath="/."
-    elseif not find(path,"/$") then
-      usedpath=path.."/."
-      path=path.."/"
-    else
-      usedpath=path
+ if isdir(path) then
+  local usedpath
+  if path=="/" then
+   usedpath="/."
+  elseif not find(path,"/$") then
+   usedpath=path.."/."
+   path=path.."/"
+  else
+   usedpath=path
+  end
+  local dirs
+  local nofdirs=0
+  for name in walkdir(usedpath) do
+   if name~="." and name~=".." then
+    local full=path..name
+    local mode=attributes(full,'mode')
+    if mode=='file' then
+     if not patt or find(full,patt) then
+      action(full)
+     end
+    elseif recurse and mode=="directory" then
+     if dirs then
+      nofdirs=nofdirs+1
+      dirs[nofdirs]=full
+     else
+      nofdirs=1
+      dirs={ full }
+     end
     end
-    local dirs
-    for name in walkdir(usedpath) do
-      if name~="." and name~=".." then
-        local full=path..name
-        local mode=attributes(full,'mode')
-        if mode=='file' then
-          if not patt or find(full,patt) then
-            action(full)
-          end
-        elseif recurse and mode=="directory" then
-          if not dirs then
-            dirs={ full }
-          else
-            dirs[#dirs+1]=full
-          end
-        end
-      end
-    end
-    if dirs then
-      for i=1,#dirs do
-        glob_pattern_function(dirs[i],patt,recurse,action)
-      end
-    end
+   end
   end
+  if dirs then
+   for i=1,nofdirs do
+    glob_pattern_function(dirs[i],patt,recurse,action)
+   end
+  end
+ end
 end
 local function glob_pattern_table(path,patt,recurse,result)
-  if not result then
-    result={}
-  end
-  if isdir(path) then
-    local usedpath
-    if path=="/" then
-      usedpath="/."
-    elseif not find(path,"/$") then
-      usedpath=path.."/."
-      path=path.."/"
-    else
-      usedpath=path
+ if not result then
+  result={}
+ end
+ local usedpath
+ if path=="/" then
+  usedpath="/."
+ elseif not find(path,"/$") then
+  usedpath=path.."/."
+  path=path.."/"
+ else
+  usedpath=path
+ end
+ local dirs
+ local nofdirs=0
+ local noffiles=#result
+ for name,a in walkdir(usedpath) do
+  if name~="." and name~=".." then
+   local full=path..name
+   local mode=attributes(full,'mode')
+   if mode=='file' then
+    if not patt or find(full,patt) then
+     noffiles=noffiles+1
+     result[noffiles]=full
     end
-    local dirs
-    for name in walkdir(usedpath) do
-      if name~="." and name~=".." then
-        local full=path..name
-        local mode=attributes(full,'mode')
-        if mode=='file' then
-          if not patt or find(full,patt) then
-            result[#result+1]=full
-          end
-        elseif recurse and mode=="directory" then
-          if not dirs then
-            dirs={ full }
-          else
-            dirs[#dirs+1]=full
-          end
-        end
-      end
-    end
+   elseif recurse and mode=="directory" then
     if dirs then
-      for i=1,#dirs do
-        glob_pattern_table(dirs[i],patt,recurse,result)
-      end
+     nofdirs=nofdirs+1
+     dirs[nofdirs]=full
+    else
+     nofdirs=1
+     dirs={ full }
     end
+   end
   end
-  return result
+ end
+ if dirs then
+  for i=1,nofdirs do
+   glob_pattern_table(dirs[i],patt,recurse,result)
+  end
+ end
+ return result
 end
 local function globpattern(path,patt,recurse,method)
-  local kind=type(method)
-  if patt and sub(patt,1,-3)==path then
-    patt=false
-  end
-  if kind=="function" then
-    return glob_pattern_function(path,patt,recurse,method)
-  elseif kind=="table" then
-    return glob_pattern_table(path,patt,recurse,method)
-  else
-    return glob_pattern_table(path,patt,recurse,{})
-  end
+ local kind=type(method)
+ if patt and sub(patt,1,-3)==path then
+  patt=false
+ end
+ local okay=isdir(path)
+ if kind=="function" then
+  return okay and glob_pattern_function(path,patt,recurse,method) or {}
+ elseif kind=="table" then
+  return okay and glob_pattern_table(path,patt,recurse,method) or method
+ else
+  return okay and glob_pattern_table(path,patt,recurse,{}) or {}
+ end
 end
 dir.globpattern=globpattern
 local function collectpattern(path,patt,recurse,result)
-  local ok,scanner
-  result=result or {}
-  if path=="/" then
-    ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end) 
-  else
-    ok,scanner,first=xpcall(function() return walkdir(path)   end,function() end) 
+ local ok,scanner
+ result=result or {}
+ if path=="/" then
+  ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end) 
+ else
+  ok,scanner,first=xpcall(function() return walkdir(path)   end,function() end) 
+ end
+ if ok and type(scanner)=="function" then
+  if not find(path,"/$") then
+   path=path..'/'
   end
-  if ok and type(scanner)=="function" then
-    if not find(path,"/$") then
-      path=path..'/'
+  for name in scanner,first do
+   if name=="." then
+   elseif name==".." then
+   else
+    local full=path..name
+    local attr=attributes(full)
+    local mode=attr.mode
+    if mode=='file' then
+     if find(full,patt) then
+      result[name]=attr
+     end
+    elseif recurse and mode=="directory" then
+     attr.list=collectpattern(full,patt,recurse)
+     result[name]=attr
     end
-    for name in scanner,first do
-      if name=="." then
-      elseif name==".." then
-      else
-        local full=path..name
-        local attr=attributes(full)
-        local mode=attr.mode
-        if mode=='file' then
-          if find(full,patt) then
-            result[name]=attr
-          end
-        elseif recurse and mode=="directory" then
-          attr.list=collectpattern(full,patt,recurse)
-          result[name]=attr
-        end
-      end
-    end
+   end
   end
-  return result
+ end
+ return result
 end
 dir.collectpattern=collectpattern
 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)
-  }
+ 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)
+ }
 else
-  pattern={
-    [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
-    [2]=C(((1-S("*?/"))^0*P("/"))^0),
-    [3]=C(P(1)^0)
-  }
+ pattern={
+  [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
+  [2]=C(((1-S("*?/"))^0*P("/"))^0),
+  [3]=C(P(1)^0)
+ }
 end
 local filter=Cs ((
-  P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
+ P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
 )^0 )
 local function glob(str,t)
-  if type(t)=="function" then
-    if type(str)=="table" then
-      for s=1,#str do
-        glob(str[s],t)
-      end
-    elseif isfile(str) then
-      t(str)
-    else
-      local root,path,base=lpegmatch(pattern,str) 
-      if root and path and base then
-        local recurse=find(base,"**",1,true) 
-        local start=root..path
-        local result=lpegmatch(filter,start..base)
-        globpattern(start,result,recurse,t)
-      end
-    end
+ if type(t)=="function" then
+  if type(str)=="table" then
+   for s=1,#str do
+    glob(str[s],t)
+   end
+  elseif isfile(str) then
+   t(str)
   else
-    if type(str)=="table" then
-      local t=t or {}
-      for s=1,#str do
-        glob(str[s],t)
-      end
-      return t
-    elseif isfile(str) then
-      if t then
-        t[#t+1]=str
-        return t
-      else
-        return { str }
-      end
-    else
-      local root,path,base=lpegmatch(pattern,str) 
-      if root and path and base then
-        local recurse=find(base,"**",1,true) 
-        local start=root..path
-        local result=lpegmatch(filter,start..base)
-        return globpattern(start,result,recurse,t)
-      else
-        return {}
-      end
-    end
+   local root,path,base=lpegmatch(pattern,str) 
+   if root and path and base then
+    local recurse=find(base,"**",1,true) 
+    local start=root..path
+    local result=lpegmatch(filter,start..base)
+    globpattern(start,result,recurse,t)
+   end
   end
+ else
+  if type(str)=="table" then
+   local t=t or {}
+   for s=1,#str do
+    glob(str[s],t)
+   end
+   return t
+  elseif isfile(str) then
+   if t then
+    t[#t+1]=str
+    return t
+   else
+    return { str }
+   end
+  else
+   local root,path,base=lpegmatch(pattern,str) 
+   if root and path and base then
+    local recurse=find(base,"**",1,true) 
+    local start=root..path
+    local result=lpegmatch(filter,start..base)
+    return globpattern(start,result,recurse,t)
+   else
+    return {}
+   end
+  end
+ end
 end
 dir.glob=glob
 local function globfiles(path,recurse,func,files) 
-  if type(func)=="string" then
-    local s=func
-    func=function(name) return find(name,s) end
-  end
-  files=files or {}
-  local noffiles=#files
-  for name in walkdir(path) do
-    if find(name,"^%.") then
-    else
-      local mode=attributes(name,'mode')
-      if mode=="directory" then
-        if recurse then
-          globfiles(path.."/"..name,recurse,func,files)
-        end
-      elseif mode=="file" then
-        if not func or func(name) then
-          noffiles=noffiles+1
-          files[noffiles]=path.."/"..name
-        end
-      end
+ if type(func)=="string" then
+  local s=func
+  func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+  if find(name,"^%.") then
+  else
+   local mode=attributes(name,'mode')
+   if mode=="directory" then
+    if recurse then
+     globfiles(path.."/"..name,recurse,func,files)
     end
+   elseif mode=="file" then
+    if not func or func(name) then
+     noffiles=noffiles+1
+     files[noffiles]=path.."/"..name
+    end
+   end
   end
-  return files
+ end
+ return files
 end
 dir.globfiles=globfiles
 local function globdirs(path,recurse,func,files) 
-  if type(func)=="string" then
-    local s=func
-    func=function(name) return find(name,s) end
-  end
-  files=files or {}
-  local noffiles=#files
-  for name in walkdir(path) do
-    if find(name,"^%.") then
-    else
-      local mode=attributes(name,'mode')
-      if mode=="directory" then
-        if not func or func(name) then
-          noffiles=noffiles+1
-          files[noffiles]=path.."/"..name
-          if recurse then
-            globdirs(path.."/"..name,recurse,func,files)
-          end
-        end
-      end
+ if type(func)=="string" then
+  local s=func
+  func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+  if find(name,"^%.") then
+  else
+   local mode=attributes(name,'mode')
+   if mode=="directory" then
+    if not func or func(name) then
+     noffiles=noffiles+1
+     files[noffiles]=path.."/"..name
+     if recurse then
+      globdirs(path.."/"..name,recurse,func,files)
+     end
     end
+   end
   end
-  return files
+ end
+ return files
 end
 dir.globdirs=globdirs
 function dir.ls(pattern)
-  return concat(glob(pattern),"\n")
+ return concat(glob(pattern),"\n")
 end
 local make_indeed=true 
 if onwindows then
-  function dir.mkdirs(...)
-    local n=select("#",...)
-    local str
-    if n==1 then
-      str=select(1,...)
-      if isdir(str) then
-        return str,true
-      end
+ function dir.mkdirs(...)
+  local n=select("#",...)
+  local str
+  if n==1 then
+   str=select(1,...)
+   if isdir(str) then
+    return str,true
+   end
+  else
+   str=""
+   for i=1,n do
+    local s=select(i,...)
+    if s=="" then
+    elseif str=="" then
+     str=s
     else
-      str=""
-      for i=1,n do
-        local s=select(i,...)
-        if s=="" then
-        elseif str=="" then
-          str=s
-        else
-          str=str.."/"..s
-        end
-      end
+     str=str.."/"..s
     end
-    local pth=""
-    local drive=false
-    local first,middle,last=match(str,"^(//)(//*)(.*)$")
+   end
+  end
+  local pth=""
+  local drive=false
+  local first,middle,last=match(str,"^(//)(//*)(.*)$")
+  if first then
+  else
+   first,last=match(str,"^(//)/*(.-)$")
+   if first then
+    middle,last=match(str,"([^/]+)/+(.-)$")
+    if middle then
+     pth="//"..middle
+    else
+     pth="//"..last
+     last=""
+    end
+   else
+    first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
     if first then
+     pth,drive=first..middle,true
     else
-      first,last=match(str,"^(//)/*(.-)$")
-      if first then
-        middle,last=match(str,"([^/]+)/+(.-)$")
-        if middle then
-          pth="//"..middle
-        else
-          pth="//"..last
-          last=""
-        end
-      else
-        first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
-        if first then
-          pth,drive=first..middle,true
-        else
-          middle,last=match(str,"^(/*)(.-)$")
-          if not middle then
-            last=str
-          end
-        end
-      end
+     middle,last=match(str,"^(/*)(.-)$")
+     if not middle then
+      last=str
+     end
     end
-    for s in gmatch(last,"[^/]+") do
-      if pth=="" then
-        pth=s
-      elseif drive then
-        pth,drive=pth..s,false
-      else
-        pth=pth.."/"..s
-      end
-      if make_indeed and not isdir(pth) then
-        mkdir(pth)
-      end
-    end
-    return pth,(isdir(pth)==true)
+   end
   end
+  for s in gmatch(last,"[^/]+") do
+   if pth=="" then
+    pth=s
+   elseif drive then
+    pth,drive=pth..s,false
+   else
+    pth=pth.."/"..s
+   end
+   if make_indeed and not isdir(pth) then
+    mkdir(pth)
+   end
+  end
+  return pth,(isdir(pth)==true)
+ end
 else
-  function dir.mkdirs(...)
-    local n=select("#",...)
-    local str,pth
-    if n==1 then
-      str=select(1,...)
-      if isdir(str) then
-        return str,true
-      end
-    else
-      str=""
-      for i=1,n do
-        local s=select(i,...)
-        if s and s~="" then 
-          if str~="" then
-            str=str.."/"..s
-          else
-            str=s
-          end
-        end
-      end
+ function dir.mkdirs(...)
+  local n=select("#",...)
+  local str,pth
+  if n==1 then
+   str=select(1,...)
+   if isdir(str) then
+    return str,true
+   end
+  else
+   str=""
+   for i=1,n do
+    local s=select(i,...)
+    if s and s~="" then 
+     if str~="" then
+      str=str.."/"..s
+     else
+      str=s
+     end
     end
-    str=gsub(str,"/+","/")
-    if find(str,"^/") then
-      pth="/"
-      for s in gmatch(str,"[^/]+") do
-        local first=(pth=="/")
-        if first then
-          pth=pth..s
-        else
-          pth=pth.."/"..s
-        end
-        if make_indeed and not first and not isdir(pth) then
-          mkdir(pth)
-        end
-      end
+   end
+  end
+  str=gsub(str,"/+","/")
+  if find(str,"^/") then
+   pth="/"
+   for s in gmatch(str,"[^/]+") do
+    local first=(pth=="/")
+    if first then
+     pth=pth..s
     else
-      pth="."
-      for s in gmatch(str,"[^/]+") do
-        pth=pth.."/"..s
-        if make_indeed and not isdir(pth) then
-          mkdir(pth)
-        end
-      end
+     pth=pth.."/"..s
     end
-    return pth,(isdir(pth)==true)
+    if make_indeed and not first and not isdir(pth) then
+     mkdir(pth)
+    end
+   end
+  else
+   pth="."
+   for s in gmatch(str,"[^/]+") do
+    pth=pth.."/"..s
+    if make_indeed and not isdir(pth) then
+     mkdir(pth)
+    end
+   end
   end
+  return pth,(isdir(pth)==true)
+ end
 end
 dir.makedirs=dir.mkdirs
 do
-  local chdir=sandbox and sandbox.original(chdir) or chdir
-  if onwindows then
-    local xcurrentdir=dir.current
-    function dir.expandname(str) 
-      local first,nothing,last=match(str,"^(//)(//*)(.*)$")
-      if first then
-        first=xcurrentdir().."/" 
-      end
-      if not first then
-        first,last=match(str,"^(//)/*(.*)$")
-      end
-      if not first then
-        first,last=match(str,"^([a-zA-Z]:)(.*)$")
-        if first and not find(last,"^/") then
-          local d=currentdir() 
-          if chdir(first) then
-            first=xcurrentdir() 
-          end
-          chdir(d)
-        end
-      end
-      if not first then
-        first,last=xcurrentdir(),str
-      end
-      last=gsub(last,"//","/")
-      last=gsub(last,"/%./","/")
-      last=gsub(last,"^/*","")
-      first=gsub(first,"/*$","")
-      if last=="" or last=="." then
-        return first
-      else
-        return first.."/"..last
-      end
+ local chdir=sandbox and sandbox.original(chdir) or chdir
+ if onwindows then
+  local xcurrentdir=dir.current
+  function dir.expandname(str) 
+   local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+   if first then
+    first=xcurrentdir().."/" 
+   end
+   if not first then
+    first,last=match(str,"^(//)/*(.*)$")
+   end
+   if not first then
+    first,last=match(str,"^([a-zA-Z]:)(.*)$")
+    if first and not find(last,"^/") then
+     local d=currentdir() 
+     if chdir(first) then
+      first=xcurrentdir() 
+     end
+     chdir(d)
     end
-  else
-    function dir.expandname(str) 
-      if not find(str,"^/") then
-        str=currentdir().."/"..str
-      end
-      str=gsub(str,"//","/")
-      str=gsub(str,"/%./","/")
-      str=gsub(str,"(.)/%.$","%1")
-      return str
-    end
+   end
+   if not first then
+    first,last=xcurrentdir(),str
+   end
+   last=gsub(last,"//","/")
+   last=gsub(last,"/%./","/")
+   last=gsub(last,"^/*","")
+   first=gsub(first,"/*$","")
+   if last=="" or last=="." then
+    return first
+   else
+    return first.."/"..last
+   end
   end
+ else
+  function dir.expandname(str) 
+   if not find(str,"^/") then
+    str=currentdir().."/"..str
+   end
+   str=gsub(str,"//","/")
+   str=gsub(str,"/%./","/")
+   str=gsub(str,"(.)/%.$","%1")
+   return str
+  end
+ end
 end
 file.expandname=dir.expandname 
 local stack={}
 function dir.push(newdir)
-  local curdir=currentdir()
-  insert(stack,curdir)
-  if newdir and newdir~="" then
-    chdir(newdir)
-    return newdir
-  else
-    return curdir
-  end
+ local curdir=currentdir()
+ insert(stack,curdir)
+ if newdir and newdir~="" then
+  chdir(newdir)
+  return newdir
+ else
+  return curdir
+ end
 end
 function dir.pop()
-  local d=remove(stack)
-  if d then
-    chdir(d)
-  end
-  return d
+ local d=remove(stack)
+ if d then
+  chdir(d)
+ end
+ return d
 end
 local function found(...) 
-  for i=1,select("#",...) do
-    local path=select(i,...)
-    local kind=type(path)
-    if kind=="string" then
-      if isdir(path) then
-        return path
-      end
-    elseif kind=="table" then
-      local path=found(unpack(path))
-      if path then
-        return path
-      end
-    end
+ for i=1,select("#",...) do
+  local path=select(i,...)
+  local kind=type(path)
+  if kind=="string" then
+   if isdir(path) then
+    return path
+   end
+  elseif kind=="table" then
+   local path=found(unpack(path))
+   if path then
+    return path
+   end
   end
+ end
 end
 dir.found=found
 
@@ -5235,69 +5562,69 @@
 
 package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
 
--- original size: 1850, stripped down to: 1568
+-- original size: 1850, stripped down to: 1498
 
 if not modules then modules={} end modules ['l-boolean']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 type,tonumber=type,tonumber
 boolean=boolean or {}
 local boolean=boolean
 function boolean.tonumber(b)
-  if b then return 1 else return 0 end 
+ if b then return 1 else return 0 end 
 end
 function toboolean(str,tolerant) 
-  if str==nil then
-    return false
-  elseif str==false then
-    return false
-  elseif str==true then
-    return true
-  elseif str=="true" then
-    return true
-  elseif str=="false" then
-    return false
-  elseif not tolerant then
-    return false
-  elseif str==0 then
-    return false
-  elseif (tonumber(str) or 0)>0 then
-    return true
-  else
-    return str=="yes" or str=="on" or str=="t"
-  end
+ if  str==nil then
+  return false
+ elseif str==false then
+  return false
+ elseif str==true then
+  return true
+ elseif str=="true" then
+  return true
+ elseif str=="false" then
+  return false
+ elseif not tolerant then
+  return false
+ elseif str==0 then
+  return false
+ elseif (tonumber(str) or 0)>0 then
+  return true
+ else
+  return str=="yes" or str=="on" or str=="t"
+ end
 end
 string.toboolean=toboolean
 function string.booleanstring(str)
-  if str=="0" then
-    return false
-  elseif str=="1" then
-    return true
-  elseif str=="" then
-    return false
-  elseif str=="false" then
-    return false
-  elseif str=="true" then
-    return true
-  elseif (tonumber(str) or 0)>0 then
-    return true
-  else
-    return str=="yes" or str=="on" or str=="t"
-  end
+ if str=="0" then
+  return false
+ elseif str=="1" then
+  return true
+ elseif str=="" then
+  return false
+ elseif str=="false" then
+  return false
+ elseif str=="true" then
+  return true
+ elseif (tonumber(str) or 0)>0 then
+  return true
+ else
+  return str=="yes" or str=="on" or str=="t"
+ end
 end
 function string.is_boolean(str,default,strict)
-  if type(str)=="string" then
-    if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then
-      return true
-    elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then
-      return false
-    end
+ if type(str)=="string" then
+  if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then
+   return true
+  elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then
+   return false
   end
-  return default
+ end
+ return default
 end
 
 
@@ -5307,18 +5634,24 @@
 
 package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
 
--- original size: 40036, stripped down to: 17837
+-- original size: 41047, stripped down to: 17171
 
 if not modules then modules={} end modules ['l-unicode']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
-utf=utf or (unicode and unicode.utf8) or {}
-utf.characters=utf.characters or string.utfcharacters
-utf.values=utf.values   or string.utfvalues
+utf=utf or {}
+unicode=nil
+if not string.utfcharacters then
+ local gmatch=string.gmatch
+ function string.characters(str)
+  return gmatch(str,".[\128-\191]*")
+ end
+end
+utf.characters=string.utfcharacters
 local type=type
 local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
 local concat=table.concat
@@ -5329,345 +5662,340 @@
 local bytepairs=string.bytepairs
 local finder=lpeg.finder
 local replacer=lpeg.replacer
-local utfvalues=utf.values
-local utfgmatch=utf.gmatch 
 local p_utftype=patterns.utftype
 local p_utfstricttype=patterns.utfstricttype
 local p_utfoffset=patterns.utfoffset
-local p_utf8char=patterns.utf8character
+local p_utf8character=patterns.utf8character
+local p_utf8char=patterns.utf8char
 local p_utf8byte=patterns.utf8byte
 local p_utfbom=patterns.utfbom
 local p_newline=patterns.newline
 local p_whitespace=patterns.whitespace
-if not unicode then
-  unicode={ utf=utf } 
-end
 if not utf.char then
-  utf.char=string.utfcharacter or (utf8 and utf8.char)
-  if not utf.char then
-    local char=string.char
-    if bit32 then
-      local rshift=bit32.rshift
-      function utf.char(n)
-        if n<0x80 then
-          return char(n)
-        elseif n<0x800 then
-          return char(
-            0xC0+rshift(n,6),
-            0x80+(n%0x40)
-          )
-        elseif n<0x10000 then
-          return char(
-            0xE0+rshift(n,12),
-            0x80+(rshift(n,6)%0x40),
-            0x80+(n%0x40)
-          )
-        elseif n<0x200000 then
-          return char(
-            0xF0+rshift(n,18),
-            0x80+(rshift(n,12)%0x40),
-            0x80+(rshift(n,6)%0x40),
-            0x80+(n%0x40)
-          )
-        else
-          return ""
-        end
-      end
+ utf.char=string.utfcharacter or (utf8 and utf8.char)
+ if not utf.char then
+  local char=string.char
+  if bit32 then
+   local rshift=bit32.rshift
+   function utf.char(n)
+    if n<0x80 then
+     return char(n)
+    elseif n<0x800 then
+     return char(
+      0xC0+rshift(n,6),
+      0x80+(n%0x40)
+     )
+    elseif n<0x10000 then
+     return char(
+      0xE0+rshift(n,12),
+      0x80+(rshift(n,6)%0x40),
+      0x80+(n%0x40)
+     )
+    elseif n<0x200000 then
+     return char(
+      0xF0+rshift(n,18),
+      0x80+(rshift(n,12)%0x40),
+      0x80+(rshift(n,6)%0x40),
+      0x80+(n%0x40)
+     )
     else
-      local floor=math.floor
-      function utf.char(n)
-        if n<0x80 then
-          return char(n)
-        elseif n<0x800 then
-          return char(
-            0xC0+floor(n/0x40),
-            0x80+(n%0x40)
-          )
-        elseif n<0x10000 then
-          return char(
-            0xE0+floor(n/0x1000),
-            0x80+(floor(n/0x40)%0x40),
-            0x80+(n%0x40)
-          )
-        elseif n<0x200000 then
-          return char(
-            0xF0+floor(n/0x40000),
-            0x80+(floor(n/0x1000)%0x40),
-            0x80+(floor(n/0x40)%0x40),
-            0x80+(n%0x40)
-          )
-        else
-          return ""
-        end
-      end
+     return ""
     end
+   end
+  else
+   local floor=math.floor
+   function utf.char(n)
+    if n<0x80 then
+     return char(n)
+    elseif n<0x800 then
+     return char(
+      0xC0+floor(n/0x40),
+      0x80+(n%0x40)
+     )
+    elseif n<0x10000 then
+     return char(
+      0xE0+floor(n/0x1000),
+      0x80+(floor(n/0x40)%0x40),
+      0x80+(n%0x40)
+     )
+    elseif n<0x200000 then
+     return char(
+      0xF0+floor(n/0x40000),
+      0x80+(floor(n/0x1000)%0x40),
+      0x80+(floor(n/0x40)%0x40),
+      0x80+(n%0x40)
+     )
+    else
+     return ""
+    end
+   end
   end
+ end
 end
 if not utf.byte then
-  utf.byte=string.utfvalue or (utf8 and utf8.codepoint)
-  if not utf.byte then
-    local utf8byte=patterns.utf8byte
-    function utf.byte(c)
-      return lpegmatch(utf8byte,c)
-    end
+ utf.byte=string.utfvalue or (utf8 and utf8.codepoint)
+ if not utf.byte then
+  function utf.byte(c)
+   return lpegmatch(p_utf8byte,c)
   end
+ end
 end
 local utfchar,utfbyte=utf.char,utf.byte
 function utf.filetype(data)
-  return data and lpegmatch(p_utftype,data) or "unknown"
+ return data and lpegmatch(p_utftype,data) or "unknown"
 end
 local toentities=Cs (
-  (
-    patterns.utf8one+(
-        patterns.utf8two+patterns.utf8three+patterns.utf8four
-      )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end
-  )^0
+ (
+  patterns.utf8one+(
+    patterns.utf8two+patterns.utf8three+patterns.utf8four
+   )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end
+ )^0
 )
 patterns.toentities=toentities
 function utf.toentities(str)
-  return lpegmatch(toentities,str)
+ return lpegmatch(toentities,str)
 end
 local one=P(1)
 local two=C(1)*C(1)
 local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
 local pattern=P("\254\255")*Cs((
-          four/function(a,b,c,d)
-                local ab=0xFF*byte(a)+byte(b)
-                local cd=0xFF*byte(c)+byte(d)
-                return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
-              end+two/function(a,b)
-                return utfchar(byte(a)*256+byte(b))
-              end+one
-        )^1 )+P("\255\254")*Cs((
-          four/function(b,a,d,c)
-                local ab=0xFF*byte(a)+byte(b)
-                local cd=0xFF*byte(c)+byte(d)
-                return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
-              end+two/function(b,a)
-                return utfchar(byte(a)*256+byte(b))
-              end+one
-        )^1 )
+     four/function(a,b,c,d)
+        local ab=0xFF*byte(a)+byte(b)
+        local cd=0xFF*byte(c)+byte(d)
+        return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+       end+two/function(a,b)
+        return utfchar(byte(a)*256+byte(b))
+       end+one
+    )^1 )+P("\255\254")*Cs((
+     four/function(b,a,d,c)
+        local ab=0xFF*byte(a)+byte(b)
+        local cd=0xFF*byte(c)+byte(d)
+        return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+       end+two/function(b,a)
+        return utfchar(byte(a)*256+byte(b))
+       end+one
+    )^1 )
 function string.toutf(s) 
-  return lpegmatch(pattern,s) or s 
+ return lpegmatch(pattern,s) or s 
 end
 local validatedutf=Cs (
-  (
-    patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
-  )^0
+ (
+  patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
 )
 patterns.validatedutf=validatedutf
 function utf.is_valid(str)
-  return type(str)=="string" and lpegmatch(validatedutf,str) or false
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
 end
 if not utf.len then
-  utf.len=string.utflength or (utf8 and utf8.len)
-  if not utf.len then
-    local n,f=0,1
-    local utfcharcounter=patterns.utfbom^-1*Cmt (
-      Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
-      function(_,t,d) 
-        n=n+(t-f)/d
-        f=t
-        return true
-      end
-    )^0
-    function utf.len(str)
-      n,f=0,1
-      lpegmatch(utfcharcounter,str or "")
-      return n
-    end
+ utf.len=string.utflength or (utf8 and utf8.len)
+ if not utf.len then
+  local n,f=0,1
+  local utfcharcounter=patterns.utfbom^-1*Cmt (
+   Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+   function(_,t,d) 
+    n=n+(t-f)/d
+    f=t
+    return true
+   end
+  )^0
+  function utf.len(str)
+   n,f=0,1
+   lpegmatch(utfcharcounter,str or "")
+   return n
   end
+ end
 end
 utf.length=utf.len
 if not utf.sub then
-  local utflength=utf.length
-  local b,e,n,first,last=0,0,0,0,0
-  local function slide_zero(s,p)
-    n=n+1
-    if n>=last then
-      e=p-1
-    else
-      return p
-    end
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+  n=n+1
+  if n>=last then
+   e=p-1
+  else
+   return p
   end
-  local function slide_one(s,p)
-    n=n+1
-    if n==first then
-      b=p
-    end
-    if n>=last then
-      e=p-1
-    else
-      return p
-    end
+ end
+ local function slide_one(s,p)
+  n=n+1
+  if n==first then
+   b=p
   end
-  local function slide_two(s,p)
-    n=n+1
-    if n==first then
-      b=p
+  if n>=last then
+   e=p-1
+  else
+   return p
+  end
+ end
+ local function slide_two(s,p)
+  n=n+1
+  if n==first then
+   b=p
+  else
+   return true
+  end
+ end
+ local pattern_zero=Cmt(p_utf8character,slide_zero)^0
+ local pattern_one=Cmt(p_utf8character,slide_one )^0
+ local pattern_two=Cmt(p_utf8character,slide_two )^0
+ local pattern_first=C(p_utf8character)
+ function utf.sub(str,start,stop)
+  if not start then
+   return str
+  end
+  if start==0 then
+   start=1
+  end
+  if not stop then
+   if start<0 then
+    local l=utflength(str) 
+    start=l+start
+   else
+    start=start-1
+   end
+   b,n,first=0,0,start
+   lpegmatch(pattern_two,str)
+   if n>=first then
+    return sub(str,b)
+   else
+    return ""
+   end
+  end
+  if start<0 or stop<0 then
+   local l=utf.length(str)
+   if start<0 then
+    start=l+start
+    if start<=0 then
+     start=1
     else
-      return true
+     start=start+1
     end
-  end
-  local pattern_zero=Cmt(p_utf8char,slide_zero)^0
-  local pattern_one=Cmt(p_utf8char,slide_one )^0
-  local pattern_two=Cmt(p_utf8char,slide_two )^0
-  local pattern_first=C(patterns.utf8character)
-  function utf.sub(str,start,stop)
-    if not start then
-      return str
-    end
-    if start==0 then
-      start=1
-    end
-    if not stop then
-      if start<0 then
-        local l=utflength(str) 
-        start=l+start
-      else
-        start=start-1
-      end
-      b,n,first=0,0,start
-      lpegmatch(pattern_two,str)
-      if n>=first then
-        return sub(str,b)
-      else
-        return ""
-      end
-    end
-    if start<0 or stop<0 then
-      local l=utf.length(str)
-      if start<0 then
-        start=l+start
-        if start<=0 then
-          start=1
-        else
-          start=start+1
-        end
-      end
-      if stop<0 then
-        stop=l+stop
-        if stop==0 then
-          stop=1
-        else
-          stop=stop+1
-        end
-      end
-    end
-    if start==1 and stop==1 then
-      return lpegmatch(pattern_first,str) or ""
-    elseif start>stop then
-      return ""
-    elseif start>1 then
-      b,e,n,first,last=0,0,0,start-1,stop
-      lpegmatch(pattern_one,str)
-      if n>=first and e==0 then
-        e=#str
-      end
-      return sub(str,b,e)
+   end
+   if stop<0 then
+    stop=l+stop
+    if stop==0 then
+     stop=1
     else
-      b,e,n,last=1,0,0,stop
-      lpegmatch(pattern_zero,str)
-      if e==0 then
-        e=#str
-      end
-      return sub(str,b,e)
+     stop=stop+1
     end
+   end
   end
+  if start==1 and stop==1 then
+   return lpegmatch(pattern_first,str) or ""
+  elseif start>stop then
+   return ""
+  elseif start>1 then
+   b,e,n,first,last=0,0,0,start-1,stop
+   lpegmatch(pattern_one,str)
+   if n>=first and e==0 then
+    e=#str
+   end
+   return sub(str,b,e)
+  else
+   b,e,n,last=1,0,0,stop
+   lpegmatch(pattern_zero,str)
+   if e==0 then
+    e=#str
+   end
+   return sub(str,b,e)
+  end
+ end
 end
 function utf.remapper(mapping,option,action) 
-  local variant=type(mapping)
-  if variant=="table" then
-    action=action or mapping
-    if option=="dynamic" then
-      local pattern=false
-      table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
-      return function(str)
-        if not str or str=="" then
-          return ""
-        else
-          if not pattern then
-            pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
-          end
-          return lpegmatch(pattern,str)
-        end
-      end
-    elseif option=="pattern" then
-      return Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ local variant=type(mapping)
+ if variant=="table" then
+  action=action or mapping
+  if option=="dynamic" then
+   local pattern=false
+   table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+   return function(str)
+    if not str or str=="" then
+     return ""
     else
-      local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
-      return function(str)
-        if not str or str=="" then
-          return ""
-        else
-          return lpegmatch(pattern,str)
-        end
-      end,pattern
+     if not pattern then
+      pattern=Cs((tabletopattern(mapping)/action+p_utf8character)^0)
+     end
+     return lpegmatch(pattern,str)
     end
-  elseif variant=="function" then
-    if option=="pattern" then
-      return Cs((p_utf8char/mapping+p_utf8char)^0)
+   end
+  elseif option=="pattern" then
+   return Cs((tabletopattern(mapping)/action+p_utf8character)^0)
+  else
+   local pattern=Cs((tabletopattern(mapping)/action+p_utf8character)^0)
+   return function(str)
+    if not str or str=="" then
+     return ""
     else
-      local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
-      return function(str)
-        if not str or str=="" then
-          return ""
-        else
-          return lpegmatch(pattern,str)
-        end
-      end,pattern
+     return lpegmatch(pattern,str)
     end
+   end,pattern
+  end
+ elseif variant=="function" then
+  if option=="pattern" then
+   return Cs((p_utf8character/mapping+p_utf8character)^0)
   else
-    return function(str)
-      return str or ""
+   local pattern=Cs((p_utf8character/mapping+p_utf8character)^0)
+   return function(str)
+    if not str or str=="" then
+     return ""
+    else
+     return lpegmatch(pattern,str)
     end
+   end,pattern
   end
-end
-function utf.replacer(t) 
-  local r=replacer(t,false,false,true)
+ else
   return function(str)
-    return lpegmatch(r,str)
+   return str or ""
   end
+ end
 end
+function utf.replacer(t) 
+ local r=replacer(t,false,false,true)
+ return function(str)
+  return lpegmatch(r,str)
+ end
+end
 function utf.subtituter(t) 
-  local f=finder (t)
-  local r=replacer(t,false,false,true)
-  return function(str)
-    local i=lpegmatch(f,str)
-    if not i then
-      return str
-    elseif i>#str then
-      return str
-    else
-      return lpegmatch(r,str)
-    end
+ local f=finder  (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+  local i=lpegmatch(f,str)
+  if not i then
+   return str
+  elseif i>#str then
+   return str
+  else
+   return lpegmatch(r,str)
   end
+ end
 end
 local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
-local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
-local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
-local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8character)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8character))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8character)^0)
 patterns.utflinesplitter=utflinesplitter
 function utf.splitlines(str)
-  return lpegmatch(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
 end
 function utf.split(str,ignorewhitespace) 
-  if ignorewhitespace then
-    return lpegmatch(utfcharsplitter_iws,str or "")
-  else
-    return lpegmatch(utfcharsplitter_ows,str or "")
-  end
+ if ignorewhitespace then
+  return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+  return lpegmatch(utfcharsplitter_ows,str or "")
+ end
 end
 function utf.totable(str) 
-  return lpegmatch(utfcharsplitter_raw,str)
+ return lpegmatch(utfcharsplitter_raw,str)
 end
 function utf.magic(f) 
-  local str=f:read(4) or ""
-  local off=lpegmatch(p_utfoffset,str)
-  if off<4 then
-    f:seek('set',off)
-  end
-  return lpegmatch(p_utftype,str)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+  f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
 end
 local utf16_to_utf8_be,utf16_to_utf8_le
 local utf32_to_utf8_be,utf32_to_utf8_le
@@ -5681,36 +6009,36 @@
 local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
 local more=0
 local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
-  local now=256*byte(left)+byte(right)
-  if more>0 then
-    now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 
-    more=0
-    return utfchar(now)
-  elseif now>=0xD800 and now<=0xDBFF then
-    more=now
-    return "" 
-  else
-    return utfchar(now)
-  end
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+  now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+  more=0
+  return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+  more=now
+  return "" 
+ else
+  return utfchar(now)
+ end
 end
 local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
-  local now=256*byte(left)+byte(right)
-  if more>0 then
-    now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 
-    more=0
-    return utfchar(now)
-  elseif now>=0xD800 and now<=0xDBFF then
-    more=now
-    return "" 
-  else
-    return utfchar(now)
-  end
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+  now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+  more=0
+  return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+  more=now
+  return "" 
+ else
+  return utfchar(now)
+ end
 end
 local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
-  return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
 end
 local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
-  return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
 end
 p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
 p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
@@ -5721,88 +6049,88 @@
 patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
 patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
 utf16_to_utf8_be=function(s)
-  if s and s~="" then
-    return lpegmatch(p_utf16_to_utf8_be,s)
-  else
-    return s
-  end
+ if s and s~="" then
+  return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+  return s
+ end
 end
 local utf16_to_utf8_be_t=function(t)
-  if not t then
-    return nil
-  elseif type(t)=="string" then
-    t=lpegmatch(utf_16_be_linesplitter,t)
+ if not t then
+  return nil
+ elseif type(t)=="string" then
+  t=lpegmatch(utf_16_be_linesplitter,t)
+ end
+ for i=1,#t do
+  local s=t[i]
+  if s~="" then
+   t[i]=lpegmatch(p_utf16_to_utf8_be,s)
   end
-  for i=1,#t do
-    local s=t[i]
-    if s~="" then
-      t[i]=lpegmatch(p_utf16_to_utf8_be,s)
-    end
-  end
-  return t
+ end
+ return t
 end
 utf16_to_utf8_le=function(s)
-  if s and s~="" then
-    return lpegmatch(p_utf16_to_utf8_le,s)
-  else
-    return s
-  end
+ if s and s~="" then
+  return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+  return s
+ end
 end
 local utf16_to_utf8_le_t=function(t)
-  if not t then
-    return nil
-  elseif type(t)=="string" then
-    t=lpegmatch(utf_16_le_linesplitter,t)
+ if not t then
+  return nil
+ elseif type(t)=="string" then
+  t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+  local s=t[i]
+  if s~="" then
+   t[i]=lpegmatch(p_utf16_to_utf8_le,s)
   end
-  for i=1,#t do
-    local s=t[i]
-    if s~="" then
-      t[i]=lpegmatch(p_utf16_to_utf8_le,s)
-    end
-  end
-  return t
+ end
+ return t
 end
 utf32_to_utf8_be=function(s)
-  if s and s~="" then
-    return lpegmatch(p_utf32_to_utf8_be,s)
-  else
-    return s
-  end
+ if s and s~="" then
+  return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+  return s
+ end
 end
 local utf32_to_utf8_be_t=function(t)
-  if not t then
-    return nil
-  elseif type(t)=="string" then
-    t=lpegmatch(utf_32_be_linesplitter,t)
+ if not t then
+  return nil
+ elseif type(t)=="string" then
+  t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+  local s=t[i]
+  if s~="" then
+   t[i]=lpegmatch(p_utf32_to_utf8_be,s)
   end
-  for i=1,#t do
-    local s=t[i]
-    if s~="" then
-      t[i]=lpegmatch(p_utf32_to_utf8_be,s)
-    end
-  end
-  return t
+ end
+ return t
 end
 utf32_to_utf8_le=function(s)
-  if s and s~="" then
-    return lpegmatch(p_utf32_to_utf8_le,s)
-  else
-    return s
-  end
+ if s and s~="" then
+  return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+  return s
+ end
 end
 local utf32_to_utf8_le_t=function(t)
-  if not t then
-    return nil
-  elseif type(t)=="string" then
-    t=lpegmatch(utf_32_le_linesplitter,t)
+ if not t then
+  return nil
+ elseif type(t)=="string" then
+  t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+  local s=t[i]
+  if s~="" then
+   t[i]=lpegmatch(p_utf32_to_utf8_le,s)
   end
-  for i=1,#t do
-    local s=t[i]
-    if s~="" then
-      t[i]=lpegmatch(p_utf32_to_utf8_le,s)
-    end
-  end
-  return t
+ end
+ return t
 end
 utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
 utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
@@ -5813,190 +6141,226 @@
 utf.utf32_to_utf8_le=utf32_to_utf8_le
 utf.utf32_to_utf8_be=utf32_to_utf8_be
 function utf.utf8_to_utf8_t(t)
-  return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
 end
 function utf.utf16_to_utf8_t(t,endian)
-  return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
 end
 function utf.utf32_to_utf8_t(t,endian)
-  return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
 end
 local function little(b)
-  if b<0x10000 then
-    return char(b%256,rshift(b,8))
-  else
-    b=b-0x10000
-    local b1=rshift(b,10)+0xD800
-    local b2=b%1024+0xDC00
-    return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
-  end
+ if b<0x10000 then
+  return char(b%256,rshift(b,8))
+ else
+  b=b-0x10000
+  local b1=rshift(b,10)+0xD800
+  local b2=b%1024+0xDC00
+  return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
+ end
 end
 local function big(b)
-  if b<0x10000 then
-    return char(rshift(b,8),b%256)
-  else
-    b=b-0x10000
-    local b1=rshift(b,10)+0xD800
-    local b2=b%1024+0xDC00
-    return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
-  end
+ if b<0x10000 then
+  return char(rshift(b,8),b%256)
+ else
+  b=b-0x10000
+  local b1=rshift(b,10)+0xD800
+  local b2=b%1024+0xDC00
+  return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
+ end
 end
 local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
 local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
 local function utf8_to_utf16_be(str,nobom)
-  if nobom then
-    return lpegmatch(b_remap,str)
-  else
-    return char(254,255)..lpegmatch(b_remap,str)
-  end
+ if nobom then
+  return lpegmatch(b_remap,str)
+ else
+  return char(254,255)..lpegmatch(b_remap,str)
+ end
 end
 local function utf8_to_utf16_le(str,nobom)
-  if nobom then
-    return lpegmatch(l_remap,str)
-  else
-    return char(255,254)..lpegmatch(l_remap,str)
-  end
+ if nobom then
+  return lpegmatch(l_remap,str)
+ else
+  return char(255,254)..lpegmatch(l_remap,str)
+ end
 end
 utf.utf8_to_utf16_be=utf8_to_utf16_be
 utf.utf8_to_utf16_le=utf8_to_utf16_le
 function utf.utf8_to_utf16(str,littleendian,nobom)
-  if littleendian then
-    return utf8_to_utf16_le(str,nobom)
-  else
-    return utf8_to_utf16_be(str,nobom)
-  end
+ if littleendian then
+  return utf8_to_utf16_le(str,nobom)
+ else
+  return utf8_to_utf16_be(str,nobom)
+ end
 end
 local pattern=Cs (
-  (p_utf8byte/function(unicode     ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+ (p_utf8byte/function(unicode    ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
 )
 function utf.tocodes(str,separator)
-  return lpegmatch(pattern,str,1,separator or " ")
+ return lpegmatch(pattern,str,1,separator or " ")
 end
 function utf.ustring(s)
-  return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
 end
 function utf.xstring(s)
-  return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
 end
 function utf.toeight(str)
-  if not str or str=="" then
-    return nil
-  end
-  local utftype=lpegmatch(p_utfstricttype,str)
-  if utftype=="utf-8" then
-    return sub(str,4)        
-  elseif utftype=="utf-16-be" then
-    return utf16_to_utf8_be(str)  
-  elseif utftype=="utf-16-le" then
-    return utf16_to_utf8_le(str)  
-  else
-    return str
-  end
+ if not str or str=="" then
+  return nil
+ end
+ local utftype=lpegmatch(p_utfstricttype,str)
+ if utftype=="utf-8" then
+  return sub(str,4)      
+ elseif utftype=="utf-16-be" then
+  return utf16_to_utf8_be(str) 
+ elseif utftype=="utf-16-le" then
+  return utf16_to_utf8_le(str) 
+ else
+  return str
+ end
 end
-local p_nany=p_utf8char/""
-if utfgmatch then
-  function utf.count(str,what)
-    if type(what)=="string" then
-      local n=0
-      for _ in utfgmatch(str,what) do
-        n=n+1
-      end
-      return n
-    else 
-      return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
-    end
+do
+ local p_nany=p_utf8character/""
+ local cache={}
+ function utf.count(str,what)
+  if type(what)=="string" then
+   local p=cache[what]
+   if not p then
+    p=Cs((P(what)/" "+p_nany)^0)
+    cache[p]=p
+   end
+   return #lpegmatch(p,str)
+  else 
+   return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
   end
-else
-  local cache={}
-  function utf.count(str,what)
-    if type(what)=="string" then
-      local p=cache[what]
-      if not p then
-        p=Cs((P(what)/" "+p_nany)^0)
-        cache[p]=p
-      end
-      return #lpegmatch(p,str)
-    else 
-      return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
-    end
-  end
+ end
 end
-if not utf.characters then
-  function utf.characters(str)
-    return gmatch(str,".[\128-\191]*")
+if not string.utfvalues then
+ local find=string.find
+ local dummy=function()
+ end
+ function string.utfvalues(str)
+  local n=#str
+  if n==0 then
+   return dummy
+  elseif n==1 then
+   return function() return utfbyte(str) end
+  else
+   local p=1
+   return function()
+     local b,e=find(str,".[\128-\191]*",p)
+     if b then
+      p=e+1
+      return utfbyte(sub(str,b,e))
+     end
+   end
   end
-  string.utfcharacters=utf.characters
+ end
 end
-if not utf.values then
-  local find=string.find
-  local dummy=function()
-  end
-  function utf.values(str)
-    local n=#str
-    if n==0 then
-      return dummy
-    elseif n==1 then
-      return function() return utfbyte(str) end
-    else
-      local p=1
-      return function()
-          local b,e=find(str,".[\128-\191]*",p)
-          if b then
-            p=e+1
-            return utfbyte(sub(str,b,e))
-          end
-      end
-    end
-  end
-  string.utfvalues=utf.values
-end
+utf.values=string.utfvalues
 function utf.chrlen(u) 
-  return
-    (u<0x80 and 1) or
-    (u<0xE0 and 2) or
-    (u<0xF0 and 3) or
-    (u<0xF8 and 4) or
-    (u<0xFC and 5) or
-    (u<0xFE and 6) or 0
+ return
+  (u<0x80 and 1) or
+  (u<0xE0 and 2) or
+  (u<0xF0 and 3) or
+  (u<0xF8 and 4) or
+  (u<0xFC and 5) or
+  (u<0xFE and 6) or 0
 end
 if bit32 then
-  local extract=bit32.extract
-  local char=string.char
-  function unicode.toutf32string(n)
-    if n<=0xFF then
-      return
-        char(n).."\000\000\000"
-    elseif n<=0xFFFF then
-      return
-        char(extract(n,0,8))..char(extract(n,8,8)).."\000\000"
-    elseif n<=0xFFFFFF then
-      return
-        char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000"
-    else
-      return
-        char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8))
-    end
+ local extract=bit32.extract
+ local char=string.char
+ function utf.toutf32string(n)
+  if n<=0xFF then
+   return
+    char(n).."\000\000\000"
+  elseif n<=0xFFFF then
+   return
+    char(extract(n,0,8))..char(extract(n,8,8)).."\000\000"
+  elseif n<=0xFFFFFF then
+   return
+    char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000"
+  else
+   return
+    char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8))
   end
+ end
 end
 local len=utf.len
 local rep=rep
 function string.utfpadd(s,n)
-  if n and n~=0 then
-    local l=len(s)
-    if n>0 then
-      local d=n-l
-      if d>0 then
-        return rep(c or " ",d)..s
-      end
-    else
-      local d=- n-l
-      if d>0 then
-        return s..rep(c or " ",d)
-      end
-    end
+ if n and n~=0 then
+  local l=len(s)
+  if n>0 then
+   local d=n-l
+   if d>0 then
+    return rep(c or " ",d)..s
+   end
+  else
+   local d=- n-l
+   if d>0 then
+    return s..rep(c or " ",d)
+   end
   end
-  return s
+ end
+ return s
 end
+do
+ local utfcharacters=utf.characters or string.utfcharacters
+ local utfchar=utf.char    or string.utfcharacter
+ lpeg.UP=P
+ if utfcharacters then
+  function lpeg.US(str)
+   local p=P(false)
+   for uc in utfcharacters(str) do
+    p=p+P(uc)
+   end
+   return p
+  end
+ else
+  function lpeg.US(str)
+   local p=P(false)
+   local f=function(uc)
+    p=p+P(uc)
+   end
+   lpegmatch((p_utf8char/f)^0,str)
+   return p
+  end
+ end
+ local range=p_utf8byte*p_utf8byte+Cc(false) 
+ function lpeg.UR(str,more)
+  local first,last
+  if type(str)=="number" then
+   first=str
+   last=more or first
+  else
+   first,last=lpegmatch(range,str)
+   if not last then
+    return P(str)
+   end
+  end
+  if first==last then
+   return P(str)
+  end
+  if not utfchar then
+   utfchar=utf.char 
+  end
+  if utfchar and (last-first<8) then 
+   local p=P(false)
+   for i=first,last do
+    p=p+P(utfchar(i))
+   end
+   return p 
+  else
+   local f=function(b)
+    return b>=first and b<=last
+   end
+   return p_utf8byte/f 
+  end
+ end
+end
 
 
 end -- of closure
@@ -6005,93 +6369,93 @@
 
 package.loaded["l-math"] = package.loaded["l-math"] or true
 
--- original size: 2555, stripped down to: 1900
+-- original size: 2555, stripped down to: 1831
 
 if not modules then modules={} end modules ['l-math']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 if not math.ceiling then
-  math.ceiling=math.ceil
+ math.ceiling=math.ceil
 end
 if not math.round then
-  local floor=math.floor
-  function math.round(x) return floor(x+0.5) end
+ local floor=math.floor
+ function math.round(x) return floor(x+0.5) end
 end
 if not math.div then
-  local floor=math.floor
-  function math.div(n,m) return floor(n/m) end
+ local floor=math.floor
+ function math.div(n,m) return floor(n/m) end
 end
 if not math.mod then
-  function math.mod(n,m) return n%m end
+ function math.mod(n,m) return n%m end
 end
 if not math.sind then
-  local sin,cos,tan=math.sin,math.cos,math.tan
-  local pipi=2*math.pi/360
-  function math.sind(d) return sin(d*pipi) end
-  function math.cosd(d) return cos(d*pipi) end
-  function math.tand(d) return tan(d*pipi) end
+ local sin,cos,tan=math.sin,math.cos,math.tan
+ local pipi=2*math.pi/360
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
 end
 if not math.odd then
-  function math.odd (n) return n%2~=0 end
-  function math.even(n) return n%2==0 end
+ function math.odd (n) return n%2~=0 end
+ function math.even(n) return n%2==0 end
 end
 if not math.cosh then
-  local exp=math.exp
-  function math.cosh(x)
-    local xx=exp(x)
-    return (xx+1/xx)/2
-  end
-  function math.sinh(x)
-    local xx=exp(x)
-    return (xx-1/xx)/2
-  end
-  function math.tanh(x)
-    local xx=exp(x)
-    return (xx-1/xx)/(xx+1/xx)
-  end
+ local exp=math.exp
+ function math.cosh(x)
+  local xx=exp(x)
+  return (xx+1/xx)/2
+ end
+ function math.sinh(x)
+  local xx=exp(x)
+  return (xx-1/xx)/2
+ end
+ function math.tanh(x)
+  local xx=exp(x)
+  return (xx-1/xx)/(xx+1/xx)
+ end
 end
 if not math.pow then
-  function math.pow(x,y)
-    return x^y
-  end
+ function math.pow(x,y)
+  return x^y
+ end
 end
 if not math.atan2 then
-  math.atan2=math.atan
+ math.atan2=math.atan
 end
 if not math.ldexp then
-  function math.ldexp(x,e)
-    return x*2.0^e
-  end
+ function math.ldexp(x,e)
+  return x*2.0^e
+ end
 end
 if not math.log10 then
-  local log=math.log
-  function math.log10(x)
-    return log(x,10)
-  end
+ local log=math.log
+ function math.log10(x)
+  return log(x,10)
+ end
 end
 if not math.type then
-  function math.type()
-    return "float"
-  end
+ function math.type()
+  return "float"
+ end
 end
 if not math.tointeger then
-  math.mininteger=-0x4FFFFFFFFFFF
-  math.maxinteger=0x4FFFFFFFFFFF
-  local floor=math.floor
-  function math.tointeger(n)
-    local f=floor(n)
-    return f==n and f or nil
-  end
+ math.mininteger=-0x4FFFFFFFFFFF
+ math.maxinteger=0x4FFFFFFFFFFF
+ local floor=math.floor
+ function math.tointeger(n)
+  local f=floor(n)
+  return f==n and f or nil
+ end
 end
 if not math.ult then
-  local floor=math.floor
-  function math.tointeger(m,n)
-    return floor(m)<floor(n) 
-  end
+ local floor=math.floor
+ function math.tointeger(m,n)
+  return floor(m)<floor(n) 
+ end
 end
 
 
@@ -6101,14 +6465,14 @@
 
 package.loaded["util-str"] = package.loaded["util-str"] or true
 
--- original size: 38734, stripped down to: 22142
+-- original size: 43539, stripped down to: 21641
 
 if not modules then modules={} end modules ['util-str']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 utilities=utilities or {}
 utilities.strings=utilities.strings or {}
@@ -6121,41 +6485,60 @@
 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 utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
-local loadstripped=nil
-local oldfashioned=LUAVERSION<5.2
-if oldfashioned then
-  loadstripped=function(str,shortcuts)
-    return load(str)
-  end
-else
-  loadstripped=function(str,shortcuts)
-    if shortcuts then
-      return load(dump(load(str),true),nil,nil,shortcuts)
-    else
-      return load(dump(load(str),true))
-    end
-  end
+local loadstripped=function(str,shortcuts)
+ if shortcuts then
+  return load(dump(load(str),true),nil,nil,shortcuts)
+ else
+  return load(dump(load(str),true))
+ end
 end
 if not number then number={} end 
-local stripper=patterns.stripzeros
+local stripzero=patterns.stripzero
+local stripzeros=patterns.stripzeros
 local newline=patterns.newline
 local endofstring=patterns.endofstring
+local anything=patterns.anything
 local whitespace=patterns.whitespace
+local space=patterns.space
 local spacer=patterns.spacer
 local spaceortab=patterns.spaceortab
+local digit=patterns.digit
+local sign=patterns.sign
+local period=patterns.period
+local ptf=1/65536
+local bpf=(7200/7227)/65536
 local function points(n)
-  n=tonumber(n)
-  return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+ if n==0 then
+  return "0pt"
+ end
+ n=tonumber(n)
+ if not n or n==0 then
+  return "0pt"
+ end
+ n=n*ptf
+ if n%1==0 then
+  return format("%ipt",n)
+ end
+ return lpegmatch(stripzeros,format("%.5fpt",n)) 
 end
 local function basepoints(n)
-  n=tonumber(n)
-  return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
+ if n==0 then
+  return "0pt"
+ end
+ n=tonumber(n)
+ if not n or n==0 then
+  return "0pt"
+ end
+ n=n*bpf
+ if n%1==0 then
+  return format("%ibp",n)
+ end
+ return lpegmatch(stripzeros,format("%.5fbp",n)) 
 end
 number.points=points
 number.basepoints=basepoints
 local rubish=spaceortab^0*newline
 local anyrubish=spaceortab+newline
-local anything=patterns.anything
 local stripped=(spaceortab^1/"")*newline
 local leading=rubish^0/""
 local trailing=(anyrubish^1*endofstring)/""
@@ -6162,232 +6545,251 @@
 local redundant=rubish^3/"\n"
 local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
 function strings.collapsecrlf(str)
-  return lpegmatch(pattern,str)
+ return lpegmatch(pattern,str)
 end
 local repeaters={} 
 function strings.newrepeater(str,offset)
-  offset=offset or 0
-  local s=repeaters[str]
-  if not s then
-    s={}
-    repeaters[str]=s
+ offset=offset or 0
+ local s=repeaters[str]
+ if not s then
+  s={}
+  repeaters[str]=s
+ end
+ local t=s[offset]
+ if t then
+  return t
+ end
+ t={}
+ setmetatable(t,{ __index=function(t,k)
+  if not k then
+   return ""
   end
-  local t=s[offset]
-  if t then
-    return t
-  end
-  t={}
-  setmetatable(t,{ __index=function(t,k)
-    if not k then
-      return ""
-    end
-    local n=k+offset
-    local s=n>0 and rep(str,n) or ""
-    t[k]=s
-    return s
-  end })
-  s[offset]=t
-  return t
+  local n=k+offset
+  local s=n>0 and rep(str,n) or ""
+  t[k]=s
+  return s
+ end })
+ s[offset]=t
+ return t
 end
 local extra,tab,start=0,0,4,0
 local nspaces=strings.newrepeater(" ")
 string.nspaces=nspaces
 local pattern=Carg(1)/function(t)
-    extra,tab,start=0,t or 7,1
-  end*Cs((
+  extra,tab,start=0,t or 7,1
+ end*Cs((
    Cp()*patterns.tab/function(position)
-     local current=(position-start+1)+extra
-     local spaces=tab-(current-1)%tab
-     if spaces>0 then
-       extra=extra+spaces-1
-       return nspaces[spaces] 
-     else
-       return ""
-     end
+    local current=(position-start+1)+extra
+    local spaces=tab-(current-1)%tab
+    if spaces>0 then
+     extra=extra+spaces-1
+     return nspaces[spaces] 
+    else
+     return ""
+    end
    end+newline*Cp()/function(position)
-     extra,start=0,position
-   end+patterns.anything
- )^1)
+    extra,start=0,position
+   end+anything
+  )^1)
 function strings.tabtospace(str,tab)
-  return lpegmatch(pattern,str,1,tab or 7)
+ return lpegmatch(pattern,str,1,tab or 7)
 end
 function string.utfpadding(s,n)
-  if not n or n==0 then
-    return ""
-  end
-  local l=utflen(s)
-  if n>0 then
-    return nspaces[n-l]
-  else
-    return nspaces[-n-l]
-  end
+ if not n or n==0 then
+  return ""
+ end
+ local l=utflen(s)
+ if n>0 then
+  return nspaces[n-l]
+ else
+  return nspaces[-n-l]
+ end
 end
-local space=spacer^0
-local nospace=space/""
+local optionalspace=spacer^0
+local nospace=optionalspace/""
 local endofline=nospace*newline
 local stripend=(whitespace^1*endofstring)/""
-local normalline=(nospace*((1-space*(newline+endofstring))^1)*nospace)
+local normalline=(nospace*((1-optionalspace*(newline+endofstring))^1)*nospace)
 local stripempty=endofline^1/""
 local normalempty=endofline^1
 local singleempty=endofline*(endofline^0/"")
 local doubleempty=endofline*endofline^-1*(endofline^0/"")
 local stripstart=stripempty^0
+local intospace=whitespace^1/" "
+local noleading=whitespace^1/""
+local notrailing=noleading*endofstring
 local p_prune_normal=Cs (stripstart*(stripend+normalline+normalempty )^0 )
 local p_prune_collapse=Cs (stripstart*(stripend+normalline+doubleempty )^0 )
 local p_prune_noempty=Cs (stripstart*(stripend+normalline+singleempty )^0 )
+local p_prune_intospace=Cs (noleading*(notrailing+intospace+1     )^0 )
 local p_retain_normal=Cs ((normalline+normalempty )^0 )
 local p_retain_collapse=Cs ((normalline+doubleempty )^0 )
 local p_retain_noempty=Cs ((normalline+singleempty )^0 )
 local striplinepatterns={
-  ["prune"]=p_prune_normal,
-  ["prune and collapse"]=p_prune_collapse,
-  ["prune and no empty"]=p_prune_noempty,
-  ["retain"]=p_retain_normal,
-  ["retain and collapse"]=p_retain_collapse,
-  ["retain and no empty"]=p_retain_noempty,
-  ["collapse"]=patterns.collapser,
+ ["prune"]=p_prune_normal,
+ ["prune and collapse"]=p_prune_collapse,
+ ["prune and no empty"]=p_prune_noempty,
+ ["prune and to space"]=p_prune_intospace,
+ ["retain"]=p_retain_normal,
+ ["retain and collapse"]=p_retain_collapse,
+ ["retain and no empty"]=p_retain_noempty,
+ ["collapse"]=patterns.collapser,
 }
 setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end })
 strings.striplinepatterns=striplinepatterns
 function strings.striplines(str,how)
-  return str and lpegmatch(striplinepatterns[how],str) or str
+ return str and lpegmatch(striplinepatterns[how],str) or str
 end
+function strings.collapse(str) 
+ return str and lpegmatch(p_prune_intospace,str) or str
+end
 strings.striplong=strings.striplines
 function strings.nice(str)
-  str=gsub(str,"[:%-+_]+"," ") 
-  return str
+ str=gsub(str,"[:%-+_]+"," ") 
+ return str
 end
 local n=0
 local sequenced=table.sequenced
 function string.autodouble(s,sep)
-  if s==nil then
-    return '""'
-  end
-  local t=type(s)
-  if t=="number" then
-    return tostring(s) 
-  end
-  if t=="table" then
-    return ('"'..sequenced(s,sep or ",")..'"')
-  end
-  return ('"'..tostring(s)..'"')
+ if s==nil then
+  return '""'
+ end
+ local t=type(s)
+ if t=="number" then
+  return tostring(s) 
+ end
+ if t=="table" then
+  return ('"'..sequenced(s,sep or ",")..'"')
+ end
+ return ('"'..tostring(s)..'"')
 end
 function string.autosingle(s,sep)
-  if s==nil then
-    return "''"
-  end
-  local t=type(s)
-  if t=="number" then
-    return tostring(s) 
-  end
-  if t=="table" then
-    return ("'"..sequenced(s,sep or ",").."'")
-  end
-  return ("'"..tostring(s).."'")
+ if s==nil then
+  return "''"
+ end
+ local t=type(s)
+ if t=="number" then
+  return tostring(s) 
+ end
+ if t=="table" then
+  return ("'"..sequenced(s,sep or ",").."'")
+ end
+ return ("'"..tostring(s).."'")
 end
 local tracedchars={ [0]=
-  "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]",
-  "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]",
-  "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]",
-  "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]",
-  "[space]",
+ "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]",
+ "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]",
+ "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]",
+ "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]",
+ "[space]",
 }
 string.tracedchars=tracedchars
 strings.tracers=tracedchars
 function string.tracedchar(b)
-  if type(b)=="number" then
-    return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")")
-  else
-    local c=utfbyte(b)
-    return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")")
-  end
+ if type(b)=="number" then
+  return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")")
+ else
+  local c=utfbyte(b)
+  return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")")
+ end
 end
 function number.signed(i)
-  if i>0 then
-    return "+",i
-  else
-    return "-",-i
-  end
+ if i>0 then
+  return "+",i
+ else
+  return "-",-i
+ end
 end
-local digit=patterns.digit
-local period=patterns.period
-local three=digit*digit*digit
+local two=digit*digit
+local three=two*digit
+local prefix=(Carg(1)*three)^1
 local splitter=Cs (
-  (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2)
+ (((1-(three^1*period))^1+C(three))*prefix+C((1-period)^1))*(anything/""*Carg(2))*C(2)
 )
+local splitter3=Cs (
+ three*prefix*endofstring+two*prefix*endofstring+digit*prefix*endofstring+three+two+digit
+)
 patterns.formattednumber=splitter
 function number.formatted(n,sep1,sep2)
-  local s=type(s)=="string" and n or format("%0.2f",n)
+ if sep1==false then
+  if type(n)=="number" then
+   n=tostring(n)
+  end
+  return lpegmatch(splitter3,n,1,sep2 or ".")
+ else
+  if type(n)=="number" then
+   n=format("%0.2f",n)
+  end
   if sep1==true then
-    return lpegmatch(splitter,s,1,".",",")
+   return lpegmatch(splitter,n,1,".",",")
   elseif sep1=="." then
-    return lpegmatch(splitter,s,1,sep1,sep2 or ",")
+   return lpegmatch(splitter,n,1,sep1,sep2 or ",")
   elseif sep1=="," then
-    return lpegmatch(splitter,s,1,sep1,sep2 or ".")
+   return lpegmatch(splitter,n,1,sep1,sep2 or ".")
   else
-    return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
+   return lpegmatch(splitter,n,1,sep1 or ",",sep2 or ".")
   end
+ end
 end
 local p=Cs(
-    P("-")^0*(P("0")^1/"")^0*(1-P("."))^0*(P(".")*P("0")^1*P(-1)/""+P(".")^0)*P(1-P("0")^1*P(-1))^0
-  )
+  P("-")^0*(P("0")^1/"")^0*(1-period)^0*(period*P("0")^1*endofstring/""+period^0)*P(1-P("0")^1*endofstring)^0
+ )
 function number.compactfloat(n,fmt)
-  if n==0 then
-    return "0"
-  elseif n==1 then
-    return "1"
-  end
-  n=lpegmatch(p,format(fmt or "%0.3f",n))
-  if n=="." or n=="" or n=="-" then
-    return "0"
-  end
-  return n
+ if n==0 then
+  return "0"
+ elseif n==1 then
+  return "1"
+ end
+ n=lpegmatch(p,format(fmt or "%0.3f",n))
+ if n=="." or n=="" or n=="-" then
+  return "0"
+ end
+ return n
 end
 local zero=P("0")^1/""
 local plus=P("+")/""
 local minus=P("-")
-local separator=S(".")
-local digit=R("09")
+local separator=period
 local trailing=zero^1*#S("eE")
-local exponent=(S("eE")*(plus+Cs((minus*zero^0*P(-1))/"")+minus)*zero^0*(P(-1)*Cc("0")+P(1)^1))
+local exponent=(S("eE")*(plus+Cs((minus*zero^0*endofstring)/"")+minus)*zero^0*(endofstring*Cc("0")+anything^1))
 local pattern_a=Cs(minus^0*digit^1*(separator/""*trailing+separator*(trailing+digit)^0)*exponent)
-local pattern_b=Cs((exponent+P(1))^0)
+local pattern_b=Cs((exponent+anything)^0)
 function number.sparseexponent(f,n)
-  if not n then
-    n=f
-    f="%e"
+ if not n then
+  n=f
+  f="%e"
+ end
+ local tn=type(n)
+ if tn=="string" then 
+  local m=tonumber(n)
+  if m then
+   return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m))
   end
-  local tn=type(n)
-  if tn=="string" then 
-    local m=tonumber(n)
-    if m then
-      return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m))
-    end
-  elseif tn=="number" then
-    return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n))
-  end
-  return tostring(n)
+ elseif tn=="number" then
+  return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n))
+ end
+ return tostring(n)
 end
 local hf={}
 local hs={}
 setmetatable(hf,{ __index=function(t,k)
-  local v="%."..k.."f"
-  t[k]=v
-  return v
+ local v="%."..k.."f"
+ t[k]=v
+ return v
 end } )
 setmetatable(hs,{ __index=function(t,k)
-  local v="%"..k.."s"
-  t[k]=v
-  return v
+ local v="%"..k.."s"
+ t[k]=v
+ return v
 end } )
 function number.formattedfloat(n,b,a)
-  local s=format(hf[a],n)
-  local l=(b or 0)+(a or 0)+1
-  if #s<l then
-    return format(hs[l],s)
-  else
-    return s
-  end
+ local s=format(hf[a],n)
+ local l=(b or 0)+(a or 0)+1
+ if #s<l then
+  return format(hs[l],s)
+ else
+  return s
+ end
 end
 local template=[[
 %s
@@ -6394,351 +6796,346 @@
 %s
 return function(%s) return %s end
 ]]
-local preamble,environment="",{}
-if oldfashioned then
-  preamble=[[
-local lpeg=lpeg
-local type=type
-local tostring=tostring
-local tonumber=tonumber
-local format=string.format
-local concat=table.concat
-local signed=number.signed
-local points=number.points
-local basepoints= number.basepoints
-local utfchar=utf.char
-local utfbyte=utf.byte
-local lpegmatch=lpeg.match
-local nspaces=string.nspaces
-local utfpadding=string.utfpadding
-local tracedchar=string.tracedchar
-local autosingle=string.autosingle
-local autodouble=string.autodouble
-local sequenced=table.sequenced
-local formattednumber=number.formatted
-local sparseexponent=number.sparseexponent
-local formattedfloat=number.formattedfloat
-    ]]
-else
-  environment={
-    global=global or _G,
-    lpeg=lpeg,
-    type=type,
-    tostring=tostring,
-    tonumber=tonumber,
-    format=string.format,
-    concat=table.concat,
-    signed=number.signed,
-    points=number.points,
-    basepoints=number.basepoints,
-    utfchar=utf.char,
-    utfbyte=utf.byte,
-    lpegmatch=lpeg.match,
-    nspaces=string.nspaces,
-    utfpadding=string.utfpadding,
-    tracedchar=string.tracedchar,
-    autosingle=string.autosingle,
-    autodouble=string.autodouble,
-    sequenced=table.sequenced,
-    formattednumber=number.formatted,
-    sparseexponent=number.sparseexponent,
-    formattedfloat=number.formattedfloat,
-  }
-end
+local preamble=""
+local environment={
+ global=global or _G,
+ lpeg=lpeg,
+ type=type,
+ tostring=tostring,
+ tonumber=tonumber,
+ format=string.format,
+ concat=table.concat,
+ signed=number.signed,
+ points=number.points,
+ basepoints=number.basepoints,
+ utfchar=utf.char,
+ utfbyte=utf.byte,
+ lpegmatch=lpeg.match,
+ nspaces=string.nspaces,
+ utfpadding=string.utfpadding,
+ tracedchar=string.tracedchar,
+ autosingle=string.autosingle,
+ autodouble=string.autodouble,
+ sequenced=table.sequenced,
+ formattednumber=number.formatted,
+ sparseexponent=number.sparseexponent,
+ formattedfloat=number.formattedfloat,
+ stripzero=lpeg.patterns.stripzero,
+ stripzeros=lpeg.patterns.stripzeros,
+ FORMAT=string.f9,
+}
 local arguments={ "a1" } 
 setmetatable(arguments,{ __index=function(t,k)
-    local v=t[k-1]..",a"..k
-    t[k]=v
-    return v
-  end
+  local v=t[k-1]..",a"..k
+  t[k]=v
+  return v
+ end
 })
-local prefix_any=C((S("+- .")+R("09"))^0)
-local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(0))
+local prefix_any=C((sign+space+period+digit)^0)
+local prefix_sub=(C((sign+digit)^0)+Cc(0))*period*(C((sign+digit)^0)+Cc(0))
 local prefix_tab=P("{")*C((1-P("}"))^0)*P("}")+C((1-R("az","AZ","09","%%"))^0)
 local format_s=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("format('%%%ss',a%s)",f,n)
-  else 
-    return format("(a%s or '')",n) 
-  end
+ n=n+1
+ if f and f~="" then
+  return format("format('%%%ss',a%s)",f,n)
+ else 
+  return format("(a%s or '')",n) 
+ end
 end
 local format_S=function(f) 
-  n=n+1
-  if f and f~="" then
-    return format("format('%%%ss',tostring(a%s))",f,n)
-  else
-    return format("tostring(a%s)",n)
-  end
+ n=n+1
+ if f and f~="" then
+  return format("format('%%%ss',tostring(a%s))",f,n)
+ else
+  return format("tostring(a%s)",n)
+ end
 end
 local format_right=function(f)
-  n=n+1
-  f=tonumber(f)
-  if not f or f==0 then
-    return format("(a%s or '')",n)
-  elseif f>0 then
-    return format("utfpadding(a%s,%i)..a%s",n,f,n)
-  else
-    return format("a%s..utfpadding(a%s,%i)",n,n,f)
-  end
+ n=n+1
+ f=tonumber(f)
+ if not f or f==0 then
+  return format("(a%s or '')",n)
+ elseif f>0 then
+  return format("utfpadding(a%s,%i)..a%s",n,f,n)
+ else
+  return format("a%s..utfpadding(a%s,%i)",n,n,f)
+ end
 end
 local format_left=function(f)
-  n=n+1
-  f=tonumber(f)
-  if not f or f==0 then
-    return format("(a%s or '')",n)
-  end
-  if f<0 then
-    return format("utfpadding(a%s,%i)..a%s",n,-f,n)
-  else
-    return format("a%s..utfpadding(a%s,%i)",n,n,-f)
-  end
+ n=n+1
+ f=tonumber(f)
+ if not f or f==0 then
+  return format("(a%s or '')",n)
+ end
+ if f<0 then
+  return format("utfpadding(a%s,%i)..a%s",n,-f,n)
+ else
+  return format("a%s..utfpadding(a%s,%i)",n,n,-f)
+ end
 end
 local format_q=function()
-  n=n+1
-  return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n)
+ n=n+1
+ return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n)
 end
 local format_Q=function() 
-  n=n+1
-  return format("format('%%q',tostring(a%s))",n)
+ n=n+1
+ return format("format('%%q',tostring(a%s))",n)
 end
 local format_i=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("format('%%%si',a%s)",f,n)
-  else
-    return format("format('%%i',a%s)",n) 
-  end
+ n=n+1
+ if f and f~="" then
+  return format("format('%%%si',a%s)",f,n)
+ else
+  return format("format('%%i',a%s)",n) 
+ end
 end
 local format_d=format_i
 local format_I=function(f)
-  n=n+1
-  return format("format('%%s%%%si',signed(a%s))",f,n)
+ n=n+1
+ return format("format('%%s%%%si',signed(a%s))",f,n)
 end
 local format_f=function(f)
-  n=n+1
-  return format("format('%%%sf',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sf',a%s)",f,n)
 end
 local format_F=function(f) 
-  n=n+1
-  if not f or f=="" then
-    return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
-  else
-    return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
-  end
+ n=n+1
+ if not f or f=="" then
+  return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
+ else
+  return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
+ end
 end
 local format_k=function(b,a) 
-  n=n+1
-  return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0)
+ n=n+1
+ return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0)
 end
 local format_g=function(f)
-  n=n+1
-  return format("format('%%%sg',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sg',a%s)",f,n)
 end
 local format_G=function(f)
-  n=n+1
-  return format("format('%%%sG',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sG',a%s)",f,n)
 end
 local format_e=function(f)
-  n=n+1
-  return format("format('%%%se',a%s)",f,n)
+ n=n+1
+ return format("format('%%%se',a%s)",f,n)
 end
 local format_E=function(f)
-  n=n+1
-  return format("format('%%%sE',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sE',a%s)",f,n)
 end
 local format_j=function(f)
-  n=n+1
-  return format("sparseexponent('%%%se',a%s)",f,n)
+ n=n+1
+ return format("sparseexponent('%%%se',a%s)",f,n)
 end
 local format_J=function(f)
-  n=n+1
-  return format("sparseexponent('%%%sE',a%s)",f,n)
+ n=n+1
+ return format("sparseexponent('%%%sE',a%s)",f,n)
 end
 local format_x=function(f)
-  n=n+1
-  return format("format('%%%sx',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sx',a%s)",f,n)
 end
 local format_X=function(f)
-  n=n+1
-  return format("format('%%%sX',a%s)",f,n)
+ n=n+1
+ return format("format('%%%sX',a%s)",f,n)
 end
 local format_o=function(f)
-  n=n+1
-  return format("format('%%%so',a%s)",f,n)
+ n=n+1
+ return format("format('%%%so',a%s)",f,n)
 end
 local format_c=function()
-  n=n+1
-  return format("utfchar(a%s)",n)
+ n=n+1
+ return format("utfchar(a%s)",n)
 end
 local format_C=function()
-  n=n+1
-  return format("tracedchar(a%s)",n)
+ n=n+1
+ return format("tracedchar(a%s)",n)
 end
 local format_r=function(f)
-  n=n+1
-  return format("format('%%%s.0f',a%s)",f,n)
+ n=n+1
+ return format("format('%%%s.0f',a%s)",f,n)
 end
 local format_h=function(f)
-  n=n+1
-  if f=="-" then
-    f=sub(f,2)
-    return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  else
-    return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  end
+ n=n+1
+ if f=="-" then
+  f=sub(f,2)
+  return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+  return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
 end
 local format_H=function(f)
-  n=n+1
-  if f=="-" then
-    f=sub(f,2)
-    return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  else
-    return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  end
+ n=n+1
+ if f=="-" then
+  f=sub(f,2)
+  return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+  return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
 end
 local format_u=function(f)
-  n=n+1
-  if f=="-" then
-    f=sub(f,2)
-    return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  else
-    return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  end
+ n=n+1
+ if f=="-" then
+  f=sub(f,2)
+  return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+  return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
 end
 local format_U=function(f)
-  n=n+1
-  if f=="-" then
-    f=sub(f,2)
-    return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  else
-    return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
-  end
+ n=n+1
+ if f=="-" then
+  f=sub(f,2)
+  return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+  return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
 end
 local format_p=function()
-  n=n+1
-  return format("points(a%s)",n)
+ n=n+1
+ return format("points(a%s)",n)
 end
 local format_b=function()
-  n=n+1
-  return format("basepoints(a%s)",n)
+ n=n+1
+ return format("basepoints(a%s)",n)
 end
 local format_t=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("concat(a%s,%q)",n,f)
-  else
-    return format("concat(a%s)",n)
-  end
+ n=n+1
+ if f and f~="" then
+  return format("concat(a%s,%q)",n,f)
+ else
+  return format("concat(a%s)",n)
+ end
 end
 local format_T=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("sequenced(a%s,%q)",n,f)
-  else
-    return format("sequenced(a%s)",n)
-  end
+ n=n+1
+ if f and f~="" then
+  return format("sequenced(a%s,%q)",n,f)
+ else
+  return format("sequenced(a%s)",n)
+ end
 end
 local format_l=function()
-  n=n+1
-  return format("(a%s and 'true' or 'false')",n)
+ n=n+1
+ return format("(a%s and 'true' or 'false')",n)
 end
 local format_L=function()
-  n=n+1
-  return format("(a%s and 'TRUE' or 'FALSE')",n)
+ n=n+1
+ return format("(a%s and 'TRUE' or 'FALSE')",n)
 end
-local format_N=function() 
-  n=n+1
-  return format("tostring(tonumber(a%s) or a%s)",n,n)
+local format_n=function() 
+ n=n+1
+ return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
 end
+local format_N=function(f) 
+ n=n+1
+ if not f or f=="" then
+  f=".9"
+ end 
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+end
 local format_a=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("autosingle(a%s,%q)",n,f)
-  else
-    return format("autosingle(a%s)",n)
-  end
+ n=n+1
+ if f and f~="" then
+  return format("autosingle(a%s,%q)",n,f)
+ else
+  return format("autosingle(a%s)",n)
+ end
 end
 local format_A=function(f)
-  n=n+1
-  if f and f~="" then
-    return format("autodouble(a%s,%q)",n,f)
-  else
-    return format("autodouble(a%s)",n)
-  end
+ n=n+1
+ if f and f~="" then
+  return format("autodouble(a%s,%q)",n,f)
+ else
+  return format("autodouble(a%s)",n)
+ end
 end
 local format_w=function(f) 
-  n=n+1
-  f=tonumber(f)
-  if f then 
-    return format("nspaces[%s+a%s]",f,n) 
-  else
-    return format("nspaces[a%s]",n) 
-  end
+ n=n+1
+ f=tonumber(f)
+ if f then 
+  return format("nspaces[%s+a%s]",f,n) 
+ else
+  return format("nspaces[a%s]",n) 
+ end
 end
 local format_W=function(f) 
-  return format("nspaces[%s]",tonumber(f) or 0)
+ return format("nspaces[%s]",tonumber(f) or 0)
 end
 local format_m=function(f)
-  n=n+1
-  if not f or f=="" then
-    f=","
-  end
+ n=n+1
+ if not f or f=="" then
+  f=","
+ end
+ if f=="0" then
+  return format([[formattednumber(a%s,false)]],n)
+ else
   return format([[formattednumber(a%s,%q,".")]],n,f)
+ end
 end
 local format_M=function(f)
-  n=n+1
-  if not f or f=="" then
-    f="."
-  end
+ n=n+1
+ if not f or f=="" then
+  f="."
+ end
+ if f=="0" then
+  return format([[formattednumber(a%s,false)]],n)
+ else
   return format([[formattednumber(a%s,%q,",")]],n,f)
+ end
 end
 local format_z=function(f)
-  n=n+(tonumber(f) or 1)
-  return "''" 
+ n=n+(tonumber(f) or 1)
+ return "''" 
 end
 local format_rest=function(s)
-  return format("%q",s) 
+ return format("%q",s) 
 end
 local format_extension=function(extensions,f,name)
-  local extension=extensions[name] or "tostring(%s)"
-  local f=tonumber(f) or 1
-  local w=find(extension,"%.%.%.")
+ local extension=extensions[name] or "tostring(%s)"
+ local f=tonumber(f) or 1
+ local w=find(extension,"%.%.%.")
+ if w then
   if f==0 then
-    if w then
-      extension=gsub(extension,"%.%.%.","")
-    end
-    return extension
+   extension=gsub(extension,"%.%.%.","")
+   return extension
   elseif f==1 then
-    if w then
-      extension=gsub(extension,"%.%.%.","%%s")
-    end
-    n=n+1
-    local a="a"..n
-    return format(extension,a,a) 
+   extension=gsub(extension,"%.%.%.","%%s")
+   n=n+1
+   local a="a"..n
+   return format(extension,a,a) 
   elseif f<0 then
-    local a="a"..(n+f+1)
-    return format(extension,a,a)
+   local a="a"..(n+f+1)
+   return format(extension,a,a)
   else
-    if w then
-      extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
-    end
-    local t={}
-    for i=1,f do
-      n=n+1
-      t[i]="a"..n
-    end
-    return format(extension,unpack(t))
+   extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+   local t={}
+   for i=1,f do
+    n=n+1
+    t[i]="a"..n
+   end
+   return format(extension,unpack(t))
   end
+ else
+  extension=gsub(extension,"%%s",function()
+   n=n+1
+   return "a"..n
+  end)
+  return extension
+ end
 end
 local builder=Cs { "start",
-  start=(
-    (
-      P("%")/""*(
-        V("!") 
+ start=(
+  (
+   P("%")/""*(
+    V("!") 
 +V("s")+V("q")+V("i")+V("d")+V("f")+V("F")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o")
 +V("c")+V("C")+V("S") 
 +V("Q") 
++V("n") 
 +V("N") 
 +V("k")
 +V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") 
@@ -6750,161 +7147,157 @@
 +V("z")
 +V(">") 
 +V("<")
-      )+V("*")
-    )*(P(-1)+Carg(1))
-  )^0,
-  ["s"]=(prefix_any*P("s"))/format_s,
-  ["q"]=(prefix_any*P("q"))/format_q,
-  ["i"]=(prefix_any*P("i"))/format_i,
-  ["d"]=(prefix_any*P("d"))/format_d,
-  ["f"]=(prefix_any*P("f"))/format_f,
-  ["F"]=(prefix_any*P("F"))/format_F,
-  ["g"]=(prefix_any*P("g"))/format_g,
-  ["G"]=(prefix_any*P("G"))/format_G,
-  ["e"]=(prefix_any*P("e"))/format_e,
-  ["E"]=(prefix_any*P("E"))/format_E,
-  ["x"]=(prefix_any*P("x"))/format_x,
-  ["X"]=(prefix_any*P("X"))/format_X,
-  ["o"]=(prefix_any*P("o"))/format_o,
-  ["S"]=(prefix_any*P("S"))/format_S,
-  ["Q"]=(prefix_any*P("Q"))/format_Q,
-  ["N"]=(prefix_any*P("N"))/format_N,
-  ["k"]=(prefix_sub*P("k"))/format_k,
-  ["c"]=(prefix_any*P("c"))/format_c,
-  ["C"]=(prefix_any*P("C"))/format_C,
-  ["r"]=(prefix_any*P("r"))/format_r,
-  ["h"]=(prefix_any*P("h"))/format_h,
-  ["H"]=(prefix_any*P("H"))/format_H,
-  ["u"]=(prefix_any*P("u"))/format_u,
-  ["U"]=(prefix_any*P("U"))/format_U,
-  ["p"]=(prefix_any*P("p"))/format_p,
-  ["b"]=(prefix_any*P("b"))/format_b,
-  ["t"]=(prefix_tab*P("t"))/format_t,
-  ["T"]=(prefix_tab*P("T"))/format_T,
-  ["l"]=(prefix_any*P("l"))/format_l,
-  ["L"]=(prefix_any*P("L"))/format_L,
-  ["I"]=(prefix_any*P("I"))/format_I,
-  ["w"]=(prefix_any*P("w"))/format_w,
-  ["W"]=(prefix_any*P("W"))/format_W,
-  ["j"]=(prefix_any*P("j"))/format_j,
-  ["J"]=(prefix_any*P("J"))/format_J,
-  ["m"]=(prefix_tab*P("m"))/format_m,
-  ["M"]=(prefix_tab*P("M"))/format_M,
-  ["z"]=(prefix_any*P("z"))/format_z,
-  ["a"]=(prefix_any*P("a"))/format_a,
-  ["A"]=(prefix_any*P("A"))/format_A,
-  ["<"]=(prefix_any*P("<"))/format_left,
-  [">"]=(prefix_any*P(">"))/format_right,
-  ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest,
-  ["?"]=Cs(((1-P("%"))^1        )^1)/format_rest,
-  ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
+   )+V("*")
+  )*(endofstring+Carg(1))
+ )^0,
+ ["s"]=(prefix_any*P("s"))/format_s,
+ ["q"]=(prefix_any*P("q"))/format_q,
+ ["i"]=(prefix_any*P("i"))/format_i,
+ ["d"]=(prefix_any*P("d"))/format_d,
+ ["f"]=(prefix_any*P("f"))/format_f,
+ ["F"]=(prefix_any*P("F"))/format_F,
+ ["g"]=(prefix_any*P("g"))/format_g,
+ ["G"]=(prefix_any*P("G"))/format_G,
+ ["e"]=(prefix_any*P("e"))/format_e,
+ ["E"]=(prefix_any*P("E"))/format_E,
+ ["x"]=(prefix_any*P("x"))/format_x,
+ ["X"]=(prefix_any*P("X"))/format_X,
+ ["o"]=(prefix_any*P("o"))/format_o,
+ ["S"]=(prefix_any*P("S"))/format_S,
+ ["Q"]=(prefix_any*P("Q"))/format_Q,
+ ["n"]=(prefix_any*P("n"))/format_n,
+ ["N"]=(prefix_any*P("N"))/format_N,
+ ["k"]=(prefix_sub*P("k"))/format_k,
+ ["c"]=(prefix_any*P("c"))/format_c,
+ ["C"]=(prefix_any*P("C"))/format_C,
+ ["r"]=(prefix_any*P("r"))/format_r,
+ ["h"]=(prefix_any*P("h"))/format_h,
+ ["H"]=(prefix_any*P("H"))/format_H,
+ ["u"]=(prefix_any*P("u"))/format_u,
+ ["U"]=(prefix_any*P("U"))/format_U,
+ ["p"]=(prefix_any*P("p"))/format_p,
+ ["b"]=(prefix_any*P("b"))/format_b,
+ ["t"]=(prefix_tab*P("t"))/format_t,
+ ["T"]=(prefix_tab*P("T"))/format_T,
+ ["l"]=(prefix_any*P("l"))/format_l,
+ ["L"]=(prefix_any*P("L"))/format_L,
+ ["I"]=(prefix_any*P("I"))/format_I,
+ ["w"]=(prefix_any*P("w"))/format_w,
+ ["W"]=(prefix_any*P("W"))/format_W,
+ ["j"]=(prefix_any*P("j"))/format_j,
+ ["J"]=(prefix_any*P("J"))/format_J,
+ ["m"]=(prefix_any*P("m"))/format_m,
+ ["M"]=(prefix_any*P("M"))/format_M,
+ ["z"]=(prefix_any*P("z"))/format_z,
+ ["a"]=(prefix_any*P("a"))/format_a,
+ ["A"]=(prefix_any*P("A"))/format_A,
+ ["<"]=(prefix_any*P("<"))/format_left,
+ [">"]=(prefix_any*P(">"))/format_right,
+ ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest,
+ ["?"]=Cs(((1-P("%"))^1      )^1)/format_rest,
+ ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
 }
 local xx=setmetatable({},{ __index=function(t,k) local v=format("%02x",k) t[k]=v return v end })
 local XX=setmetatable({},{ __index=function(t,k) local v=format("%02X",k) t[k]=v return v end })
 local preset={
-  ["%02x"]=function(n) return xx[n] end,
-  ["%02X"]=function(n) return XX[n] end,
+ ["%02x"]=function(n) return xx[n] end,
+ ["%02X"]=function(n) return XX[n] end,
 }
-local direct=P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]]
+local direct=P("%")*(sign+space+period+digit)^0*S("sqidfgGeExXo")*endofstring/[[local format = string.format return function(str) return format("%0",str) end]]
 local function make(t,str)
-  local f=preset[str]
-  if f then
-    return f
-  end
-  local p=lpegmatch(direct,str)
-  if p then
-    f=loadstripped(p)()
+ local f=preset[str]
+ if f then
+  return f
+ end
+ local p=lpegmatch(direct,str)
+ if p then
+  f=loadstripped(p)()
+ else
+  n=0
+  p=lpegmatch(builder,str,1,t._connector_,t._extensions_) 
+  if n>0 then
+   p=format(template,preamble,t._preamble_,arguments[n],p)
+   f=loadstripped(p,t._environment_)() 
   else
-    n=0
-    p=lpegmatch(builder,str,1,t._connector_,t._extensions_) 
-    if n>0 then
-      p=format(template,preamble,t._preamble_,arguments[n],p)
-      f=loadstripped(p,t._environment_)() 
-    else
-      f=function() return str end
-    end
+   f=function() return str end
   end
-  t[str]=f
-  return f
+ end
+ t[str]=f
+ return f
 end
 local function use(t,fmt,...)
-  return t[fmt](...)
+ return t[fmt](...)
 end
 strings.formatters={}
-if oldfashioned then
-  function strings.formatters.new(noconcat)
-    local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_=preamble,_environment_={} }
-    setmetatable(t,{ __index=make,__call=use })
-    return t
-  end
-else
-  function strings.formatters.new(noconcat)
-    local e={} 
-    for k,v in next,environment do
-      e[k]=v
-    end
-    local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_="",_environment_=e }
-    setmetatable(t,{ __index=make,__call=use })
-    return t
-  end
+function strings.formatters.new(noconcat)
+ local e={} 
+ for k,v in next,environment do
+  e[k]=v
+ end
+ local t={
+  _type_="formatter",
+  _connector_=noconcat and "," or "..",
+  _extensions_={},
+  _preamble_="",
+  _environment_=e,
+ }
+ setmetatable(t,{ __index=make,__call=use })
+ return t
 end
 local formatters=strings.formatters.new() 
 string.formatters=formatters 
 string.formatter=function(str,...) return formatters[str](...) end 
 local function add(t,name,template,preamble)
-  if type(t)=="table" and t._type_=="formatter" then
-    t._extensions_[name]=template or "%s"
-    if type(preamble)=="string" then
-      t._preamble_=preamble.."\n"..t._preamble_ 
-    elseif type(preamble)=="table" then
-      for k,v in next,preamble do
-        t._environment_[k]=v
-      end
-    end
+ if type(t)=="table" and t._type_=="formatter" then
+  t._extensions_[name]=template or "%s"
+  if type(preamble)=="string" then
+   t._preamble_=preamble.."\n"..t._preamble_ 
+  elseif type(preamble)=="table" then
+   for k,v in next,preamble do
+    t._environment_[k]=v
+   end
   end
+ end
 end
 strings.formatters.add=add
-patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0)
-patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0)
+patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+anything)^0)
+patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+anything)^0)
 patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) 
 patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"'))
-if oldfashioned then
-  add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape")
-  add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape")
-  add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape")
-else
-  add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape })
-  add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
-  add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
-end
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
 local dquote=patterns.dquote 
 local equote=patterns.escaped+dquote/'\\"'+1
-local space=patterns.space
 local cquote=Cc('"')
-local pattern=Cs(dquote*(equote-P(-2))^0*dquote)          
+local pattern=Cs(dquote*(equote-P(-2))^0*dquote)     
 +Cs(cquote*(equote-space)^0*space*equote^0*cquote) 
 function string.optionalquoted(str)
-  return lpegmatch(pattern,str) or str
+ return lpegmatch(pattern,str) or str
 end
 local pattern=Cs((newline/(os.newline or "\r")+1)^0)
 function string.replacenewlines(str)
-  return lpegmatch(pattern,str)
+ return lpegmatch(pattern,str)
 end
 function strings.newcollector()
-  local result,r={},0
-  return
-    function(fmt,str,...) 
-      r=r+1
-      result[r]=str==nil and fmt or formatters[fmt](str,...)
-    end,
-    function(connector) 
-      if result then
-        local str=concat(result,connector)
-        result,r={},0
-        return str
-      end
-    end
+ local result,r={},0
+ return
+  function(fmt,str,...) 
+   r=r+1
+   result[r]=str==nil and fmt or formatters[fmt](str,...)
+  end,
+  function(connector) 
+   if result then
+    local str=concat(result,connector)
+    result,r={},0
+    return str
+   end
+  end
 end
+local f_16_16=formatters["%0.5N"]
+function number.to16dot16(n)
+ return f_16_16(n/65536.0)
+end
 
 
 end -- of closure
@@ -6913,14 +7306,14 @@
 
 package.loaded["util-tab"] = package.loaded["util-tab"] or true
 
--- original size: 27741, stripped down to: 17085
+-- original size: 28772, stripped down to: 16111
 
 if not modules then modules={} end modules ['util-tab']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 utilities=utilities or {}
 utilities.tables=utilities.tables or {}
@@ -6935,219 +7328,220 @@
 local utftoeight=utf.toeight
 local splitter=lpeg.tsplitat(".")
 function utilities.tables.definetable(target,nofirst,nolast) 
-  local composed,t=nil,{}
-  local snippets=lpegmatch(splitter,target)
-  for i=1,#snippets-(nolast and 1 or 0) do
-    local name=snippets[i]
-    if composed then
-      composed=composed.."."..name
-        t[#t+1]=formatters["if not %s then %s = { } end"](composed,composed)
-    else
-      composed=name
-      if not nofirst then
-        t[#t+1]=formatters["%s = %s or { }"](composed,composed)
-      end
-    end
-  end
+ local composed=nil
+ local t={}
+ local snippets=lpegmatch(splitter,target)
+ for i=1,#snippets-(nolast and 1 or 0) do
+  local name=snippets[i]
   if composed then
-    if nolast then
-      composed=composed.."."..snippets[#snippets]
-    end
-    return concat(t,"\n"),composed 
+   composed=composed.."."..name
+    t[#t+1]=formatters["if not %s then %s = { } end"](composed,composed)
   else
-    return "",target
+   composed=name
+   if not nofirst then
+    t[#t+1]=formatters["%s = %s or { }"](composed,composed)
+   end
   end
+ end
+ if composed then
+  if nolast then
+   composed=composed.."."..snippets[#snippets]
+  end
+  return concat(t,"\n"),composed 
+ else
+  return "",target
+ end
 end
 function tables.definedtable(...)
-  local t=_G
-  for i=1,select("#",...) do
-    local li=select(i,...)
-    local tl=t[li]
-    if not tl then
-      tl={}
-      t[li]=tl
-    end
-    t=tl
+ local t=_G
+ for i=1,select("#",...) do
+  local li=select(i,...)
+  local tl=t[li]
+  if not tl then
+   tl={}
+   t[li]=tl
   end
-  return t
+  t=tl
+ end
+ return t
 end
 function tables.accesstable(target,root)
-  local t=root or _G
-  for name in gmatch(target,"([^%.]+)") do
-    t=t[name]
-    if not t then
-      return
-    end
+ local t=root or _G
+ for name in gmatch(target,"([^%.]+)") do
+  t=t[name]
+  if not t then
+   return
   end
-  return t
+ end
+ return t
 end
 function tables.migratetable(target,v,root)
-  local t=root or _G
-  local names=lpegmatch(splitter,target)
-  for i=1,#names-1 do
-    local name=names[i]
-    t[name]=t[name] or {}
-    t=t[name]
-    if not t then
-      return
-    end
+ local t=root or _G
+ local names=lpegmatch(splitter,target)
+ for i=1,#names-1 do
+  local name=names[i]
+  t[name]=t[name] or {}
+  t=t[name]
+  if not t then
+   return
   end
-  t[names[#names]]=v
+ end
+ t[names[#names]]=v
 end
 function tables.removevalue(t,value) 
-  if value then
-    for i=1,#t do
-      if t[i]==value then
-        remove(t,i)
-      end
-    end
+ if value then
+  for i=1,#t do
+   if t[i]==value then
+    remove(t,i)
+   end
   end
+ end
 end
 function tables.replacevalue(t,oldvalue,newvalue)
-  if oldvalue and newvalue then
-    for i=1,#t do
-      if t[i]==oldvalue then
-        t[i]=newvalue
-      end
-    end
+ if oldvalue and newvalue then
+  for i=1,#t do
+   if t[i]==oldvalue then
+    t[i]=newvalue
+   end
   end
+ end
 end
 function tables.insertbeforevalue(t,value,extra)
-  for i=1,#t do
-    if t[i]==extra then
-      remove(t,i)
-    end
+ for i=1,#t do
+  if t[i]==extra then
+   remove(t,i)
   end
-  for i=1,#t do
-    if t[i]==value then
-      insert(t,i,extra)
-      return
-    end
+ end
+ for i=1,#t do
+  if t[i]==value then
+   insert(t,i,extra)
+   return
   end
-  insert(t,1,extra)
+ end
+ insert(t,1,extra)
 end
 function tables.insertaftervalue(t,value,extra)
-  for i=1,#t do
-    if t[i]==extra then
-      remove(t,i)
-    end
+ for i=1,#t do
+  if t[i]==extra then
+   remove(t,i)
   end
-  for i=1,#t do
-    if t[i]==value then
-      insert(t,i+1,extra)
-      return
-    end
+ end
+ for i=1,#t do
+  if t[i]==value then
+   insert(t,i+1,extra)
+   return
   end
-  insert(t,#t+1,extra)
+ end
+ insert(t,#t+1,extra)
 end
 local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"'))
 function table.tocsv(t,specification)
-  if t and #t>0 then
-    local result={}
-    local r={}
-    specification=specification or {}
-    local fields=specification.fields
-    if type(fields)~="string" then
-      fields=sortedkeys(t[1])
+ if t and #t>0 then
+  local result={}
+  local r={}
+  specification=specification or {}
+  local fields=specification.fields
+  if type(fields)~="string" then
+   fields=sortedkeys(t[1])
+  end
+  local separator=specification.separator or ","
+  local noffields=#fields
+  if specification.preamble==true then
+   for f=1,noffields do
+    r[f]=lpegmatch(escape,tostring(fields[f]))
+   end
+   result[1]=concat(r,separator)
+  end
+  for i=1,#t do
+   local ti=t[i]
+   for f=1,noffields do
+    local field=ti[fields[f]]
+    if type(field)=="string" then
+     r[f]=lpegmatch(escape,field)
+    else
+     r[f]=tostring(field)
     end
-    local separator=specification.separator or ","
-    local noffields=#fields
-    if specification.preamble==true then
-      for f=1,noffields do
-        r[f]=lpegmatch(escape,tostring(fields[f]))
-      end
-      result[1]=concat(r,separator)
-    end
-    for i=1,#t do
-      local ti=t[i]
-      for f=1,noffields do
-        local field=ti[fields[f]]
-        if type(field)=="string" then
-          r[f]=lpegmatch(escape,field)
-        else
-          r[f]=tostring(field)
-        end
-      end
-      result[i+1]=concat(r,separator)
-    end
-    return concat(result,"\n")
-  else
-    return ""
+   end
+   result[i+1]=concat(r,separator)
   end
+  return concat(result,"\n")
+ else
+  return ""
+ end
 end
 local nspaces=utilities.strings.newrepeater(" ")
 local function toxml(t,d,result,step)
-  local r=#result
-  for k,v in sortedpairs(t) do
-    local s=nspaces[d] 
-    local tk=type(k)
-    local tv=type(v)
-    if tv=="table" then
-      if tk=="number" then
-        r=r+1 result[r]=formatters["%s<entry n='%s'>"](s,k)
-        toxml(v,d+step,result,step)
-        r=r+1 result[r]=formatters["%s</entry>"](s,k)
-      else
-        r=r+1 result[r]=formatters["%s<%s>"](s,k)
-        toxml(v,d+step,result,step)
-        r=r+1 result[r]=formatters["%s</%s>"](s,k)
-      end
-    elseif tv=="string" then
-      if tk=="number" then
-        r=r+1 result[r]=formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k)
-      else
-        r=r+1 result[r]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k)
-      end
-    elseif tk=="number" then
-      r=r+1 result[r]=formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k)
-    else
-      r=r+1 result[r]=formatters["%s<%s>%S</%s>"](s,k,v,k)
-    end
+ local r=#result
+ for k,v in sortedpairs(t) do
+  local s=nspaces[d] 
+  local tk=type(k)
+  local tv=type(v)
+  if tv=="table" then
+   if tk=="number" then
+    r=r+1 result[r]=formatters["%s<entry n='%s'>"](s,k)
+    toxml(v,d+step,result,step)
+    r=r+1 result[r]=formatters["%s</entry>"](s,k)
+   else
+    r=r+1 result[r]=formatters["%s<%s>"](s,k)
+    toxml(v,d+step,result,step)
+    r=r+1 result[r]=formatters["%s</%s>"](s,k)
+   end
+  elseif tv=="string" then
+   if tk=="number" then
+    r=r+1 result[r]=formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k)
+   else
+    r=r+1 result[r]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k)
+   end
+  elseif tk=="number" then
+   r=r+1 result[r]=formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k)
+  else
+   r=r+1 result[r]=formatters["%s<%s>%S</%s>"](s,k,v,k)
   end
+ end
 end
 function table.toxml(t,specification)
-  specification=specification or {}
-  local name=specification.name
-  local noroot=name==false
-  local result=(specification.nobanner or noroot) and {} or { "<?xml version='1.0' standalone='yes' ?>" }
-  local indent=specification.indent or 0
-  local spaces=specification.spaces or 1
-  if noroot then
-    toxml(t,indent,result,spaces)
-  else
-    toxml({ [name or "data"]=t },indent,result,spaces)
-  end
-  return concat(result,"\n")
+ specification=specification or {}
+ local name=specification.name
+ local noroot=name==false
+ local result=(specification.nobanner or noroot) and {} or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent=specification.indent or 0
+ local spaces=specification.spaces or 1
+ if noroot then
+  toxml(t,indent,result,spaces)
+ else
+  toxml({ [name or "data"]=t },indent,result,spaces)
+ end
+ return concat(result,"\n")
 end
 function tables.encapsulate(core,capsule,protect)
-  if type(capsule)~="table" then
-    protect=true
-    capsule={}
+ if type(capsule)~="table" then
+  protect=true
+  capsule={}
+ end
+ for key,value in next,core do
+  if capsule[key] then
+   print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
+   os.exit()
+  else
+   capsule[key]=value
   end
+ end
+ if protect then
   for key,value in next,core do
+   core[key]=nil
+  end
+  setmetatable(core,{
+   __index=capsule,
+   __newindex=function(t,key,value)
     if capsule[key] then
-      print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
-      os.exit()
+     print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+     os.exit()
     else
-      capsule[key]=value
+     rawset(t,key,value)
     end
-  end
-  if protect then
-    for key,value in next,core do
-      core[key]=nil
-    end
-    setmetatable(core,{
-      __index=capsule,
-      __newindex=function(t,key,value)
-        if capsule[key] then
-          print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
-          os.exit()
-        else
-          rawset(t,key,value)
-        end
-      end
-    } )
-  end
+   end
+  } )
+ end
 end
 local f_hashed_string=formatters["[%q]=%q,"]
 local f_hashed_number=formatters["[%q]=%s,"]
@@ -7161,157 +7555,157 @@
 local f_ordered_number=formatters["%s,"]
 local f_ordered_boolean=formatters["%l,"]
 function table.fastserialize(t,prefix)
-  local r={ type(prefix)=="string" and prefix or "return" }
-  local m=1
-  local function fastserialize(t,outer) 
-    local n=#t
-    m=m+1
-    r[m]="{"
-    if n>0 then
-      for i=0,n do
-        local v=t[i]
-        local tv=type(v)
-        if tv=="string" then
-          m=m+1 r[m]=f_ordered_string(v)
-        elseif tv=="number" then
-          m=m+1 r[m]=f_ordered_number(v)
-        elseif tv=="table" then
-          fastserialize(v)
-        elseif tv=="boolean" then
-          m=m+1 r[m]=f_ordered_boolean(v)
-        end
-      end
+ local r={ type(prefix)=="string" and prefix or "return" }
+ local m=1
+ local function fastserialize(t,outer) 
+  local n=#t
+  m=m+1
+  r[m]="{"
+  if n>0 then
+   for i=0,n do
+    local v=t[i]
+    local tv=type(v)
+    if tv=="string" then
+     m=m+1 r[m]=f_ordered_string(v)
+    elseif tv=="number" then
+     m=m+1 r[m]=f_ordered_number(v)
+    elseif tv=="table" then
+     fastserialize(v)
+    elseif tv=="boolean" then
+     m=m+1 r[m]=f_ordered_boolean(v)
     end
-    for k,v in next,t do
-      local tk=type(k)
-      if tk=="number" then
-        if k>n or k<0 then
-          local tv=type(v)
-          if tv=="string" then
-            m=m+1 r[m]=f_indexed_string(k,v)
-          elseif tv=="number" then
-            m=m+1 r[m]=f_indexed_number(k,v)
-          elseif tv=="table" then
-            m=m+1 r[m]=f_indexed_table(k)
-            fastserialize(v)
-          elseif tv=="boolean" then
-            m=m+1 r[m]=f_indexed_boolean(k,v)
-          end
-        end
-      else
-        local tv=type(v)
-        if tv=="string" then
-          m=m+1 r[m]=f_hashed_string(k,v)
-        elseif tv=="number" then
-          m=m+1 r[m]=f_hashed_number(k,v)
-        elseif tv=="table" then
-          m=m+1 r[m]=f_hashed_table(k)
-          fastserialize(v)
-        elseif tv=="boolean" then
-          m=m+1 r[m]=f_hashed_boolean(k,v)
-        end
-      end
+   end
+  end
+  for k,v in next,t do
+   local tk=type(k)
+   if tk=="number" then
+    if k>n or k<0 then
+     local tv=type(v)
+     if tv=="string" then
+      m=m+1 r[m]=f_indexed_string(k,v)
+     elseif tv=="number" then
+      m=m+1 r[m]=f_indexed_number(k,v)
+     elseif tv=="table" then
+      m=m+1 r[m]=f_indexed_table(k)
+      fastserialize(v)
+     elseif tv=="boolean" then
+      m=m+1 r[m]=f_indexed_boolean(k,v)
+     end
     end
-    m=m+1
-    if outer then
-      r[m]="}"
-    else
-      r[m]="},"
+   else
+    local tv=type(v)
+    if tv=="string" then
+     m=m+1 r[m]=f_hashed_string(k,v)
+    elseif tv=="number" then
+     m=m+1 r[m]=f_hashed_number(k,v)
+    elseif tv=="table" then
+     m=m+1 r[m]=f_hashed_table(k)
+     fastserialize(v)
+    elseif tv=="boolean" then
+     m=m+1 r[m]=f_hashed_boolean(k,v)
     end
-    return r
+   end
   end
-  return concat(fastserialize(t,true))
+  m=m+1
+  if outer then
+   r[m]="}"
+  else
+   r[m]="},"
+  end
+  return r
+ end
+ return concat(fastserialize(t,true))
 end
 function table.deserialize(str)
-  if not str or str=="" then
-    return
-  end
-  local code=load(str)
-  if not code then
-    return
-  end
-  code=code()
-  if not code then
-    return
-  end
-  return code
+ if not str or str=="" then
+  return
+ end
+ local code=load(str)
+ if not code then
+  return
+ end
+ code=code()
+ if not code then
+  return
+ end
+ return code
 end
 function table.load(filename,loader)
-  if filename then
-    local t=(loader or io.loaddata)(filename)
-    if t and t~="" then
-      local t=utftoeight(t)
-      t=load(t)
-      if type(t)=="function" then
-        t=t()
-        if type(t)=="table" then
-          return t
-        end
-      end
+ if filename then
+  local t=(loader or io.loaddata)(filename)
+  if t and t~="" then
+   local t=utftoeight(t)
+   t=load(t)
+   if type(t)=="function" then
+    t=t()
+    if type(t)=="table" then
+     return t
     end
+   end
   end
+ end
 end
 function table.save(filename,t,n,...)
-  io.savedata(filename,table.serialize(t,n==nil and true or n,...)) 
+ io.savedata(filename,table.serialize(t,n==nil and true or n,...)) 
 end
 local f_key_value=formatters["%s=%q"]
 local f_add_table=formatters[" {%t},\n"]
 local f_return_table=formatters["return {\n%t}"]
 local function slowdrop(t) 
-  local r={}
-  local l={}
-  for i=1,#t do
-    local ti=t[i]
-    local j=0
-    for k,v in next,ti do
-      j=j+1
-      l[j]=f_key_value(k,v)
-    end
-    r[i]=f_add_table(l)
+ local r={}
+ local l={}
+ for i=1,#t do
+  local ti=t[i]
+  local j=0
+  for k,v in next,ti do
+   j=j+1
+   l[j]=f_key_value(k,v)
   end
-  return f_return_table(r)
+  r[i]=f_add_table(l)
+ end
+ return f_return_table(r)
 end
 local function fastdrop(t)
-  local r={ "return {\n" }
-  local m=1
-  for i=1,#t do
-    local ti=t[i]
-    m=m+1 r[m]=" {"
-    for k,v in next,ti do
-      m=m+1 r[m]=f_key_value(k,v)
-    end
-    m=m+1 r[m]="},\n"
+ local r={ "return {\n" }
+ local m=1
+ for i=1,#t do
+  local ti=t[i]
+  m=m+1 r[m]=" {"
+  for k,v in next,ti do
+   m=m+1 r[m]=f_key_value(k,v)
   end
-  m=m+1
-  r[m]="}"
-  return concat(r)
+  m=m+1 r[m]="},\n"
+ end
+ m=m+1
+ r[m]="}"
+ return concat(r)
 end
 function table.drop(t,slow) 
-  if #t==0 then
-    return "return { }"
-  elseif slow==true then
-    return slowdrop(t) 
-  else
-    return fastdrop(t) 
-  end
+ if #t==0 then
+  return "return { }"
+ elseif slow==true then
+  return slowdrop(t) 
+ else
+  return fastdrop(t) 
+ end
 end
 local selfmapper={ __index=function(t,k) t[k]=k return k end }
-function table.twowaymapper(t)  
-  if not t then         
-    t={}          
-  else             
-    local zero=rawget(t,0) 
-    for i=zero and 0 or 1,#t do
-      local ti=t[i]    
-      if ti then
-        local i=tostring(i)
-        t[i]=ti   
-        t[ti]=i    
-      end
-    end
+function table.twowaymapper(t) 
+ if not t then     
+  t={}       
+ else        
+  local zero=rawget(t,0)  
+  for i=zero and 0 or 1,#t do
+   local ti=t[i]    
+   if ti then
+    local i=tostring(i)
+    t[i]=ti   
+    t[ti]=i    
+   end
   end
-  setmetatable(t,selfmapper)
-  return t
+ end
+ setmetatable(t,selfmapper)
+ return t
 end
 local f_start_key_idx=formatters["%w{"]
 local f_start_key_num=formatters["%w[%s]={"]
@@ -7349,188 +7743,224 @@
 local original_serialize=table.serialize
 local is_simple_table=table.is_simple_table
 local function serialize(root,name,specification)
-  if type(specification)=="table" then
-    return original_serialize(root,name,specification) 
+ if type(specification)=="table" then
+  return original_serialize(root,name,specification) 
+ end
+ local t 
+ local n=1
+ local unknown=false
+ local function do_serialize(root,name,depth,level,indexed)
+  if level>0 then
+   n=n+1
+   if indexed then
+    t[n]=f_start_key_idx(depth)
+   else
+    local tn=type(name)
+    if tn=="number" then
+     t[n]=f_start_key_num(depth,name)
+    elseif tn=="string" then
+     t[n]=f_start_key_str(depth,name)
+    elseif tn=="boolean" then
+     t[n]=f_start_key_boo(depth,name)
+    else
+     t[n]=f_start_key_nop(depth)
+    end
+   end
+   depth=depth+1
   end
-  local t  
-  local n=1
-  local unknown=false
-  local function do_serialize(root,name,depth,level,indexed)
-    if level>0 then
-      n=n+1
-      if indexed then
-        t[n]=f_start_key_idx(depth)
+  if root and next(root)~=nil then
+   local first=nil
+   local last=0
+   last=#root
+   for k=1,last do
+    if rawget(root,k)==nil then
+     last=k-1
+     break
+    end
+   end
+   if last>0 then
+    first=1
+   end
+   local sk=sortedkeys(root) 
+   for i=1,#sk do
+    local k=sk[i]
+    local v=root[k]
+    local tv=type(v)
+    local tk=type(k)
+    if first and tk=="number" and k<=last and k>=first then
+     if tv=="number" then
+      n=n+1 t[n]=f_val_num(depth,v)
+     elseif tv=="string" then
+      n=n+1 t[n]=f_val_str(depth,v)
+     elseif tv=="table" then
+      if next(v)==nil then 
+       n=n+1 t[n]=f_val_not(depth)
       else
-        local tn=type(name)
-        if tn=="number" then
-          t[n]=f_start_key_num(depth,name)
-        elseif tn=="string" then
-          t[n]=f_start_key_str(depth,name)
-        elseif tn=="boolean" then
-          t[n]=f_start_key_boo(depth,name)
-        else
-          t[n]=f_start_key_nop(depth)
-        end
+       local st=is_simple_table(v)
+       if st then
+        n=n+1 t[n]=f_val_seq(depth,st)
+       else
+        do_serialize(v,k,depth,level+1,true)
+       end
       end
-      depth=depth+1
-    end
-    if root and next(root)~=nil then
-      local first=nil
-      local last=0
-      last=#root
-      for k=1,last do
-        if rawget(root,k)==nil then
-          last=k-1
-          break
-        end
+     elseif tv=="boolean" then
+      n=n+1 t[n]=f_val_boo(depth,v)
+     elseif unknown then
+      n=n+1 t[n]=f_val_str(depth,tostring(v))
+     end
+    elseif tv=="number" then
+     if tk=="number" then
+      n=n+1 t[n]=f_key_num_value_num(depth,k,v)
+     elseif tk=="string" then
+      n=n+1 t[n]=f_key_str_value_num(depth,k,v)
+     elseif tk=="boolean" then
+      n=n+1 t[n]=f_key_boo_value_num(depth,k,v)
+     elseif unknown then
+      n=n+1 t[n]=f_key_str_value_num(depth,tostring(k),v)
+     end
+    elseif tv=="string" then
+     if tk=="number" then
+      n=n+1 t[n]=f_key_num_value_str(depth,k,v)
+     elseif tk=="string" then
+      n=n+1 t[n]=f_key_str_value_str(depth,k,v)
+     elseif tk=="boolean" then
+      n=n+1 t[n]=f_key_boo_value_str(depth,k,v)
+     elseif unknown then
+      n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),v)
+     end
+    elseif tv=="table" then
+     if next(v)==nil then
+      if tk=="number" then
+       n=n+1 t[n]=f_key_num_value_not(depth,k)
+      elseif tk=="string" then
+       n=n+1 t[n]=f_key_str_value_not(depth,k)
+      elseif tk=="boolean" then
+       n=n+1 t[n]=f_key_boo_value_not(depth,k)
+      elseif unknown then
+       n=n+1 t[n]=f_key_str_value_not(depth,tostring(k))
       end
-      if last>0 then
-        first=1
+     else
+      local st=is_simple_table(v)
+      if not st then
+       do_serialize(v,k,depth,level+1)
+      elseif tk=="number" then
+       n=n+1 t[n]=f_key_num_value_seq(depth,k,st)
+      elseif tk=="string" then
+       n=n+1 t[n]=f_key_str_value_seq(depth,k,st)
+      elseif tk=="boolean" then
+       n=n+1 t[n]=f_key_boo_value_seq(depth,k,st)
+      elseif unknown then
+       n=n+1 t[n]=f_key_str_value_seq(depth,tostring(k),st)
       end
-      local sk=sortedkeys(root) 
-      for i=1,#sk do
-        local k=sk[i]
-        local v=root[k]
-        local tv=type(v)
-        local tk=type(k)
-        if first and tk=="number" and k<=last and k>=first then
-          if tv=="number" then
-            n=n+1 t[n]=f_val_num(depth,v)
-          elseif tv=="string" then
-            n=n+1 t[n]=f_val_str(depth,v)
-          elseif tv=="table" then
-            if next(v)==nil then 
-              n=n+1 t[n]=f_val_not(depth)
-            else
-              local st=is_simple_table(v)
-              if st then
-                n=n+1 t[n]=f_val_seq(depth,st)
-              else
-                do_serialize(v,k,depth,level+1,true)
-              end
-            end
-          elseif tv=="boolean" then
-            n=n+1 t[n]=f_val_boo(depth,v)
-          elseif unknown then
-            n=n+1 t[n]=f_val_str(depth,tostring(v))
-          end
-        elseif tv=="number" then
-          if tk=="number" then
-            n=n+1 t[n]=f_key_num_value_num(depth,k,v)
-          elseif tk=="string" then
-            n=n+1 t[n]=f_key_str_value_num(depth,k,v)
-          elseif tk=="boolean" then
-            n=n+1 t[n]=f_key_boo_value_num(depth,k,v)
-          elseif unknown then
-            n=n+1 t[n]=f_key_str_value_num(depth,tostring(k),v)
-          end
-        elseif tv=="string" then
-          if tk=="number" then
-            n=n+1 t[n]=f_key_num_value_str(depth,k,v)
-          elseif tk=="string" then
-            n=n+1 t[n]=f_key_str_value_str(depth,k,v)
-          elseif tk=="boolean" then
-            n=n+1 t[n]=f_key_boo_value_str(depth,k,v)
-          elseif unknown then
-            n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),v)
-          end
-        elseif tv=="table" then
-          if next(v)==nil then
-            if tk=="number" then
-              n=n+1 t[n]=f_key_num_value_not(depth,k)
-            elseif tk=="string" then
-              n=n+1 t[n]=f_key_str_value_not(depth,k)
-            elseif tk=="boolean" then
-              n=n+1 t[n]=f_key_boo_value_not(depth,k)
-            elseif unknown then
-              n=n+1 t[n]=f_key_str_value_not(depth,tostring(k))
-            end
-          else
-            local st=is_simple_table(v)
-            if not st then
-              do_serialize(v,k,depth,level+1)
-            elseif tk=="number" then
-              n=n+1 t[n]=f_key_num_value_seq(depth,k,st)
-            elseif tk=="string" then
-              n=n+1 t[n]=f_key_str_value_seq(depth,k,st)
-            elseif tk=="boolean" then
-              n=n+1 t[n]=f_key_boo_value_seq(depth,k,st)
-            elseif unknown then
-              n=n+1 t[n]=f_key_str_value_seq(depth,tostring(k),st)
-            end
-          end
-        elseif tv=="boolean" then
-          if tk=="number" then
-            n=n+1 t[n]=f_key_num_value_boo(depth,k,v)
-          elseif tk=="string" then
-            n=n+1 t[n]=f_key_str_value_boo(depth,k,v)
-          elseif tk=="boolean" then
-            n=n+1 t[n]=f_key_boo_value_boo(depth,k,v)
-          elseif unknown then
-            n=n+1 t[n]=f_key_str_value_boo(depth,tostring(k),v)
-          end
-        else
-          if tk=="number" then
-            n=n+1 t[n]=f_key_num_value_str(depth,k,tostring(v))
-          elseif tk=="string" then
-            n=n+1 t[n]=f_key_str_value_str(depth,k,tostring(v))
-          elseif tk=="boolean" then
-            n=n+1 t[n]=f_key_boo_value_str(depth,k,tostring(v))
-          elseif unknown then
-            n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),tostring(v))
-          end
-        end
-      end
+     end
+    elseif tv=="boolean" then
+     if tk=="number" then
+      n=n+1 t[n]=f_key_num_value_boo(depth,k,v)
+     elseif tk=="string" then
+      n=n+1 t[n]=f_key_str_value_boo(depth,k,v)
+     elseif tk=="boolean" then
+      n=n+1 t[n]=f_key_boo_value_boo(depth,k,v)
+     elseif unknown then
+      n=n+1 t[n]=f_key_str_value_boo(depth,tostring(k),v)
+     end
+    else
+     if tk=="number" then
+      n=n+1 t[n]=f_key_num_value_str(depth,k,tostring(v))
+     elseif tk=="string" then
+      n=n+1 t[n]=f_key_str_value_str(depth,k,tostring(v))
+     elseif tk=="boolean" then
+      n=n+1 t[n]=f_key_boo_value_str(depth,k,tostring(v))
+     elseif unknown then
+      n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),tostring(v))
+     end
     end
-    if level>0 then
-      n=n+1 t[n]=f_stop(depth-1)
-    end
+   end
   end
-  local tname=type(name)
-  if tname=="string" then
-    if name=="return" then
-      t={ f_table_return() }
-    else
-      t={ f_table_name(name) }
-    end
-  elseif tname=="number" then
-    t={ f_table_entry(name) }
-  elseif tname=="boolean" then
-    if name then
-      t={ f_table_return() }
-    else
-      t={ f_table_direct() }
-    end
+  if level>0 then
+   n=n+1 t[n]=f_stop(depth-1)
+  end
+ end
+ local tname=type(name)
+ if tname=="string" then
+  if name=="return" then
+   t={ f_table_return() }
   else
-    t={ f_table_name("t") }
+   t={ f_table_name(name) }
   end
-  if root then
-    if getmetatable(root) then 
-      local dummy=root._w_h_a_t_e_v_e_r_ 
-      root._w_h_a_t_e_v_e_r_=nil
-    end
-    if next(root)~=nil then
-      local st=is_simple_table(root)
-      if st then
-        return t[1]..f_fin_seq(st) 
-      else
-        do_serialize(root,name,1,0)
-      end
-    end
+ elseif tname=="number" then
+  t={ f_table_entry(name) }
+ elseif tname=="boolean" then
+  if name then
+   t={ f_table_return() }
+  else
+   t={ f_table_direct() }
   end
-  n=n+1
-  t[n]=f_table_finish()
-  return concat(t,"\n")
+ else
+  t={ f_table_name("t") }
+ end
+ if root then
+  if getmetatable(root) then 
+   local dummy=root._w_h_a_t_e_v_e_r_ 
+   root._w_h_a_t_e_v_e_r_=nil
+  end
+  if next(root)~=nil then
+   local st=is_simple_table(root)
+   if st then
+    return t[1]..f_fin_seq(st) 
+   else
+    do_serialize(root,name,1,0)
+   end
+  end
+ end
+ n=n+1
+ t[n]=f_table_finish()
+ return concat(t,"\n")
 end
 table.serialize=serialize
 if setinspector then
-  setinspector("table",function(v)
-    if type(v)=="table" then
-      print(serialize(v,"table",{ metacheck=false }))
-      return true
-    end
-  end)
+ setinspector("table",function(v)
+  if type(v)=="table" then
+   print(serialize(v,"table",{ metacheck=false }))
+   return true
+  end
+ end)
 end
+local mt={
+ __newindex=function(t,k,v)
+  local n=t.last+1
+  t.last=n
+  t.list[n]=k
+  t.hash[k]=v
+ end,
+ __index=function(t,k)
+  return t.hash[k]
+ end,
+ __len=function(t)
+  return t.last
+ end,
+}
+function table.orderedhash()
+ return setmetatable({ list={},hash={},last=0 },mt)
+end
+function table.ordered(t)
+ local n=t.last
+ if n>0 then
+  local l=t.list
+  local i=1
+  local h=t.hash
+  local f=function()
+   if i<=n then
+    local k=i
+    local v=h[l[k]]
+    i=i+1
+    return k,v
+   end
+  end
+  return f,1,h[l[1]]
+ else
+  return function() end
+ end
+end
 
 
 end -- of closure
@@ -7539,15 +7969,16 @@
 
 package.loaded["util-fil"] = package.loaded["util-fil"] or true
 
--- original size: 7787, stripped down to: 5858
+-- original size: 8607, stripped down to: 6727
 
 if not modules then modules={} end modules ['util-fil']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 tonumber=tonumber
 local byte=string.byte
 local char=string.char
 utilities=utilities or {}
@@ -7555,252 +7986,281 @@
 utilities.files=files
 local zerobased={}
 function files.open(filename,zb)
-  local f=io.open(filename,"rb")
-  if f then
-    zerobased[f]=zb or false
-  end
-  return f
+ local f=io.open(filename,"rb")
+ if f then
+  zerobased[f]=zb or false
+ end
+ return f
 end
 function files.close(f)
-  zerobased[f]=nil
-  f:close()
+ zerobased[f]=nil
+ f:close()
 end
 function files.size(f)
-  local current=f:seek()
-  local size=f:seek("end")
-  f:seek("set",current)
-  return size
+ local current=f:seek()
+ local size=f:seek("end")
+ f:seek("set",current)
+ return size
 end
 files.getsize=files.size
 function files.setposition(f,n)
-  if zerobased[f] then
-    f:seek("set",n)
-  else
-    f:seek("set",n-1)
-  end
+ if zerobased[f] then
+  f:seek("set",n)
+ else
+  f:seek("set",n-1)
+ end
 end
 function files.getposition(f)
-  if zerobased[f] then
-    return f:seek()
-  else
-    return f:seek()+1
-  end
+ if zerobased[f] then
+  return f:seek()
+ else
+  return f:seek()+1
+ end
 end
 function files.look(f,n,chars)
-  local p=f:seek()
-  local s=f:read(n)
-  f:seek("set",p)
-  if chars then
-    return s
-  else
-    return byte(s,1,#s)
-  end
+ local p=f:seek()
+ local s=f:read(n)
+ f:seek("set",p)
+ if chars then
+  return s
+ else
+  return byte(s,1,#s)
+ end
 end
 function files.skip(f,n)
-  if n==1 then
-    f:read(n)
-  else
-    f:seek("set",f:seek()+n)
-  end
+ if n==1 then
+  f:read(n)
+ else
+  f:seek("set",f:seek()+n)
+ end
 end
 function files.readbyte(f)
-  return byte(f:read(1))
+ return byte(f:read(1))
 end
 function files.readbytes(f,n)
-  return byte(f:read(n),1,n)
+ return byte(f:read(n),1,n)
 end
 function files.readbytetable(f,n)
-  local s=f:read(n or 1)
-  return { byte(s,1,#s) } 
+ local s=f:read(n or 1)
+ return { byte(s,1,#s) } 
 end
 function files.readchar(f)
-  return f:read(1)
+ return f:read(1)
 end
 function files.readstring(f,n)
-  return f:read(n or 1)
+ return f:read(n or 1)
 end
-function files.readinteger1(f) 
-  local n=byte(f:read(1))
-  if n>=0x80 then
-    return n-0x100
-  else
-    return n
-  end
+function files.readinteger1(f)  
+ local n=byte(f:read(1))
+ if n>=0x80 then
+  return n-0x100
+ else
+  return n
+ end
 end
-files.readcardinal1=files.readbyte 
+files.readcardinal1=files.readbyte  
 files.readcardinal=files.readcardinal1
 files.readinteger=files.readinteger1
 files.readsignedbyte=files.readinteger1
 function files.readcardinal2(f)
-  local a,b=byte(f:read(2),1,2)
-  return 0x100*a+b
+ local a,b=byte(f:read(2),1,2)
+ return 0x100*a+b
 end
 function files.readcardinal2le(f)
-  local b,a=byte(f:read(2),1,2)
-  return 0x100*a+b
+ local b,a=byte(f:read(2),1,2)
+ return 0x100*a+b
 end
 function files.readinteger2(f)
-  local a,b=byte(f:read(2),1,2)
-  if a>=0x80 then
-    return 0x100*a+b-0x10000
-  else
-    return 0x100*a+b
-  end
+ local a,b=byte(f:read(2),1,2)
+ if a>=0x80 then
+  return 0x100*a+b-0x10000
+ else
+  return 0x100*a+b
+ end
 end
 function files.readinteger2le(f)
-  local b,a=byte(f:read(2),1,2)
-  if a>=0x80 then
-    return 0x100*a+b-0x10000
-  else
-    return 0x100*a+b
-  end
+ local b,a=byte(f:read(2),1,2)
+ if a>=0x80 then
+  return 0x100*a+b-0x10000
+ else
+  return 0x100*a+b
+ end
 end
 function files.readcardinal3(f)
-  local a,b,c=byte(f:read(3),1,3)
-  return 0x10000*a+0x100*b+c
+ local a,b,c=byte(f:read(3),1,3)
+ return 0x10000*a+0x100*b+c
 end
 function files.readcardinal3le(f)
-  local c,b,a=byte(f:read(3),1,3)
-  return 0x10000*a+0x100*b+c
+ local c,b,a=byte(f:read(3),1,3)
+ return 0x10000*a+0x100*b+c
 end
 function files.readinteger3(f)
-  local a,b,c=byte(f:read(3),1,3)
-  if a>=0x80 then
-    return 0x10000*a+0x100*b+c-0x1000000
-  else
-    return 0x10000*a+0x100*b+c
-  end
+ local a,b,c=byte(f:read(3),1,3)
+ if a>=0x80 then
+  return 0x10000*a+0x100*b+c-0x1000000
+ else
+  return 0x10000*a+0x100*b+c
+ end
 end
 function files.readinteger3le(f)
-  local c,b,a=byte(f:read(3),1,3)
-  if a>=0x80 then
-    return 0x10000*a+0x100*b+c-0x1000000
-  else
-    return 0x10000*a+0x100*b+c
-  end
+ local c,b,a=byte(f:read(3),1,3)
+ if a>=0x80 then
+  return 0x10000*a+0x100*b+c-0x1000000
+ else
+  return 0x10000*a+0x100*b+c
+ end
 end
 function files.readcardinal4(f)
-  local a,b,c,d=byte(f:read(4),1,4)
-  return 0x1000000*a+0x10000*b+0x100*c+d
+ local a,b,c,d=byte(f:read(4),1,4)
+ return 0x1000000*a+0x10000*b+0x100*c+d
 end
 function files.readcardinal4le(f)
-  local d,c,b,a=byte(f:read(4),1,4)
-  return 0x1000000*a+0x10000*b+0x100*c+d
+ local d,c,b,a=byte(f:read(4),1,4)
+ return 0x1000000*a+0x10000*b+0x100*c+d
 end
 function files.readinteger4(f)
-  local a,b,c,d=byte(f:read(4),1,4)
-  if a>=0x80 then
-    return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
-  else
-    return 0x1000000*a+0x10000*b+0x100*c+d
-  end
+ local a,b,c,d=byte(f:read(4),1,4)
+ 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 files.readinteger4le(f)
-  local d,c,b,a=byte(f:read(4),1,4)
-  if a>=0x80 then
-    return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
-  else
-    return 0x1000000*a+0x10000*b+0x100*c+d
-  end
+ local d,c,b,a=byte(f:read(4),1,4)
+ 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 files.readfixed2(f)
-  local a,b=byte(f:read(2),1,2)
-  if a>=0x80 then
-    return (a-0x100)+b/0x100
-  else
-    return (a    )+b/0x100
-  end
+ local a,b=byte(f:read(2),1,2)
+ if a>=0x80 then
+  tonumber((a-0x100).."."..b)
+ else
+  tonumber((a    ).."."..b)
+ end
 end
 function files.readfixed4(f)
-  local a,b,c,d=byte(f:read(4),1,4)
+ local a,b,c,d=byte(f:read(4),1,4)
+ if a>=0x80 then
+  tonumber((0x100*a+b-0x10000).."."..(0x100*c+d))
+ else
+  tonumber((0x100*a+b    ).."."..(0x100*c+d))
+ end
+end
+if bit32 then
+ local extract=bit32.extract
+ local band=bit32.band
+ function files.read2dot14(f)
+  local a,b=byte(f:read(2),1,2)
   if a>=0x80 then
-    return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000
+   local n=-(0x100*a+b)
+   return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0))
   else
-    return (0x100*a+b     )+(0x100*c+d)/0x10000
+   local n=0x100*a+b
+   return   (extract(n,14,2)+(band(n,0x3FFF)/16384.0))
   end
+ end
 end
-if bit32 then
-  local extract=bit32.extract
-  local band=bit32.band
-  function files.read2dot14(f)
-    local a,b=byte(f:read(2),1,2)
-    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 files.skipshort(f,n)
-  f:read(2*(n or 1))
+ f:read(2*(n or 1))
 end
 function files.skiplong(f,n)
-  f:read(4*(n or 1))
+ f:read(4*(n or 1))
 end
 if bit32 then
-  local rshift=bit32.rshift
-  function files.writecardinal2(f,n)
-    local a=char(n%256)
-    n=rshift(n,8)
-    local b=char(n%256)
-    f:write(b,a)
-  end
-else
-  local floor=math.floor
-  function files.writecardinal2(f,n)
-    local a=char(n%256)
-    n=floor(n/256)
-    local b=char(n%256)
-    f:write(b,a)
-  end
-end
-function files.writecardinal4(f,n)
+ local rshift=bit32.rshift
+ function files.writecardinal2(f,n)
   local a=char(n%256)
   n=rshift(n,8)
   local b=char(n%256)
-  n=rshift(n,8)
-  local c=char(n%256)
-  n=rshift(n,8)
-  local d=char(n%256)
-  f:write(d,c,b,a)
+  f:write(b,a)
+ end
+else
+ local floor=math.floor
+ function files.writecardinal2(f,n)
+  local a=char(n%256)
+  n=floor(n/256)
+  local b=char(n%256)
+  f:write(b,a)
+ end
 end
+function files.writecardinal4(f,n)
+ local a=char(n%256)
+ n=rshift(n,8)
+ local b=char(n%256)
+ n=rshift(n,8)
+ local c=char(n%256)
+ n=rshift(n,8)
+ local d=char(n%256)
+ f:write(d,c,b,a)
+end
 function files.writestring(f,s)
-  f:write(char(byte(s,1,#s)))
+ f:write(char(byte(s,1,#s)))
 end
 function files.writebyte(f,b)
-  f:write(char(b))
+ f:write(char(b))
 end
 if fio and fio.readcardinal1 then
-  files.readcardinal1=fio.readcardinal1
-  files.readcardinal2=fio.readcardinal2
-  files.readcardinal3=fio.readcardinal3
-  files.readcardinal4=fio.readcardinal4
-  files.readinteger1=fio.readinteger1
-  files.readinteger2=fio.readinteger2
-  files.readinteger3=fio.readinteger3
-  files.readinteger4=fio.readinteger4
-  files.readfixed2=fio.readfixed2
-  files.readfixed4=fio.readfixed4
-  files.read2dot14=fio.read2dot14
-  files.setposition=fio.setposition
-  files.getposition=fio.getposition
-  files.readbyte=files.readcardinal1
-  files.readsignedbyte=files.readinteger1
-  files.readcardinal=files.readcardinal1
-  files.readinteger=files.readinteger1
-  local skipposition=fio.skipposition
-  files.skipposition=skipposition
-  files.readbytes=fio.readbytes
-  files.readbytetable=fio.readbytetable
-  function files.skipshort(f,n)
-    skipposition(f,2*(n or 1))
-  end
-  function files.skiplong(f,n)
-    skipposition(f,4*(n or 1))
-  end
+ files.readcardinal1=fio.readcardinal1
+ files.readcardinal2=fio.readcardinal2
+ files.readcardinal3=fio.readcardinal3
+ files.readcardinal4=fio.readcardinal4
+ files.readinteger1=fio.readinteger1
+ files.readinteger2=fio.readinteger2
+ files.readinteger3=fio.readinteger3
+ files.readinteger4=fio.readinteger4
+ files.readfixed2=fio.readfixed2
+ files.readfixed4=fio.readfixed4
+ files.read2dot14=fio.read2dot14
+ files.setposition=fio.setposition
+ files.getposition=fio.getposition
+ files.readbyte=files.readcardinal1
+ files.readsignedbyte=files.readinteger1
+ files.readcardinal=files.readcardinal1
+ files.readinteger=files.readinteger1
+ local skipposition=fio.skipposition
+ files.skipposition=skipposition
+ files.readbytes=fio.readbytes
+ files.readbytetable=fio.readbytetable
+ function files.skipshort(f,n)
+  skipposition(f,2*(n or 1))
+ end
+ function files.skiplong(f,n)
+  skipposition(f,4*(n or 1))
+ end
 end
+if fio and fio.readcardinaltable then
+ files.readcardinaltable=fio.readcardinaltable
+ files.readintegertable=fio.readintegertable
+else
+ local readcardinal1=files.readcardinal1
+ local readcardinal2=files.readcardinal2
+ local readcardinal3=files.readcardinal3
+ local readcardinal4=files.readcardinal4
+ function files.readcardinaltable(f,n,b)
+  local t={}
+   if b==1 then for i=1,n do t[i]=readcardinal1(f) end
+  elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end
+  elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end
+  elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end
+  return t
+ end
+ local readinteger1=files.readinteger1
+ local readinteger2=files.readinteger2
+ local readinteger3=files.readinteger3
+ local readinteger4=files.readinteger4
+ function files.readintegertable(f,n,b)
+  local t={}
+   if b==1 then for i=1,n do t[i]=readinteger1(f) end
+  elseif b==2 then for i=1,n do t[i]=readinteger2(f) end
+  elseif b==3 then for i=1,n do t[i]=readinteger3(f) end
+  elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end
+  return t
+ end
+end
 
 
 end -- of closure
@@ -7809,338 +8269,412 @@
 
 package.loaded["util-sac"] = package.loaded["util-sac"] or true
 
--- original size: 8716, stripped down to: 6754
+-- original size: 11065, stripped down to: 8209
 
 if not modules then modules={} end modules ['util-sac']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 extract=bit32 and bit32.extract
+local tonumber=tonumber
 utilities=utilities or {}
 local streams={}
 utilities.streams=streams
 function streams.open(filename,zerobased)
-  local f=io.loaddata(filename)
+ 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.close()
 end
 function streams.size(f)
-  return f and f[3] or 0
+ return f and f[3] or 0
 end
 function streams.setposition(f,i)
-  if f[4] then
-    if i<=0 then
-      f[2]=1
-    else
-      f[2]=i+1
-    end
+ if f[4] then
+  if i<=0 then
+   f[2]=1
   else
-    if i<=1 then
-      f[2]=1
-    else
-      f[2]=i
-    end
+   f[2]=i+1
   end
-end
-function streams.getposition(f)
-  if f[4] then
-    return f[2]-1
+ else
+  if i<=1 then
+   f[2]=1
   else
-    return f[2]
+   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
+ 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
+ f[2]=f[2]+n
 end
 function streams.readbyte(f)
-  local i=f[2]
-  f[2]=i+1
-  return byte(f[1],i)
+ 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)
+ 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) }
+ 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
+ f[2]=f[2]+n
 end
 function streams.readchar(f)
-  local i=f[2]
-  f[2]=i+1
-  return sub(f[1],i,i)
+ 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)
+ 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
+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.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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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.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
+ 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
+ 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 a,b=byte(f[1],i,j)
+ if a>=0x80 then
+  tonumber((a-0x100).."."..b)
+ else
+  tonumber((a  ).."."..b)
+ end
+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)
-  if a>=0x80 then
-    return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000
-  else
-    return (0x100*a+b     )+(0x100*c+d)/0x10000
-  end
+ 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
+  tonumber((0x100*a+b-0x10000).."."..(0x100*c+d))
+ else
+  tonumber((0x100*a+b    ).."."..(0x100*c+d))
+ end
 end
-function streams.readfixed2(f)
+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
-    return (a-0x100)+b/0x100
+   local n=-(0x100*a+b)
+   return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0))
   else
-    return (a    )+b/0x100
+   local n=0x100*a+b
+   return   (extract(n,14,2)+(band(n,0x3FFF)/16384.0))
   end
+ end
 end
-if extract 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)
+ f[2]=f[2]+2*(n or 1)
 end
 function streams.skiplong(f,n)
-  f[2]=f[2]+4*(n or 1)
+ 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)
+ 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.read2dot4(f)
+  local i=f[2]
+  f[2]=i+2
+  return read2dot4(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
-  function streams.readcardinal2(f)
-    local i=f[2]
-    f[2]=i+2
-    return readcardinal2(f[1],i)
+  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
-  function streams.readcardinal3(f)
-    local i=f[2]
-    f[2]=i+3
-    return readcardinal3(f[1],i)
+  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
-  function streams.readcardinal4(f)
-    local i=f[2]
-    f[2]=i+4
-    return readcardinal4(f[1],i)
+  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
-  function streams.readinteger1(f)
-    local i=f[2]
-    f[2]=i+1
-    return readinteger1(f[1],i)
+  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
-  function streams.readinteger2(f)
-    local i=f[2]
-    f[2]=i+2
-    return readinteger2(f[1],i)
+  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
-  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.read2dot4(f)
-    local i=f[2]
-    f[2]=i+2
-    return read2dot4(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
+  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
 
 
@@ -8150,14 +8684,14 @@
 
 package.loaded["util-sto"] = package.loaded["util-sto"] or true
 
--- original size: 6449, stripped down to: 3069
+-- original size: 6661, stripped down to: 3074
 
 if not modules then modules={} end modules ['util-sto']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 setmetatable,getmetatable,rawset,type=setmetatable,getmetatable,rawset,type
 utilities=utilities or {}
@@ -8164,143 +8698,155 @@
 utilities.storage=utilities.storage or {}
 local storage=utilities.storage
 function storage.mark(t)
-  if not t then
-    print("\nfatal error: storage cannot be marked\n")
-    os.exit()
-    return
-  end
-  local m=getmetatable(t)
-  if not m then
-    m={}
-    setmetatable(t,m)
-  end
-  m.__storage__=true
-  return t
+ if not t then
+  print("\nfatal error: storage cannot be marked\n")
+  os.exit()
+  return
+ end
+ local m=getmetatable(t)
+ if not m then
+  m={}
+  setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
 end
 function storage.allocate(t)
-  t=t or {}
-  local m=getmetatable(t)
-  if not m then
-    m={}
-    setmetatable(t,m)
-  end
-  m.__storage__=true
-  return t
+ t=t or {}
+ local m=getmetatable(t)
+ if not m then
+  m={}
+  setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
 end
 function storage.marked(t)
-  local m=getmetatable(t)
-  return m and m.__storage__
+ local m=getmetatable(t)
+ return m and m.__storage__
 end
 function storage.checked(t)
-  if not t then
-    report("\nfatal error: storage has not been allocated\n")
-    os.exit()
-    return
-  end
-  return t
+ if not t then
+  report("\nfatal error: storage has not been allocated\n")
+  os.exit()
+  return
+ end
+ return t
 end
 function storage.setinitializer(data,initialize)
-  local m=getmetatable(data) or {}
-  m.__index=function(data,k)
-    m.__index=nil 
-    initialize()
-    return data[k]
-  end
-  setmetatable(data,m)
+ local m=getmetatable(data) or {}
+ m.__index=function(data,k)
+  m.__index=nil 
+  initialize()
+  return data[k]
+ end
+ setmetatable(data,m)
 end
 local keyisvalue={ __index=function(t,k)
-  t[k]=k
-  return k
+ t[k]=k
+ return k
 end }
 function storage.sparse(t)
-  t=t or {}
-  setmetatable(t,keyisvalue)
-  return t
+ t=t or {}
+ setmetatable(t,keyisvalue)
+ return t
 end
-local function f_empty ()              return "" end 
-local function f_self (t,k) t[k]=k        return k end
-local function f_table (t,k) local v={} t[k]=v return v end
-local function f_number(t,k) t[k]=0        return 0 end 
-local function f_ignore()                   end 
+local function f_empty ()         return "" end 
+local function f_self  (t,k) t[k]=k      return k  end
+local function f_table (t,k) local v={} t[k]=v return v  end
+local function f_number(t,k) t[k]=0      return 0  end 
+local function f_ignore()          end 
 local f_index={
-  ["empty"]=f_empty,
-  ["self"]=f_self,
-  ["table"]=f_table,
-  ["number"]=f_number,
+ ["empty"]=f_empty,
+ ["self"]=f_self,
+ ["table"]=f_table,
+ ["number"]=f_number,
 }
 function table.setmetatableindex(t,f)
-  if type(t)~="table" then
-    f,t=t,{}
-  end
-  local m=getmetatable(t)
-  local i=f_index[f] or f
-  if m then
-    m.__index=i
-  else
-    setmetatable(t,{ __index=i })
-  end
-  return t
+ if type(t)~="table" then
+  f,t=t,{}
+ end
+ local m=getmetatable(t)
+ local i=f_index[f] or f
+ if m then
+  m.__index=i
+ else
+  setmetatable(t,{ __index=i })
+ end
+ return t
 end
 local f_index={
-  ["ignore"]=f_ignore,
+ ["ignore"]=f_ignore,
 }
 function table.setmetatablenewindex(t,f)
-  if type(t)~="table" then
-    f,t=t,{}
-  end
-  local m=getmetatable(t)
-  local i=f_index[f] or f
-  if m then
-    m.__newindex=i
-  else
-    setmetatable(t,{ __newindex=i })
-  end
-  return t
+ if type(t)~="table" then
+  f,t=t,{}
+ end
+ local m=getmetatable(t)
+ local i=f_index[f] or f
+ if m then
+  m.__newindex=i
+ else
+  setmetatable(t,{ __newindex=i })
+ end
+ return t
 end
 function table.setmetatablecall(t,f)
-  if type(t)~="table" then
-    f,t=t,{}
-  end
-  local m=getmetatable(t)
-  if m then
-    m.__call=f
-  else
-    setmetatable(t,{ __call=f })
-  end
-  return t
+ if type(t)~="table" then
+  f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+  m.__call=f
+ else
+  setmetatable(t,{ __call=f })
+ end
+ return t
 end
 function table.setmetatableindices(t,f,n,c)
-  if type(t)~="table" then
-    f,t=t,{}
-  end
-  local m=getmetatable(t)
-  local i=f_index[f] or f
-  if m then
-    m.__index=i
-    m.__newindex=n
-    m.__call=c
-  else
-    setmetatable(t,{
-      __index=i,
-      __newindex=n,
-      __call=c,
-    })
-  end
-  return t
+ if type(t)~="table" then
+  f,t=t,{}
+ end
+ local m=getmetatable(t)
+ local i=f_index[f] or f
+ if m then
+  m.__index=i
+  m.__newindex=n
+  m.__call=c
+ else
+  setmetatable(t,{
+   __index=i,
+   __newindex=n,
+   __call=c,
+  })
+ end
+ return t
 end
 function table.setmetatablekey(t,key,value)
-  local m=getmetatable(t)
-  if not m then
-    m={}
-    setmetatable(t,m)
-  end
-  m[key]=value
-  return t
+ local m=getmetatable(t)
+ if not m then
+  m={}
+  setmetatable(t,m)
+ end
+ m[key]=value
+ return t
 end
 function table.getmetatablekey(t,key,value)
-  local m=getmetatable(t)
-  return m and m[key]
+ local m=getmetatable(t)
+ return m and m[key]
 end
+function table.makeweak(t)
+ if not t then
+  t={}
+ end
+ local m=getmetatable(t)
+ if m then
+  m.__mode="v"
+ else
+  setmetatable(t,{ __mode="v" })
+ end
+ return t
+end
 
 
 end -- of closure
@@ -8309,14 +8855,14 @@
 
 package.loaded["util-prs"] = package.loaded["util-prs"] or true
 
--- original size: 22956, stripped down to: 16106
+-- original size: 23460, stripped down to: 15834
 
 if not modules then modules={} end modules ['util-prs']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 lpeg,table,string=lpeg,table,string
 local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp
@@ -8338,6 +8884,7 @@
 local digit=R("09")
 local space=P(' ')
 local equal=P("=")
+local colon=P(":")
 local comma=P(",")
 local lbrace=P("{")
 local rbrace=P("}")
@@ -8357,8 +8904,8 @@
 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
+ [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
+ [2]=left*V(1)*right
 }
 local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
 local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
@@ -8366,311 +8913,329 @@
 local spaces=space^0
 local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
 local content=(1-endofstring)^0
-lpegpatterns.nestedbraces=nestedbraces 
+lpegpatterns.nestedbraces=nestedbraces  
 lpegpatterns.nestedparents=nestedparents 
-lpegpatterns.nested=nestedbraces 
+lpegpatterns.nested=nestedbraces  
 lpegpatterns.argument=argument   
 lpegpatterns.content=content    
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0)
 local key=C((1-equal-comma)^1)
 local pattern_a=(space+comma)^0*(key*equal*value+key*C(""))
 local pattern_c=(space+comma)^0*(key*equal*value)
+local pattern_d=(space+comma)^0*(key*(equal+colon)*value+key*C(""))
 local key=C((1-space-equal-comma)^1)
 local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C("")))
 local hash={}
 local function set(key,value)
-  hash[key]=value
+ hash[key]=value
 end
 local pattern_a_s=(pattern_a/set)^1
 local pattern_b_s=(pattern_b/set)^1
 local pattern_c_s=(pattern_c/set)^1
+local pattern_d_s=(pattern_d/set)^1
 patterns.settings_to_hash_a=pattern_a_s
 patterns.settings_to_hash_b=pattern_b_s
 patterns.settings_to_hash_c=pattern_c_s
+patterns.settings_to_hash_d=pattern_d_s
 function parsers.make_settings_to_hash_pattern(set,how)
-  if how=="strict" then
-    return (pattern_c/set)^1
-  elseif how=="tolerant" then
-    return (pattern_b/set)^1
-  else
-    return (pattern_a/set)^1
-  end
+ if how=="strict" then
+  return (pattern_c/set)^1
+ elseif how=="tolerant" then
+  return (pattern_b/set)^1
+ else
+  return (pattern_a/set)^1
+ end
 end
 function parsers.settings_to_hash(str,existing)
-  if not str or str=="" then
-    return {}
-  elseif type(str)=="table" then
-    if existing then
-      for k,v in next,str do
-        existing[k]=v
-      end
-      return exiting
-    else
-      return str
-    end
+ if not str or str=="" then
+  return {}
+ elseif type(str)=="table" then
+  if existing then
+   for k,v in next,str do
+    existing[k]=v
+   end
+   return exiting
   else
-    hash=existing or {}
-    lpegmatch(pattern_a_s,str)
-    return hash
+   return str
   end
+ else
+  hash=existing or {}
+  lpegmatch(pattern_a_s,str)
+  return hash
+ end
 end
+function parsers.settings_to_hash_colon_too(str)
+ if not str or str=="" then
+  return {}
+ elseif type(str)=="table" then
+  return str
+ else
+  hash={}
+  lpegmatch(pattern_d_s,str)
+  return hash
+ end
+end
 function parsers.settings_to_hash_tolerant(str,existing)
-  if not str or str=="" then
-    return {}
-  elseif type(str)=="table" then
-    if existing then
-      for k,v in next,str do
-        existing[k]=v
-      end
-      return exiting
-    else
-      return str
-    end
+ if not str or str=="" then
+  return {}
+ elseif type(str)=="table" then
+  if existing then
+   for k,v in next,str do
+    existing[k]=v
+   end
+   return exiting
   else
-    hash=existing or {}
-    lpegmatch(pattern_b_s,str)
-    return hash
+   return str
   end
+ else
+  hash=existing or {}
+  lpegmatch(pattern_b_s,str)
+  return hash
+ end
 end
 function parsers.settings_to_hash_strict(str,existing)
-  if not str or str=="" then
-    return nil
-  elseif type(str)=="table" then
-    if existing then
-      for k,v in next,str do
-        existing[k]=v
-      end
-      return exiting
-    else
-      return str
-    end
-  elseif str and str~="" then
-    hash=existing or {}
-    lpegmatch(pattern_c_s,str)
-    return next(hash) and hash
+ if not str or str=="" then
+  return nil
+ elseif type(str)=="table" then
+  if existing then
+   for k,v in next,str do
+    existing[k]=v
+   end
+   return exiting
+  else
+   return str
   end
+ elseif str and str~="" then
+  hash=existing or {}
+  lpegmatch(pattern_c_s,str)
+  return next(hash) and hash
+ end
 end
 local separator=comma*space^0
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0)
 local pattern=spaces*Ct(value*(separator*value)^0)
 patterns.settings_to_array=pattern
 function parsers.settings_to_array(str,strict)
-  if not str or str=="" then
-    return {}
-  elseif type(str)=="table" then
-    return str
-  elseif strict then
-    if find(str,"{",1,true) then
-      return lpegmatch(pattern,str)
-    else
-      return { str }
-    end
-  elseif find(str,",",1,true) then
-    return lpegmatch(pattern,str)
+ if not str or str=="" then
+  return {}
+ elseif type(str)=="table" then
+  return str
+ elseif strict then
+  if find(str,"{",1,true) then
+   return lpegmatch(pattern,str)
   else
-    return { str }
+   return { str }
   end
+ elseif find(str,",",1,true) then
+  return lpegmatch(pattern,str)
+ else
+  return { str }
+ end
 end
 function parsers.settings_to_numbers(str)
-  if not str or str=="" then
-    return {}
-  end
-  if type(str)=="table" then
-  elseif find(str,",",1,true) then
-    str=lpegmatch(pattern,str)
-  else
-    return { tonumber(str) }
-  end
-  for i=1,#str do
-    str[i]=tonumber(str[i])
-  end
-  return str
+ if not str or str=="" then
+  return {}
+ end
+ if type(str)=="table" then
+ elseif find(str,",",1,true) then
+  str=lpegmatch(pattern,str)
+ else
+  return { tonumber(str) }
+ end
+ for i=1,#str do
+  str[i]=tonumber(str[i])
+ end
+ return str
 end
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+nestedbrackets+nestedparents+(1-comma))^0)
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+nestedbrackets+nestedparents+(1-comma))^0)
 local pattern=spaces*Ct(value*(separator*value)^0)
 function parsers.settings_to_array_obey_fences(str)
-  return lpegmatch(pattern,str)
+ return lpegmatch(pattern,str)
 end
 local cache_a={}
 local cache_b={}
 function parsers.groupedsplitat(symbol,withaction)
-  if not symbol then
-    symbol=","
+ if not symbol then
+  symbol=","
+ end
+ local pattern=(withaction and cache_b or cache_a)[symbol]
+ 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)
+  if withaction then
+   local withvalue=Carg(1)*value/function(f,s) return f(s) end
+   pattern=spaces*withvalue*(separator*withvalue)^0
+   cache_b[symbol]=pattern
+  else
+   pattern=spaces*Ct(value*(separator*value)^0)
+   cache_a[symbol]=pattern
   end
-  local pattern=(withaction and cache_b or cache_a)[symbol]
-  if not pattern then
-    local symbols=S(symbol)
-    local separator=space^0*symbols*space^0
-    local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+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
-      cache_b[symbol]=pattern
-    else
-      pattern=spaces*Ct(value*(separator*value)^0)
-      cache_a[symbol]=pattern
-    end
-  end
-  return pattern
+ end
+ return pattern
 end
 local pattern_a=parsers.groupedsplitat(",",false)
 local pattern_b=parsers.groupedsplitat(",",true)
 function parsers.stripped_settings_to_array(str)
-  if not str or str=="" then
-    return {}
-  else
-    return lpegmatch(pattern_a,str)
-  end
+ if not str or str=="" then
+  return {}
+ else
+  return lpegmatch(pattern_a,str)
+ end
 end
 function parsers.process_stripped_settings(str,action)
-  if not str or str=="" then
-    return {}
-  else
-    return lpegmatch(pattern_b,str,1,action)
-  end
+ if not str or str=="" then
+  return {}
+ else
+  return lpegmatch(pattern_b,str,1,action)
+ end
 end
 local function set(t,v)
-  t[#t+1]=v
+ t[#t+1]=v
 end
 local value=P(Carg(1)*value)/set
 local pattern=value*(separator*value)^0*Carg(1)
 function parsers.add_settings_to_array(t,str)
-  return lpegmatch(pattern,str,nil,t)
+ return lpegmatch(pattern,str,nil,t)
 end
 function parsers.hash_to_string(h,separator,yes,no,strict,omit)
-  if h then
-    local t,tn,s={},0,sortedkeys(h)
-    omit=omit and tohash(omit)
-    for i=1,#s do
-      local key=s[i]
-      if not omit or not omit[key] then
-        local value=h[key]
-        if type(value)=="boolean" then
-          if yes and no then
-            if value then
-              tn=tn+1
-              t[tn]=key..'='..yes
-            elseif not strict then
-              tn=tn+1
-              t[tn]=key..'='..no
-            end
-          elseif value or not strict then
-            tn=tn+1
-            t[tn]=key..'='..tostring(value)
-          end
-        else
-          tn=tn+1
-          t[tn]=key..'='..value
-        end
+ if h then
+  local t={}
+  local tn=0
+  local s=sortedkeys(h)
+  omit=omit and tohash(omit)
+  for i=1,#s do
+   local key=s[i]
+   if not omit or not omit[key] then
+    local value=h[key]
+    if type(value)=="boolean" then
+     if yes and no then
+      if value then
+       tn=tn+1
+       t[tn]=key..'='..yes
+      elseif not strict then
+       tn=tn+1
+       t[tn]=key..'='..no
       end
+     elseif value or not strict then
+      tn=tn+1
+      t[tn]=key..'='..tostring(value)
+     end
+    else
+     tn=tn+1
+     t[tn]=key..'='..value
     end
-    return concat(t,separator or ",")
-  else
-    return ""
+   end
   end
+  return concat(t,separator or ",")
+ else
+  return ""
+ end
 end
 function parsers.array_to_string(a,separator)
-  if a then
-    return concat(a,separator or ",")
-  else
-    return ""
-  end
+ if a then
+  return concat(a,separator or ",")
+ else
+  return ""
+ end
 end
 local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset)
 function utilities.parsers.settings_to_set(str)
-  return str and lpegmatch(pattern,str) or {}
+ return str and lpegmatch(pattern,str) or {}
 end
 hashes.settings_to_set=table.setmetatableindex(function(t,k) 
-  local v=k and lpegmatch(pattern,k) or {}
-  t[k]=v
-  return v
+ local v=k and lpegmatch(pattern,k) or {}
+ t[k]=v
+ return v
 end)
 getmetatable(hashes.settings_to_set).__mode="kv" 
 function parsers.simple_hash_to_string(h,separator)
-  local t,tn={},0
-  for k,v in sortedhash(h) do
-    if v then
-      tn=tn+1
-      t[tn]=k
-    end
+ local t={}
+ local tn=0
+ for k,v in sortedhash(h) do
+  if v then
+   tn=tn+1
+   t[tn]=k
   end
-  return concat(t,separator or ",")
+ end
+ return concat(t,separator or ",")
 end
 local str=Cs(lpegpatterns.unquoted)+C((1-whitespace-equal)^1)
 local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset)
 local splitter=setting^1
 function utilities.parsers.options_to_hash(str,target)
-  return str and lpegmatch(splitter,str,1,target or {}) or {}
+ return str and lpegmatch(splitter,str,1,target or {}) or {}
 end
 local splitter=lpeg.tsplitat(" ")
 function utilities.parsers.options_to_array(str)
-  return str and lpegmatch(splitter,str) or {}
+ return str and lpegmatch(splitter,str) or {}
 end
 local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
 local pattern_a=spaces*Ct(value*(separator*value)^0)
 local function repeater(n,str)
-  if not n then
-    return str
+ if not n then
+  return str
+ else
+  local s=lpegmatch(pattern_a,str)
+  if n==1 then
+   return unpack(s)
   else
-    local s=lpegmatch(pattern_a,str)
-    if n==1 then
-      return unpack(s)
-    else
-      local t,tn={},0
-      for i=1,n do
-        for j=1,#s do
-          tn=tn+1
-          t[tn]=s[j]
-        end
-      end
-      return unpack(t)
+   local t={}
+   local tn=0
+   for i=1,n do
+    for j=1,#s do
+     tn=tn+1
+     t[tn]=s[j]
     end
+   end
+   return unpack(t)
   end
+ end
 end
 local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1)
 local pattern_b=spaces*Ct(value*(separator*value)^0)
 function parsers.settings_to_array_with_repeat(str,expand) 
-  if expand then
-    return lpegmatch(pattern_b,str) or {}
-  else
-    return lpegmatch(pattern_a,str) or {}
-  end
+ if expand then
+  return lpegmatch(pattern_b,str) or {}
+ else
+  return lpegmatch(pattern_a,str) or {}
+ end
 end
 local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace
 local pattern=Ct((space+value)^0)
 function parsers.arguments_to_table(str)
-  return lpegmatch(pattern,str)
+ return lpegmatch(pattern,str)
 end
 function parsers.getparameters(self,class,parentclass,settings)
-  local sc=self[class]
-  if not sc then
-    sc={}
-    self[class]=sc
-    if parentclass then
-      local sp=self[parentclass]
-      if not sp then
-        sp={}
-        self[parentclass]=sp
-      end
-      setmetatableindex(sc,sp)
-    end
+ local sc=self[class]
+ if not sc then
+  sc={}
+  self[class]=sc
+  if parentclass then
+   local sp=self[parentclass]
+   if not sp then
+    sp={}
+    self[parentclass]=sp
+   end
+   setmetatableindex(sc,sp)
   end
-  parsers.settings_to_hash(settings,sc)
+ end
+ parsers.settings_to_hash(settings,sc)
 end
 function parsers.listitem(str)
-  return gmatch(str,"[^, ]+")
+ return gmatch(str,"[^, ]+")
 end
 local pattern=Cs { "start",
-  start=V("one")+V("two")+V("three"),
-  rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0,
-  thousand=digit*digit*digit,
-  one=digit*V("rest"),
-  two=digit*digit*V("rest"),
-  three=V("thousand")*V("rest"),
+ start=V("one")+V("two")+V("three"),
+ rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0,
+ thousand=digit*digit*digit,
+ one=digit*V("rest"),
+ two=digit*digit*V("rest"),
+ three=V("thousand")*V("rest"),
 }
 lpegpatterns.splitthousands=pattern 
 function parsers.splitthousands(str)
-  return lpegmatch(pattern,str) or str
+ return lpegmatch(pattern,str) or str
 end
 local optionalwhitespace=whitespace^0
 lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1)
@@ -8684,75 +9249,75 @@
 local value=dquote*C((1-dquote-escape*dquote)^0)*dquote
 local pattern=Cf(Ct("")*(Cg(key*equal*value)*separator^0)^1,rawset)^0*P(-1)
 function parsers.keq_to_hash(str)
-  if str and str~="" then
-    return lpegmatch(pattern,str)
-  else
-    return {}
-  end
+ if str and str~="" then
+  return lpegmatch(pattern,str)
+ else
+  return {}
+ end
 end
 local defaultspecification={ separator=",",quote='"' }
 function parsers.csvsplitter(specification)
-  specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
-  local separator=specification.separator
-  local quotechar=specification.quote
-  local separator=S(separator~="" and separator or ",")
-  local whatever=C((1-separator-newline)^0)
-  if quotechar and quotechar~="" then
-    local quotedata=nil
-    for chr in gmatch(quotechar,".") do
-      local quotechar=P(chr)
-      local quoteword=quotechar*C((1-quotechar)^0)*quotechar
-      if quotedata then
-        quotedata=quotedata+quoteword
-      else
-        quotedata=quoteword
-      end
-    end
-    whatever=quotedata+whatever
+ specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local whatever=C((1-separator-newline)^0)
+ if quotechar and quotechar~="" then
+  local quotedata=nil
+  for chr in gmatch(quotechar,".") do
+   local quotechar=P(chr)
+   local quoteword=quotechar*C((1-quotechar)^0)*quotechar
+   if quotedata then
+    quotedata=quotedata+quoteword
+   else
+    quotedata=quoteword
+   end
   end
-  local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 )
-  return function(data)
-    return lpegmatch(parser,data)
-  end
+  whatever=quotedata+whatever
+ end
+ local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 )
+ return function(data)
+  return lpegmatch(parser,data)
+ end
 end
 function parsers.rfc4180splitter(specification)
-  specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
-  local separator=specification.separator 
-  local quotechar=P(specification.quote) 
-  local dquotechar=quotechar*quotechar  
+ specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator 
+ local quotechar=P(specification.quote)  
+ local dquotechar=quotechar*quotechar   
 /specification.quote
-  local separator=S(separator~="" and separator or ",")
-  local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar
-  local non_escaped=C((1-quotechar-newline-separator)^1)
-  local field=escaped+non_escaped+Cc("")
-  local record=Ct(field*(separator*field)^1)
-  local headerline=record*Cp()
-  local morerecords=(newline^(specification.strict and -1 or 1)*record)^0
-  local headeryes=Ct(morerecords)
-  local headernop=Ct(record*morerecords)
-  return function(data,getheader)
-    if getheader then
-      local header,position=lpegmatch(headerline,data)
-      local data=lpegmatch(headeryes,data,position)
-      return data,header
-    else
-      return lpegmatch(headernop,data)
-    end
+ local separator=S(separator~="" and separator or ",")
+ local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar
+ local non_escaped=C((1-quotechar-newline-separator)^1)
+ local field=escaped+non_escaped+Cc("")
+ local record=Ct(field*(separator*field)^1)
+ local headerline=record*Cp()
+ local morerecords=(newline^(specification.strict and -1 or 1)*record)^0
+ local headeryes=Ct(morerecords)
+ local headernop=Ct(record*morerecords)
+ return function(data,getheader)
+  if getheader then
+   local header,position=lpegmatch(headerline,data)
+   local data=lpegmatch(headeryes,data,position)
+   return data,header
+  else
+   return lpegmatch(headernop,data)
   end
+ end
 end
 local function ranger(first,last,n,action)
-  if not first then
-  elseif last==true then
-    for i=first,n or first do
-      action(i)
-    end
-  elseif last then
-    for i=first,last do
-      action(i)
-    end
-  else
-    action(first)
+ if not first then
+ elseif last==true then
+  for i=first,n or first do
+   action(i)
   end
+ elseif last then
+  for i=first,last do
+   action(i)
+  end
+ else
+  action(first)
+ end
 end
 local cardinal=lpegpatterns.cardinal/tonumber
 local spacers=lpegpatterns.spacer^0
@@ -8760,89 +9325,89 @@
 local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
 local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring 
 function parsers.stepper(str,n,action)
-  if type(n)=="function" then
-    lpegmatch(stepper,str,1,false,n or print)
-  else
-    lpegmatch(stepper,str,1,n,action or print)
-  end
+ if type(n)=="function" then
+  lpegmatch(stepper,str,1,false,n or print)
+ else
+  lpegmatch(stepper,str,1,n,action or print)
+ end
 end
 local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
 local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
 patterns.unittotex=pattern
 function parsers.unittotex(str,textmode)
-  return lpegmatch(textmode and pattern_text or pattern_math,str)
+ return lpegmatch(textmode and pattern_text or pattern_math,str)
 end
 local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+anything)^0)
 function parsers.unittoxml(str)
-  return lpegmatch(pattern,str)
+ return lpegmatch(pattern,str)
 end
 local cache={}
 local spaces=lpegpatterns.space^0
 local dummy=function() end
 setmetatableindex(cache,function(t,k)
-  local separator=P(k)
-  local value=(1-separator)^0
-  local pattern=spaces*C(value)*separator^0*Cp()
-  t[k]=pattern
-  return pattern
+ local separator=P(k)
+ local value=(1-separator)^0
+ local pattern=spaces*C(value)*separator^0*Cp()
+ t[k]=pattern
+ return pattern
 end)
 local commalistiterator=cache[","]
 function utilities.parsers.iterator(str,separator)
-  local n=#str
-  if n==0 then
-    return dummy
-  else
-    local pattern=separator and cache[separator] or commalistiterator
-    local p=1
-    return function()
-      if p<=n then
-        local s,e=lpegmatch(pattern,str,p)
-        if e then
-          p=e
-          return s
-        end
-      end
+ local n=#str
+ if n==0 then
+  return dummy
+ else
+  local pattern=separator and cache[separator] or commalistiterator
+  local p=1
+  return function()
+   if p<=n then
+    local s,e=lpegmatch(pattern,str,p)
+    if e then
+     p=e
+     return s
     end
+   end
   end
+ end
 end
 local function initialize(t,name)
-  local source=t[name]
-  if source then
-    local result={}
-    for k,v in next,t[name] do
-      result[k]=v
-    end
-    return result
-  else
-    return {}
+ local source=t[name]
+ if source then
+  local result={}
+  for k,v in next,t[name] do
+   result[k]=v
   end
+  return result
+ else
+  return {}
+ end
 end
 local function fetch(t,name)
-  return t[name] or {}
+ return t[name] or {}
 end
 local function process(result,more)
-  for k,v in next,more do
-    result[k]=v
-  end
-  return result
+ for k,v in next,more do
+  result[k]=v
+ end
+ return result
 end
 local name=C((1-S(", "))^1)
 local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0
 local merge=Cf(parser,process)
 function utilities.parsers.mergehashes(hash,list)
-  return lpegmatch(merge,list,1,hash)
+ return lpegmatch(merge,list,1,hash)
 end
 function utilities.parsers.runtime(time)
-  if not time then
-    time=os.runtime()
-  end
-  local days=div(time,24*60*60)
-  time=mod(time,24*60*60)
-  local hours=div(time,60*60)
-  time=mod(time,60*60)
-  local minutes=div(time,60)
-  local seconds=mod(time,60)
-  return days,hours,minutes,seconds
+ if not time then
+  time=os.runtime()
+ end
+ local days=div(time,24*60*60)
+ time=mod(time,24*60*60)
+ local hours=div(time,60*60)
+ time=mod(time,60*60)
+ local minutes=div(time,60)
+ local seconds=mod(time,60)
+ return days,hours,minutes,seconds
 end
 local spacing=whitespace^0
 local apply=P("->")
@@ -8850,11 +9415,11 @@
 local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1)
 local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token
 function utilities.parsers.splitmethod(str,default)
-  if str then
-    return lpegmatch(pattern,str,1,default or false)
-  else
-    return default or false,""
-  end
+ if str then
+  return lpegmatch(pattern,str,1,default or false)
+ else
+  return default or false,""
+ end
 end
 
 
@@ -8864,14 +9429,14 @@
 
 package.loaded["util-fmt"] = package.loaded["util-fmt"] or true
 
--- original size: 2274, stripped down to: 1781
+-- original size: 2541, stripped down to: 1624
 
 if not modules then modules={} end modules ['util-fmt']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 utilities=utilities or {}
 utilities.formatters=utilities.formatters or {}
@@ -8882,61 +9447,1272 @@
 local lpegmatch=lpeg.match
 local stripper=lpeg.patterns.stripzeros
 function formatters.stripzeros(str)
-  return lpegmatch(stripper,str)
+ return lpegmatch(stripper,str)
 end
 function formatters.formatcolumns(result,between)
-  if result and #result>0 then
-    between=between or "   "
-    local widths,numbers={},{}
-    local first=result[1]
-    local n=#first
-    for i=1,n do
-      widths[i]=0
+ if result and #result>0 then
+  between=between or "   "
+  local widths,numbers={},{}
+  local first=result[1]
+  local n=#first
+  for i=1,n do
+   widths[i]=0
+  end
+  for i=1,#result do
+   local r=result[i]
+   for j=1,n do
+    local rj=r[j]
+    local tj=type(rj)
+    if tj=="number" then
+     numbers[j]=true
+     rj=tostring(rj)
+    elseif tj~="string" then
+     rj=tostring(rj)
+     r[j]=rj
     end
-    for i=1,#result do
-      local r=result[i]
-      for j=1,n do
-        local rj=r[j]
-        local tj=type(rj)
-        if tj=="number" then
-          numbers[j]=true
-        end
-        if tj~="string" then
-          rj=tostring(rj)
-          r[j]=rj
-        end
-        local w=#rj
-        if w>widths[j] then
-          widths[j]=w
-        end
+    local w=#rj
+    if w>widths[j] then
+     widths[j]=w
+    end
+   end
+  end
+  for i=1,n do
+   local w=widths[i]
+   if numbers[i] then
+    if w>80 then
+     widths[i]="%s"..between
+     else
+     widths[i]="%0"..w.."i"..between
+    end
+   else
+    if w>80 then
+     widths[i]="%s"..between
+     elseif w>0 then
+     widths[i]="%-"..w.."s"..between
+    else
+     widths[i]="%s"
+    end
+   end
+  end
+  local template=strip(concat(widths))
+  for i=1,#result do
+   local str=format(template,unpack(result[i]))
+   result[i]=strip(str)
+  end
+ end
+ return result
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-reset"] = package.loaded["util-soc-imp-reset"] or true
+
+-- original size: 374, stripped down to: 282
+
+local loaded=package.loaded
+loaded["socket"]=nil
+loaded["copas"]=nil
+loaded["ltn12"]=nil
+loaded["mbox"]=nil
+loaded["mime"]=nil
+loaded["socket.url"]=nil
+loaded["socket.headers"]=nil
+loaded["socket.tp"]=nil
+loaded["socket.http"]=nil
+loaded["socket.ftp"]=nil
+loaded["socket.smtp"]=nil
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-socket"] = package.loaded["util-soc-imp-socket"] or true
+
+-- original size: 4870, stripped down to: 3527
+
+
+local type,tostring,setmetatable=type,tostring,setmetatable
+local min=math.min
+local format=string.format
+local socket=require("socket.core")
+local connect=socket.connect
+local tcp4=socket.tcp4
+local tcp6=socket.tcp6
+local getaddrinfo=socket.dns.getaddrinfo
+local defaulthost="0.0.0.0"
+local function report(fmt,first,...)
+ if logs then
+  report=logs and logs.reporter("socket")
+  report(fmt,first,...)
+ elseif fmt then
+  fmt="socket: "..fmt
+  if first then
+   print(format(fmt,first,...))
+  else
+   print(fmt)
+  end
+ end
+end
+socket.report=report
+function socket.connect4(address,port,laddress,lport)
+ return connect(address,port,laddress,lport,"inet")
+end
+function socket.connect6(address,port,laddress,lport)
+ return connect(address,port,laddress,lport,"inet6")
+end
+function socket.bind(host,port,backlog)
+ if host=="*" or host=="" then
+  host=defaulthost
+ end
+ local addrinfo,err=getaddrinfo(host)
+ if not addrinfo then
+  return nil,err
+ end
+ for i=1,#addrinfo do
+  local alt=addrinfo[i]
+  local sock,err=(alt.family=="inet" and tcp4 or tcp6)()
+  if not sock then
+   return nil,err or "unknown error"
+  end
+  sock:setoption("reuseaddr",true)
+  local res,err=sock:bind(alt.addr,port)
+  if res then
+   res,err=sock:listen(backlog)
+   if res then
+    return sock
+   else
+    sock:close()
+   end
+  else
+   sock:close()
+  end
+ end
+ return nil,"invalid address"
+end
+socket.try=socket.newtry()
+function socket.choose(list)
+ return function(name,opt1,opt2)
+  if type(name)~="string" then
+   name,opt1,opt2="default",name,opt1
+  end
+  local f=list[name or "nil"]
+  if f then
+   return f(opt1,opt2)
+  else
+   report("error: unknown key '%s'",tostring(name))
+  end
+ end
+end
+local sourcet={}
+local sinkt={}
+socket.sourcet=sourcet
+socket.sinkt=sinkt
+socket.BLOCKSIZE=2048
+sinkt["close-when-done"]=function(sock)
+ return setmetatable (
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },
+  {
+   __call=function(self,chunk,err)
+    if chunk then
+     return sock:send(chunk)
+    else
+     sock:close()
+     return 1 
+    end
+   end
+  }
+ )
+end
+sinkt["keep-open"]=function(sock)
+ return setmetatable (
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },{
+   __call=function(self,chunk,err)
+    if chunk then
+     return sock:send(chunk)
+    else
+     return 1 
+    end
+   end
+  }
+ )
+end
+sinkt["default"]=sinkt["keep-open"]
+socket.sink=socket.choose(sinkt)
+sourcet["by-length"]=function(sock,length)
+ local blocksize=socket.BLOCKSIZE
+ return setmetatable (
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },
+  {
+   __call=function()
+    if length<=0 then
+     return nil
+    end
+    local chunk,err=sock:receive(min(blocksize,length))
+    if err then
+     return nil,err
+    end
+    length=length-#chunk
+    return chunk
+   end
+  }
+ )
+end
+sourcet["until-closed"]=function(sock)
+ local blocksize=socket.BLOCKSIZE
+ local done=false
+ return setmetatable (
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },{
+   __call=function()
+    if done then
+     return nil
+    end
+    local chunk,status,partial=sock:receive(blocksize)
+    if not status then
+     return chunk
+    elseif status=="closed" then
+     sock:close()
+     done=true
+     return partial
+    else
+     return nil,status
+    end
+   end
+  }
+ )
+end
+sourcet["default"]=sourcet["until-closed"]
+socket.source=socket.choose(sourcet)
+_G.socket=socket 
+package.loaded["socket"]=socket
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-copas"] = package.loaded["util-soc-imp-copas"] or true
+
+-- original size: 25844, stripped down to: 14821
+
+
+local socket=socket or require("socket")
+local ssl=ssl or nil 
+local WATCH_DOG_TIMEOUT=120
+local UDP_DATAGRAM_MAX=8192
+local type,next,pcall,getmetatable,tostring=type,next,pcall,getmetatable,tostring
+local min,max,random=math.min,math.max,math.random
+local find=string.find
+local insert,remove=table.insert,table.remove
+local gettime=socket.gettime
+local selectsocket=socket.select
+local createcoroutine=coroutine.create
+local resumecoroutine=coroutine.resume
+local yieldcoroutine=coroutine.yield
+local runningcoroutine=coroutine.running
+local function report(fmt,first,...)
+ if logs then
+  report=logs and logs.reporter("copas")
+  report(fmt,first,...)
+ elseif fmt then
+  fmt="copas: "..fmt
+  if first then
+   print(format(fmt,first,...))
+  else
+   print(fmt)
+  end
+ end
+end
+local copas={
+ _COPYRIGHT="Copyright (C) 2005-2016 Kepler Project",
+ _DESCRIPTION="Coroutine Oriented Portable Asynchronous Services",
+ _VERSION="Copas 2.0.1",
+ autoclose=true,
+ running=false,
+ report=report,
+}
+local function statushandler(status,...)
+ if status then
+  return...
+ end
+ local err=(...)
+ if type(err)=="table" then
+  err=err[1]
+ end
+ report("error: %s",tostring(err))
+ return nil,err
+end
+function socket.protect(func)
+ return function(...)
+  return statushandler(pcall(func,...))
+ end
+end
+function socket.newtry(finalizer)
+ return function (...)
+  local status=(...)
+  if not status then
+   local detail=select(2,...)
+   pcall(finalizer,detail)
+   report("error: %s",tostring(detail))
+   return
+  end
+  return...
+ end
+end
+local function newset()
+ local reverse={}
+ local set={}
+ local queue={}
+ setmetatable(set,{
+  __index={
+   insert=function(set,value)
+     if not reverse[value] then
+      local n=#set+1
+      set[n]=value
+      reverse[value]=n
+     end
+    end,
+   remove=function(set,value)
+     local index=reverse[value]
+     if index then
+      reverse[value]=nil
+      local n=#set
+      local top=set[n]
+      set[n]=nil
+      if top~=value then
+       reverse[top]=index
+       set[index]=top
       end
+     end
+    end,
+   push=function (set,key,itm)
+     local entry=queue[key]
+     if entry==nil then 
+      queue[key]={ itm }
+     else
+      entry[#entry+1]=itm
+     end
+    end,
+   pop=function (set,key)
+     local top=queue[key]
+     if top~=nil then
+      local ret=remove(top,1)
+      if top[1]==nil then
+       queue[key]=nil
+      end
+      return ret
+     end
     end
-    for i=1,n do
-      local w=widths[i]
-      if numbers[i] then
-        if w>80 then
-          widths[i]="%s"..between
-         else
-          widths[i]="%0"..w.."i"..between
-        end
-      else
-        if w>80 then
-          widths[i]="%s"..between
-         elseif w>0 then
-          widths[i]="%-"..w.."s"..between
-        else
-          widths[i]="%s"
-        end
+  }
+ } )
+ return set
+end
+local _sleeping={
+ times={},
+ cos={},
+ lethargy={},
+ insert=function()
+  end,
+ remove=function()
+  end,
+ push=function(self,sleeptime,co)
+   if not co then
+    return
+   end
+   if sleeptime<0 then
+    self.lethargy[co]=true
+    return
+   else
+    sleeptime=gettime()+sleeptime
+   end
+   local t=self.times
+   local c=self.cos
+   local i=1
+   local n=#t
+   while i<=n and t[i]<=sleeptime do
+    i=i+1
+   end
+   insert(t,i,sleeptime)
+   insert(c,i,co)
+  end,
+ getnext=
+  function(self)
+   local t=self.times
+   local delay=t[1] and t[1]-gettime() or nil
+   return delay and max(delay,0) or nil
+  end,
+ pop=
+  function(self,time)
+   local t=self.times
+   local c=self.cos
+   if #t==0 or time<t[1] then
+    return
+   end
+   local co=c[1]
+   remove(t,1)
+   remove(c,1)
+   return co
+  end,
+  wakeup=function(self,co)
+    local let=self.lethargy
+    if let[co] then
+     self:push(0,co)
+     let[co]=nil
+    else
+     local c=self.cos
+     local t=self.times
+     for i=1,#c do
+      if c[i]==co then
+       remove(c,i)
+       remove(t,i)
+       self:push(0,co)
+       return
       end
+     end
     end
-    local template=strip(concat(widths))
-    for i=1,#result do
-      local str=format(template,unpack(result[i]))
-      result[i]=strip(str)
+   end
+}
+local _servers=newset() 
+local _reading=newset() 
+local _writing=newset() 
+local _reading_log={}
+local _writing_log={}
+local _is_timeout={  
+ timeout=true,
+ wantread=true,
+ wantwrite=true,
+}
+local function isTCP(socket)
+ return not find(tostring(socket),"^udp")
+end
+local function copasreceive(client,pattern,part)
+ if not pattern or pattern=="" then
+  pattern="*l"
+ end
+ local current_log=_reading_log
+ local s,err
+ repeat
+  s,err,part=client:receive(pattern,part)
+  if s or (not _is_timeout[err]) then
+   current_log[client]=nil
+   return s,err,part
+  end
+  if err=="wantwrite" then
+   current_log=_writing_log
+   current_log[client]=gettime()
+   yieldcoroutine(client,_writing)
+  else
+   current_log=_reading_log
+   current_log[client]=gettime()
+   yieldcoroutine(client,_reading)
+  end
+ until false
+end
+local function copasreceivefrom(client,size)
+ local s,err,port
+ if not size or size==0 then
+  size=UDP_DATAGRAM_MAX
+ end
+ repeat
+  s,err,port=client:receivefrom(size)
+  if s or err~="timeout" then
+   _reading_log[client]=nil
+   return s,err,port
+  end
+  _reading_log[client]=gettime()
+  yieldcoroutine(client,_reading)
+ until false
+end
+local function copasreceivepartial(client,pattern,part)
+ if not pattern or pattern=="" then
+  pattern="*l"
+ end
+ local logger=_reading_log
+ local queue=_reading
+ local s,err
+ repeat
+  s,err,part=client:receive(pattern,part)
+  if s or (type(pattern)=="number" and part~="" and part) or not _is_timeout[err] then
+    logger[client]=nil
+    return s,err,part
+  end
+  if err=="wantwrite" then
+   logger=_writing_log
+   queue=_writing
+  else
+   logger=_reading_log
+   queue=_reading
+  end
+  logger[client]=gettime()
+  yieldcoroutine(client,queue)
+ until false
+end
+local function copassend(client,data,from,to)
+ if not from then
+  from=1
+ end
+ local lastIndex=from-1
+ local logger=_writing_log
+ local queue=_writing
+ local s,err
+ repeat
+  s,err,lastIndex=client:send(data,lastIndex+1,to)
+  if random(100)>90 then
+   logger[client]=gettime()
+   yieldcoroutine(client,queue)
+  end
+  if s or not _is_timeout[err] then
+   logger[client]=nil
+   return s,err,lastIndex
+  end
+  if err=="wantread" then
+   logger=_reading_log
+   queue=_reading
+  else
+   logger=_writing_log
+   queue=_writing
+  end
+  logger[client]=gettime()
+  yieldcoroutine(client,queue)
+ until false
+end
+local function copassendto(client,data,ip,port)
+ repeat
+  local s,err=client:sendto(data,ip,port)
+  if random(100)>90 then
+   _writing_log[client]=gettime()
+   yieldcoroutine(client,_writing)
+  end
+  if s or err~="timeout" then
+   _writing_log[client]=nil
+   return s,err
+  end
+  _writing_log[client]=gettime()
+  yieldcoroutine(client,_writing)
+ until false
+end
+local function copasconnect(skt,host,port)
+ skt:settimeout(0)
+ local ret,err,tried_more_than_once
+ repeat
+  ret,err=skt:connect (host,port)
+  if ret or (err~="timeout" and err~="Operation already in progress") then
+   if not ret and err=="already connected" and tried_more_than_once then
+    ret=1
+    err=nil
+   end
+   _writing_log[skt]=nil
+   return ret,err
+  end
+  tried_more_than_once=tried_more_than_once or true
+  _writing_log[skt]=gettime()
+  yieldcoroutine(skt,_writing)
+ until false
+end
+local function copasdohandshake(skt,sslt) 
+ if not ssl then
+  ssl=require("ssl")
+ end
+ if not ssl then
+  report("error: no ssl library")
+  return
+ end
+ local nskt,err=ssl.wrap(skt,sslt)
+ if not nskt then
+  report("error: %s",tostring(err))
+  return
+ end
+ nskt:settimeout(0)
+ local queue
+ repeat
+  local success,err=nskt:dohandshake()
+  if success then
+   return nskt
+  elseif err=="wantwrite" then
+   queue=_writing
+  elseif err=="wantread" then
+   queue=_reading
+  else
+   report("error: %s",tostring(err))
+   return
+  end
+  yieldcoroutine(nskt,queue)
+ until false
+end
+local function copasflush(client)
+end
+copas.connect=copassconnect
+copas.send=copassend
+copas.sendto=copassendto
+copas.receive=copasreceive
+copas.receivefrom=copasreceivefrom
+copas.copasreceivepartial=copasreceivepartial
+copas.copasreceivePartial=copasreceivepartial
+copas.dohandshake=copasdohandshake
+copas.flush=copasflush
+local function _skt_mt_tostring(self)
+ return tostring(self.socket).." (copas wrapped)"
+end
+local _skt_mt_tcp_index={
+ send=function(self,data,from,to)
+   return copassend (self.socket,data,from,to)
+  end,
+ receive=function (self,pattern,prefix)
+   if self.timeout==0 then
+    return copasreceivePartial(self.socket,pattern,prefix)
+   else
+    return copasreceive(self.socket,pattern,prefix)
+   end
+  end,
+ flush=function (self)
+   return copasflush(self.socket)
+  end,
+ settimeout=function (self,time)
+   self.timeout=time
+   return true
+  end,
+ connect=function(self,...)
+   local res,err=copasconnect(self.socket,...)
+   if res and self.ssl_params then
+    res,err=self:dohandshake()
+   end
+   return res,err
+  end,
+ close=function(self,...)
+   return self.socket:close(...)
+  end,
+ bind=function(self,...)
+   return self.socket:bind(...)
+  end,
+ getsockname=function(self,...)
+   return self.socket:getsockname(...)
+  end,
+ getstats=function(self,...)
+   return self.socket:getstats(...)
+  end,
+ setstats=function(self,...)
+   return self.socket:setstats(...)
+  end,
+ listen=function(self,...)
+   return self.socket:listen(...)
+  end,
+ accept=function(self,...)
+   return self.socket:accept(...)
+  end,
+ setoption=function(self,...)
+   return self.socket:setoption(...)
+  end,
+ getpeername=function(self,...)
+   return self.socket:getpeername(...)
+  end,
+ shutdown=function(self,...)
+   return self.socket:shutdown(...)
+  end,
+ dohandshake=function(self,sslt)
+   self.ssl_params=sslt or self.ssl_params
+   local nskt,err=copasdohandshake(self.socket,self.ssl_params)
+   if not nskt then
+    return nskt,err
+   end
+   self.socket=nskt
+   return self
+  end,
+}
+local _skt_mt_tcp={
+ __tostring=_skt_mt_tostring,
+ __index=_skt_mt_tcp_index,
+}
+local _skt_mt_udp_index={
+ sendto=function (self,...)
+   return copassendto(self.socket,...)
+  end,
+ receive=function (self,size)
+   return copasreceive(self.socket,size or UDP_DATAGRAM_MAX)
+  end,
+ receivefrom=function (self,size)
+   return copasreceivefrom(self.socket,size or UDP_DATAGRAM_MAX)
+  end,
+ setpeername=function(self,...)
+   return self.socket:getpeername(...)
+  end,
+ setsockname=function(self,...)
+   return self.socket:setsockname(...)
+  end,
+ close=function(self,...)
+   return true
+  end
+}
+local _skt_mt_udp={
+ __tostring=_skt_mt_tostring,
+ __index=_skt_mt_udp_index,
+}
+for k,v in next,_skt_mt_tcp_index do
+ if not _skt_mt_udp_index[k] then
+  _skt_mt_udp_index[k]=v
+ end
+end
+local function wrap(skt,sslt)
+ if getmetatable(skt)==_skt_mt_tcp or getmetatable(skt)==_skt_mt_udp then
+  return skt 
+ end
+ skt:settimeout(0)
+ if isTCP(skt) then
+  return setmetatable ({ socket=skt,ssl_params=sslt },_skt_mt_tcp)
+ else
+  return setmetatable ({ socket=skt },_skt_mt_udp)
+ end
+end
+copas.wrap=wrap
+function copas.handler(handler,sslparams)
+ return function (skt,...)
+  skt=wrap(skt)
+  if sslparams then
+   skt:dohandshake(sslparams)
+  end
+  return handler(skt,...)
+ end
+end
+local _errhandlers={}
+function copas.setErrorHandler(err)
+ local co=runningcoroutine()
+ if co then
+  _errhandlers[co]=err
+ end
+end
+local function _deferror (msg,co,skt)
+ report("%s (%s) (%s)",msg,tostring(co),tostring(skt))
+end
+local function _doTick (co,skt,...)
+ if not co then
+  return
+ end
+ local ok,res,new_q=resumecoroutine(co,skt,...)
+ if ok and res and new_q then
+  new_q:insert(res)
+  new_q:push(res,co)
+ else
+  if not ok then
+   pcall(_errhandlers[co] or _deferror,res,co,skt)
+  end
+  if skt and copas.autoclose and isTCP(skt) then
+   skt:close()
+  end
+  _errhandlers[co]=nil
+ end
+end
+local function _accept(input,handler)
+ local client=input:accept()
+ if client then
+  client:settimeout(0)
+  local co=createcoroutine(handler)
+  _doTick (co,client)
+ end
+ return client
+end
+local function _tickRead(skt)
+ _doTick(_reading:pop(skt),skt)
+end
+local function _tickWrite(skt)
+ _doTick(_writing:pop(skt),skt)
+end
+local function addTCPserver(server,handler,timeout)
+ server:settimeout(timeout or 0)
+ _servers[server]=handler
+ _reading:insert(server)
+end
+local function addUDPserver(server,handler,timeout)
+ server:settimeout(timeout or 0)
+ local co=createcoroutine(handler)
+ _reading:insert(server)
+ _doTick(co,server)
+end
+function copas.addserver(server,handler,timeout)
+ if isTCP(server) then
+  addTCPserver(server,handler,timeout)
+ else
+  addUDPserver(server,handler,timeout)
+ end
+end
+function copas.removeserver(server,keep_open)
+ local s=server
+ local mt=getmetatable(server)
+ if mt==_skt_mt_tcp or mt==_skt_mt_udp then
+  s=server.socket
+ end
+ _servers[s]=nil
+ _reading:remove(s)
+ if keep_open then
+  return true
+ end
+ return server:close()
+end
+function copas.addthread(handler,...)
+ local thread=createcoroutine(function(_,...) return handler(...) end)
+ _doTick(thread,nil,...)
+ return thread
+end
+local _tasks={}
+local function addtaskRead(task)
+ task.def_tick=_tickRead
+ _tasks[task]=true
+end
+local function addtaskWrite(task)
+ task.def_tick=_tickWrite
+ _tasks[task]=true
+end
+local function tasks()
+ return next,_tasks
+end
+local _readable_t={
+ events=function(self)
+   local i=0
+   return function ()
+    i=i+1
+    return self._evs[i]
+   end
+  end,
+ tick=function(self,input)
+   local handler=_servers[input]
+   if handler then
+    input=_accept(input,handler)
+   else
+    _reading:remove(input)
+    self.def_tick(input)
+   end
+  end
+}
+addtaskRead(_readable_t)
+local _writable_t={
+ events=function(self)
+   local i=0
+   return function()
+    i=i+1
+    return self._evs[i]
+   end
+  end,
+ tick=function(self,output)
+   _writing:remove(output)
+   self.def_tick(output)
+  end
+}
+addtaskWrite(_writable_t)
+local _sleeping_t={
+ tick=function(self,time,...)
+  _doTick(_sleeping:pop(time),...)
+ end
+}
+function copas.sleep(sleeptime)
+ yieldcoroutine((sleeptime or 0),_sleeping)
+end
+function copas.wakeup(co)
+ _sleeping:wakeup(co)
+end
+local last_cleansing=0
+local function _select(timeout)
+ local now=gettime()
+ local r_evs,w_evs,err=selectsocket(_reading,_writing,timeout)
+ _readable_t._evs=r_evs
+ _writable_t._evs=w_evs
+ if (last_cleansing-now)>WATCH_DOG_TIMEOUT then
+  last_cleansing=now
+  for skt,time in next,_reading_log do
+   if not r_evs[skt] and (time-now)>WATCH_DOG_TIMEOUT then
+    local n=#r_evs+1
+    _reading_log[skt]=nil
+    r_evs[n]=skt
+    r_evs[skt]=n
+   end
+  end
+  for skt,time in next,_writing_log do
+   if not w_evs[skt] and (time-now)>WATCH_DOG_TIMEOUT then
+    local n=#w_evs+1
+    _writing_log[skt]=nil
+    w_evs[n]=skt
+    w_evs[skt]=n
+   end
+  end
+ end
+ if err=="timeout" and #r_evs+#w_evs>0 then
+  return nil
+ else
+  return err
+ end
+end
+local function copasfinished()
+ return not (next(_reading) or next(_writing) or _sleeping:getnext())
+end
+local function copasstep(timeout)
+ _sleeping_t:tick(gettime())
+ local nextwait=_sleeping:getnext()
+ if nextwait then
+  timeout=timeout and min(nextwait,timeout) or nextwait
+ elseif copasfinished() then
+  return false
+ end
+ local err=_select(timeout)
+ if err then
+  if err=="timeout" then
+   return false
+  end
+  return nil,err
+ end
+ for task in tasks() do
+  for event in task:events() do
+   task:tick(event)
+  end
+ end
+ return true
+end
+copas.finished=copasfinished
+copas.step=copasstep
+function copas.loop(timeout)
+ copas.running=true
+ while not copasfinished() do
+  copasstep(timeout)
+ end
+ copas.running=false
+end
+package.loaded["copas"]=copas
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-ltn12"] = package.loaded["util-soc-imp-ltn12"] or true
+
+-- original size: 8709, stripped down to: 5411
+
+
+local select,unpack=select,unpack
+local insert,remove=table.insert,table.remove
+local sub=string.sub
+local function report(fmt,first,...)
+ if logs then
+  report=logs and logs.reporter("ltn12")
+  report(fmt,first,...)
+ elseif fmt then
+  fmt="ltn12: "..fmt
+  if first then
+   print(format(fmt,first,...))
+  else
+   print(fmt)
+  end
+ end
+end
+local filter={}
+local source={}
+local sink={}
+local pump={}
+local ltn12={
+ _VERSION="LTN12 1.0.3",
+ BLOCKSIZE=2048,
+ filter=filter,
+ source=source,
+ sink=sink,
+ pump=pump,
+ report=report,
+}
+function filter.cycle(low,ctx,extra)
+ if low then
+  return function(chunk)
+   return (low(ctx,chunk,extra))
+  end
+ end
+end
+function filter.chain(...)
+ local arg={... }
+ local n=select('#',...)
+ local top=1
+ local index=1
+ local retry=""
+ return function(chunk)
+  retry=chunk and retry
+  while true do
+   local action=arg[index]
+   if index==top then
+    chunk=action(chunk)
+    if chunk=="" or top==n then
+     return chunk
+    elseif chunk then
+     index=index+1
+    else
+     top=top+1
+     index=top
     end
+   else
+    chunk=action(chunk or "")
+    if chunk=="" then
+     index=index-1
+     chunk=retry
+    elseif chunk then
+     if index==n then
+      return chunk
+     else
+      index=index+1
+     end
+    else
+     report("error: filter returned inappropriate 'nil'")
+     return
+    end
+   end
   end
-  return result
+ end
 end
+local function empty()
+ return nil
+end
+function source.empty()
+ return empty
+end
+local function sourceerror(err)
+ return function()
+  return nil,err
+ end
+end
+source.error=sourceerror
+function source.file(handle,io_err)
+ if handle then
+  local blocksize=ltn12.BLOCKSIZE
+  return function()
+   local chunk=handle:read(blocksize)
+   if not chunk then
+    handle:close()
+   end
+   return chunk
+  end
+ else
+  return sourceerror(io_err or "unable to open file")
+ end
+end
+function source.simplify(src)
+ return function()
+  local chunk,err_or_new=src()
+  if err_or_new then
+   src=err_or_new
+  end
+  if chunk then
+   return chunk
+  else
+   return nil,err_or_new
+  end
+ end
+end
+function source.string(s)
+ if s then
+  local blocksize=ltn12.BLOCKSIZE
+  local i=1
+  return function()
+   local nexti=i+blocksize
+   local chunk=sub(s,i,nexti-1)
+   i=nexti
+   if chunk~="" then
+    return chunk
+   else
+    return nil
+   end
+  end
+ else return source.empty() end
+end
+function source.rewind(src)
+ local t={}
+ return function(chunk)
+  if chunk then
+   insert(t,chunk)
+  else
+   chunk=remove(t)
+   if chunk then
+    return chunk
+   else
+    return src()
+   end
+  end
+ end
+end
+function source.chain(src,f,...)
+ if... then
+  f=filter.chain(f,...)
+ end
+ local last_in=""
+ local last_out=""
+ local state="feeding"
+ local err
+ return function()
+  if not last_out then
+   report("error: source is empty")
+   return
+  end
+  while true do
+   if state=="feeding" then
+    last_in,err=src()
+    if err then
+     return nil,err
+    end
+    last_out=f(last_in)
+    if not last_out then
+     if last_in then
+      report("error: filter returned inappropriate 'nil'")
+     end
+     return nil
+    elseif last_out~="" then
+     state="eating"
+     if last_in then
+      last_in=""
+     end
+     return last_out
+    end
+   else
+    last_out=f(last_in)
+    if last_out=="" then
+     if last_in=="" then
+      state="feeding"
+     else
+      report("error: filter returned nothing")
+      return
+     end
+    elseif not last_out then
+     if last_in then
+      report("filter returned inappropriate 'nil'")
+     end
+     return nil
+    else
+     return last_out
+    end
+   end
+  end
+ end
+end
+function source.cat(...)
+ local arg={... }
+ local src=remove(arg,1)
+ return function()
+  while src do
+   local chunk,err=src()
+   if chunk then
+    return chunk
+   end
+   if err then
+    return nil,err
+   end
+   src=remove(arg,1)
+  end
+ end
+end
+function sink.table(t)
+ if not t then
+  t={}
+ end
+ local f=function(chunk,err)
+  if chunk then
+   insert(t,chunk)
+  end
+  return 1
+ end
+ return f,t
+end
+function sink.simplify(snk)
+ return function(chunk,err)
+  local ret,err_or_new=snk(chunk,err)
+  if not ret then
+   return nil,err_or_new
+  end
+  if err_or_new then
+   snk=err_or_new
+  end
+  return 1
+ end
+end
+local function null()
+ return 1
+end
+function sink.null()
+ return null
+end
+local function sinkerror(err)
+ return function()
+  return nil,err
+ end
+end
+sink.error=sinkerror
+function sink.file(handle,io_err)
+ if handle then
+  return function(chunk,err)
+   if not chunk then
+    handle:close()
+    return 1
+   else
+    return handle:write(chunk)
+   end
+  end
+ else
+  return sinkerror(io_err or "unable to open file")
+ end
+end
+function sink.chain(f,snk,...)
+ if... then
+  local args={ f,snk,... }
+  snk=remove(args,#args)
+  f=filter.chain(unpack(args))
+ end
+ return function(chunk,err)
+  if chunk~="" then
+   local filtered=f(chunk)
+   local done=chunk and ""
+   while true do
+    local ret,snkerr=snk(filtered,err)
+    if not ret then
+     return nil,snkerr
+    end
+    if filtered==done then
+     return 1
+    end
+    filtered=f(done)
+   end
+  else
+   return 1
+  end
+ end
+end
+function pump.step(src,snk)
+ local chunk,src_err=src()
+ local ret,snk_err=snk(chunk,src_err)
+ if chunk and ret then
+  return 1
+ else
+  return nil,src_err or snk_err
+ end
+end
+function pump.all(src,snk,step)
+ if not step then
+  step=pump.step
+ end
+ while true do
+  local ret,err=step(src,snk)
+  if not ret then
+   if err then
+    return nil,err
+   else
+    return 1
+   end
+  end
+ end
+end
+package.loaded["ltn12"]=ltn12
 
 
 end -- of closure
@@ -8943,16 +10719,1631 @@
 
 do -- create closure to overcome 200 locals limit
 
+package.loaded["util-soc-imp-mime"] = package.loaded["util-soc-imp-mime"] or true
+
+-- original size: 2328, stripped down to: 1874
+
+
+local type,tostring=type,tostring
+local mime=require("mime.core")
+local ltn12=ltn12 or require("ltn12")
+local filtercycle=ltn12.filter.cycle
+local function report(fmt,first,...)
+ if logs then
+  report=logs and logs.reporter("mime")
+  report(fmt,first,...)
+ elseif fmt then
+  fmt="mime: "..fmt
+  if first then
+   print(format(fmt,first,...))
+  else
+   print(fmt)
+  end
+ end
+end
+mime.report=report
+local encodet={}
+local decodet={}
+local wrapt={}
+mime.encodet=encodet
+mime.decodet=decodet
+mime.wrapt=wrapt
+local mime_b64=mime.b64
+local mime_qp=mime.qp
+local mime_unb64=mime.unb64
+local mime_unqp=mime.unqp
+local mime_wrp=mime.wrp
+local mime_qpwrp=mime.qpwrp
+local mime_eol=mime_eol
+local mime_dot=mime_dot
+encodet['base64']=function()
+ return filtercycle(mime_b64,"")
+end
+encodet['quoted-printable']=function(mode)
+ return filtercycle(mime_qp,"",mode=="binary" and "=0D=0A" or "\r\n")
+end
+decodet['base64']=function()
+ return filtercycle(mime_unb64,"")
+end
+decodet['quoted-printable']=function()
+ return filtercycle(mime_unqp,"")
+end
+local wraptext=function(length)
+ if not length then
+  length=76
+ end
+ return filtercycle(mime_wrp,length,length)
+end
+local wrapquoted=function()
+ return filtercycle(mime_qpwrp,76,76)
+end
+wrapt['text']=wraptext
+wrapt['base64']=wraptext
+wrapt['default']=wraptext
+wrapt['quoted-printable']=wrapquoted
+function mime.normalize(marker)
+ return filtercycle(mime_eol,0,marker)
+end
+function mime.stuff()
+ return filtercycle(mime_dot,2)
+end
+local function choose(list)
+ return function(name,opt1,opt2)
+  if type(name)~="string" then
+   name,opt1,opt2="default",name,opt1
+  end
+  local filter=list[name or "nil"]
+  if filter then
+   return filter(opt1,opt2)
+  else
+   report("error: unknown key '%s'",tostring(name))
+  end
+ end
+end
+mime.encode=choose(encodet)
+mime.decode=choose(decodet)
+mime.wrap=choose(wrapt)
+package.loaded["mime"]=mime
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-url"] = package.loaded["util-soc-imp-url"] or true
+
+-- original size: 6863, stripped down to: 5269
+
+
+local tonumber,tostring,type=tonumber,tostring,type
+local gsub,sub,match,find,format,byte,char=string.gsub,string.sub,string.match,string.find,string.format,string.byte,string.char
+local insert=table.insert
+local socket=socket or require("socket")
+local url={
+ _VERSION="URL 1.0.3",
+}
+socket.url=url
+function url.escape(s)
+ return (gsub(s,"([^A-Za-z0-9_])",function(c)
+  return format("%%%02x",byte(c))
+ end))
+end
+local function make_set(t) 
+ local s={}
+ for i=1,#t do
+  s[t[i]]=true
+ end
+ return s
+end
+local segment_set=make_set {
+ "-","_",".","!","~","*","'","(",
+ ")",":","@","&","=","+","$",",",
+}
+local function protect_segment(s)
+ return gsub(s,"([^A-Za-z0-9_])",function(c)
+  if segment_set[c] then
+   return c
+  else
+   return format("%%%02X",byte(c))
+  end
+ end)
+end
+function url.unescape(s)
+ return (gsub(s,"%%(%x%x)",function(hex)
+  return char(tonumber(hex,16))
+ end))
+end
+local function absolute_path(base_path,relative_path)
+ if find(relative_path,"^/") then
+  return relative_path
+ end
+ local path=gsub(base_path,"[^/]*$","")
+ path=path..relative_path
+ path=gsub(path,"([^/]*%./)",function (s)
+  if s~="./" then
+   return s
+  else
+   return ""
+  end
+ end)
+ path=gsub(path,"/%.$","/")
+ local reduced
+ while reduced~=path do
+  reduced=path
+  path=gsub(reduced,"([^/]*/%.%./)",function (s)
+   if s~="../../" then
+    return ""
+   else
+    return s
+   end
+  end)
+ end
+ path=gsub(reduced,"([^/]*/%.%.)$",function (s)
+  if s~="../.." then
+   return ""
+  else
+   return s
+  end
+ end)
+ return path
+end
+function url.parse(url,default)
+ local parsed={}
+ for k,v in next,default or parsed do
+  parsed[k]=v
+ end
+ if not url or url=="" then
+  return nil,"invalid url"
+ end
+ url=gsub(url,"#(.*)$",function(f)
+  parsed.fragment=f
+  return ""
+ end)
+ url=gsub(url,"^([%w][%w%+%-%.]*)%:",function(s)
+  parsed.scheme=s
+  return ""
+ end)
+ url=gsub(url,"^//([^/]*)",function(n)
+  parsed.authority=n
+  return ""
+ end)
+ url=gsub(url,"%?(.*)",function(q)
+  parsed.query=q
+  return ""
+ end)
+ url=gsub(url,"%;(.*)",function(p)
+  parsed.params=p
+  return ""
+ end)
+ if url~="" then
+  parsed.path=url
+ end
+ local authority=parsed.authority
+ if not authority then
+  return parsed
+ end
+ authority=gsub(authority,"^([^@]*)@",function(u)
+  parsed.userinfo=u
+  return ""
+ end)
+ authority=gsub(authority,":([^:%]]*)$",function(p)
+  parsed.port=p
+  return ""
+ end)
+ if authority~="" then
+  parsed.host=match(authority,"^%[(.+)%]$") or authority
+ end
+ local userinfo=parsed.userinfo
+ if not userinfo then
+  return parsed
+ end
+ userinfo=gsub(userinfo,":([^:]*)$",function(p)
+  parsed.password=p
+  return ""
+ end)
+ parsed.user=userinfo
+ return parsed
+end
+function url.build(parsed)
+ local url=parsed.path or ""
+ if parsed.params then
+  url=url..";"..parsed.params
+ end
+ if parsed.query then
+  url=url.."?"..parsed.query
+ end
+ local authority=parsed.authority
+ if parsed.host then
+  authority=parsed.host
+  if find(authority,":") then 
+   authority="["..authority.."]"
+  end
+  if parsed.port then
+   authority=authority..":"..tostring(parsed.port)
+  end
+  local userinfo=parsed.userinfo
+  if parsed.user then
+   userinfo=parsed.user
+   if parsed.password then
+    userinfo=userinfo..":"..parsed.password
+   end
+  end
+  if userinfo then authority=userinfo.."@"..authority end
+ end
+ if authority then
+  url="//"..authority..url
+ end
+ if parsed.scheme then
+  url=parsed.scheme..":"..url
+ end
+ if parsed.fragment then
+  url=url.."#"..parsed.fragment
+ end
+ return url
+end
+function url.absolute(base_url,relative_url)
+ local base_parsed
+ if type(base_url)=="table" then
+  base_parsed=base_url
+  base_url=url.build(base_parsed)
+ else
+  base_parsed=url.parse(base_url)
+ end
+ local relative_parsed=url.parse(relative_url)
+ if not base_parsed then
+  return relative_url
+ elseif not relative_parsed then
+  return base_url
+ elseif relative_parsed.scheme then
+  return relative_url
+ else
+  relative_parsed.scheme=base_parsed.scheme
+  if not relative_parsed.authority then
+   relative_parsed.authority=base_parsed.authority
+   if not relative_parsed.path then
+    relative_parsed.path=base_parsed.path
+    if not relative_parsed.params then
+     relative_parsed.params=base_parsed.params
+     if not relative_parsed.query then
+      relative_parsed.query=base_parsed.query
+     end
+    end
+   else
+    relative_parsed.path=absolute_path(base_parsed.path or "",relative_parsed.path)
+   end
+  end
+  return url.build(relative_parsed)
+ end
+end
+function url.parse_path(path)
+ local parsed={}
+ path=path or ""
+ gsub(path,"([^/]+)",function (s)
+  insert(parsed,s)
+ end)
+ for i=1,#parsed do
+  parsed[i]=url.unescape(parsed[i])
+ end
+ if sub(path,1,1)=="/" then
+  parsed.is_absolute=1
+ end
+ if sub(path,-1,-1)=="/" then
+  parsed.is_directory=1
+ end
+ return parsed
+end
+function url.build_path(parsed,unsafe)
+ local path=""
+ local n=#parsed
+ if unsafe then
+  for i=1,n-1 do
+   path=path..parsed[i].."/"
+  end
+  if n>0 then
+   path=path..parsed[n]
+   if parsed.is_directory then
+    path=path.."/"
+   end
+  end
+ else
+  for i=1,n-1 do
+   path=path..protect_segment(parsed[i]).."/"
+  end
+  if n>0 then
+   path=path..protect_segment(parsed[n])
+   if parsed.is_directory then
+    path=path.."/"
+   end
+  end
+ end
+ if parsed.is_absolute then
+  path="/"..path
+ end
+ return path
+end
+package.loaded["socket.url"]=url
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-headers"] = package.loaded["util-soc-imp-headers"] or true
+
+-- original size: 5721, stripped down to: 3754
+
+
+local next=next
+local lower=string.lower
+local concat=table.concat
+local socket=socket or require("socket")
+local headers={}
+socket.headers=headers
+local canonic={
+ ["accept"]="Accept",
+ ["accept-charset"]="Accept-Charset",
+ ["accept-encoding"]="Accept-Encoding",
+ ["accept-language"]="Accept-Language",
+ ["accept-ranges"]="Accept-Ranges",
+ ["action"]="Action",
+ ["alternate-recipient"]="Alternate-Recipient",
+ ["age"]="Age",
+ ["allow"]="Allow",
+ ["arrival-date"]="Arrival-Date",
+ ["authorization"]="Authorization",
+ ["bcc"]="Bcc",
+ ["cache-control"]="Cache-Control",
+ ["cc"]="Cc",
+ ["comments"]="Comments",
+ ["connection"]="Connection",
+ ["content-description"]="Content-Description",
+ ["content-disposition"]="Content-Disposition",
+ ["content-encoding"]="Content-Encoding",
+ ["content-id"]="Content-ID",
+ ["content-language"]="Content-Language",
+ ["content-length"]="Content-Length",
+ ["content-location"]="Content-Location",
+ ["content-md5"]="Content-MD5",
+ ["content-range"]="Content-Range",
+ ["content-transfer-encoding"]="Content-Transfer-Encoding",
+ ["content-type"]="Content-Type",
+ ["cookie"]="Cookie",
+ ["date"]="Date",
+ ["diagnostic-code"]="Diagnostic-Code",
+ ["dsn-gateway"]="DSN-Gateway",
+ ["etag"]="ETag",
+ ["expect"]="Expect",
+ ["expires"]="Expires",
+ ["final-log-id"]="Final-Log-ID",
+ ["final-recipient"]="Final-Recipient",
+ ["from"]="From",
+ ["host"]="Host",
+ ["if-match"]="If-Match",
+ ["if-modified-since"]="If-Modified-Since",
+ ["if-none-match"]="If-None-Match",
+ ["if-range"]="If-Range",
+ ["if-unmodified-since"]="If-Unmodified-Since",
+ ["in-reply-to"]="In-Reply-To",
+ ["keywords"]="Keywords",
+ ["last-attempt-date"]="Last-Attempt-Date",
+ ["last-modified"]="Last-Modified",
+ ["location"]="Location",
+ ["max-forwards"]="Max-Forwards",
+ ["message-id"]="Message-ID",
+ ["mime-version"]="MIME-Version",
+ ["original-envelope-id"]="Original-Envelope-ID",
+ ["original-recipient"]="Original-Recipient",
+ ["pragma"]="Pragma",
+ ["proxy-authenticate"]="Proxy-Authenticate",
+ ["proxy-authorization"]="Proxy-Authorization",
+ ["range"]="Range",
+ ["received"]="Received",
+ ["received-from-mta"]="Received-From-MTA",
+ ["references"]="References",
+ ["referer"]="Referer",
+ ["remote-mta"]="Remote-MTA",
+ ["reply-to"]="Reply-To",
+ ["reporting-mta"]="Reporting-MTA",
+ ["resent-bcc"]="Resent-Bcc",
+ ["resent-cc"]="Resent-Cc",
+ ["resent-date"]="Resent-Date",
+ ["resent-from"]="Resent-From",
+ ["resent-message-id"]="Resent-Message-ID",
+ ["resent-reply-to"]="Resent-Reply-To",
+ ["resent-sender"]="Resent-Sender",
+ ["resent-to"]="Resent-To",
+ ["retry-after"]="Retry-After",
+ ["return-path"]="Return-Path",
+ ["sender"]="Sender",
+ ["server"]="Server",
+ ["smtp-remote-recipient"]="SMTP-Remote-Recipient",
+ ["status"]="Status",
+ ["subject"]="Subject",
+ ["te"]="TE",
+ ["to"]="To",
+ ["trailer"]="Trailer",
+ ["transfer-encoding"]="Transfer-Encoding",
+ ["upgrade"]="Upgrade",
+ ["user-agent"]="User-Agent",
+ ["vary"]="Vary",
+ ["via"]="Via",
+ ["warning"]="Warning",
+ ["will-retry-until"]="Will-Retry-Until",
+ ["www-authenticate"]="WWW-Authenticate",
+ ["x-mailer"]="X-Mailer",
+}
+headers.canonic=setmetatable(canonic,{
+ __index=function(t,k)
+  socket.report("invalid header: %s",k)
+  t[k]=k
+  return k
+ end
+})
+function headers.normalize(headers)
+ if not headers then
+  return {}
+ end
+ local normalized={}
+ for k,v in next,headers do
+  normalized[#normalized+1]=canonic[k]..": "..v
+ end
+ normalized[#normalized+1]=""
+ normalized[#normalized+1]=""
+ return concat(normalized,"\r\n")
+end
+function headers.lower(lowered,headers)
+ if not lowered then
+  return {}
+ end
+ if not headers then
+  lowered,headers={},lowered
+ end
+ for k,v in next,headers do
+  lowered[lower(k)]=v
+ end
+ return lowered
+end
+socket.headers=headers
+package.loaded["socket.headers"]=headers
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-tp"] = package.loaded["util-soc-imp-tp"] or true
+
+-- original size: 3116, stripped down to: 2533
+
+
+local setmetatable,next,type,tonumber=setmetatable,next,type,tonumber
+local find,upper=string.find,string.upper
+local socket=socket or require("socket")
+local ltn12=ltn12  or require("ltn12")
+local skipsocket=socket.skip
+local sinksocket=socket.sink
+local tcpsocket=socket.tcp
+local ltn12pump=ltn12.pump
+local pumpall=ltn12pump.all
+local pumpstep=ltn12pump.step
+local tp={
+ TIMEOUT=60,
+}
+socket.tp=tp
+local function get_reply(c)
+ local line,err=c:receive()
+ local reply=line
+ if err then return
+  nil,err
+ end
+ local code,sep=skipsocket(2,find(line,"^(%d%d%d)(.?)"))
+ if not code then
+  return nil,"invalid server reply"
+ end
+ if sep=="-" then
+  local current
+  repeat
+   line,err=c:receive()
+   if err then
+    return nil,err
+   end
+   current,sep=skipsocket(2,find(line,"^(%d%d%d)(.?)"))
+   reply=reply.."\n"..line
+  until code==current and sep==" "
+ end
+ return code,reply
+end
+local methods={}
+local mt={ __index=methods }
+function methods.getpeername(self)
+ return self.c:getpeername()
+end
+function methods.getsockname(self)
+ return self.c:getpeername()
+end
+function methods.check(self,ok)
+ local code,reply=get_reply(self.c)
+ if not code then
+  return nil,reply
+ end
+ local c=tonumber(code)
+ local t=type(ok)
+ if t=="function" then
+  return ok(c,reply)
+ elseif t=="table" then
+  for i=1,#ok do
+   if find(code,ok[i]) then
+    return c,reply
+   end
+  end
+  return nil,reply
+ elseif find(code,ok) then
+  return c,reply
+ else
+  return nil,reply
+ end
+end
+function methods.command(self,cmd,arg)
+ cmd=upper(cmd)
+ if arg then
+  cmd=cmd.." "..arg.."\r\n"
+ else
+  cmd=cmd.."\r\n"
+ end
+ return self.c:send(cmd)
+end
+function methods.sink(self,snk,pat)
+ local chunk,err=self.c:receive(pat)
+ return snk(chunk,err)
+end
+function methods.send(self,data)
+ return self.c:send(data)
+end
+function methods.receive(self,pat)
+ return self.c:receive(pat)
+end
+function methods.getfd(self)
+ return self.c:getfd()
+end
+function methods.dirty(self)
+ return self.c:dirty()
+end
+function methods.getcontrol(self)
+ return self.c
+end
+function methods.source(self,source,step)
+ local sink=sinksocket("keep-open",self.c)
+ local ret,err=pumpall(source,sink,step or pumpstep)
+ return ret,err
+end
+function methods.close(self)
+ self.c:close()
+ return 1
+end
+function tp.connect(host,port,timeout,create)
+ local c,e=(create or tcpsocket)()
+ if not c then
+  return nil,e
+ end
+ c:settimeout(timeout or tp.TIMEOUT)
+ local r,e=c:connect(host,port)
+ if not r then
+  c:close()
+  return nil,e
+ end
+ return setmetatable({ c=c },mt)
+end
+package.loaded["socket.tp"]=tp
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-http"] = package.loaded["util-soc-imp-http"] or true
+
+-- original size: 12577, stripped down to: 9577
+
+
+local tostring,tonumber,setmetatable,next,type=tostring,tonumber,setmetatable,next,type
+local find,lower,format,gsub,match=string.find,string.lower,string.format,string.gsub,string.match
+local concat=table.concat
+local socket=socket   or require("socket")
+local url=socket.url  or require("socket.url")
+local ltn12=ltn12    or require("ltn12")
+local mime=mime     or require("mime")
+local headers=socket.headers or require("socket.headers")
+local normalizeheaders=headers.normalize
+local parseurl=url.parse
+local buildurl=url.build
+local absoluteurl=url.absolute
+local unescapeurl=url.unescape
+local skipsocket=socket.skip
+local sinksocket=socket.sink
+local sourcesocket=socket.source
+local trysocket=socket.try
+local tcpsocket=socket.tcp
+local newtrysocket=socket.newtry
+local protectsocket=socket.protect
+local emptysource=ltn12.source.empty
+local stringsource=ltn12.source.string
+local rewindsource=ltn12.source.rewind
+local pumpstep=ltn12.pump.step
+local pumpall=ltn12.pump.all
+local sinknull=ltn12.sink.null
+local sinktable=ltn12.sink.table
+local lowerheaders=headers.lower
+local mimeb64=mime.b64
+local http={
+ TIMEOUT=60,
+ USERAGENT=socket._VERSION,
+}
+socket.http=http
+local PORT=80
+local SCHEMES={
+ http=true,
+}
+local function receiveheaders(sock,headers)
+ if not headers then
+  headers={}
+ end
+ local line,err=sock:receive()
+ if err then
+  return nil,err
+ end
+ while line~="" do
+  local name,value=skipsocket(2,find(line,"^(.-):%s*(.*)"))
+  if not (name and value) then
+   return nil,"malformed reponse headers"
+  end
+  name=lower(name)
+  line,err=sock:receive()
+  if err then
+   return nil,err
+  end
+  while find(line,"^%s") do
+   value=value..line
+   line=sock:receive()
+   if err then
+    return nil,err
+   end
+  end
+  local found=headers[name]
+  if found then
+   value=found..", "..value
+  end
+  headers[name]=value
+ end
+ return headers
+end
+socket.sourcet["http-chunked"]=function(sock,headers)
+ return setmetatable (
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },{
+   __call=function()
+    local line,err=sock:receive()
+    if err then
+     return nil,err
+    end
+    local size=tonumber(gsub(line,";.*",""),16)
+    if not size then
+     return nil,"invalid chunk size"
+    end
+    if size>0 then
+     local chunk,err,part=sock:receive(size)
+     if chunk then
+      sock:receive()
+     end
+     return chunk,err
+    else
+     headers,err=receiveheaders(sock,headers)
+     if not headers then
+      return nil,err
+     end
+    end
+   end
+  }
+ )
+end
+socket.sinkt["http-chunked"]=function(sock)
+ return setmetatable(
+  {
+   getfd=function() return sock:getfd() end,
+   dirty=function() return sock:dirty() end,
+  },
+  {
+   __call=function(self,chunk,err)
+    if not chunk then
+     chunk=""
+    end
+    return sock:send(format("%X\r\n%s\r\n",#chunk,chunk))
+   end
+ })
+end
+local methods={}
+local mt={ __index=methods }
+local function openhttp(host,port,create)
+ local c=trysocket((create or tcpsocket)())
+ local h=setmetatable({ c=c },mt)
+ local try=newtrysocket(function() h:close() end)
+ h.try=try
+ try(c:settimeout(http.TIMEOUT))
+ try(c:connect(host,port or PORT))
+ return h
+end
+http.open=openhttp
+function methods.sendrequestline(self,method,uri)
+ local requestline=format("%s %s HTTP/1.1\r\n",method or "GET",uri)
+ return self.try(self.c:send(requestline))
+end
+function methods.sendheaders(self,headers)
+ self.try(self.c:send(normalizeheaders(headers)))
+ return 1
+end
+function methods.sendbody(self,headers,source,step)
+ if not source then
+  source=emptysource()
+ end
+ if not step then
+  step=pumpstep
+ end
+ local mode="http-chunked"
+ if headers["content-length"] then
+  mode="keep-open"
+ end
+ return self.try(pumpall(source,sinksocket(mode,self.c),step))
+end
+function methods.receivestatusline(self)
+ local try=self.try
+ local status=try(self.c:receive(5))
+ if status~="HTTP/" then
+  return nil,status 
+ end
+ status=try(self.c:receive("*l",status))
+ local code=skipsocket(2,find(status,"HTTP/%d*%.%d* (%d%d%d)"))
+ return try(tonumber(code),status)
+end
+function methods.receiveheaders(self)
+ return self.try(receiveheaders(self.c))
+end
+function methods.receivebody(self,headers,sink,step)
+ if not sink then
+  sink=sinknull()
+ end
+ if not step then
+  step=pumpstep
+ end
+ local length=tonumber(headers["content-length"])
+ local encoding=headers["transfer-encoding"] 
+ local mode="default" 
+ if encoding and encoding~="identity" then
+  mode="http-chunked"
+ elseif length then
+  mode="by-length"
+ end
+ return self.try(pumpall(sourcesocket(mode,self.c,length),sink,step))
+end
+function methods.receive09body(self,status,sink,step)
+ local source=rewindsource(sourcesocket("until-closed",self.c))
+ source(status)
+ return self.try(pumpall(source,sink,step))
+end
+function methods.close(self)
+ return self.c:close()
+end
+local function adjusturi(request)
+ if not request.proxy and not http.PROXY then
+  request={
+     path=trysocket(request.path,"invalid path 'nil'"),
+     params=request.params,
+     query=request.query,
+     fragment=request.fragment,
+  }
+ end
+ return buildurl(request)
+end
+local function adjustheaders(request)
+ local headers={
+  ["user-agent"]=http.USERAGENT,
+  ["host"]=gsub(request.authority,"^.-@",""),
+  ["connection"]="close, TE",
+  ["te"]="trailers"
+ }
+ local username=request.user
+ local password=request.password
+ if username and password then
+  headers["authorization"]="Basic "..(mimeb64(username..":"..unescapeurl(password)))
+ end
+ local proxy=request.proxy or http.PROXY
+ if proxy then
+  proxy=parseurl(proxy)
+  local username=proxy.user
+  local password=proxy.password
+  if username and password then
+   headers["proxy-authorization"]="Basic "..(mimeb64(username..":"..password))
+  end
+ end
+ local requestheaders=request.headers
+ if requestheaders then
+  headers=lowerheaders(headers,requestheaders)
+ end
+ return headers
+end
+local default={
+ host="",
+ port=PORT,
+ path="/",
+ scheme="http"
+}
+local function adjustrequest(originalrequest)
+ local url=originalrequest.url
+ local request=url and parseurl(url,default) or {}
+ for k,v in next,originalrequest do
+  request[k]=v
+ end
+ local host=request.host
+ local port=request.port
+ local uri=request.uri
+ if not host or host=="" then
+  trysocket(nil,"invalid host '"..tostring(host).."'")
+ end
+ if port=="" then
+  request.port=PORT
+ end
+ if not uri or uri=="" then
+  request.uri=adjusturi(request)
+ end
+ request.headers=adjustheaders(request)
+ local proxy=request.proxy or http.PROXY
+ if proxy then
+  proxy=parseurl(proxy)
+  request.host=proxy.host
+  request.port=proxy.port or 3128
+ end
+ return request
+end
+local maxredericts=4
+local validredirects={ [301]=true,[302]=true,[303]=true,[307]=true }
+local validmethods={ [false]=true,GET=true,HEAD=true }
+local function shouldredirect(request,code,headers)
+ local location=headers.location
+ if not location then
+  return false
+ end
+ location=gsub(location,"%s","")
+ if location=="" then
+  return false
+ end
+ local scheme=match(location,"^([%w][%w%+%-%.]*)%:")
+ if scheme and not SCHEMES[scheme] then
+  return false
+ end
+ local method=request.method
+ local redirect=request.redirect
+ local redirects=request.nredirects or 0
+ return redirect and validredirects[code] and validmethods[method] and redirects<=maxredericts
+end
+local function shouldreceivebody(request,code)
+ if request.method=="HEAD" then
+  return nil
+ end
+ if code==204 or code==304 then
+  return nil
+ end
+ if code>=100 and code<200 then
+  return nil
+ end
+ return 1
+end
+local tredirect,trequest,srequest
+tredirect=function(request,location)
+ local result,code,headers,status=trequest {
+  url=absoluteurl(request.url,location),
+  source=request.source,
+  sink=request.sink,
+  headers=request.headers,
+  proxy=request.proxy,
+  nredirects=(request.nredirects or 0)+1,
+  create=request.create,
+ }
+ if not headers then
+  headers={}
+ end
+ if not headers.location then
+  headers.location=location
+ end
+ return result,code,headers,status
+end
+trequest=function(originalrequest)
+ local request=adjustrequest(originalrequest)
+ local connection=openhttp(request.host,request.port,request.create)
+ local headers=request.headers
+ connection:sendrequestline(request.method,request.uri)
+ connection:sendheaders(headers)
+ if request.source then
+  connection:sendbody(headers,request.source,request.step)
+ end
+ local code,status=connection:receivestatusline()
+ if not code then
+  connection:receive09body(status,request.sink,request.step)
+  return 1,200
+ end
+ while code==100 do
+  headers=connection:receiveheaders()
+  code,status=connection:receivestatusline()
+ end
+ headers=connection:receiveheaders()
+ if shouldredirect(request,code,headers) and not request.source then
+  connection:close()
+  return tredirect(originalrequest,headers.location)
+ end
+ if shouldreceivebody(request,code) then
+  connection:receivebody(headers,request.sink,request.step)
+ end
+ connection:close()
+ return 1,code,headers,status
+end
+local function genericform(url,body)
+ local buffer={}
+ local request={
+  url=url,
+  sink=sinktable(buffer),
+  target=buffer,
+ }
+ if body then
+  request.source=stringsource(body)
+  request.method="POST"
+  request.headers={
+   ["content-length"]=#body,
+   ["content-type"]="application/x-www-form-urlencoded"
+  }
+ end
+ return request
+end
+http.genericform=genericform
+srequest=function(url,body)
+ local request=genericform(url,body)
+ local _,code,headers,status=trequest(request)
+ return concat(request.target),code,headers,status
+end
+http.request=protectsocket(function(request,body)
+ if type(request)=="string" then
+  return srequest(request,body)
+ else
+  return trequest(request)
+ end
+end)
+package.loaded["socket.http"]=http
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-ftp"] = package.loaded["util-soc-imp-ftp"] or true
+
+-- original size: 10357, stripped down to: 8548
+
+
+local setmetatable,type,next=setmetatable,type,next
+local find,format,gsub,match=string.find,string.format,string.gsub,string.match
+local concat=table.concat
+local mod=math.mod
+local socket=socket  or require("socket")
+local url=socket.url or require("socket.url")
+local tp=socket.tp  or require("socket.tp")
+local ltn12=ltn12   or require("ltn12")
+local tcpsocket=socket.tcp
+local trysocket=socket.try
+local skipsocket=socket.skip
+local sinksocket=socket.sink
+local selectsocket=socket.select
+local bindsocket=socket.bind
+local newtrysocket=socket.newtry
+local sourcesocket=socket.source
+local protectsocket=socket.protect
+local parseurl=url.parse
+local unescapeurl=url.unescape
+local pumpall=ltn12.pump.all
+local pumpstep=ltn12.pump.step
+local sourcestring=ltn12.source.string
+local sinktable=ltn12.sink.table
+local ftp={
+ TIMEOUT=60,
+ USER="ftp",
+ PASSWORD="anonymous at anonymous.org",
+}
+socket.ftp=ftp
+local PORT=21
+local methods={}
+local mt={ __index=methods }
+function ftp.open(server,port,create)
+ local tp=trysocket(tp.connect(server,port or PORT,ftp.TIMEOUT,create))
+ local f=setmetatable({ tp=tp },metat)
+ f.try=newtrysocket(function() f:close() end)
+ return f
+end
+function methods.portconnect(self)
+ local try=self.try
+ local server=self.server
+ try(server:settimeout(ftp.TIMEOUT))
+ self.data=try(server:accept())
+ try(self.data:settimeout(ftp.TIMEOUT))
+end
+function methods.pasvconnect(self)
+ local try=self.try
+ self.data=try(tcpsocket())
+ self(self.data:settimeout(ftp.TIMEOUT))
+ self(self.data:connect(self.pasvt.address,self.pasvt.port))
+end
+function methods.login(self,user,password)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("user",user or ftp.USER))
+ local code,reply=try(tp:check{"2..",331})
+ if code==331 then
+  try(tp:command("pass",password or ftp.PASSWORD))
+  try(tp:check("2.."))
+ end
+ return 1
+end
+function methods.pasv(self)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("pasv"))
+ local code,reply=try(self.tp:check("2.."))
+ local pattern="(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
+ local a,b,c,d,p1,p2=skipsocket(2,find(reply,pattern))
+ try(a and b and c and d and p1 and p2,reply)
+ local address=format("%d.%d.%d.%d",a,b,c,d)
+ local port=p1*256+p2
+ local server=self.server
+ self.pasvt={
+  address=address,
+  port=port,
+ }
+ if server then
+  server:close()
+  self.server=nil
+ end
+ return address,port
+end
+function methods.epsv(self)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("epsv"))
+ local code,reply=try(tp:check("229"))
+ local pattern="%((.)(.-)%1(.-)%1(.-)%1%)"
+ local d,prt,address,port=match(reply,pattern)
+ try(port,"invalid epsv response")
+ local address=tp:getpeername()
+ local server=self.server
+ self.pasvt={
+  address=address,
+  port=port,
+ }
+ if self.server then
+  server:close()
+  self.server=nil
+ end
+ return address,port
+end
+function methods.port(self,address,port)
+ local try=self.try
+ local tp=self.tp
+ self.pasvt=nil
+ if not address then
+  address,port=try(tp:getsockname())
+  self.server=try(bindsocket(address,0))
+  address,port=try(self.server:getsockname())
+  try(self.server:settimeout(ftp.TIMEOUT))
+ end
+ local pl=mod(port,256)
+ local ph=(port-pl)/256
+ local arg=gsub(format("%s,%d,%d",address,ph,pl),"%.",",")
+ try(tp:command("port",arg))
+ try(tp:check("2.."))
+ return 1
+end
+function methods.eprt(self,family,address,port)
+ local try=self.try
+ local tp=self.tp
+ self.pasvt=nil
+ if not address then
+  address,port=try(tp:getsockname())
+  self.server=try(bindsocket(address,0))
+  address,port=try(self.server:getsockname())
+  try(self.server:settimeout(ftp.TIMEOUT))
+ end
+ local arg=format("|%s|%s|%d|",family,address,port)
+ try(tp:command("eprt",arg))
+ try(tp:check("2.."))
+ return 1
+end
+function methods.send(self,sendt)
+ local try=self.try
+ local tp=self.tp
+ try(self.pasvt or self.server,"need port or pasv first")
+ if self.pasvt then
+  self:pasvconnect()
+ end
+ local argument=sendt.argument or unescapeurl(gsub(sendt.path or "","^[/\\]",""))
+ if argument=="" then
+  argument=nil
+ end
+ local command=sendt.command or "stor"
+ try(tp:command(command,argument))
+ local code,reply=try(tp:check{"2..","1.."})
+ if not self.pasvt then
+  self:portconnect()
+ end
+ local step=sendt.step or pumpstep
+ local readt={ tp }
+ local checkstep=function(src,snk)
+  local readyt=selectsocket(readt,nil,0)
+  if readyt[tp] then
+   code=try(tp:check("2.."))
+  end
+  return step(src,snk)
+ end
+ local sink=sinksocket("close-when-done",self.data)
+ try(pumpall(sendt.source,sink,checkstep))
+ if find(code,"1..") then
+  try(tp:check("2.."))
+ end
+ self.data:close()
+ local sent=skipsocket(1,self.data:getstats())
+ self.data=nil
+ return sent
+end
+function methods.receive(self,recvt)
+ local try=self.try
+ local tp=self.tp
+ try(self.pasvt or self.server,"need port or pasv first")
+ if self.pasvt then self:pasvconnect() end
+ local argument=recvt.argument or unescapeurl(gsub(recvt.path or "","^[/\\]",""))
+ if argument=="" then
+  argument=nil
+ end
+ local command=recvt.command or "retr"
+ try(tp:command(command,argument))
+ local code,reply=try(tp:check{"1..","2.."})
+ if code>=200 and code<=299 then
+  recvt.sink(reply)
+  return 1
+ end
+ if not self.pasvt then
+  self:portconnect()
+ end
+ local source=sourcesocket("until-closed",self.data)
+ local step=recvt.step or pumpstep
+ try(pumpall(source,recvt.sink,step))
+ if find(code,"1..") then
+  try(tp:check("2.."))
+ end
+ self.data:close()
+ self.data=nil
+ return 1
+end
+function methods.cwd(self,dir)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("cwd",dir))
+ try(tp:check(250))
+ return 1
+end
+function methods.type(self,typ)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("type",typ))
+ try(tp:check(200))
+ return 1
+end
+function methods.greet(self)
+ local try=self.try
+ local tp=self.tp
+ local code=try(tp:check{"1..","2.."})
+ if find(code,"1..") then
+  try(tp:check("2.."))
+ end
+ return 1
+end
+function methods.quit(self)
+ local try=self.try
+ try(self.tp:command("quit"))
+ try(self.tp:check("2.."))
+ return 1
+end
+function methods.close(self)
+ local data=self.data
+ if data then
+  data:close()
+ end
+ local server=self.server
+ if server then
+  server:close()
+ end
+ local tp=self.tp
+ if tp then
+  tp:close()
+ end
+end
+local function override(t)
+ if t.url then
+  local u=parseurl(t.url)
+  for k,v in next,t do
+   u[k]=v
+  end
+  return u
+ else
+  return t
+ end
+end
+local function tput(putt)
+ putt=override(putt)
+ local host=putt.host
+ trysocket(host,"missing hostname")
+ local f=ftp.open(host,putt.port,putt.create)
+ f:greet()
+ f:login(putt.user,putt.password)
+ local typ=putt.type
+ if typ then
+  f:type(typ)
+ end
+ f:epsv()
+ local sent=f:send(putt)
+ f:quit()
+ f:close()
+ return sent
+end
+local default={
+ path="/",
+ scheme="ftp",
+}
+local function genericform(u)
+ local t=trysocket(parseurl(u,default))
+ trysocket(t.scheme=="ftp","wrong scheme '"..t.scheme.."'")
+ trysocket(t.host,"missing hostname")
+ local pat="^type=(.)$"
+ if t.params then
+  local typ=skipsocket(2,find(t.params,pat))
+  t.type=typ
+  trysocket(typ=="a" or typ=="i","invalid type '"..typ.."'")
+ end
+ return t
+end
+ftp.genericform=genericform
+local function sput(u,body)
+ local putt=genericform(u)
+ putt.source=sourcestring(body)
+ return tput(putt)
+end
+ftp.put=protectsocket(function(putt,body)
+ if type(putt)=="string" then
+  return sput(putt,body)
+ else
+  return tput(putt)
+ end
+end)
+local function tget(gett)
+ gett=override(gett)
+ local host=gett.host
+ trysocket(host,"missing hostname")
+ local f=ftp.open(host,gett.port,gett.create)
+ f:greet()
+ f:login(gett.user,gett.password)
+ if gett.type then
+  f:type(gett.type)
+ end
+ f:epsv()
+ f:receive(gett)
+ f:quit()
+ return f:close()
+end
+local function sget(u)
+ local gett=genericform(u)
+ local t={}
+ gett.sink=sinktable(t)
+ tget(gett)
+ return concat(t)
+end
+ftp.command=protectsocket(function(cmdt)
+ cmdt=override(cmdt)
+ local command=cmdt.command
+ local argument=cmdt.argument
+ local check=cmdt.check
+ local host=cmdt.host
+ trysocket(host,"missing hostname")
+ trysocket(command,"missing command")
+ local f=ftp.open(host,cmdt.port,cmdt.create)
+ local try=f.try
+ local tp=f.tp
+ f:greet()
+ f:login(cmdt.user,cmdt.password)
+ if type(command)=="table" then
+  local argument=argument or {}
+  for i=1,#command do
+   local cmd=command[i]
+   try(tp:command(cmd,argument[i]))
+   if check and check[i] then
+    try(tp:check(check[i]))
+   end
+  end
+ else
+  try(tp:command(command,argument))
+  if check then
+   try(tp:check(check))
+  end
+ end
+ f:quit()
+ return f:close()
+end)
+ftp.get=protectsocket(function(gett)
+ if type(gett)=="string" then
+  return sget(gett)
+ else
+  return tget(gett)
+ end
+end)
+package.loaded["socket.ftp"]=ftp
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["util-soc-imp-smtp"] = package.loaded["util-soc-imp-smtp"] or true
+
+-- original size: 7018, stripped down to: 5883
+
+
+local type,setmetatable,next=type,setmetatable,next
+local find,lower,format=string.find,string.lower,string.format
+local osdate,osgetenv=os.date,os.getenv
+local random=math.random
+local socket=socket   or require("socket")
+local headers=socket.headers or require("socket.headers")
+local ltn12=ltn12    or require("ltn12")
+local tp=socket.tp   or require("socket.tp")
+local mime=mime     or require("mime")
+local mimeb64=mime.b64
+local mimestuff=mime.stuff
+local skipsocket=socket.skip
+local trysocket=socket.try
+local newtrysocket=socket.newtry
+local protectsocket=socket.protect
+local normalizeheaders=headers.normalize
+local lowerheaders=headers.lower
+local createcoroutine=coroutine.create
+local resumecoroutine=coroutine.resume
+local yieldcoroutine=coroutine.resume
+local smtp={
+ TIMEOUT=60,
+ SERVER="localhost",
+ PORT=25,
+ DOMAIN=osgetenv("SERVER_NAME") or "localhost",
+ ZONE="-0000",
+}
+socket.smtp=smtp
+local methods={}
+local mt={ __index=methods }
+function methods.greet(self,domain)
+ local try=self.try
+ local tp=self.tp
+ try(tp:check("2.."))
+ try(tp:command("EHLO",domain or _M.DOMAIN))
+ return skipsocket(1,try(tp:check("2..")))
+end
+function methods.mail(self,from)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("MAIL","FROM:"..from))
+ return try(tp:check("2.."))
+end
+function methods.rcpt(self,to)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("RCPT","TO:"..to))
+ return try(tp:check("2.."))
+end
+function methods.data(self,src,step)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("DATA"))
+ try(tp:check("3.."))
+ try(tp:source(src,step))
+ try(tp:send("\r\n.\r\n"))
+ return try(tp:check("2.."))
+end
+function methods.quit(self)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("QUIT"))
+ return try(tp:check("2.."))
+end
+function methods.close(self)
+ return self.tp:close()
+end
+function methods.login(self,user,password)
+ local try=self.try
+ local tp=self.tp
+ try(tp:command("AUTH","LOGIN"))
+ try(tp:check("3.."))
+ try(tp:send(mimeb64(user).."\r\n"))
+ try(tp:check("3.."))
+ try(tp:send(mimeb64(password).."\r\n"))
+ return try(tp:check("2.."))
+end
+function methods.plain(self,user,password)
+ local try=self.try
+ local tp=self.tp
+ local auth="PLAIN "..mimeb64("\0"..user.."\0"..password)
+ try(tp:command("AUTH",auth))
+ return try(tp:check("2.."))
+end
+function methods.auth(self,user,password,ext)
+ if not user or not password then
+  return 1
+ end
+ local try=self.try
+ if find(ext,"AUTH[^\n]+LOGIN") then
+  return self:login(user,password)
+ elseif find(ext,"AUTH[^\n]+PLAIN") then
+  return self:plain(user,password)
+ else
+  try(nil,"authentication not supported")
+ end
+end
+function methods.send(self,mail)
+ self:mail(mail.from)
+ local receipt=mail.rcpt
+ if type(receipt)=="table" then
+  for i=1,#receipt do
+   self:rcpt(receipt[i])
+  end
+ elseif receipt then
+  self:rcpt(receipt)
+ end
+ self:data(ltn12.source.chain(mail.source,mimestuff()),mail.step)
+end
+local function opensmtp(self,server,port,create)
+ if not server or server=="" then
+  server=smtp.SERVER
+ end
+ if not port or port=="" then
+  port=smtp.PORT
+ end
+ local s={
+  tp=trysocket(tp.connect(server,port,smtp.TIMEOUT,create)),
+  try=newtrysocket(function()
+   s:close()
+  end),
+ }
+ setmetatable(s,mt)
+ return s
+end
+smtp.open=opensmtp
+local nofboundaries=0
+local function newboundary()
+ nofboundaries=nofboundaries+1
+ return format('%s%05d==%05u',osdate('%d%m%Y%H%M%S'),random(0,99999),nofboundaries)
+end
+local send_message
+local function send_headers(headers)
+ yieldcoroutine(normalizeheaders(headers))
+end
+local function send_multipart(message)
+ local boundary=newboundary()
+ local headers=lowerheaders(message.headers)
+ local body=message.body
+ local preamble=body.preamble
+ local epilogue=body.epilogue
+ local content=headers['content-type'] or 'multipart/mixed'
+ headers['content-type']=content..'; boundary="'..boundary..'"'
+ send_headers(headers)
+ if preamble then
+  yieldcoroutine(preamble)
+  yieldcoroutine("\r\n")
+ end
+ for i=1,#body do
+  yieldcoroutine("\r\n--"..boundary.."\r\n")
+  send_message(body[i])
+ end
+ yieldcoroutine("\r\n--"..boundary.."--\r\n\r\n")
+ if epilogue then
+  yieldcoroutine(epilogue)
+  yieldcoroutine("\r\n")
+ end
+end
+local default_content_type='text/plain; charset="UTF-8"'
+local function send_source(message)
+ local headers=lowerheaders(message.headers)
+ if not headers['content-type'] then
+  headers['content-type']=default_content_type
+ end
+ send_headers(headers)
+ local getchunk=message.body
+ while true do
+  local chunk,err=getchunk()
+  if err then
+   yieldcoroutine(nil,err)
+  elseif chunk then
+   yieldcoroutine(chunk)
+  else
+   break
+  end
+ end
+end
+local function send_string(message)
+ local headers=lowerheaders(message.headers)
+ if not headers['content-type'] then
+  headers['content-type']=default_content_type
+ end
+ send_headers(headers)
+ yieldcoroutine(message.body)
+end
+function send_message(message)
+ local body=message.body
+ if type(body)=="table" then
+  send_multipart(message)
+ elseif type(body)=="function" then
+  send_source(message)
+ else
+  send_string(message)
+ end
+end
+local function adjust_headers(message)
+ local headers=lowerheaders(message.headers)
+ if not headers["date"] then
+  headers["date"]=osdate("!%a, %d %b %Y %H:%M:%S ")..(message.zone or smtp.ZONE)
+ end
+ if not headers["x-mailer"] then
+  headers["x-mailer"]=socket._VERSION
+ end
+ headers["mime-version"]="1.0"
+ return headers
+end
+function smtp.message(message)
+ message.headers=adjust_headers(message)
+ local action=createcoroutine(function()
+  send_message(message)
+ end)
+ return function()
+  local ret,a,b=resumecoroutine(action)
+  if ret then
+   return a,b
+  else
+   return nil,a
+  end
+ end
+end
+smtp.send=protectsocket(function(mail)
+ local snd=opensmtp(smtp,mail.server,mail.port,mail.create)
+ local ext=snd:greet(mail.domain)
+ snd:auth(mail.user,mail.password,ext)
+ snd:send(mail)
+ snd:quit()
+ return snd:close()
+end)
+package.loaded["socket.smtp"]=smtp
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
 package.loaded["trac-set"] = package.loaded["trac-set"] or true
 
--- original size: 13044, stripped down to: 9231
+-- original size: 13340, stripped down to: 8826
 
 if not modules then modules={} end modules ['trac-set']={ 
-  version=1.001,
-  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"
+ version=1.001,
+ 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 type,next,tostring,tonumber=type,next,tostring,tonumber
 local concat,sortedhash=table.concat,table.sortedhash
@@ -8967,305 +12358,318 @@
 local data={}
 local trace_initialize=false 
 function setters.initialize(filename,name,values) 
-  local setter=data[name]
-  if setter then
-    frozen=true
-    local data=setter.data
-    if data then
-      for key,newvalue in sortedhash(values) do
-        local newvalue=is_boolean(newvalue,newvalue,true) 
-        local functions=data[key]
-        if functions then
-          local oldvalue=functions.value
-          if functions.frozen then
-            if trace_initialize then
-              setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
-            end
-          elseif #functions>0 and not oldvalue then
-            if trace_initialize then
-              setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
-            end
-            for i=1,#functions do
-              functions[i](newvalue)
-            end
-            functions.value=newvalue
-            functions.frozen=functions.frozen or frozen
-          else
-            if trace_initialize then
-              setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
-            end
-          end
-        else
-          functions={ default=newvalue,frozen=frozen }
-          data[key]=functions
-          if trace_initialize then
-            setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
-          end
-        end
+ local setter=data[name]
+ if setter then
+  frozen=true
+  local data=setter.data
+  if data then
+   for key,newvalue in sortedhash(values) do
+    local newvalue=is_boolean(newvalue,newvalue,true) 
+    local functions=data[key]
+    if functions then
+     local oldvalue=functions.value
+     if functions.frozen then
+      if trace_initialize then
+       setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
       end
-      return true
+     elseif #functions>0 and not oldvalue then
+      if trace_initialize then
+       setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
+      end
+      for i=1,#functions do
+       functions[i](newvalue)
+      end
+      functions.value=newvalue
+      functions.frozen=functions.frozen or frozen
+     else
+      if trace_initialize then
+       setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
+      end
+     end
+    else
+     functions={ default=newvalue,frozen=frozen }
+     data[key]=functions
+     if trace_initialize then
+      setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
+     end
     end
+   end
+   return true
   end
+ end
 end
 local function set(t,what,newvalue)
-  local data=t.data
-  if not data.frozen then
-    local done=t.done
-    if type(what)=="string" then
-      what=settings_to_hash(what) 
+ local data=t.data
+ if not data.frozen then
+  local done=t.done
+  if type(what)=="string" then
+   what=settings_to_hash(what) 
+  end
+  if type(what)~="table" then
+   return
+  end
+  if not done then 
+   done={}
+   t.done=done
+  end
+  for w,value in sortedhash(what) do
+   if value=="" then
+    value=newvalue
+   elseif not value then
+    value=false 
+   else
+    value=is_boolean(value,value,true) 
+   end
+   w=topattern(w,true,true)
+   for name,functions in sortedhash(data) do
+    if done[name] then
+    elseif find(name,w) then
+     done[name]=true
+     for i=1,#functions do
+      functions[i](value)
+     end
+     functions.value=value
     end
-    if type(what)~="table" then
-      return
-    end
-    if not done then 
-      done={}
-      t.done=done
-    end
-    for w,value in sortedhash(what) do
-      if value=="" then
-        value=newvalue
-      elseif not value then
-        value=false 
-      else
-        value=is_boolean(value,value,true) 
-      end
-      w=topattern(w,true,true)
-      for name,functions in sortedhash(data) do
-        if done[name] then
-        elseif find(name,w) then
-          done[name]=true
-          for i=1,#functions do
-            functions[i](value)
-          end
-          functions.value=value
-        end
-      end
-    end
+   end
   end
+ end
 end
 local function reset(t)
-  local data=t.data
-  if not data.frozen then
-    for name,functions in sortedthash(data) do
-      for i=1,#functions do
-        functions[i](false)
-      end
-      functions.value=false
-    end
+ local data=t.data
+ if not data.frozen then
+  for name,functions in sortedthash(data) do
+   for i=1,#functions do
+    functions[i](false)
+   end
+   functions.value=false
   end
+ end
 end
 local function enable(t,what)
-  set(t,what,true)
+ set(t,what,true)
 end
 local function disable(t,what)
-  local data=t.data
-  if not what or what=="" then
-    t.done={}
-    reset(t)
-  else
-    set(t,what,false)
-  end
+ local data=t.data
+ if not what or what=="" then
+  t.done={}
+  reset(t)
+ else
+  set(t,what,false)
+ end
 end
 function setters.register(t,what,...)
-  local data=t.data
-  what=lower(what)
-  local functions=data[what]
-  if not functions then
-    functions={}
-    data[what]=functions
-    if trace_initialize then
-      t.report("defining %a",what)
-    end
+ local data=t.data
+ what=lower(what)
+ local functions=data[what]
+ if not functions then
+  functions={}
+  data[what]=functions
+  if trace_initialize then
+   t.report("defining %a",what)
   end
-  local default=functions.default 
-  for i=1,select("#",...) do
-    local fnc=select(i,...)
-    local typ=type(fnc)
-    if typ=="string" then
-      if trace_initialize then
-        t.report("coupling %a to %a",what,fnc)
-      end
-      local s=fnc 
-      fnc=function(value) set(t,s,value) end
-    elseif typ~="function" then
-      fnc=nil
-    end
-    if fnc then
-      functions[#functions+1]=fnc
-      local value=functions.value or default
-      if value~=nil then
-        fnc(value)
-        functions.value=value
-      end
-    end
+ end
+ local default=functions.default 
+ for i=1,select("#",...) do
+  local fnc=select(i,...)
+  local typ=type(fnc)
+  if typ=="string" then
+   if trace_initialize then
+    t.report("coupling %a to %a",what,fnc)
+   end
+   local s=fnc 
+   fnc=function(value) set(t,s,value) end
+  elseif typ~="function" then
+   fnc=nil
   end
-  return false 
+  if fnc then
+   functions[#functions+1]=fnc
+   local value=functions.value or default
+   if value~=nil then
+    fnc(value)
+    functions.value=value
+   end
+  end
+ end
+ return false 
 end
 function setters.enable(t,what)
-  local e=t.enable
-  t.enable,t.done=enable,{}
-  enable(t,what)
-  t.enable,t.done=e,{}
+ local e=t.enable
+ t.enable,t.done=enable,{}
+ enable(t,what)
+ t.enable,t.done=e,{}
 end
 function setters.disable(t,what)
-  local e=t.disable
-  t.disable,t.done=disable,{}
-  disable(t,what)
-  t.disable,t.done=e,{}
+ local e=t.disable
+ t.disable,t.done=disable,{}
+ disable(t,what)
+ t.disable,t.done=e,{}
 end
 function setters.reset(t)
-  t.done={}
-  reset(t)
+ t.done={}
+ reset(t)
 end
 function setters.list(t) 
-  local list=table.sortedkeys(t.data)
-  local user,system={},{}
-  for l=1,#list do
-    local what=list[l]
-    if find(what,"^%*") then
-      system[#system+1]=what
-    else
-      user[#user+1]=what
-    end
+ local list=table.sortedkeys(t.data)
+ local user,system={},{}
+ for l=1,#list do
+  local what=list[l]
+  if find(what,"^%*") then
+   system[#system+1]=what
+  else
+   user[#user+1]=what
   end
-  return user,system
+ end
+ return user,system
 end
 function setters.show(t)
-  local list=setters.list(t)
-  t.report()
-  for k=1,#list do
-    local name=list[k]
-    local functions=t.data[name]
-    if functions then
-      local value=functions.value
-      local default=functions.default
-      local modules=#functions
-      if default==nil then
-        default="unset"
-      elseif type(default)=="table" then
-        default=concat(default,"|")
-      else
-        default=tostring(default)
-      end
-      if value==nil then
-        value="unset"
-      elseif type(value)=="table" then
-        value=concat(value,"|")
-      else
-        value=tostring(value)
-      end
-      t.report(name)
-      t.report("    modules : %i",modules)
-      t.report("    default : %s",default)
-      t.report("    value   : %s",value)
-      t.report()
-    end
+ local list=setters.list(t)
+ t.report()
+ for k=1,#list do
+  local name=list[k]
+  local functions=t.data[name]
+  if functions then
+   local value=functions.value
+   local default=functions.default
+   local modules=#functions
+   if default==nil then
+    default="unset"
+   elseif type(default)=="table" then
+    default=concat(default,"|")
+   else
+    default=tostring(default)
+   end
+   if value==nil then
+    value="unset"
+   elseif type(value)=="table" then
+    value=concat(value,"|")
+   else
+    value=tostring(value)
+   end
+   t.report(name)
+   t.report("    modules : %i",modules)
+   t.report("    default : %s",default)
+   t.report("    value   : %s",value)
+   t.report()
   end
+ end
 end
 local enable,disable,register,list,show=setters.enable,setters.disable,setters.register,setters.list,setters.show
 function setters.report(setter,...)
-  print(format("%-15s : %s\n",setter.name,format(...)))
+ print(format("%-15s : %s\n",setter.name,format(...)))
 end
 local function default(setter,name)
-  local d=setter.data[name]
-  return d and d.default
+ local d=setter.data[name]
+ return d and d.default
 end
 local function value(setter,name)
-  local d=setter.data[name]
-  return d and (d.value or d.default)
+ local d=setter.data[name]
+ return d and (d.value or d.default)
 end
 function setters.new(name) 
-  local setter 
-  setter={
-    data=allocate(),
-    name=name,
-    report=function(...) setters.report (setter,...) end,
-    enable=function(...)     enable (setter,...) end,
-    disable=function(...)     disable (setter,...) end,
-    reset=function(...)     reset  (setter,...) end,
-    register=function(...)     register(setter,...) end,
-    list=function(...)     list  (setter,...) end,
-    show=function(...)     show  (setter,...) end,
-    default=function(...) return default (setter,...) end,
-    value=function(...) return value  (setter,...) end,
-  }
-  data[name]=setter
-  return setter
+ local setter 
+ setter={
+  data=allocate(),
+  name=name,
+  report=function(...) setters.report  (setter,...) end,
+  enable=function(...)   enable  (setter,...) end,
+  disable=function(...)   disable (setter,...) end,
+  reset=function(...)   reset   (setter,...) end,
+  register=function(...)   register(setter,...) end,
+  list=function(...)   list (setter,...) end,
+  show=function(...)   show (setter,...) end,
+  default=function(...)  return default (setter,...) end,
+  value=function(...)  return value   (setter,...) end,
+ }
+ data[name]=setter
+ return setter
 end
 trackers=setters.new("trackers")
 directives=setters.new("directives")
 experiments=setters.new("experiments")
-local t_enable,t_disable=trackers  .enable,trackers  .disable
+local t_enable,t_disable=trackers   .enable,trackers   .disable
 local d_enable,d_disable=directives .enable,directives .disable
 local e_enable,e_disable=experiments.enable,experiments.disable
-local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end)
-local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end)
+local trace_directives=false local trace_directives=false  trackers.register("system.directives",function(v) trace_directives=v end)
+local trace_experiments=false local trace_experiments=false  trackers.register("system.experiments",function(v) trace_experiments=v end)
 function directives.enable(...)
-  if trace_directives then
-    directives.report("enabling: % t",{...})
-  end
-  d_enable(...)
+ if trace_directives then
+  directives.report("enabling: % t",{...})
+ end
+ d_enable(...)
 end
 function directives.disable(...)
-  if trace_directives then
-    directives.report("disabling: % t",{...})
-  end
-  d_disable(...)
+ if trace_directives then
+  directives.report("disabling: % t",{...})
+ end
+ d_disable(...)
 end
 function experiments.enable(...)
-  if trace_experiments then
-    experiments.report("enabling: % t",{...})
-  end
-  e_enable(...)
+ if trace_experiments then
+  experiments.report("enabling: % t",{...})
+ end
+ e_enable(...)
 end
 function experiments.disable(...)
-  if trace_experiments then
-    experiments.report("disabling: % t",{...})
-  end
-  e_disable(...)
+ if trace_experiments then
+  experiments.report("disabling: % t",{...})
+ end
+ e_disable(...)
 end
 directives.register("system.nostatistics",function(v)
-  if statistics then
-    statistics.enable=not v
-  else
-  end
+ if statistics then
+  statistics.enable=not v
+ else
+ end
 end)
 directives.register("system.nolibraries",function(v)
-  if libraries then
-    libraries=nil 
-  else
-  end
+ if libraries then
+  libraries=nil 
+ else
+ end
 end)
 if environment then
-  local engineflags=environment.engineflags
-  if engineflags then
-    local list=engineflags["c:trackers"] or engineflags["trackers"]
-    if type(list)=="string" then
-      setters.initialize("commandline flags","trackers",settings_to_hash(list))
-    end
-    local list=engineflags["c:directives"] or engineflags["directives"]
-    if type(list)=="string" then
-      setters.initialize("commandline flags","directives",settings_to_hash(list))
-    end
+ local engineflags=environment.engineflags
+ if engineflags then
+  local list=engineflags["c:trackers"] or engineflags["trackers"]
+  if type(list)=="string" then
+   setters.initialize("commandline flags","trackers",settings_to_hash(list))
   end
+  local list=engineflags["c:directives"] or engineflags["directives"]
+  if type(list)=="string" then
+   setters.initialize("commandline flags","directives",settings_to_hash(list))
+  end
+ end
 end
 if texconfig then
-  local function set(k,v)
-    v=tonumber(v)
-    if v then
-      texconfig[k]=v
-    end
+ local function set(k,v)
+  v=tonumber(v)
+  if v then
+   texconfig[k]=v
   end
-  directives.register("luatex.expanddepth",function(v) set("expand_depth",v)  end)
-  directives.register("luatex.hashextra",function(v) set("hash_extra",v)   end)
-  directives.register("luatex.nestsize",function(v) set("nest_size",v)   end)
-  directives.register("luatex.maxinopen",function(v) set("max_in_open",v)  end)
-  directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end)
-  directives.register("luatex.maxstrings",function(v) set("max_strings",v)  end)
-  directives.register("luatex.paramsize",function(v) set("param_size",v)   end)
-  directives.register("luatex.savesize",function(v) set("save_size",v)   end)
-  directives.register("luatex.stacksize",function(v) set("stack_size",v)   end)
+ end
+ directives.register("luatex.expanddepth",function(v) set("expand_depth",v)   end)
+ directives.register("luatex.hashextra",function(v) set("hash_extra",v)  end)
+ directives.register("luatex.nestsize",function(v) set("nest_size",v)   end)
+ directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end)
+ directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end)
+ directives.register("luatex.maxstrings",function(v) set("max_strings",v) end)
+ directives.register("luatex.paramsize",function(v) set("param_size",v)  end)
+ directives.register("luatex.savesize",function(v) set("save_size",v)   end)
+ directives.register("luatex.stacksize",function(v) set("stack_size",v)  end)
 end
+local data=table.setmetatableindex("table")
+updaters={
+ register=function(what,f)
+  local d=data[what]
+  d[#d+1]=f
+ end,
+ apply=function(what,...)
+  local d=data[what]
+  for i=1,#d do
+   d[i](...)
+  end
+ end,
+}
 
 
 end -- of closure
@@ -9274,14 +12678,14 @@
 
 package.loaded["trac-log"] = package.loaded["trac-log"] or true
 
--- original size: 32922, stripped down to: 23011
+-- original size: 32608, stripped down to: 20925
 
 if not modules then modules={} end modules ['trac-log']={
-  version=1.001,
-  comment="companion to trac-log.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local next,type,select,print=next,type,select,print
 local format,gmatch,find=string.format,string.gmatch,string.find
@@ -9292,7 +12696,7 @@
 local openfile=io.open
 local runningtex=tex and (tex.jobname or tex.formatname)
 local write_nl=runningtex and texio and texio.write_nl or print
-local write=runningtex and texio and texio.write  or io.write
+local write=runningtex and texio and texio.write or io.write
 local setmetatableindex=table.setmetatableindex
 local formatters=string.formatters
 local settings_to_hash=utilities.parsers.settings_to_hash
@@ -9308,12 +12712,12 @@
 wiki     : http://contextgarden.net
 ]]
 formatters.add (
-  formatters,"unichr",
-  [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+ formatters,"unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
 )
 formatters.add (
-  formatters,"chruni",
-  [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+ formatters,"chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
 )
 local function ignore() end
 setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
@@ -9320,392 +12724,392 @@
 local report,subreport,status,settarget,setformats,settranslations
 local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters,newline
 if runningtex then
-  if texio.setescape then
-    texio.setescape(0) 
+ if texio.setescape then
+  texio.setescape(0) 
+ end
+ if arg then
+  for k,v in next,arg do 
+   if v=="--ansi" or v=="--c:ansi" then
+    variant="ansi"
+    break
+   end
   end
-  if arg then
-    for k,v in next,arg do 
-      if v=="--ansi" or v=="--c:ansi" then
-        variant="ansi"
-        break
-      end
-    end
+ end
+ local function useluawrites()
+  local texio_write_nl=texio.write_nl
+  local texio_write=texio.write
+  local io_write=io.write
+  write_nl=function(target,...)
+   if not io_write then
+    io_write=io.write
+   end
+   if target=="term and log" then
+    texio_write_nl("log",...)
+    texio_write_nl("term","")
+    io_write(...)
+   elseif target=="log" then
+    texio_write_nl("log",...)
+   elseif target=="term" then
+    texio_write_nl("term","")
+    io_write(...)
+   elseif type(target)=="number" then
+    texio_write_nl(target,...) 
+   elseif target~="none" then
+    texio_write_nl("log",target,...)
+    texio_write_nl("term","")
+    io_write(target,...)
+   end
   end
-  local function useluawrites()
-    local texio_write_nl=texio.write_nl
-    local texio_write=texio.write
-    local io_write=io.write
-    write_nl=function(target,...)
-      if not io_write then
-        io_write=io.write
-      end
-      if target=="term and log" then
-        texio_write_nl("log",...)
-        texio_write_nl("term","")
-        io_write(...)
-      elseif target=="log" then
-        texio_write_nl("log",...)
-      elseif target=="term" then
-        texio_write_nl("term","")
-        io_write(...)
-      elseif type(target)=="number" then
-        texio_write_nl(target,...) 
-      elseif target~="none" then
-        texio_write_nl("log",target,...)
-        texio_write_nl("term","")
-        io_write(target,...)
-      end
-    end
-    write=function(target,...)
-      if not io_write then
-        io_write=io.write
-      end
-      if target=="term and log" then
-        texio_write("log",...)
-        io_write(...)
-      elseif target=="log" then
-        texio_write("log",...)
-      elseif target=="term" then
-        io_write(...)
-      elseif type(target)=="number" then
-        texio_write(target,...) 
-      elseif target~="none" then
-        texio_write("log",target,...)
-        io_write(target,...)
-      end
-    end
-    texio.write=write
-    texio.write_nl=write_nl
-    useluawrites=ignore
+  write=function(target,...)
+   if not io_write then
+    io_write=io.write
+   end
+   if target=="term and log" then
+    texio_write("log",...)
+    io_write(...)
+   elseif target=="log" then
+    texio_write("log",...)
+   elseif target=="term" then
+    io_write(...)
+   elseif type(target)=="number" then
+    texio_write(target,...) 
+   elseif target~="none" then
+    texio_write("log",target,...)
+    io_write(target,...)
+   end
   end
-  local whereto="both"
-  local target=nil
-  local targets=nil
-  local formats=table.setmetatableindex("self")
-  local translations=table.setmetatableindex("self")
-  local report_yes,subreport_yes,direct_yes,subdirect_yes,status_yes
-  local report_nop,subreport_nop,direct_nop,subdirect_nop,status_nop
-  local variants={
-    default={
-      formats={
-        report_yes=formatters["%-15s > %s\n"],
-        report_nop=formatters["%-15s >\n"],
-        direct_yes=formatters["%-15s > %s"],
-        direct_nop=formatters["%-15s >"],
-        subreport_yes=formatters["%-15s > %s > %s\n"],
-        subreport_nop=formatters["%-15s > %s >\n"],
-        subdirect_yes=formatters["%-15s > %s > %s"],
-        subdirect_nop=formatters["%-15s > %s >"],
-        status_yes=formatters["%-15s : %s\n"],
-        status_nop=formatters["%-15s :\n"],
-      },
-      targets={
-        logfile="log",
-        log="log",
-        file="log",
-        console="term",
-        terminal="term",
-        both="term and log",
-      },
-    },
-    ansi={
-      formats={
-        report_yes=formatters["%-15s > %s\n"],
-        report_nop=formatters["%-15s >\n"],
-        direct_yes=formatters["%-15s > %s"],
-        direct_nop=formatters["%-15s >"],
-        subreport_yes=formatters["%-15s > %s > %s\n"],
-        subreport_nop=formatters["%-15s > %s >\n"],
-        subdirect_yes=formatters["%-15s > %s > %s"],
-        subdirect_nop=formatters["%-15s > %s >"],
-        status_yes=formatters["%-15s : %s\n"],
-        status_nop=formatters["%-15s :\n"],
-      },
-      targets={
-        logfile="none",
-        log="none",
-        file="none",
-        console="term",
-        terminal="term",
-        both="term",
-      },
-    }
+  texio.write=write
+  texio.write_nl=write_nl
+  useluawrites=ignore
+ end
+ local whereto="both"
+ local target=nil
+ local targets=nil
+ local formats=table.setmetatableindex("self")
+ local translations=table.setmetatableindex("self")
+ local report_yes,subreport_yes,direct_yes,subdirect_yes,status_yes
+ local report_nop,subreport_nop,direct_nop,subdirect_nop,status_nop
+ local variants={
+  default={
+   formats={
+    report_yes=formatters["%-15s > %s\n"],
+    report_nop=formatters["%-15s >\n"],
+    direct_yes=formatters["%-15s > %s"],
+    direct_nop=formatters["%-15s >"],
+    subreport_yes=formatters["%-15s > %s > %s\n"],
+    subreport_nop=formatters["%-15s > %s >\n"],
+    subdirect_yes=formatters["%-15s > %s > %s"],
+    subdirect_nop=formatters["%-15s > %s >"],
+    status_yes=formatters["%-15s : %s\n"],
+    status_nop=formatters["%-15s :\n"],
+   },
+   targets={
+    logfile="log",
+    log="log",
+    file="log",
+    console="term",
+    terminal="term",
+    both="term and log",
+   },
+  },
+  ansi={
+   formats={
+    report_yes=formatters["%-15s > %s\n"],
+    report_nop=formatters["%-15s >\n"],
+    direct_yes=formatters["%-15s > %s"],
+    direct_nop=formatters["%-15s >"],
+    subreport_yes=formatters["%-15s > %s > %s\n"],
+    subreport_nop=formatters["%-15s > %s >\n"],
+    subdirect_yes=formatters["%-15s > %s > %s"],
+    subdirect_nop=formatters["%-15s > %s >"],
+    status_yes=formatters["%-15s : %s\n"],
+    status_nop=formatters["%-15s :\n"],
+   },
+   targets={
+    logfile="none",
+    log="none",
+    file="none",
+    console="term",
+    terminal="term",
+    both="term",
+   },
   }
-  logs.flush=io.flush
-  writer=function(...)
-    write_nl(target,...)
+ }
+ logs.flush=io.flush
+ writer=function(...)
+  write_nl(target,...)
+ end
+ newline=function()
+  write_nl(target,"\n")
+ end
+ report=function(a,b,c,...)
+  if c~=nil then
+   write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
+  elseif b then
+   write_nl(target,report_yes(translations[a],formats[b]))
+  elseif a then
+   write_nl(target,report_nop(translations[a]))
+  else
+   write_nl(target,"\n")
   end
-  newline=function()
-    write_nl(target,"\n")
+ end
+ direct=function(a,b,c,...)
+  if c~=nil then
+   return direct_yes(translations[a],formatters[formats[b]](c,...))
+  elseif b then
+   return direct_yes(translations[a],formats[b])
+  elseif a then
+   return direct_nop(translations[a])
+  else
+   return ""
   end
-  report=function(a,b,c,...)
-    if c~=nil then
-      write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
-    elseif b then
-      write_nl(target,report_yes(translations[a],formats[b]))
-    elseif a then
-      write_nl(target,report_nop(translations[a]))
-    else
-      write_nl(target,"\n")
-    end
+ end
+ subreport=function(a,s,b,c,...)
+  if c~=nil then
+   write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
+  elseif b then
+   write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
+  elseif a then
+   write_nl(target,subreport_nop(translations[a],translations[s]))
+  else
+   write_nl(target,"\n")
   end
-  direct=function(a,b,c,...)
-    if c~=nil then
-      return direct_yes(translations[a],formatters[formats[b]](c,...))
-    elseif b then
-      return direct_yes(translations[a],formats[b])
-    elseif a then
-      return direct_nop(translations[a])
-    else
-      return ""
-    end
+ end
+ subdirect=function(a,s,b,c,...)
+  if c~=nil then
+   return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
+  elseif b then
+   return subdirect_yes(translations[a],translations[s],formats[b])
+  elseif a then
+   return subdirect_nop(translations[a],translations[s])
+  else
+   return ""
   end
-  subreport=function(a,s,b,c,...)
-    if c~=nil then
-      write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
-    elseif b then
-      write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
-    elseif a then
-      write_nl(target,subreport_nop(translations[a],translations[s]))
-    else
-      write_nl(target,"\n")
-    end
+ end
+ status=function(a,b,c,...)
+  if c~=nil then
+   write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
+  elseif b then
+   write_nl(target,status_yes(translations[a],formats[b]))
+  elseif a then
+   write_nl(target,status_nop(translations[a]))
+  else
+   write_nl(target,"\n")
   end
-  subdirect=function(a,s,b,c,...)
-    if c~=nil then
-      return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
-    elseif b then
-      return subdirect_yes(translations[a],translations[s],formats[b])
-    elseif a then
-      return subdirect_nop(translations[a],translations[s])
-    else
-      return ""
-    end
+ end
+ settarget=function(askedwhereto)
+  whereto=askedwhereto or whereto or "both"
+  target=targets[whereto]
+  if not target then
+   whereto="both"
+   target=targets[whereto]
   end
-  status=function(a,b,c,...)
-    if c~=nil then
-      write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
-    elseif b then
-      write_nl(target,status_yes(translations[a],formats[b]))
-    elseif a then
-      write_nl(target,status_nop(translations[a]))
-    else
-      write_nl(target,"\n")
-    end
+  if target=="term" or target=="term and log" then
+   logs.flush=io.flush
+  else
+   logs.flush=ignore
   end
-  settarget=function(askedwhereto)
-    whereto=askedwhereto or whereto or "both"
-    target=targets[whereto]
-    if not target then
-      whereto="both"
-      target=targets[whereto]
-    end
-    if target=="term" or target=="term and log" then
-      logs.flush=io.flush
-    else
-      logs.flush=ignore
-    end
+ end
+ local stack={}
+ pushtarget=function(newtarget)
+  insert(stack,target)
+  settarget(newtarget)
+ end
+ poptarget=function()
+  if #stack>0 then
+   settarget(remove(stack))
   end
-  local stack={}
-  pushtarget=function(newtarget)
-    insert(stack,target)
-    settarget(newtarget)
+ end
+ setformats=function(f)
+  formats=f
+ end
+ settranslations=function(t)
+  translations=t
+ end
+ setprocessor=function(f)
+  local writeline=write_nl
+  write_nl=function(target,...)
+   writeline(target,f(...))
   end
-  poptarget=function()
-    if #stack>0 then
-      settarget(remove(stack))
-    end
+ end
+ setformatters=function(specification)
+  local t=nil
+  local f=nil
+  local d=variants.default
+  if not specification then
+  elseif type(specification)=="table" then
+   t=specification.targets
+   f=specification.formats or specification
+  else
+   local v=variants[specification]
+   if v then
+    t=v.targets
+    f=v.formats
+    variant=specification
+   end
   end
-  setformats=function(f)
-    formats=f
+  targets=t or d.targets
+  target=targets[whereto] or target
+  if f then
+   d=d.formats
+  else
+   f=d.formats
+   d=f
   end
-  settranslations=function(t)
-    translations=t
+  setmetatableindex(f,d)
+  report_yes=f.report_yes
+  report_nop=f.report_nop
+  subreport_yes=f.subreport_yes
+  subreport_nop=f.subreport_nop
+  direct_yes=f.direct_yes
+  direct_nop=f.direct_nop
+  subdirect_yes=f.subdirect_yes
+  subdirect_nop=f.subdirect_nop
+  status_yes=f.status_yes
+  status_nop=f.status_nop
+  if variant=="ansi" then
+   useluawrites() 
   end
-  setprocessor=function(f)
-    local writeline=write_nl
-    write_nl=function(target,...)
-      writeline(target,f(...))
-    end
+  settarget(whereto)
+ end
+ setformatters(variant)
+ setlogfile=ignore
+ settimedlog=ignore
+else
+ local report_yes,subreport_yes,status_yes
+ local report_nop,subreport_nop,status_nop
+ local variants={
+  default={
+   formats={
+    report_yes=formatters["%-15s | %s"],
+    report_nop=formatters["%-15s |"],
+    subreport_yes=formatters["%-15s | %s | %s"],
+    subreport_nop=formatters["%-15s | %s |"],
+    status_yes=formatters["%-15s : %s\n"],
+    status_nop=formatters["%-15s :\n"],
+   },
+  },
+  ansi={
+   formats={
+    report_yes=formatters["%-15s | %s"],
+    report_nop=formatters["%-15s |"],
+    subreport_yes=formatters["%-15s | %s | %s"],
+    subreport_nop=formatters["%-15s | %s |"],
+    status_yes=formatters["%-15s : %s\n"],
+    status_nop=formatters["%-15s :\n"],
+   },
+  },
+ }
+ logs.flush=ignore
+ writer=function(s)
+  write_nl(s)
+ end
+ newline=function()
+  write_nl("\n")
+ end
+ report=function(a,b,c,...)
+  if c then
+   write_nl(report_yes(a,formatters[b](c,...)))
+  elseif b then
+   write_nl(report_yes(a,b))
+  elseif a then
+   write_nl(report_nop(a))
+  else
+   write_nl("")
   end
-  setformatters=function(specification)
-    local t=nil
-    local f=nil
-    local d=variants.default
-    if not specification then
-    elseif type(specification)=="table" then
-      t=specification.targets
-      f=specification.formats or specification
-    else
-      local v=variants[specification]
-      if v then
-        t=v.targets
-        f=v.formats
-        variant=specification
-      end
-    end
-    targets=t or d.targets
-    target=targets[whereto] or target
-    if f then
-      d=d.formats
-    else
-      f=d.formats
-      d=f
-    end
-    setmetatableindex(f,d)
-    report_yes=f.report_yes
-    report_nop=f.report_nop
-    subreport_yes=f.subreport_yes
-    subreport_nop=f.subreport_nop
-    direct_yes=f.direct_yes
-    direct_nop=f.direct_nop
-    subdirect_yes=f.subdirect_yes
-    subdirect_nop=f.subdirect_nop
-    status_yes=f.status_yes
-    status_nop=f.status_nop
-    if variant=="ansi" then
-      useluawrites() 
-    end
-    settarget(whereto)
+ end
+ subreport=function(a,sub,b,c,...)
+  if c then
+   write_nl(subreport_yes(a,sub,formatters[b](c,...)))
+  elseif b then
+   write_nl(subreport_yes(a,sub,b))
+  elseif a then
+   write_nl(subreport_nop(a,sub))
+  else
+   write_nl("")
   end
-  setformatters(variant)
-  setlogfile=ignore
-  settimedlog=ignore
-else
-  local report_yes,subreport_yes,status_yes
-  local report_nop,subreport_nop,status_nop
-  local variants={
-    default={
-      formats={
-        report_yes=formatters["%-15s | %s"],
-        report_nop=formatters["%-15s |"],
-        subreport_yes=formatters["%-15s | %s | %s"],
-        subreport_nop=formatters["%-15s | %s |"],
-        status_yes=formatters["%-15s : %s\n"],
-        status_nop=formatters["%-15s :\n"],
-      },
-    },
-    ansi={
-      formats={
-        report_yes=formatters["%-15s | %s"],
-        report_nop=formatters["%-15s |"],
-        subreport_yes=formatters["%-15s | %s | %s"],
-        subreport_nop=formatters["%-15s | %s |"],
-        status_yes=formatters["%-15s : %s\n"],
-        status_nop=formatters["%-15s :\n"],
-      },
-    },
-  }
-  logs.flush=ignore
-  writer=function(s)
-    write_nl(s)
+ end
+ status=function(a,b,c,...) 
+  if c then
+   write_nl(status_yes(a,formatters[b](c,...)))
+  elseif b then
+   write_nl(status_yes(a,b)) 
+  elseif a then
+   write_nl(status_nop(a))
+  else
+   write_nl("\n")
   end
-  newline=function()
-    write_nl("\n")
+ end
+ direct=ignore
+ subdirect=ignore
+ settarget=ignore
+ pushtarget=ignore
+ poptarget=ignore
+ setformats=ignore
+ settranslations=ignore
+ setprocessor=function(f)
+  local writeline=write_nl
+  write_nl=function(s)
+   writeline(f(s))
   end
-  report=function(a,b,c,...)
-    if c then
-      write_nl(report_yes(a,formatters[b](c,...)))
-    elseif b then
-      write_nl(report_yes(a,b))
-    elseif a then
-      write_nl(report_nop(a))
-    else
-      write_nl("")
+ end
+ setformatters=function(specification)
+  local f=nil
+  local d=variants.default
+  if specification then
+   if type(specification)=="table" then
+    f=specification.formats or specification
+   else
+    local v=variants[specification]
+    if v then
+     f=v.formats
     end
+   end
   end
-  subreport=function(a,sub,b,c,...)
-    if c then
-      write_nl(subreport_yes(a,sub,formatters[b](c,...)))
-    elseif b then
-      write_nl(subreport_yes(a,sub,b))
-    elseif a then
-      write_nl(subreport_nop(a,sub))
-    else
-      write_nl("")
-    end
+  if f then
+   d=d.formats
+  else
+   f=d.formats
+   d=f
   end
-  status=function(a,b,c,...) 
-    if c then
-      write_nl(status_yes(a,formatters[b](c,...)))
-    elseif b then
-      write_nl(status_yes(a,b)) 
-    elseif a then
-      write_nl(status_nop(a))
-    else
-      write_nl("\n")
+  setmetatableindex(f,d)
+  report_yes=f.report_yes
+  report_nop=f.report_nop
+  subreport_yes=f.subreport_yes
+  subreport_nop=f.subreport_nop
+  status_yes=f.status_yes
+  status_nop=f.status_nop
+ end
+ setformatters(variant)
+ setlogfile=function(name,keepopen)
+  if name and name~="" then
+   local localtime=os.localtime
+   local writeline=write_nl
+   if keepopen then
+    local f=io.open(name,"ab")
+    write_nl=function(s)
+     writeline(s)
+     f:write(localtime()," | ",s,"\n")
     end
-  end
-  direct=ignore
-  subdirect=ignore
-  settarget=ignore
-  pushtarget=ignore
-  poptarget=ignore
-  setformats=ignore
-  settranslations=ignore
-  setprocessor=function(f)
-    local writeline=write_nl
+   else
     write_nl=function(s)
-      writeline(f(s))
+     writeline(s)
+     local f=io.open(name,"ab")
+     f:write(localtime()," | ",s,"\n")
+     f:close()
     end
+   end
   end
-  setformatters=function(specification)
-    local f=nil
-    local d=variants.default
-    if specification then
-      if type(specification)=="table" then
-        f=specification.formats or specification
-      else
-        local v=variants[specification]
-        if v then
-          f=v.formats
-        end
-      end
-    end
-    if f then
-      d=d.formats
-    else
-      f=d.formats
-      d=f
-    end
-    setmetatableindex(f,d)
-    report_yes=f.report_yes
-    report_nop=f.report_nop
-    subreport_yes=f.subreport_yes
-    subreport_nop=f.subreport_nop
-    status_yes=f.status_yes
-    status_nop=f.status_nop
+  setlogfile=ignore
+ end
+ settimedlog=function()
+  local localtime=os.localtime
+  local writeline=write_nl
+  write_nl=function(s)
+   writeline(localtime().." | "..s)
   end
-  setformatters(variant)
-  setlogfile=function(name,keepopen)
-    if name and name~="" then
-      local localtime=os.localtime
-      local writeline=write_nl
-      if keepopen then
-        local f=io.open(name,"ab")
-        write_nl=function(s)
-          writeline(s)
-          f:write(localtime()," | ",s,"\n")
-        end
-      else
-        write_nl=function(s)
-          writeline(s)
-          local f=io.open(name,"ab")
-          f:write(localtime()," | ",s,"\n")
-          f:close()
-        end
-      end
-    end
-    setlogfile=ignore
-  end
-  settimedlog=function()
-    local localtime=os.localtime
-    local writeline=write_nl
-    write_nl=function(s)
-      writeline(localtime().." | "..s)
-    end
-    settimedlog=ignore
-  end
+  settimedlog=ignore
+ end
 end
 logs.report=report
 logs.subreport=subreport
@@ -9727,198 +13131,186 @@
 local states=nil
 local force=false
 function logs.reporter(category,subcategory)
-  local logger=data[category]
-  if not logger then
-    local state=states==true
-    if not state and type(states)=="table" then
-      for c,_ in next,states do
-        if find(category,c) then
-          state=true
-          break
-        end
-      end
+ local logger=data[category]
+ if not logger then
+  local state=states==true
+  if not state and type(states)=="table" then
+   for c,_ in next,states do
+    if find(category,c) then
+     state=true
+     break
     end
-    logger={
-      reporters={},
-      state=state,
-    }
-    data[category]=logger
+   end
   end
-  local reporter=logger.reporters[subcategory or "default"]
-  if not reporter then
-    if subcategory then
-      reporter=function(...)
-        if force or not logger.state then
-          subreport(category,subcategory,...)
-        end
-      end
-      logger.reporters[subcategory]=reporter
-    else
-      local tag=category
-      reporter=function(...)
-        if force or not logger.state then
-          report(category,...)
-        end
-      end
-      logger.reporters.default=reporter
+  logger={
+   reporters={},
+   state=state,
+  }
+  data[category]=logger
+ end
+ local reporter=logger.reporters[subcategory or "default"]
+ if not reporter then
+  if subcategory then
+   reporter=function(...)
+    if force or not logger.state then
+     subreport(category,subcategory,...)
     end
+   end
+   logger.reporters[subcategory]=reporter
+  else
+   local tag=category
+   reporter=function(...)
+    if force or not logger.state then
+     report(category,...)
+    end
+   end
+   logger.reporters.default=reporter
   end
-  return reporter
+ end
+ return reporter
 end
 logs.new=logs.reporter
 local ctxreport=logs.writer
 function logs.setmessenger(m)
-  ctxreport=m
+ ctxreport=m
 end
 function logs.messenger(category,subcategory)
-  if subcategory then
-    return function(...)
-      ctxreport(subdirect(category,subcategory,...))
-    end
-  else
-    return function(...)
-      ctxreport(direct(category,...))
-    end
+ if subcategory then
+  return function(...)
+   ctxreport(subdirect(category,subcategory,...))
   end
+ else
+  return function(...)
+   ctxreport(direct(category,...))
+  end
+ end
 end
 local function setblocked(category,value) 
-  if category==true or category=="all" then
-    category,value="*",true
-  elseif category==false then
-    category,value="*",false
-  elseif value==nil then
-    value=true
+ if category==true or category=="all" then
+  category,value="*",true
+ elseif category==false then
+  category,value="*",false
+ elseif value==nil then
+  value=true
+ end
+ if category=="*" then
+  states=value
+  for k,v in next,data do
+   v.state=value
   end
-  if category=="*" then
-    states=value
+ else
+  alllocked=false
+  states=settings_to_hash(category,type(states)=="table" and states or nil)
+  for c in next,states do
+   local v=data[c]
+   if v then
+    v.state=value
+   else
+    c=topattern(c,true,true)
     for k,v in next,data do
+     if find(k,c) then
       v.state=value
+     end
     end
-  else
-    alllocked=false
-    states=settings_to_hash(category,type(states)=="table" and states or nil)
-    for c in next,states do
-      local v=data[c]
-      if v then
-        v.state=value
-      else
-        c=topattern(c,true,true)
-        for k,v in next,data do
-          if find(k,c) then
-            v.state=value
-          end
-        end
-      end
-    end
+   end
   end
+ end
 end
 function logs.disable(category,value)
-  setblocked(category,value==nil and true or value)
+ setblocked(category,value==nil and true or value)
 end
 function logs.enable(category)
-  setblocked(category,false)
+ setblocked(category,false)
 end
 function logs.categories()
-  return sortedkeys(data)
+ return sortedkeys(data)
 end
 function logs.show()
-  local n,c,s,max=0,0,0,0
-  for category,v in table.sortedpairs(data) do
-    n=n+1
-    local state=v.state
-    local reporters=v.reporters
-    local nc=#category
-    if nc>c then
-      c=nc
-    end
-    for subcategory,_ in next,reporters do
-      local ns=#subcategory
-      if ns>c then
-        s=ns
-      end
-      local m=nc+ns
-      if m>max then
-        max=m
-      end
-    end
-    local subcategories=concat(sortedkeys(reporters),", ")
-    if state==true then
-      state="disabled"
-    elseif state==false then
-      state="enabled"
-    else
-      state="unknown"
-    end
-    report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ local n,c,s,max=0,0,0,0
+ for category,v in table.sortedpairs(data) do
+  n=n+1
+  local state=v.state
+  local reporters=v.reporters
+  local nc=#category
+  if nc>c then
+   c=nc
   end
-  report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
+  for subcategory,_ in next,reporters do
+   local ns=#subcategory
+   if ns>c then
+    s=ns
+   end
+   local m=nc+ns
+   if m>max then
+    max=m
+   end
+  end
+  local subcategories=concat(sortedkeys(reporters),", ")
+  if state==true then
+   state="disabled"
+  elseif state==false then
+   state="enabled"
+  else
+   state="unknown"
+  end
+  report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
 end
 local delayed_reporters={}
 setmetatableindex(delayed_reporters,function(t,k)
-  local v=logs.reporter(k.name)
-  t[k]=v
-  return v
+ local v=logs.reporter(k.name)
+ t[k]=v
+ return v
 end)
 function utilities.setters.report(setter,...)
-  delayed_reporters[setter](...)
+ delayed_reporters[setter](...)
 end
 directives.register("logs.blocked",function(v)
-  setblocked(v,true)
+ setblocked(v,true)
 end)
 directives.register("logs.target",function(v)
-  settarget(v)
+ settarget(v)
 end)
 if tex then
-  local report=logs.reporter("pages") 
-  local texgetcount=tex and tex.getcount
-  local real,user,sub
-  function logs.start_page_number()
-    real=texgetcount("realpageno")
-    user=texgetcount("userpageno")
-    sub=texgetcount("subpageno")
+ local report=logs.reporter("pages") 
+ local texgetcount=tex and tex.getcount
+ local real,user,sub=0,0,0
+ function logs.start_page_number()
+  real=texgetcount("realpageno")
+  user=texgetcount("userpageno")
+  sub=texgetcount("subpageno")
+ end
+ local timing=false
+ local lasttime=nil
+ trackers.register("pages.timing",function(v) 
+  timing=""
+ end)
+ function logs.stop_page_number() 
+  if timing then
+   local elapsed=statistics.currenttime(statistics)
+   local average,page
+   if not lasttime or real<2 then
+    average=elapsed
+    page=elapsed
+   else
+    average=elapsed/(real-1)
+    page=elapsed-lasttime
+   end
+   lasttime=elapsed
+   timing=formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
   end
-  local timing=false
-  local starttime=nil
-  local lasttime=nil
-  trackers.register("pages.timing",function(v) 
-    starttime=os.clock() 
-    timing=true
-  end)
-  function logs.stop_page_number() 
-    if timing then
-      local elapsed,average
-      local stoptime=os.clock()
-      if not lasttime or real<2 then
-        elapsed=stoptime
-        average=stoptime
-        starttime=stoptime
-      else
-        elapsed=stoptime-lasttime
-        average=(stoptime-starttime)/(real-1)
-      end
-      lasttime=stoptime
-      if real<=0 then
-        report("flushing page, time %0.04f / %0.04f",elapsed,average)
-      elseif user<=0 then
-        report("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
-      elseif sub<=0 then
-        report("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
-      else
-        report("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
-      end
-    else
-      if real<=0 then
-        report("flushing page")
-      elseif user<=0 then
-        report("flushing realpage %s",real)
-      elseif sub<=0 then
-        report("flushing realpage %s, userpage %s",real,user)
-      else
-        report("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
-      end
-    end
-    logs.flush()
+  if real<=0 then
+   report("flushing page%s",timing)
+  elseif user<=0 then
+   report("flushing realpage %s%s",real,timing)
+  elseif sub<=0 then
+   report("flushing realpage %s, userpage %s%s",real,user,timing)
+  else
+   report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
   end
+  logs.flush()
+ end
 end
 local nesting=0
 local verbose=false
@@ -9942,53 +13334,53 @@
 local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
 local p_newline=lpeg.patterns.newline
 local linewise=(
-  Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t)  t.report() end+p_newline
+ Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t)   t.report()  end+p_newline
 )^1
 local function reportlines(t,str)
-  if str then
-    lpegmatch(linewise,str,1,t)
-  end
+ if str then
+  lpegmatch(linewise,str,1,t)
+ end
 end
 local function reportbanner(t)
-  local banner=t.banner
-  if banner then
-    t.report(banner)
-    t.report()
-  end
+ local banner=t.banner
+ if banner then
+  t.report(banner)
+  t.report()
+ end
 end
 local function reportversion(t)
-  local banner=t.banner
-  if banner then
-    t.report(banner)
-  end
+ local banner=t.banner
+ if banner then
+  t.report(banner)
+ end
 end
 local function reporthelp(t,...)
-  local helpinfo=t.helpinfo
-  if type(helpinfo)=="string" then
-    reportlines(t,helpinfo)
-  elseif type(helpinfo)=="table" then
-    for i=1,select("#",...) do
-      reportlines(t,t.helpinfo[select(i,...)])
-      if i<n then
-        t.report()
-      end
-    end
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="string" then
+  reportlines(t,helpinfo)
+ elseif type(helpinfo)=="table" then
+  for i=1,select("#",...) do
+   reportlines(t,t.helpinfo[select(i,...)])
+   if i<n then
+    t.report()
+   end
   end
+ end
 end
 local function reportinfo(t)
-  t.report()
-  reportlines(t,t.moreinfo)
+ t.report()
+ reportlines(t,t.moreinfo)
 end
 local function reportexport(t,method)
-  report(t.helpinfo)
+ report(t.helpinfo)
 end
 local reporters={
-  lines=reportlines,
-  banner=reportbanner,
-  version=reportversion,
-  help=reporthelp,
-  info=reportinfo,
-  export=reportexport,
+ lines=reportlines,
+ banner=reportbanner,
+ version=reportversion,
+ help=reporthelp,
+ info=reportinfo,
+ export=reportexport,
 }
 local exporters={
 }
@@ -9995,169 +13387,169 @@
 logs.reporters=reporters
 logs.exporters=exporters
 function logs.application(t)
-  t.name=t.name  or "unknown"
-  t.banner=t.banner
-  t.moreinfo=moreinfo
-  t.report=logs.reporter(t.name)
-  t.help=function(...)
-    reporters.banner(t)
-    reporters.help(t,...)
-    reporters.info(t)
-  end
-  t.export=function(...)
-    reporters.export(t,...)
-  end
-  t.identify=function()
-    reporters.banner(t)
-  end
-  t.version=function()
-    reporters.version(t)
-  end
-  return t
+ t.name=t.name   or "unknown"
+ t.banner=t.banner
+ t.moreinfo=moreinfo
+ t.report=logs.reporter(t.name)
+ t.help=function(...)
+  reporters.banner(t)
+  reporters.help(t,...)
+  reporters.info(t)
+ end
+ t.export=function(...)
+  reporters.export(t,...)
+ end
+ t.identify=function()
+  reporters.banner(t)
+ end
+ t.version=function()
+  reporters.version(t)
+ end
+ return t
 end
 local f_syslog=formatters["%s %s => %s => %s => %s\r"]
 function logs.system(whereto,process,jobname,category,fmt,arg,...)
-  local message=f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg==nil and fmt or format(fmt,arg,...))
-  for i=1,10 do
-    local f=openfile(whereto,"a") 
-    if f then
-      f:write(message)
-      f:close()
-      break
-    else
-      sleep(0.1)
-    end
+ local message=f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg==nil and fmt or format(fmt,arg,...))
+ for i=1,10 do
+  local f=openfile(whereto,"a") 
+  if f then
+   f:write(message)
+   f:close()
+   break
+  else
+   sleep(0.1)
   end
+ end
 end
 local report_system=logs.reporter("system","logs")
 function logs.obsolete(old,new)
-  local o=loadstring("return "..new)()
-  if type(o)=="function" then
-    return function(...)
-      report_system("function %a is obsolete, use %a",old,new)
-      loadstring(old.."="..new.." return "..old)()(...)
-    end
-  elseif type(o)=="table" then
-    local t,m={},{}
-    m.__index=function(t,k)
-      report_system("table %a is obsolete, use %a",old,new)
-      m.__index,m.__newindex=o,o
-      return o[k]
-    end
-    m.__newindex=function(t,k,v)
-      report_system("table %a is obsolete, use %a",old,new)
-      m.__index,m.__newindex=o,o
-      o[k]=v
-    end
-    if libraries then
-      libraries.obsolete[old]=t 
-    end
-    setmetatable(t,m)
-    return t
+ local o=loadstring("return "..new)()
+ if type(o)=="function" then
+  return function(...)
+   report_system("function %a is obsolete, use %a",old,new)
+   loadstring(old.."="..new.." return "..old)()(...)
   end
+ elseif type(o)=="table" then
+  local t,m={},{}
+  m.__index=function(t,k)
+   report_system("table %a is obsolete, use %a",old,new)
+   m.__index,m.__newindex=o,o
+   return o[k]
+  end
+  m.__newindex=function(t,k,v)
+   report_system("table %a is obsolete, use %a",old,new)
+   m.__index,m.__newindex=o,o
+   o[k]=v
+  end
+  if libraries then
+   libraries.obsolete[old]=t 
+  end
+  setmetatable(t,m)
+  return t
+ end
 end
 if utilities then
-  utilities.report=report_system
+ utilities.report=report_system
 end
 if tex and tex.error then
-  function logs.texerrormessage(...) 
-    tex.error(format(...),{})
-  end
+ function logs.texerrormessage(...) 
+  tex.error(format(...))
+ end
 else
-  function logs.texerrormessage(...)
-    print(format(...))
-  end
+ function logs.texerrormessage(...)
+  print(format(...))
+ end
 end
 io.stdout:setvbuf('no')
 io.stderr:setvbuf('no')
 if package.helpers.report then
-  package.helpers.report=logs.reporter("package loader") 
+ package.helpers.report=logs.reporter("package loader") 
 end
 if tex then
-  local finalactions={}
-  local fatalerrors={}
-  local possiblefatal={}
-  local loggingerrors=false
-  function logs.loggingerrors()
-    return loggingerrors
+ local finalactions={}
+ local fatalerrors={}
+ local possiblefatal={}
+ local loggingerrors=false
+ function logs.loggingerrors()
+  return loggingerrors
+ end
+ directives.register("logs.errors",function(v)
+  loggingerrors=v
+  if type(v)=="string" then
+   fatalerrors=settings_to_hash(v)
+  else
+   fatalerrors={}
   end
-  directives.register("logs.errors",function(v)
-    loggingerrors=v
-    if type(v)=="string" then
-      fatalerrors=settings_to_hash(v)
-    else
-      fatalerrors={}
-    end
-  end)
-  function logs.registerfinalactions(...)
-    insert(finalactions,...) 
+ end)
+ function logs.registerfinalactions(...)
+  insert(finalactions,...) 
+ end
+ local what=nil
+ local report=nil
+ local state=nil
+ local target=nil
+ local function startlogging(t,r,w,s)
+  target=t
+  state=force
+  force=true
+  report=type(r)=="function" and r or logs.reporter(r)
+  what=w
+  pushtarget(target)
+  newline()
+  if s then
+   report("start %s: %s",what,s)
+  else
+   report("start %s",what)
   end
-  local what=nil
-  local report=nil
-  local state=nil
-  local target=nil
-  local function startlogging(t,r,w,s)
-    target=t
-    state=force
-    force=true
-    report=type(r)=="function" and r or logs.reporter(r)
-    what=w
-    pushtarget(target)
-    newline()
-    if s then
-      report("start %s: %s",what,s)
-    else
-      report("start %s",what)
-    end
-    if target=="logfile" then
-      newline()
-    end
-    return report
+  if target=="logfile" then
+   newline()
   end
-  local function stoplogging()
-    if target=="logfile" then
-      newline()
-    end
-    report("stop %s",what)
-    if target=="logfile" then
-      newline()
-    end
-    poptarget()
-    state=oldstate
+  return report
+ end
+ local function stoplogging()
+  if target=="logfile" then
+   newline()
   end
-  function logs.startfilelogging(...)
-    return startlogging("logfile",...)
+  report("stop %s",what)
+  if target=="logfile" then
+   newline()
   end
-  logs.stopfilelogging=stoplogging
-  local done=false
-  function logs.starterrorlogging(r,w,...)
-    if not done then
-      pushtarget("terminal")
-      newline()
-      logs.report("error logging","start possible issues")
-      poptarget()
-      done=true
-    end
-    if fatalerrors[w] then
-      possiblefatal[w]=true
-    end
-    return startlogging("terminal",r,w,...)
+  poptarget()
+  state=oldstate
+ end
+ function logs.startfilelogging(...)
+  return startlogging("logfile",...)
+ end
+ logs.stopfilelogging=stoplogging
+ local done=false
+ function logs.starterrorlogging(r,w,...)
+  if not done then
+   pushtarget("terminal")
+   newline()
+   logs.report("error logging","start possible issues")
+   poptarget()
+   done=true
   end
-  logs.stoperrorlogging=stoplogging
-  function logs.finalactions()
-    if #finalactions>0 then
-      for i=1,#finalactions do
-        finalactions[i]()
-      end
-      if done then
-        pushtarget("terminal")
-        newline()
-        logs.report("error logging","stop possible issues")
-        poptarget()
-      end
-      return next(possiblefatal) and sortedkeys(possiblefatal) or false
-    end
+  if fatalerrors[w] then
+   possiblefatal[w]=true
   end
+  return startlogging("terminal",r,w,...)
+ end
+ logs.stoperrorlogging=stoplogging
+ function logs.finalactions()
+  if #finalactions>0 then
+   for i=1,#finalactions do
+    finalactions[i]()
+   end
+   if done then
+    pushtarget("terminal")
+    newline()
+    logs.report("error logging","stop possible issues")
+    poptarget()
+   end
+   return next(possiblefatal) and sortedkeys(possiblefatal) or false
+  end
+ end
 end
 
 
@@ -10167,14 +13559,14 @@
 
 package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
 
--- original size: 8097, stripped down to: 5534
+-- original size: 9072, stripped down to: 6055
 
 if not modules then modules={} end modules ['trac-inf']={
-  version=1.001,
-  comment="companion to trac-inf.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="companion to trac-inf.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local type,tonumber,select=type,tonumber,select
 local format,lower,find=string.format,string.lower,string.find
@@ -10189,161 +13581,191 @@
 statistics.threshold=0.01
 local statusinfo,n,registered,timers={},0,{},{}
 setmetatableindex(timers,function(t,k)
-  local v={ timing=0,loadtime=0 }
-  t[k]=v
-  return v
+ local v={ timing=0,loadtime=0 }
+ t[k]=v
+ return v
 end)
 local function hastiming(instance)
-  return instance and timers[instance]
+ return instance and timers[instance]
 end
 local function resettiming(instance)
-  timers[instance or "notimer"]={ timing=0,loadtime=0 }
+ timers[instance or "notimer"]={ timing=0,loadtime=0 }
 end
 local ticks=clock
 local seconds=function(n) return n or 0 end
-local function starttiming(instance)
-  local timer=timers[instance or "notimer"]
-  local it=timer.timing
-  if it==0 then
-    timer.starttime=ticks()
-    if not timer.loadtime then
-      timer.loadtime=0
-    end
+local function starttiming(instance,reset)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing
+ if reset then
+  it=0
+  timer.loadtime=0
+ end
+ if it==0 then
+  timer.starttime=ticks()
+  if not timer.loadtime then
+   timer.loadtime=0
   end
-  timer.timing=it+1
+ end
+ timer.timing=it+1
 end
 local function stoptiming(instance)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing
+ if it>1 then
+  timer.timing=it-1
+ else
+  local starttime=timer.starttime
+  if starttime and starttime>0 then
+   local stoptime=ticks()
+   local loadtime=stoptime-starttime
+   timer.stoptime=stoptime
+   timer.loadtime=timer.loadtime+loadtime
+   timer.timing=0
+   timer.starttime=0
+   return loadtime
+  end
+ end
+ return 0
+end
+local function elapsed(instance)
+ if type(instance)=="number" then
+  return instance
+ else
   local timer=timers[instance or "notimer"]
+  return timer and seconds(timer.loadtime) or 0
+ end
+end
+local function currenttime(instance)
+ if type(instance)=="number" then
+  return instance
+ else
+  local timer=timers[instance or "notimer"]
   local it=timer.timing
   if it>1 then
-    timer.timing=it-1
   else
-    local starttime=timer.starttime
-    if starttime and starttime>0 then
-      local stoptime=ticks()
-      local loadtime=stoptime-starttime
-      timer.stoptime=stoptime
-      timer.loadtime=timer.loadtime+loadtime
-      timer.timing=0
-      timer.starttime=0
-      return loadtime
-    end
+   local starttime=timer.starttime
+   if starttime and starttime>0 then
+    return seconds(timer.loadtime+ticks()-starttime)
+   end
   end
   return 0
+ end
 end
-local function elapsed(instance)
-  if type(instance)=="number" then
-    return instance
-  else
-    local timer=timers[instance or "notimer"]
-    return timer and seconds(timer.loadtime) or 0
-  end
-end
 local function elapsedtime(instance)
-  return format("%0.3f",elapsed(instance))
+ return format("%0.3f",elapsed(instance))
 end
 local function elapsedindeed(instance)
-  return elapsed(instance)>statistics.threshold
+ return elapsed(instance)>statistics.threshold
 end
 local function elapsedseconds(instance,rest) 
-  if elapsedindeed(instance) then
-    return format("%0.3f seconds %s",elapsed(instance),rest or "")
-  end
+ if elapsedindeed(instance) then
+  return format("%0.3f seconds %s",elapsed(instance),rest or "")
+ end
 end
 statistics.hastiming=hastiming
 statistics.resettiming=resettiming
 statistics.starttiming=starttiming
 statistics.stoptiming=stoptiming
+statistics.currenttime=currenttime
 statistics.elapsed=elapsed
 statistics.elapsedtime=elapsedtime
 statistics.elapsedindeed=elapsedindeed
 statistics.elapsedseconds=elapsedseconds
 function statistics.register(tag,fnc)
-  if statistics.enable and type(fnc)=="function" then
-    local rt=registered[tag] or (#statusinfo+1)
-    statusinfo[rt]={ tag,fnc }
-    registered[tag]=rt
-    if #tag>n then n=#tag end
-  end
+ if statistics.enable and type(fnc)=="function" then
+  local rt=registered[tag] or (#statusinfo+1)
+  statusinfo[rt]={ tag,fnc }
+  registered[tag]=rt
+  if #tag>n then n=#tag end
+ end
 end
 local report=logs.reporter("mkiv lua stats")
 function statistics.show()
-  if statistics.enable then
-    local register=statistics.register
-    register("used platform",function()
-      return format("%s, type: %s, binary subtree: %s",
-        os.platform or "unknown",os.type or "unknown",environment.texos or "unknown")
-    end)
-    register("used engine",function()
-      return format("%s version %s with functionality level %s, banner: %s",
-        LUATEXENGINE,LUATEXVERSION,LUATEXFUNCTIONALITY,lower(status.banner))
-    end)
-    register("control sequences",function()
-      return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
-    end)
-    register("callbacks",statistics.callbacks)
-    if TEXENGINE=="luajittex" and JITSUPPORTED then
-      local jitstatus=jit.status
-      if jitstatus then
-        local jitstatus={ jitstatus() }
-        if jitstatus[1] then
-          register("luajit options",concat(jitstatus," ",2))
-        end
-      end
+ if statistics.enable then
+  local register=statistics.register
+  register("used platform",function()
+   return format("%s, type: %s, binary subtree: %s",
+    os.platform or "unknown",os.type or "unknown",environment.texos or "unknown")
+  end)
+  register("used engine",function()
+   return format("%s version %s with functionality level %s, banner: %s",
+    LUATEXENGINE,LUATEXVERSION,LUATEXFUNCTIONALITY,lower(status.banner))
+  end)
+  register("control sequences",function()
+   return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
+  end)
+  register("callbacks",statistics.callbacks)
+  if TEXENGINE=="luajittex" and JITSUPPORTED then
+   local jitstatus=jit.status
+   if jitstatus then
+    local jitstatus={ jitstatus() }
+    if jitstatus[1] then
+     register("luajit options",concat(jitstatus," ",2))
     end
-    register("lua properties",function()
-      local hashchar=tonumber(status.luatex_hashchars)
-      local hashtype=status.luatex_hashtype
-      local mask=lua.mask or "ascii"
-      return format("engine: %s %s, used memory: %s, hash type: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
-        jit and "luajit" or "lua",
-        LUAVERSION,
-        statistics.memused(),
-        hashtype or "default",
-        hashchar and 2^hashchar or "unknown",
-        mask,
-        mask=="utf" and "τεχ" or "tex")
-    end)
-    register("runtime",statistics.runtime)
-    logs.newline() 
-    for i=1,#statusinfo do
-      local s=statusinfo[i]
-      local r=s[2]()
-      if r then
-        report("%s: %s",s[1],r)
-      end
-    end
-    statistics.enable=false
+   end
   end
+  register("lua properties",function()
+   local hashchar=tonumber(status.luatex_hashchars)
+   local hashtype=status.luatex_hashtype
+   local mask=lua.mask or "ascii"
+   return format("engine: %s %s, used memory: %s, hash type: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
+    jit and "luajit" or "lua",
+    LUAVERSION,
+    statistics.memused(),
+    hashtype or "default",
+    hashchar and 2^hashchar or "unknown",
+    mask,
+    mask=="utf" and "τεχ" or "tex")
+  end)
+  register("runtime",statistics.runtime)
+  logs.newline() 
+  for i=1,#statusinfo do
+   local s=statusinfo[i]
+   local r=s[2]()
+   if r then
+    report("%s: %s",s[1],r)
+   end
+  end
+  statistics.enable=false
+ end
 end
 function statistics.memused() 
-  local round=math.round or math.floor
-  return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
+ local round=math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
 end
 starttiming(statistics)
 function statistics.formatruntime(runtime) 
-  return format("%s seconds",runtime)  
+ return format("%s seconds",runtime)   
 end
 function statistics.runtime()
-  stoptiming(statistics)
-  return statistics.formatruntime(elapsedtime(statistics))
+ stoptiming(statistics)
+ local runtime=lua.getruntime and lua.getruntime() or elapsedtime(statistics)
+ return statistics.formatruntime(runtime)
 end
 local report=logs.reporter("system")
-function statistics.timed(action)
-  starttiming("run")
-  action()
-  stoptiming("run")
-  report("total runtime: %s seconds",elapsedtime("run"))
+function statistics.timed(action,all)
+ starttiming("run")
+ action()
+ stoptiming("run")
+ local runtime=tonumber(elapsedtime("run"))
+ if all then
+  local alltime=tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics))
+  if alltime and alltime>0 then
+   report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime)
+   return
+  end
+ end
+ report("total runtime: %0.3f seconds",runtime)
 end
 function statistics.tracefunction(base,tag,...)
-  for i=1,select("#",...) do
-    local name=select(i,...)
-    local stat={}
-    local func=base[name]
-    setmetatableindex(stat,function(t,k) t[k]=0 return 0 end)
-    base[name]=function(n,k,v) stat[k]=stat[k]+1 return func(n,k,v) end
-    statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
-  end
+ for i=1,select("#",...) do
+  local name=select(i,...)
+  local stat={}
+  local func=base[name]
+  setmetatableindex(stat,function(t,k) t[k]=0 return 0 end)
+  base[name]=function(n,k,v) stat[k]=stat[k]+1 return func(n,k,v) end
+  statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
+ end
 end
 
 
@@ -10353,124 +13775,124 @@
 
 package.loaded["trac-pro"] = package.loaded["trac-pro"] or true
 
--- original size: 5841, stripped down to: 3511
+-- original size: 5841, stripped down to: 3352
 
 if not modules then modules={} end modules ['trac-pro']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 getmetatable,setmetatable,rawset,type,next=getmetatable,setmetatable,rawset,type,next
-local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end)
+local trace_namespaces=false  trackers.register("system.namespaces",function(v) trace_namespaces=v end)
 local report_system=logs.reporter("system","protection")
 namespaces=namespaces or {}
 local namespaces=namespaces
 local registered={}
 local function report_index(k,name)
-  if trace_namespaces then
-    report_system("reference to %a in protected namespace %a: %s",k,name)
-    debugger.showtraceback(report_system)
-  else
-    report_system("reference to %a in protected namespace %a",k,name)
-  end
+ if trace_namespaces then
+  report_system("reference to %a in protected namespace %a: %s",k,name)
+  debugger.showtraceback(report_system)
+ else
+  report_system("reference to %a in protected namespace %a",k,name)
+ end
 end
 local function report_newindex(k,name)
-  if trace_namespaces then
-    report_system("assignment to %a in protected namespace %a: %s",k,name)
-    debugger.showtraceback(report_system)
-  else
-    report_system("assignment to %a in protected namespace %a",k,name)
-  end
+ if trace_namespaces then
+  report_system("assignment to %a in protected namespace %a: %s",k,name)
+  debugger.showtraceback(report_system)
+ else
+  report_system("assignment to %a in protected namespace %a",k,name)
+ end
 end
 local function register(name)
-  local data=name=="global" and _G or _G[name]
-  if not data then
-    return 
+ local data=name=="global" and _G or _G[name]
+ if not data then
+  return 
+ end
+ registered[name]=data
+ local m=getmetatable(data)
+ if not m then
+  m={}
+  setmetatable(data,m)
+ end
+ local index,newindex={},{}
+ m.__saved__index=m.__index
+ m.__no__index=function(t,k)
+  if not index[k] then
+   index[k]=true
+   report_index(k,name)
   end
-  registered[name]=data
-  local m=getmetatable(data)
-  if not m then
-    m={}
-    setmetatable(data,m)
+  return nil
+ end
+ m.__saved__newindex=m.__newindex
+ m.__no__newindex=function(t,k,v)
+  if not newindex[k] then
+   newindex[k]=true
+   report_newindex(k,name)
   end
-  local index,newindex={},{}
-  m.__saved__index=m.__index
-  m.__no__index=function(t,k)
-    if not index[k] then
-      index[k]=true
-      report_index(k,name)
-    end
-    return nil
-  end
-  m.__saved__newindex=m.__newindex
-  m.__no__newindex=function(t,k,v)
-    if not newindex[k] then
-      newindex[k]=true
-      report_newindex(k,name)
-    end
-    rawset(t,k,v)
-  end
-  m.__protection__depth=0
+  rawset(t,k,v)
+ end
+ m.__protection__depth=0
 end
 local function private(name) 
-  local data=registered[name]
+ local data=registered[name]
+ if not data then
+  data=_G[name]
   if not data then
-    data=_G[name]
-    if not data then
-      data={}
-      _G[name]=data
-    end
-    register(name)
+   data={}
+   _G[name]=data
   end
-  return data
+  register(name)
+ end
+ return data
 end
 local function protect(name)
-  local data=registered[name]
-  if not data then
-    return
-  end
-  local m=getmetatable(data)
-  local pd=m.__protection__depth
-  if pd>0 then
-    m.__protection__depth=pd+1
-  else
-    m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex
-    m.__index,m.__newindex=m.__no__index,m.__no__newindex
-    m.__protection__depth=1
-  end
+ local data=registered[name]
+ if not data then
+  return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>0 then
+  m.__protection__depth=pd+1
+ else
+  m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex
+  m.__index,m.__newindex=m.__no__index,m.__no__newindex
+  m.__protection__depth=1
+ end
 end
 local function unprotect(name)
-  local data=registered[name]
-  if not data then
-    return
-  end
-  local m=getmetatable(data)
-  local pd=m.__protection__depth
-  if pd>1 then
-    m.__protection__depth=pd-1
-  else
-    m.__index,m.__newindex=m.__saved__index,m.__saved__newindex
-    m.__protection__depth=0
-  end
+ local data=registered[name]
+ if not data then
+  return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>1 then
+  m.__protection__depth=pd-1
+ else
+  m.__index,m.__newindex=m.__saved__index,m.__saved__newindex
+  m.__protection__depth=0
+ end
 end
 local function protectall()
-  for name,_ in next,registered do
-    if name~="global" then
-      protect(name)
-    end
+ for name,_ in next,registered do
+  if name~="global" then
+   protect(name)
   end
+ end
 end
 local function unprotectall()
-  for name,_ in next,registered do
-    if name~="global" then
-      unprotect(name)
-    end
+ for name,_ in next,registered do
+  if name~="global" then
+   unprotect(name)
   end
+ end
 end
-namespaces.register=register    
-namespaces.private=private     
+namespaces.register=register  
+namespaces.private=private   
 namespaces.protect=protect
 namespaces.unprotect=unprotect
 namespaces.protectall=protectall
@@ -10477,20 +13899,20 @@
 namespaces.unprotectall=unprotectall
 namespaces.private("namespaces") registered={} register("global") 
 directives.register("system.protect",function(v)
-  if v then
-    protectall()
-  else
-    unprotectall()
-  end
+ if v then
+  protectall()
+ else
+  unprotectall()
+ end
 end)
 directives.register("system.checkglobals",function(v)
-  if v then
-    report_system("enabling global namespace guard")
-    protect("global")
-  else
-    report_system("disabling global namespace guard")
-    unprotect("global")
-  end
+ if v then
+  report_system("enabling global namespace guard")
+  protect("global")
+ else
+  report_system("disabling global namespace guard")
+  unprotect("global")
+ end
 end)
 
 
@@ -10500,15 +13922,15 @@
 
 package.loaded["util-lua"] = package.loaded["util-lua"] or true
 
--- original size: 6621, stripped down to: 4764
+-- original size: 6664, stripped down to: 4589
 
 if not modules then modules={} end modules ['util-lua']={
-  version=1.001,
-  comment="companion to luat-lib.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  comment="the strip code is written by Peter Cawley",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment="the strip code is written by Peter Cawley",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format
 local load,loadfile,type,collectgarbage=load,loadfile,type,collectgarbage
@@ -10519,7 +13941,7 @@
 local report_mem=logs.reporter("system","lua memory")
 local tracestripping=false
 local tracememory=false
-luautilities.stripcode=true 
+luautilities.stripcode=true  
 luautilities.alwaysstripcode=false 
 luautilities.nofstrippedchunks=0
 luautilities.nofstrippedbytes=0
@@ -10526,143 +13948,144 @@
 local strippedchunks={} 
 luautilities.strippedchunks=strippedchunks
 luautilities.suffixes={
-  tma="tma",
-  tmc=jit and "tmb" or "tmc",
-  lua="lua",
-  luc=jit and "lub" or "luc",
-  lui="lui",
-  luv="luv",
-  luj="luj",
-  tua="tua",
-  tuc="tuc",
+ tma="tma",
+ tmc=jit and "tmb" or "tmc",
+ lua="lua",
+ luc=jit and "lub" or "luc",
+ lui="lui",
+ luv="luv",
+ luj="luj",
+ tua="tua",
+ tuc="tuc",
 }
 local function register(name) 
-  if tracestripping then
-    report_lua("stripped bytecode from %a",name or "unknown")
-  end
-  strippedchunks[#strippedchunks+1]=name
-  luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ if tracestripping then
+  report_lua("stripped bytecode from %a",name or "unknown")
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
 end
 local function stupidcompile(luafile,lucfile,strip)
-  local code=io.loaddata(luafile)
-  if code and code~="" then
-    code=load(code)
-    if code then
-      code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
-      if code and code~="" then
-        register(name)
-        io.savedata(lucfile,code)
-        return true,0
-      end
-    else
-      report_lua("fatal error %a in file %a",1,luafile)
-    end
+ local code=io.loaddata(luafile)
+ if code and code~="" then
+  code=load(code)
+  if code then
+   code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
+   if code and code~="" then
+    register(name)
+    io.savedata(lucfile,code)
+    return true,0
+   end
   else
-    report_lua("fatal error %a in file %a",2,luafile)
+   report_lua("fatal error %a in file %a",1,luafile)
   end
-  return false,0
+ else
+  report_lua("fatal error %a in file %a",2,luafile)
+ end
+ return false,0
 end
 function luautilities.loadedluacode(fullname,forcestrip,name,macros)
-  name=name or fullname
-  if macros then
-    macros=lua.macros
+ name=name or fullname
+ if macros then
+  macros=lua.macros
+ end
+ local code,message
+ if macros then
+  code,message=macros.loaded(fullname,true,false)
+ else
+  code,message=loadfile(fullname)
+ end
+ if code then
+  code()
+ else
+  report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
+  code,message=loadfile(fullname)
+ end
+ if forcestrip and luautilities.stripcode then
+  if type(forcestrip)=="function" then
+   forcestrip=forcestrip(fullname)
   end
-  local code,message
-  if macros then
-    code,message=macros.loaded(fullname,true,false)
+  if forcestrip or luautilities.alwaysstripcode then
+   register(name)
+   return load(dump(code,true)),0
   else
-    code,message=loadfile(fullname)
+   return code,0
   end
-  if code then
-    code()
-  else
-    report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
-  end
-  if forcestrip and luautilities.stripcode then
-    if type(forcestrip)=="function" then
-      forcestrip=forcestrip(fullname)
-    end
-    if forcestrip or luautilities.alwaysstripcode then
-      register(name)
-      return load(dump(code,true)),0
-    else
-      return code,0
-    end
-  elseif luautilities.alwaysstripcode then
-    register(name)
-    return load(dump(code,true)),0
-  else
-    return code,0
-  end
+ elseif luautilities.alwaysstripcode then
+  register(name)
+  return load(dump(code,true)),0
+ else
+  return code,0
+ end
 end
 function luautilities.strippedloadstring(code,name,forcestrip) 
-  local code,message=load(code)
-  if not code then
-    report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
-  end
-  if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
-    register(name)
-    return load(dump(code,true)),0 
-  else
-    return code,0
-  end
+ local code,message=load(code)
+ if not code then
+  report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
+ end
+ if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
+  register(name)
+  return load(dump(code,true)),0 
+ else
+  return code,0
+ end
 end
 function luautilities.loadstring(code,name) 
-  local code,message=load(code)
-  if not code then
-    report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
-  end
-  return code,0
+ local code,message=load(code)
+ if not code then
+  report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
+ end
+ return code,0
 end
 function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) 
-  report_lua("compiling %a into %a",luafile,lucfile)
-  os.remove(lucfile)
-  local done=stupidcompile(luafile,lucfile,strip~=false)
-  if done then
-    report_lua("dumping %a into %a stripped",luafile,lucfile)
-    if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
-      report_lua("removing %a",luafile)
-      os.remove(luafile)
-    end
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=stupidcompile(luafile,lucfile,strip~=false)
+ if done then
+  report_lua("dumping %a into %a stripped",luafile,lucfile)
+  if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+   report_lua("removing %a",luafile)
+   os.remove(luafile)
   end
-  return done
+ end
+ return done
 end
 function luautilities.loadstripped(...)
-  local l=load(...)
-  if l then
-    return load(dump(l,true))
-  end
+ local l=load(...)
+ if l then
+  return load(dump(l,true))
+ end
 end
 local finalizers={}
 setmetatable(finalizers,{
-  __gc=function(t)
-    for i=1,#t do
-      pcall(t[i]) 
-    end
+ __gc=function(t)
+  for i=1,#t do
+   pcall(t[i]) 
   end
+ end
 } )
 function luautilities.registerfinalizer(f)
-  finalizers[#finalizers+1]=f
+ finalizers[#finalizers+1]=f
 end
 function luautilities.checkmemory(previous,threshold,trace) 
-  local current=collectgarbage("count")
-  if previous then
-    local checked=(threshold or 64)*1024
-    local delta=current-previous
-    if current-previous>checked then
-      collectgarbage("collect")
-      local afterwards=collectgarbage("count")
-      if trace or tracememory then
-        report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB, afterwards %i MB",
-          previous/1024,current/1024,delta/1024,threshold,afterwards)
-      end
-      return afterwards
-    elseif trace or tracememory then
-      report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB",
-        previous/1024,current/1024,delta/1024,threshold)
-    end
+ local current=collectgarbage("count")
+ if previous then
+  local checked=(threshold or 64)*1024
+  local delta=current-previous
+  if current-previous>checked then
+   collectgarbage("collect")
+   local afterwards=collectgarbage("count")
+   if trace or tracememory then
+    report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB",
+     previous/1024,current/1024,delta/1024,threshold,afterwards)
+   end
+   return afterwards
+  elseif trace or tracememory then
+   report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB",
+    previous/1024,current/1024,delta/1024,threshold)
   end
-  return current
+ end
+ return current
 end
 
 
@@ -10672,17 +14095,15 @@
 
 package.loaded["util-deb"] = package.loaded["util-deb"] or true
 
--- original size: 8984, stripped down to: 6573
+-- original size: 9955, stripped down to: 6693
 
 if not modules then modules={} end modules ['util-deb']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 debug=require "debug"
-local getinfo,sethook=debug.getinfo,debug.sethook
 local type,next,tostring,tonumber=type,next,tostring,tonumber
 local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub
 local insert,remove,sort=table.insert,table.remove,table.sort
@@ -10700,38 +14121,38 @@
 local initialize=false
 if not (FFISUPPORTED and ffi) then
 elseif os.type=="windows" then
-  initialize=function()
-    local kernel=ffilib("kernel32","system") 
-    if kernel then
-      local tonumber=ffi.number or tonumber
-      ffi.cdef[[
+ initialize=function()
+  local kernel=ffilib("kernel32","system") 
+  if kernel then
+   local tonumber=ffi.number or tonumber
+   ffi.cdef[[
                 int QueryPerformanceFrequency(int64_t *lpFrequency);
                 int QueryPerformanceCounter(int64_t *lpPerformanceCount);
             ]]
-      local target=ffi.new("__int64[1]")
-      ticks=function()
-        if kernel.QueryPerformanceCounter(target)==1 then
-          return tonumber(target[0])
-        else
-          return 0
-        end
-      end
-      local target=ffi.new("__int64[1]")
-      seconds=function(ticks)
-        if kernel.QueryPerformanceFrequency(target)==1 then
-          return ticks/tonumber(target[0])
-        else
-          return 0
-        end
-      end
+   local target=ffi.new("__int64[1]")
+   ticks=function()
+    if kernel.QueryPerformanceCounter(target)==1 then
+     return tonumber(target[0])
+    else
+     return 0
     end
-    initialize=false
+   end
+   local target=ffi.new("__int64[1]")
+   seconds=function(ticks)
+    if kernel.QueryPerformanceFrequency(target)==1 then
+     return ticks/tonumber(target[0])
+    else
+     return 0
+    end
+   end
   end
+  initialize=false
+ end
 elseif os.type=="unix" then
-  initialize=function()
-    local C=ffi.C
-    local tonumber=ffi.number or tonumber
-    ffi.cdef [[
+ initialize=function()
+  local C=ffi.C
+  local tonumber=ffi.number or tonumber
+  ffi.cdef [[
             /* what a mess */
             typedef int clk_id_t;
             typedef enum { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID } clk_id;
@@ -10738,190 +14159,228 @@
             typedef struct timespec { long sec; long nsec; } ctx_timespec;
             int clock_gettime(clk_id_t timerid, struct timespec *t);
         ]]
-    local target=ffi.new("ctx_timespec[?]",1)
-    local clock=C.CLOCK_PROCESS_CPUTIME_ID
-    ticks=function ()
-      C.clock_gettime(clock,target)
-      return tonumber(target[0].sec*1000000000+target[0].nsec)
-    end
-    seconds=function(ticks)
-      return ticks/1000000000
-    end
-    initialize=false
+  local target=ffi.new("ctx_timespec[?]",1)
+  local clock=C.CLOCK_PROCESS_CPUTIME_ID
+  ticks=function ()
+   C.clock_gettime(clock,target)
+   return tonumber(target[0].sec*1000000000+target[0].nsec)
   end
+  seconds=function(ticks)
+   return ticks/1000000000
+  end
+  initialize=false
+ end
 end
 setmetatableindex(names,function(t,name)
-  local v=setmetatableindex(function(t,source)
-    local v=setmetatableindex(function(t,line)
-      local v={ total=0,count=0 }
-      t[line]=v
-      return v
-    end)
-    t[source]=v
-    return v
+ local v=setmetatableindex(function(t,source)
+  local v=setmetatableindex(function(t,line)
+   local v={ total=0,count=0,nesting=0 }
+   t[line]=v
+   return v
   end)
-  t[name]=v
+  t[source]=v
   return v
+ end)
+ t[name]=v
+ return v
 end)
+local getinfo=nil
+local sethook=nil
 local function hook(where)
-  local f=getinfo(2,"nSl")
-  if f then
-    local source=f.short_src
-    if not source then
-      return
+ local f=getinfo(2,"nSl")
+ if f then
+  local source=f.short_src
+  if not source then
+   return
+  end
+  local line=f.linedefined or 0
+  local name=f.name
+  if not name then
+   local what=f.what
+   if what=="C" then
+    name="<anonymous>"
+   else
+    name=f.namewhat or what or "<unknown>"
+   end
+  end
+  local data=names[name][source][line]
+  if where=="call" then
+   local nesting=data.nesting
+   if nesting==0 then
+    data.count=data.count+1
+    insert(data,ticks())
+    data.nesting=1
+   else
+    data.nesting=nesting+1
+   end
+  elseif where=="return" then
+   local nesting=data.nesting
+   if nesting==1 then
+    local t=remove(data)
+    if t then
+     data.total=data.total+ticks()-t
     end
-    local line=f.linedefined or 0
-    local name=f.name
-    if not name then
-      local what=f.what
-      if what=="C" then
-        name="<anonymous>"
-      else
-        name=f.namewhat or what or "<unknown>"
-      end
-    end
-    local data=names[name][source][line]
-    if where=="call" then
-      data.count=data.count+1
-      insert(data,ticks())
-    elseif where=="return" then
-      local t=remove(data)
-      if t then
-        data.total=data.total+ticks()-t
-      end
-    end
+    data.nesting=0
+   else
+    data.nesting=nesting-1
+   end
   end
+ end
 end
 function debugger.showstats(printer,threshold)
-  local printer=printer or report
-  local calls=0
-  local functions=0
-  local dataset={}
-  local length=0
-  local realtime=0
-  local totaltime=0
-  local threshold=threshold or 0
-  for name,sources in next,names do
-    for source,lines in next,sources do
-      for line,data in next,lines do
-        local count=data.count
-        if count>threshold then
-          if #name>length then
-            length=#name
-          end
-          local total=data.total
-          local real=total
-          if real>0 then
-            real=total-(count*overhead/dummycalls)
-            if real<0 then
-              real=0
-            end
-            realtime=realtime+real
-          end
-          totaltime=totaltime+total
-          if line<0 then
-            line=0
-          end
-          dataset[#dataset+1]={ real,total,count,name,source,line }
-        end
+ local printer=printer or report
+ local calls=0
+ local functions=0
+ local dataset={}
+ local length=0
+ local realtime=0
+ local totaltime=0
+ local threshold=threshold or 0
+ for name,sources in next,names do
+  for source,lines in next,sources do
+   for line,data in next,lines do
+    local count=data.count
+    if count>threshold then
+     if #name>length then
+      length=#name
+     end
+     local total=data.total
+     local real=total
+     if real>0 then
+      real=total-(count*overhead/dummycalls)
+      if real<0 then
+       real=0
       end
+      realtime=realtime+real
+     end
+     totaltime=totaltime+total
+     if line<0 then
+      line=0
+     end
+     dataset[#dataset+1]={ real,total,count,name,source,line }
     end
+   end
   end
-  sort(dataset,function(a,b)
-    if a[1]==b[1] then
-      if a[2]==b[2] then
-        if a[3]==b[3] then
-          if a[4]==b[4] then
-            if a[5]==b[5] then
-              return a[6]<b[6]
-            else
-              return a[5]<b[5]
-            end
-          else
-            return a[4]<b[4]
-          end
-        else
-          return b[3]<a[3]
-        end
+ end
+ sort(dataset,function(a,b)
+  if a[1]==b[1] then
+   if a[2]==b[2] then
+    if a[3]==b[3] then
+     if a[4]==b[4] then
+      if a[5]==b[5] then
+       return a[6]<b[6]
       else
-        return b[2]<a[2]
+       return a[5]<b[5]
       end
+     else
+      return a[4]<b[4]
+     end
     else
-      return b[1]<a[1]
+     return b[3]<a[3]
     end
-  end)
-  if length>50 then
-    length=50
+   else
+    return b[2]<a[2]
+   end
+  else
+   return b[1]<a[1]
   end
-  local fmt=string.formatters["%4.9k s  %3.3k %%  %4.9k s  %3.3k %%  %8i #  %-"..length.."s  %4i  %s"]
-  for i=1,#dataset do
-    local data=dataset[i]
-    local real=data[1]
-    local total=data[2]
-    local count=data[3]
-    local name=data[4]
-    local source=data[5]
-    local line=data[6]
-    calls=calls+count
-    functions=functions+1
-    name=gsub(name,"%s+"," ")
-    if #name>length then
-      name=sub(name,1,length)
-    end
-    printer(fmt(seconds(total),100*total/totaltime,seconds(real),100*real/realtime,count,name,line,source))
+ end)
+ if length>50 then
+  length=50
+ end
+ local fmt=string.formatters["%4.9k s  %3.3k %%  %4.9k s  %3.3k %%  %8i #  %-"..length.."s  %4i  %s"]
+ for i=1,#dataset do
+  local data=dataset[i]
+  local real=data[1]
+  local total=data[2]
+  local count=data[3]
+  local name=data[4]
+  local source=data[5]
+  local line=data[6]
+  calls=calls+count
+  functions=functions+1
+  name=gsub(name,"%s+"," ")
+  if #name>length then
+   name=sub(name,1,length)
   end
-  printer("")
-  printer(format("functions : %i",functions))
-  printer(format("calls     : %i",calls))
-  printer(format("overhead  : %f",seconds(overhead/1000)))
+  printer(fmt(seconds(total),100*total/totaltime,seconds(real),100*real/realtime,count,name,line,source))
+ end
+ printer("")
+ printer(format("functions : %i",functions))
+ printer(format("calls     : %i",calls))
+ printer(format("overhead  : %f",seconds(overhead/1000)))
 end
+local function getdebug()
+ if sethook and getinfo then
+  return
+ end
+ if not debug then
+  local okay
+  okay,debug=pcall(require,"debug")
+ end
+ if type(debug)~="table" then
+  return
+ end
+ getinfo=debug.getinfo
+ sethook=debug.sethook
+ if type(getinfo)~="function" then
+  getinfo=nil
+ end
+ if type(sethook)~="function" then
+  sethook=nil
+ end
+end
 function debugger.savestats(filename,threshold)
-  local f=io.open(filename,'w')
-  if f then
-    debugger.showstats(function(str) f:write(str,"\n") end,threshold)
-    f:close()
-  end
+ local f=io.open(filename,'w')
+ if f then
+  debugger.showstats(function(str) f:write(str,"\n") end,threshold)
+  f:close()
+ end
 end
 function debugger.enable()
-  if nesting==0 then
-    running=true
-    if initialize then
-      initialize()
-    end
-    sethook(hook,"cr")
-    local function dummy() end
-    local t=ticks()
-    for i=1,dummycalls do
-      dummy()
-    end
-    overhead=ticks()-t
+ getdebug()
+ if sethook and getinfo and nesting==0 then
+  running=true
+  if initialize then
+   initialize()
   end
-  if nesting>0 then
-    nesting=nesting+1
+  sethook(hook,"cr")
+  local function dummy() end
+  local t=ticks()
+  for i=1,dummycalls do
+   dummy()
   end
+  overhead=ticks()-t
+ end
+ if nesting>0 then
+  nesting=nesting+1
+ end
 end
 function debugger.disable()
-  if nesting>0 then
-    nesting=nesting-1
-  end
-  if nesting==0 then
-    sethook()
-  end
+ if nesting>0 then
+  nesting=nesting-1
+ end
+ if sethook and getinfo and nesting==0 then
+  sethook()
+ end
 end
 local function showtraceback(rep) 
+ getdebug()
+ if getinfo then
   local level=2 
   local reporter=rep or report
   while true do
-    local info=getinfo(level,"Sl")
-    if not info then
-      break
-    elseif info.what=="C" then
-      reporter("%2i : %s",level-1,"C function")
-    else
-      reporter("%2i : %s : %s",level-1,info.short_src,info.currentline)
-    end
-    level=level+1
+   local info=getinfo(level,"Sl")
+   if not info then
+    break
+   elseif info.what=="C" then
+    reporter("%2i : %s",level-1,"C function")
+   else
+    reporter("%2i : %s : %s",level-1,info.short_src,info.currentline)
+   end
+   level=level+1
   end
+ end
 end
 debugger.showtraceback=showtraceback
 
@@ -10932,18 +14391,18 @@
 
 package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
 
--- original size: 7112, stripped down to: 3988
+-- original size: 7112, stripped down to: 3887
 
 if not modules then modules={} end modules ['util-tpl']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 utilities.templates=utilities.templates or {}
 local templates=utilities.templates
-local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end)
+local trace_template=false  trackers.register("templates.trace",function(v) trace_template=v end)
 local report_template=logs.reporter("template")
 local tostring,next=tostring,next
 local format,sub,byte=string.format,string.sub,string.byte
@@ -10950,29 +14409,29 @@
 local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns
 local replacer
 local function replacekey(k,t,how,recursive)
-  local v=t[k]
-  if not v then
-    if trace_template then
-      report_template("unknown key %a",k)
-    end
-    return ""
+ local v=t[k]
+ if not v then
+  if trace_template then
+   report_template("unknown key %a",k)
+  end
+  return ""
+ else
+  v=tostring(v)
+  if trace_template then
+   report_template("setting key %a to value %a",k,v)
+  end
+  if recursive then
+   return lpegmatch(replacer,v,1,t,how,recursive)
   else
-    v=tostring(v)
-    if trace_template then
-      report_template("setting key %a to value %a",k,v)
-    end
-    if recursive then
-      return lpegmatch(replacer,v,1,t,how,recursive)
-    else
-      return v
-    end
+   return v
   end
+ end
 end
 local sqlescape=lpeg.replacer {
-  { "'","''"  },
-  { "\\","\\\\" },
-  { "\r\n","\\n" },
-  { "\r","\\n" },
+ { "'","''"   },
+ { "\\","\\\\" },
+ { "\r\n","\\n"  },
+ { "\r","\\n"  },
 }
 local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'"))
 lpegpatterns.sqlescape=sqlescape
@@ -10979,44 +14438,44 @@
 lpegpatterns.sqlquoted=sqlquoted
 local luaescape=lpegpatterns.luaescape
 local escapers={
-  lua=function(s)
-    return lpegmatch(luaescape,s)
-  end,
-  sql=function(s)
-    return lpegmatch(sqlescape,s)
-  end,
+ lua=function(s)
+  return lpegmatch(luaescape,s)
+ end,
+ sql=function(s)
+  return lpegmatch(sqlescape,s)
+ end,
 }
 local quotedescapers={
-  lua=function(s)
-    return format("%q",s)
-  end,
-  sql=function(s)
-    return lpegmatch(sqlquoted,s)
-  end,
+ lua=function(s)
+  return format("%q",s)
+ end,
+ sql=function(s)
+  return lpegmatch(sqlquoted,s)
+ end,
 }
 local luaescaper=escapers.lua
 local quotedluaescaper=quotedescapers.lua
 local function replacekeyunquoted(s,t,how,recurse) 
-  if how==false then
-    return replacekey(s,t,how,recurse)
-  else
-    local escaper=how and escapers[how] or luaescaper
-    return escaper(replacekey(s,t,how,recurse))
-  end
+ if how==false then
+  return replacekey(s,t,how,recurse)
+ else
+  local escaper=how and escapers[how] or luaescaper
+  return escaper(replacekey(s,t,how,recurse))
+ end
 end
 local function replacekeyquoted(s,t,how,recurse) 
-  if how==false then
-    return replacekey(s,t,how,recurse)
-  else
-    local escaper=how and quotedescapers[how] or quotedluaescaper
-    return escaper(replacekey(s,t,how,recurse))
-  end
+ if how==false then
+  return replacekey(s,t,how,recurse)
+ else
+  local escaper=how and quotedescapers[how] or quotedluaescaper
+  return escaper(replacekey(s,t,how,recurse))
+ end
 end
 local function replaceoptional(l,m,r,t,how,recurse)
-  local v=t[l]
-  return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
+ local v=t[l]
+ return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
 end
-local single=P("%") 
+local single=P("%")  
 local double=P("%%") 
 local lquoted=P("%[") 
 local rquoted=P("]%") 
@@ -11033,41 +14492,41 @@
 local noroptional=P("?%")/''
 local nomoptional=P(":")/''
 local args=Carg(1)*Carg(2)*Carg(3)
-local key=nosingle*((C((1-nosingle  )^1)*args)/replacekey    )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
+local key=nosingle*((C((1-nosingle   )^1)*args)/replacekey  )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted  )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted  )^1)*args)/replacekeyunquoted)*norquoted
 local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
 local any=P(1)
    replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
 local function replace(str,mapping,how,recurse)
-  if mapping and str then
-    return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
-  else
-    return str
-  end
+ if mapping and str then
+  return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+  return str
+ end
 end
 templates.replace=replace
 function templates.replacer(str,how,recurse) 
-  return function(mapping)
-    return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
-  end
+ return function(mapping)
+  return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ end
 end
 function templates.load(filename,mapping,how,recurse)
-  local data=io.loaddata(filename) or ""
-  if mapping and next(mapping) then
-    return replace(data,mapping,how,recurse)
-  else
-    return data
-  end
+ local data=io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+  return replace(data,mapping,how,recurse)
+ else
+  return data
+ end
 end
 function templates.resolve(t,mapping,how,recurse)
-  if not mapping then
-    mapping=t
-  end
-  for k,v in next,t do
-    t[k]=replace(v,mapping,how,recurse)
-  end
-  return t
+ if not mapping then
+  mapping=t
+ end
+ for k,v in next,t do
+  t[k]=replace(v,mapping,how,recurse)
+ end
+ return t
 end
 
 
@@ -11077,14 +14536,14 @@
 
 package.loaded["util-sbx"] = package.loaded["util-sbx"] or true
 
--- original size: 20393, stripped down to: 13924
+-- original size: 20393, stripped down to: 13121
 
 if not modules then modules={} end modules ['util-sbx']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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"
 }
 if not sandbox then require("l-sandbox") end 
 local next,type=next,type
@@ -11117,144 +14576,144 @@
 trackers.register("sandbox",function(v) trace=v end) 
 sandbox.setreporter(report)
 sandbox.finalizer {
-  category="files",
-  action=function()
-    finalized=true
-  end
+ category="files",
+ action=function()
+  finalized=true
+ end
 }
 local function registerroot(root,what) 
-  if finalized then
-    report("roots are already finalized")
-  else
-    if type(root)=="table" then
-      root,what=root[1],root[2]
-    end
-    if type(root)=="string" and root~="" then
-      root=collapsepath(expandname(root))
-      if what=="r" or what=="ro" or what=="readable" then
-        what="read"
-      elseif what=="w" or what=="wo" or what=="writable" then
-        what="write"
-      end
-      validroots[root]=what=="write" or false
-    end
+ if finalized then
+  report("roots are already finalized")
+ else
+  if type(root)=="table" then
+   root,what=root[1],root[2]
   end
+  if type(root)=="string" and root~="" then
+   root=collapsepath(expandname(root))
+   if what=="r" or what=="ro" or what=="readable" then
+    what="read"
+   elseif what=="w" or what=="wo" or what=="writable" then
+    what="write"
+   end
+   validroots[root]=what=="write" or false
+  end
+ end
 end
 sandbox.finalizer {
-  category="files",
-  action=function() 
+ category="files",
+ action=function() 
+  if p_validroot then
+   report("roots are already initialized")
+  else
+   sandbox.registerroot(".","write")
+   for name in sortedhash(validroots) do
     if p_validroot then
-      report("roots are already initialized")
+     p_validroot=P(name)+p_validroot
     else
-      sandbox.registerroot(".","write")
-      for name in sortedhash(validroots) do
-        if p_validroot then
-          p_validroot=P(name)+p_validroot
-        else
-          p_validroot=P(name)
-        end
-      end
-      p_validroot=p_validroot/validroots
+     p_validroot=P(name)
     end
+   end
+   p_validroot=p_validroot/validroots
   end
+ end
 }
 local function registerbinary(name)
-  if finalized then
-    report("binaries are already finalized")
-  elseif type(name)=="string" and name~="" then
-    if not validbinaries then
-      return
-    end
-    if validbinaries==true then
-      validbinaries={ [name]=true }
-    else
-      validbinaries[name]=true
-    end
-  elseif name==true then
-    validbinaries={}
+ if finalized then
+  report("binaries are already finalized")
+ elseif type(name)=="string" and name~="" then
+  if not validbinaries then
+   return
   end
+  if validbinaries==true then
+   validbinaries={ [name]=true }
+  else
+   validbinaries[name]=true
+  end
+ elseif name==true then
+  validbinaries={}
+ end
 end
 local function registerlibrary(name)
-  if finalized then
-    report("libraries are already finalized")
-  elseif type(name)=="string" and name~="" then
-    if not validlibraries then
-      return
-    end
-    if validlibraries==true then
-      validlibraries={ [nameonly(name)]=true }
-    else
-      validlibraries[nameonly(name)]=true
-    end
-  elseif name==true then
-    validlibraries={}
+ if finalized then
+  report("libraries are already finalized")
+ elseif type(name)=="string" and name~="" then
+  if not validlibraries then
+   return
   end
+  if validlibraries==true then
+   validlibraries={ [nameonly(name)]=true }
+  else
+   validlibraries[nameonly(name)]=true
+  end
+ elseif name==true then
+  validlibraries={}
+ end
 end
 local p_write=S("wa")    p_write=(1-p_write)^0*p_write
-local p_path=S("\\/~$%:") p_path=(1-p_path )^0*p_path 
+local p_path=S("\\/~$%:")  p_path=(1-p_path )^0*p_path  
 local function normalized(name) 
-  if platform=="windows" then
-    name=gsub(name,"/","\\")
-  end
-  return name
+ if platform=="windows" then
+  name=gsub(name,"/","\\")
+ end
+ return name
 end
 function sandbox.possiblepath(name)
-  return lpegmatch(p_path,name) and true or false
+ return lpegmatch(p_path,name) and true or false
 end
 local filenamelogger=false
 function sandbox.setfilenamelogger(l)
-  filenamelogger=type(l)=="function" and l or false
+ filenamelogger=type(l)=="function" and l or false
 end
 local function validfilename(name,what)
-  if p_validroot and type(name)=="string" and lpegmatch(p_path,name) then
-    local asked=collapsepath(expandname(name))
-    local okay=lpegmatch(p_validroot,asked)
-    if okay==true then
-      if filenamelogger then
-        filenamelogger(name,"w",asked,true)
-      end
-      return name
-    elseif okay==false then
-      if not what then
-        if filenamelogger then
-          filenamelogger(name,"r",asked,true)
-        end
-        return name
-      elseif lpegmatch(p_write,what) then
-        if filenamelogger then
-          filenamelogger(name,"w",asked,false)
-        end
-        return 
-      else
-        if filenamelogger then
-          filenamelogger(name,"r",asked,true)
-        end
-        return name
-      end
-    elseif filenamelogger then
-      filenamelogger(name,"*",name,false)
+ if p_validroot and type(name)=="string" and lpegmatch(p_path,name) then
+  local asked=collapsepath(expandname(name))
+  local okay=lpegmatch(p_validroot,asked)
+  if okay==true then
+   if filenamelogger then
+    filenamelogger(name,"w",asked,true)
+   end
+   return name
+  elseif okay==false then
+   if not what then
+    if filenamelogger then
+     filenamelogger(name,"r",asked,true)
     end
-  else
     return name
+   elseif lpegmatch(p_write,what) then
+    if filenamelogger then
+     filenamelogger(name,"w",asked,false)
+    end
+    return 
+   else
+    if filenamelogger then
+     filenamelogger(name,"r",asked,true)
+    end
+    return name
+   end
+  elseif filenamelogger then
+   filenamelogger(name,"*",name,false)
   end
+ else
+  return name
+ end
 end
 local function readable(name,finalized)
-  return validfilename(name,"r")
+ return validfilename(name,"r")
 end
 local function normalizedreadable(name,finalized)
-  local valid=validfilename(name,"r")
-  if valid then
-    return normalized(valid)
-  end
+ local valid=validfilename(name,"r")
+ if valid then
+  return normalized(valid)
+ end
 end
 local function writeable(name,finalized)
-  return validfilename(name,"w")
+ return validfilename(name,"w")
 end
 local function normalizedwriteable(name,finalized)
-  local valid=validfilename(name,"w")
-  if valid then
-    return normalized(valid)
-  end
+ local valid=validfilename(name,"w")
+ if valid then
+  return normalized(valid)
+ end
 end
 validators.readable=readable
 validators.writeable=normalizedwriteable
@@ -11262,316 +14721,316 @@
 validators.normalizedwriteable=writeable
 validators.filename=readable
 table.setmetatableindex(validators,function(t,k)
-  if k then
-    t[k]=readable
-  end
-  return readable
+ if k then
+  t[k]=readable
+ end
+ return readable
 end)
 function validators.string(s,finalized)
-  if finalized and suspicious(s) then
-    return ""
-  else
-    return s
-  end
+ if finalized and suspicious(s) then
+  return ""
+ else
+  return s
+ end
 end
 function validators.cache(s)
-  if finalized then
-    return basename(s)
-  else
-    return s
-  end
+ if finalized then
+  return basename(s)
+ else
+  return s
+ end
 end
 function validators.url(s)
-  if finalized and find("^file:") then
-    return ""
-  else
-    return s
-  end
+ if finalized and find("^file:") then
+  return ""
+ else
+  return s
+ end
 end
 local function filehandlerone(action,one,...)
-  local checkedone=validfilename(one)
-  if checkedone then
-    return action(one,...)
-  else
-  end
+ local checkedone=validfilename(one)
+ if checkedone then
+  return action(one,...)
+ else
+ end
 end
 local function filehandlertwo(action,one,two,...)
-  local checkedone=validfilename(one)
-  if checkedone then
-    local checkedtwo=validfilename(two)
-    if checkedtwo then
-      return action(one,two,...)
-    else
-    end
+ local checkedone=validfilename(one)
+ if checkedone then
+  local checkedtwo=validfilename(two)
+  if checkedtwo then
+   return action(one,two,...)
   else
   end
+ else
+ end
 end
 local function iohandler(action,one,...)
-  if type(one)=="string" then
-    local checkedone=validfilename(one)
-    if checkedone then
-      return action(one,...)
-    end
-  elseif one then
-    return action(one,...)
-  else
-    return action()
+ if type(one)=="string" then
+  local checkedone=validfilename(one)
+  if checkedone then
+   return action(one,...)
   end
+ elseif one then
+  return action(one,...)
+ else
+  return action()
+ end
 end
 local osexecute=sandbox.original(os.execute)
 local iopopen=sandbox.original(io.popen)
 local reported={}
 local function validcommand(name,program,template,checkers,defaults,variables,reporter,strict)
-  if validbinaries~=false and (validbinaries==true or validbinaries[program]) then
-    if variables then
-      for variable,value in next,variables do
-        local checker=validators[checkers[variable]]
-        if checker then
-          value=checker(unquoted(value),strict)
-          if value then
-            variables[variable]=optionalquoted(value)
-          else
-            report("variable %a with value %a fails the check",variable,value)
-            return
-          end
-        else
-          report("variable %a has no checker",variable)
-          return
-        end
+ if validbinaries~=false and (validbinaries==true or validbinaries[program]) then
+  if variables then
+   for variable,value in next,variables do
+    local checker=validators[checkers[variable]]
+    if checker then
+     value=checker(unquoted(value),strict)
+     if value then
+      variables[variable]=optionalquoted(value)
+     else
+      report("variable %a with value %a fails the check",variable,value)
+      return
+     end
+    else
+     report("variable %a has no checker",variable)
+     return
+    end
+   end
+   for variable,default in next,defaults do
+    local value=variables[variable]
+    if not value or value=="" then
+     local checker=validators[checkers[variable]]
+     if checker then
+      default=checker(unquoted(default),strict)
+      if default then
+       variables[variable]=optionalquoted(default)
+      else
+       report("variable %a with default %a fails the check",variable,default)
+       return
       end
-      for variable,default in next,defaults do
-        local value=variables[variable]
-        if not value or value=="" then
-          local checker=validators[checkers[variable]]
-          if checker then
-            default=checker(unquoted(default),strict)
-            if default then
-              variables[variable]=optionalquoted(default)
-            else
-              report("variable %a with default %a fails the check",variable,default)
-              return
-            end
-          end
-        end
-      end
+     end
     end
-    local command=program.." "..replace(template,variables)
-    if reporter then
-      reporter("executing runner %a: %s",name,command)
-    elseif trace then
-      report("executing runner %a: %s",name,command)
-    end
-    return command
-  elseif not reported[name] then
-    report("executing program %a of runner %a is not permitted",program,name)
-    reported[name]=true
+   end
   end
+  local command=program.." "..replace(template,variables)
+  if reporter then
+   reporter("executing runner %a: %s",name,command)
+  elseif trace then
+   report("executing runner %a: %s",name,command)
+  end
+  return command
+ elseif not reported[name] then
+  report("executing program %a of runner %a is not permitted",program,name)
+  reported[name]=true
+ end
 end
 local runners={
-  resultof=function(...)
-    local command=validcommand(...)
-    if command then
-      if trace then
-        report("resultof: %s",command)
-      end
-      local handle=iopopen(command,"r") 
-      if handle then
-        local result=handle:read("*all") or ""
-        handle:close()
-        return result
-      end
-    end
-  end,
-  execute=function(...)
-    local command=validcommand(...)
-    if command then
-      if trace then
-        report("execute: %s",command)
-      end
-      return osexecute(command)
-    end
-  end,
-  pipeto=function(...)
-    local command=validcommand(...)
-    if command then
-      if trace then
-        report("pipeto: %s",command)
-      end
-      return iopopen(command,"w") 
-    end
-  end,
-}
-function sandbox.registerrunner(specification)
-  if type(specification)=="string" then
-    local wrapped=validrunners[specification]
-    inspect(table.sortedkeys(validrunners))
-    if wrapped then
-      return wrapped
-    else
-      report("unknown predefined runner %a",specification)
-      return
-    end
+ resultof=function(...)
+  local command=validcommand(...)
+  if command then
+   if trace then
+    report("resultof: %s",command)
+   end
+   local handle=iopopen(command,"r") 
+   if handle then
+    local result=handle:read("*all") or ""
+    handle:close()
+    return result
+   end
   end
-  if type(specification)~="table" then
-    report("specification should be a table (or string)")
-    return
+ end,
+ execute=function(...)
+  local command=validcommand(...)
+  if command then
+   if trace then
+    report("execute: %s",command)
+   end
+   return osexecute(command)
   end
-  local name=specification.name
-  if type(name)~="string" then
-    report("invalid name, string expected",name)
-    return
+ end,
+ pipeto=function(...)
+  local command=validcommand(...)
+  if command then
+   if trace then
+    report("pipeto: %s",command)
+   end
+   return iopopen(command,"w") 
   end
-  if validrunners[name] then
-    report("invalid name, runner %a already defined")
-    return
+ end,
+}
+function sandbox.registerrunner(specification)
+ if type(specification)=="string" then
+  local wrapped=validrunners[specification]
+  inspect(table.sortedkeys(validrunners))
+  if wrapped then
+   return wrapped
+  else
+   report("unknown predefined runner %a",specification)
+   return
   end
-  local program=specification.program
-  if type(program)=="string" then
-  elseif type(program)=="table" then
-    program=program[platform] or program.default or program.unix
+ end
+ if type(specification)~="table" then
+  report("specification should be a table (or string)")
+  return
+ end
+ local name=specification.name
+ if type(name)~="string" then
+  report("invalid name, string expected",name)
+  return
+ end
+ if validrunners[name] then
+  report("invalid name, runner %a already defined")
+  return
+ end
+ local program=specification.program
+ if type(program)=="string" then
+ elseif type(program)=="table" then
+  program=program[platform] or program.default or program.unix
+ end
+ if type(program)~="string" or program=="" then
+  report("invalid runner %a specified for platform %a",name,platform)
+  return
+ end
+ local template=specification.template
+ if not template then
+  report("missing template for runner %a",name)
+  return
+ end
+ local method=specification.method   or "execute"
+ local checkers=specification.checkers or {}
+ local defaults=specification.defaults or {}
+ local runner=runners[method]
+ if runner then
+  local finalized=finalized 
+  local wrapped=function(variables)
+   return runner(name,program,template,checkers,defaults,variables,specification.reporter,finalized)
   end
-  if type(program)~="string" or program=="" then
-    report("invalid runner %a specified for platform %a",name,platform)
-    return
-  end
-  local template=specification.template
-  if not template then
-    report("missing template for runner %a",name)
-    return
-  end
-  local method=specification.method  or "execute"
-  local checkers=specification.checkers or {}
-  local defaults=specification.defaults or {}
-  local runner=runners[method]
-  if runner then
-    local finalized=finalized 
-    local wrapped=function(variables)
-      return runner(name,program,template,checkers,defaults,variables,specification.reporter,finalized)
-    end
-    validrunners[name]=wrapped
-    return wrapped
-  else
-    validrunners[name]=nil
-    report("invalid method for runner %a",name)
-  end
+  validrunners[name]=wrapped
+  return wrapped
+ else
+  validrunners[name]=nil
+  report("invalid method for runner %a",name)
+ end
 end
 function sandbox.getrunner(name)
-  return name and validrunners[name]
+ return name and validrunners[name]
 end
 local function suspicious(str)
-  return (find(str,"[/\\]") or find(command,"..",1,true)) and true or false
+ return (find(str,"[/\\]") or find(command,"..",1,true)) and true or false
 end
 local function binaryrunner(action,command,...)
-  if validbinaries==false then
-    report("no binaries permitted, ignoring command: %s",command)
-    return
-  end
-  if type(command)~="string" then
-    report("command should be a string")
-    return
-  end
-  local program=lpegmatch(p_split,command)
-  if not program or program=="" then
-    report("unable to filter binary from command: %s",command)
-    return
-  end
-  if validbinaries==true then
-  elseif not validbinaries[program] then
-    report("binary not permitted, ignoring command: %s",command)
-    return
-  elseif suspicious(command) then
-    report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command)
-    return
-  end
-  return action(command,...)
+ if validbinaries==false then
+  report("no binaries permitted, ignoring command: %s",command)
+  return
+ end
+ if type(command)~="string" then
+  report("command should be a string")
+  return
+ end
+ local program=lpegmatch(p_split,command)
+ if not program or program=="" then
+  report("unable to filter binary from command: %s",command)
+  return
+ end
+ if validbinaries==true then
+ elseif not validbinaries[program] then
+  report("binary not permitted, ignoring command: %s",command)
+  return
+ elseif suspicious(command) then
+  report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command)
+  return
+ end
+ return action(command,...)
 end
 local function dummyrunner(action,command,...)
-  if type(command)=="table" then
-    command=concat(command," ",command[0] and 0 or 1)
-  end
-  report("ignoring command: %s",command)
+ if type(command)=="table" then
+  command=concat(command," ",command[0] and 0 or 1)
+ end
+ report("ignoring command: %s",command)
 end
 sandbox.filehandlerone=filehandlerone
 sandbox.filehandlertwo=filehandlertwo
 sandbox.iohandler=iohandler
 function sandbox.disablerunners()
-  validbinaries=false
+ validbinaries=false
 end
 function sandbox.disablelibraries()
-  validlibraries=false
+ validlibraries=false
 end
 if FFISUPPORTED and ffi then
-  function sandbox.disablelibraries()
-    validlibraries=false
-    for k,v in next,ffi do
-      if k~="gc" then
-        ffi[k]=nil
-      end
-    end
+ function sandbox.disablelibraries()
+  validlibraries=false
+  for k,v in next,ffi do
+   if k~="gc" then
+    ffi[k]=nil
+   end
   end
-  local fiiload=ffi.load
-  if fiiload then
-    local reported={}
-    function ffi.load(name,...)
-      if validlibraries==false then
-      elseif validlibraries==true then
-        return fiiload(name,...)
-      elseif validlibraries[nameonly(name)] then
-        return fiiload(name,...)
-      else
-      end
-      if not reported[name] then
-        report("using library %a is not permitted",name)
-        reported[name]=true
-      end
-      return nil
-    end
+ end
+ local fiiload=ffi.load
+ if fiiload then
+  local reported={}
+  function ffi.load(name,...)
+   if validlibraries==false then
+   elseif validlibraries==true then
+    return fiiload(name,...)
+   elseif validlibraries[nameonly(name)] then
+    return fiiload(name,...)
+   else
+   end
+   if not reported[name] then
+    report("using library %a is not permitted",name)
+    reported[name]=true
+   end
+   return nil
   end
+ end
 end
 local overload=sandbox.overload
 local register=sandbox.register
-  overload(loadfile,filehandlerone,"loadfile") 
+ overload(loadfile,filehandlerone,"loadfile") 
 if io then
-  overload(io.open,filehandlerone,"io.open")
-  overload(io.popen,binaryrunner,"io.popen")
-  overload(io.input,iohandler,"io.input")
-  overload(io.output,iohandler,"io.output")
-  overload(io.lines,filehandlerone,"io.lines")
+ overload(io.open,filehandlerone,"io.open")
+ overload(io.popen,binaryrunner,"io.popen")
+ overload(io.input,iohandler,"io.input")
+ overload(io.output,iohandler,"io.output")
+ overload(io.lines,filehandlerone,"io.lines")
 end
 if os then
-  overload(os.execute,binaryrunner,"os.execute")
-  overload(os.spawn,dummyrunner,"os.spawn")
-  overload(os.exec,dummyrunner,"os.exec")
-  overload(os.resultof,binaryrunner,"os.resultof")
-  overload(os.pipeto,binaryrunner,"os.pipeto")
-  overload(os.rename,filehandlertwo,"os.rename")
-  overload(os.remove,filehandlerone,"os.remove")
+ overload(os.execute,binaryrunner,"os.execute")
+ overload(os.spawn,dummyrunner,"os.spawn")
+ overload(os.exec,dummyrunner,"os.exec")
+ overload(os.resultof,binaryrunner,"os.resultof")
+ overload(os.pipeto,binaryrunner,"os.pipeto")
+ overload(os.rename,filehandlertwo,"os.rename")
+ overload(os.remove,filehandlerone,"os.remove")
 end
 if lfs then
-  overload(lfs.chdir,filehandlerone,"lfs.chdir")
-  overload(lfs.mkdir,filehandlerone,"lfs.mkdir")
-  overload(lfs.rmdir,filehandlerone,"lfs.rmdir")
-  overload(lfs.isfile,filehandlerone,"lfs.isfile")
-  overload(lfs.isdir,filehandlerone,"lfs.isdir")
-  overload(lfs.attributes,filehandlerone,"lfs.attributes")
-  overload(lfs.dir,filehandlerone,"lfs.dir")
-  overload(lfs.lock_dir,filehandlerone,"lfs.lock_dir")
-  overload(lfs.touch,filehandlerone,"lfs.touch")
-  overload(lfs.link,filehandlertwo,"lfs.link")
-  overload(lfs.setmode,filehandlerone,"lfs.setmode")
-  overload(lfs.readlink,filehandlerone,"lfs.readlink")
-  overload(lfs.shortname,filehandlerone,"lfs.shortname")
-  overload(lfs.symlinkattributes,filehandlerone,"lfs.symlinkattributes")
+ overload(lfs.chdir,filehandlerone,"lfs.chdir")
+ overload(lfs.mkdir,filehandlerone,"lfs.mkdir")
+ overload(lfs.rmdir,filehandlerone,"lfs.rmdir")
+ overload(lfs.isfile,filehandlerone,"lfs.isfile")
+ overload(lfs.isdir,filehandlerone,"lfs.isdir")
+ overload(lfs.attributes,filehandlerone,"lfs.attributes")
+ overload(lfs.dir,filehandlerone,"lfs.dir")
+ overload(lfs.lock_dir,filehandlerone,"lfs.lock_dir")
+ overload(lfs.touch,filehandlerone,"lfs.touch")
+ overload(lfs.link,filehandlertwo,"lfs.link")
+ overload(lfs.setmode,filehandlerone,"lfs.setmode")
+ overload(lfs.readlink,filehandlerone,"lfs.readlink")
+ overload(lfs.shortname,filehandlerone,"lfs.shortname")
+ overload(lfs.symlinkattributes,filehandlerone,"lfs.symlinkattributes")
 end
 if zip then
-  zip.open=register(zip.open,filehandlerone,"zip.open")
+ zip.open=register(zip.open,filehandlerone,"zip.open")
 end
 if fontloader then
-  fontloader.open=register(fontloader.open,filehandlerone,"fontloader.open")
-  fontloader.info=register(fontloader.info,filehandlerone,"fontloader.info")
+ fontloader.open=register(fontloader.open,filehandlerone,"fontloader.open")
+ fontloader.info=register(fontloader.info,filehandlerone,"fontloader.info")
 end
 if epdf then
-  epdf.open=register(epdf.open,filehandlerone,"epdf.open")
+ epdf.open=register(epdf.open,filehandlerone,"epdf.open")
 end
 sandbox.registerroot=registerroot
 sandbox.registerbinary=registerbinary
@@ -11585,14 +15044,14 @@
 
 package.loaded["util-mrg"] = package.loaded["util-mrg"] or true
 
--- original size: 7757, stripped down to: 6015
+-- original size: 7819, stripped down to: 5881
 
 if not modules then modules={} end modules ['util-mrg']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 gsub,format=string.gsub,string.format
 local concat=table.concat
@@ -11620,19 +15079,19 @@
 ]]
 local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]]
 local function self_fake()
-  return m_faked
+ return m_faked
 end
 local function self_nothing()
-  return ""
+ return ""
 end
 local function self_load(name)
-  local data=io.loaddata(name) or ""
-  if data=="" then
-    report("unknown file %a",name)
-  else
-    report("inserting file %a",name)
-  end
-  return data or ""
+ local data=io.loaddata(name) or ""
+ if data=="" then
+  report("unknown file %a",name)
+ else
+  report("inserting file %a",name)
+ end
+ return data or ""
 end
 local space=patterns.space
 local eol=patterns.newline
@@ -11661,98 +15120,99 @@
 local pack=digit*space^1*operator4*optionalspacing+optionalspacing*operator1*optionalspacing+optionalspacing*operator2*optionalspaces+mandatespacing*operator3*mandatespaces+optionalspaces*separator*optionalspaces
 local lines=emptyline^2/"\n"
 local spaces=(space*space)/" "
+local spaces=(space*space*space*space)/" "
 local compact=Cs ((
-  ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1
+ ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1
 )^1 )
 local strip=Cs((emptyline^2/"\n"+1)^0)
 local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1)
 function merger.compact(data)
-  return lpegmatch(strip,lpegmatch(compact,data))
+ return lpegmatch(strip,lpegmatch(compact,data))
 end
 local function self_compact(data)
-  local delta=0
-  if merger.strip_comment then
-    local before=#data
-    data=lpegmatch(compact,data)
-    data=lpegmatch(strip,data)
-    local after=#data
-    delta=before-after
-    report("original size %s, compacted to %s, stripped %s",before,after,delta)
-    data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
-  end
-  return lpegmatch(stripreturn,data) or data,delta
+ local delta=0
+ if merger.strip_comment then
+  local before=#data
+  data=lpegmatch(compact,data)
+  data=lpegmatch(strip,data)
+  local after=#data
+  delta=before-after
+  report("original size %s, compacted to %s, stripped %s",before,after,delta)
+  data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
+ end
+ return lpegmatch(stripreturn,data) or data,delta
 end
 local function self_save(name,data)
-  if data~="" then
-    io.savedata(name,data)
-    report("saving %s with size %s",name,#data)
-  end
+ if data~="" then
+  io.savedata(name,data)
+  report("saving %s with size %s",name,#data)
+ end
 end
 local function self_swap(data,code)
-  return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or ""
+ return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or ""
 end
 local function self_libs(libs,list)
-  local result,f,frozen,foundpath={},nil,false,nil
-  result[#result+1]="\n"
-  if type(libs)=='string' then libs={ libs } end
-  if type(list)=='string' then list={ list } end
+ local result,f,frozen,foundpath={},nil,false,nil
+ result[#result+1]="\n"
+ if type(libs)=='string' then libs={ libs } end
+ if type(list)=='string' then list={ list } end
+ for i=1,#libs do
+  local lib=libs[i]
+  for j=1,#list do
+   local pth=gsub(list[j],"\\","/") 
+   report("checking library path %a",pth)
+   local name=pth.."/"..lib
+   if lfs.isfile(name) then
+    foundpath=pth
+   end
+  end
+  if foundpath then break end
+ end
+ if foundpath then
+  report("using library path %a",foundpath)
+  local right,wrong,original,stripped={},{},0,0
   for i=1,#libs do
-    local lib=libs[i]
-    for j=1,#list do
-      local pth=gsub(list[j],"\\","/") 
-      report("checking library path %a",pth)
-      local name=pth.."/"..lib
-      if lfs.isfile(name) then
-        foundpath=pth
-      end
-    end
-    if foundpath then break end
+   local lib=libs[i]
+   local fullname=foundpath.."/"..lib
+   if lfs.isfile(fullname) then
+    report("using library %a",fullname)
+    local preloaded=file.nameonly(lib)
+    local data=io.loaddata(fullname,true)
+    original=original+#data
+    local data,delta=self_compact(data)
+    right[#right+1]=lib
+    result[#result+1]=m_begin_closure
+    result[#result+1]=format(m_preloaded,preloaded,preloaded)
+    result[#result+1]=data
+    result[#result+1]=m_end_closure
+    stripped=stripped+delta
+   else
+    report("skipping library %a",fullname)
+    wrong[#wrong+1]=lib
+   end
   end
-  if foundpath then
-    report("using library path %a",foundpath)
-    local right,wrong,original,stripped={},{},0,0
-    for i=1,#libs do
-      local lib=libs[i]
-      local fullname=foundpath.."/"..lib
-      if lfs.isfile(fullname) then
-        report("using library %a",fullname)
-        local preloaded=file.nameonly(lib)
-        local data=io.loaddata(fullname,true)
-        original=original+#data
-        local data,delta=self_compact(data)
-        right[#right+1]=lib
-        result[#result+1]=m_begin_closure
-        result[#result+1]=format(m_preloaded,preloaded,preloaded)
-        result[#result+1]=data
-        result[#result+1]=m_end_closure
-        stripped=stripped+delta
-      else
-        report("skipping library %a",fullname)
-        wrong[#wrong+1]=lib
-      end
-    end
-    right=#right>0 and concat(right," ") or "-"
-    wrong=#wrong>0 and concat(wrong," ") or "-"
-    report("used libraries: %a",right)
-    report("skipped libraries: %a",wrong)
-    report("original bytes: %a",original)
-    report("stripped bytes: %a",stripped)
-    result[#result+1]=format(m_report,right,wrong,original,stripped)
-  else
-    report("no valid library path found")
-  end
-  return concat(result,"\n\n")
+  right=#right>0 and concat(right," ") or "-"
+  wrong=#wrong>0 and concat(wrong," ") or "-"
+  report("used libraries: %a",right)
+  report("skipped libraries: %a",wrong)
+  report("original bytes: %a",original)
+  report("stripped bytes: %a",stripped)
+  result[#result+1]=format(m_report,right,wrong,original,stripped)
+ else
+  report("no valid library path found")
+ end
+ return concat(result,"\n\n")
 end
 function merger.selfcreate(libs,list,target)
-  if target then
-    self_save(target,self_swap(self_fake(),self_libs(libs,list)))
-  end
+ if target then
+  self_save(target,self_swap(self_fake(),self_libs(libs,list)))
+ end
 end
 function merger.selfmerge(name,libs,list,target)
-  self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
+ self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
 end
 function merger.selfclean(name)
-  self_save(name,self_swap(self_load(name),self_nothing()))
+ self_save(name,self_swap(self_load(name),self_nothing()))
 end
 
 
@@ -11762,14 +15222,14 @@
 
 package.loaded["util-env"] = package.loaded["util-env"] or true
 
--- original size: 9400, stripped down to: 5499
+-- original size: 9738, stripped down to: 5531
 
 if not modules then modules={} end modules ['util-env']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 allocate,mark=utilities.storage.allocate,utilities.storage.mark
 local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
@@ -11781,178 +15241,193 @@
 setlocale(nil,nil)
 local report=logs.reporter("system")
 function os.setlocale(a,b)
-  if a or b then
-    if report then
-      report()
-      report("You're messing with os.locale in a supposedly locale neutral enviroment. From")
-      report("now on are on your own and without support. Crashes or unexpected side effects")
-      report("can happen but don't bother the luatex and context developer team with it.")
-      report()
-      report=nil
-    end
-    setlocale(a,b)
+ if a or b then
+  if report then
+   report()
+   report("You're messing with os.locale in a supposedly locale neutral enviroment. From")
+   report("now on are on your own and without support. Crashes or unexpected side effects")
+   report("can happen but don't bother the luatex and context developer team with it.")
+   report()
+   report=nil
   end
+  setlocale(a,b)
+ end
 end
 local validengines=allocate {
-  ["luatex"]=true,
-  ["luajittex"]=true,
+ ["luatex"]=true,
+ ["luajittex"]=true,
 }
 local basicengines=allocate {
-  ["luatex"]="luatex",
-  ["texlua"]="luatex",
-  ["texluac"]="luatex",
-  ["luajittex"]="luajittex",
-  ["texluajit"]="luajittex",
+ ["luatex"]="luatex",
+ ["texlua"]="luatex",
+ ["texluac"]="luatex",
+ ["luajittex"]="luajittex",
+ ["texluajit"]="luajittex",
 }
 local luaengines=allocate {
-  ["lua"]=true,
-  ["luajit"]=true,
+ ["lua"]=true,
+ ["luajit"]=true,
 }
 environment.validengines=validengines
 environment.basicengines=basicengines
 if not arg then
-  environment.used_as_library=true
+ environment.used_as_library=true
 elseif luaengines[file.removesuffix(arg[-1])] then
 elseif validengines[file.removesuffix(arg[0])] then
-  if arg[1]=="--luaonly" then
-    arg[-1]=arg[0]
-    arg[ 0]=arg[2]
-    for k=3,#arg do
-      arg[k-2]=arg[k]
-    end
-    remove(arg) 
-    remove(arg) 
-  else
+ if arg[1]=="--luaonly" then
+  arg[-1]=arg[0]
+  arg[ 0]=arg[2]
+  for k=3,#arg do
+   arg[k-2]=arg[k]
   end
-  local originalzero=file.basename(arg[0])
-  local specialmapping={ luatools=="base" }
-  if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then
+  remove(arg) 
+  remove(arg) 
+ else
+ end
+ local originalzero=file.basename(arg[0])
+ local specialmapping={ luatools=="base" }
+ if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then
     arg[0]=specialmapping[originalzero] or originalzero
     insert(arg,0,"--script")
     insert(arg,0,"mtxrun")
-  end
+ end
 end
 environment.arguments=allocate()
 environment.files=allocate()
 environment.sortedflags=nil
 function environment.initializearguments(arg)
-  local arguments,files={},{}
-  environment.arguments,environment.files,environment.sortedflags=arguments,files,nil
-  for index=1,#arg do
-    local argument=arg[index]
-    if index>0 then
-      local flag,value=match(argument,"^%-+(.-)=(.-)$")
-      if flag then
-        flag=gsub(flag,"^c:","")
-        arguments[flag]=unquoted(value or "")
-      else
-        flag=match(argument,"^%-+(.+)")
-        if flag then
-          flag=gsub(flag,"^c:","")
-          arguments[flag]=true
-        else
-          files[#files+1]=argument
-        end
-      end
+ local arguments={}
+ local files={}
+ environment.arguments=arguments
+ environment.files=files
+ environment.sortedflags=nil
+ for index=1,#arg do
+  local argument=arg[index]
+  if index>0 then
+   local flag,value=match(argument,"^%-+(.-)=(.-)$")
+   if flag then
+    flag=gsub(flag,"^c:","")
+    arguments[flag]=unquoted(value or "")
+   else
+    flag=match(argument,"^%-+(.+)")
+    if flag then
+     flag=gsub(flag,"^c:","")
+     arguments[flag]=true
+    else
+     files[#files+1]=argument
     end
+   end
   end
-  environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua')
+ end
+ if not environment.ownname then
+  if os.selfpath and os.selfname then
+   environment.ownname=file.addsuffix(file.join(os.selfpath,os.selfname),"lua")
+  end
+ end
+ environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua')
 end
 function environment.setargument(name,value)
-  environment.arguments[name]=value
+ environment.arguments[name]=value
 end
 function environment.getargument(name,partial)
-  local arguments,sortedflags=environment.arguments,environment.sortedflags
-  if arguments[name] then
-    return arguments[name]
-  elseif partial then
-    if not sortedflags then
-      sortedflags=allocate(table.sortedkeys(arguments))
-      for k=1,#sortedflags do
-        sortedflags[k]="^"..sortedflags[k]
-      end
-      environment.sortedflags=sortedflags
-    end
-    for k=1,#sortedflags do
-      local v=sortedflags[k]
-      if find(name,v) then
-        return arguments[sub(v,2,#v)]
-      end
-    end
+ local arguments,sortedflags=environment.arguments,environment.sortedflags
+ if arguments[name] then
+  return arguments[name]
+ elseif partial then
+  if not sortedflags then
+   sortedflags=allocate(table.sortedkeys(arguments))
+   for k=1,#sortedflags do
+    sortedflags[k]="^"..sortedflags[k]
+   end
+   environment.sortedflags=sortedflags
   end
-  return nil
+  for k=1,#sortedflags do
+   local v=sortedflags[k]
+   if find(name,v) then
+    return arguments[sub(v,2,#v)]
+   end
+  end
+ end
+ return nil
 end
 environment.argument=environment.getargument
 function environment.splitarguments(separator) 
-  local done,before,after=false,{},{}
-  local originalarguments=environment.originalarguments
-  for k=1,#originalarguments do
-    local v=originalarguments[k]
-    if not done and v==separator then
-      done=true
-    elseif done then
-      after[#after+1]=v
-    else
-      before[#before+1]=v
-    end
+ local done,before,after=false,{},{}
+ local originalarguments=environment.originalarguments
+ for k=1,#originalarguments do
+  local v=originalarguments[k]
+  if not done and v==separator then
+   done=true
+  elseif done then
+   after[#after+1]=v
+  else
+   before[#before+1]=v
   end
-  return before,after
+ end
+ return before,after
 end
 function environment.reconstructcommandline(arg,noquote)
-  local resolveprefix=resolvers.resolve 
-  arg=arg or environment.originalarguments
-  if noquote and #arg==1 then
-    return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
-  elseif #arg>0 then
-    local result={}
-    for i=1,#arg do
-      result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
-    end
-    return concat(result," ")
-  else
-    return ""
+ local resolveprefix=resolvers.resolve 
+ arg=arg or environment.originalarguments
+ if noquote and #arg==1 then
+  return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
+ elseif #arg>0 then
+  local result={}
+  for i=1,#arg do
+   result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
   end
+  return concat(result," ")
+ else
+  return ""
+ end
 end
 function environment.relativepath(path,root)
-  if not path then
-    path=""
+ if not path then
+  path=""
+ end
+ if not file.is_rootbased_path(path) then
+  if not root then
+   root=file.pathpart(environment.ownscript or environment.ownname or ".")
   end
-  if not file.is_rootbased_path(path) then
-    if not root then
-      root=file.pathpart(environment.ownscript or environment.ownname or ".")
-    end
-    if root=="" then
-      root="."
-    end
-    path=root.."/"..path
+  if root=="" then
+   root="."
   end
-  return file.collapsepath(path,true)
+  path=root.."/"..path
+ end
+ return file.collapsepath(path,true)
 end
 if arg then
-  local newarg,instring={},false
-  for index=1,#arg do
-    local argument=arg[index]
-    if find(argument,"^\"") then
-      newarg[#newarg+1]=gsub(argument,"^\"","")
-      if not find(argument,"\"$") then
-        instring=true
-      end
-    elseif find(argument,"\"$") then
-      newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","")
-      instring=false
-    elseif instring then
-      newarg[#newarg]=newarg[#newarg].." "..argument
-    else
-      newarg[#newarg+1]=argument
-    end
+ local newarg,instring={},false
+ for index=1,#arg do
+  local argument=arg[index]
+  if find(argument,"^\"") then
+   if find(argument,"\"$") then
+    newarg[#newarg+1]=gsub(argument,"^\"(.-)\"$","%1")
+    instring=false
+   else
+    newarg[#newarg+1]=gsub(argument,"^\"","")
+    instring=true
+   end
+  elseif find(argument,"\"$") then
+   if instring then
+    newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","")
+    instring=false
+   else
+    newarg[#newarg+1]=argument
+   end
+  elseif instring then
+   newarg[#newarg]=newarg[#newarg].." "..argument
+  else
+   newarg[#newarg+1]=argument
   end
-  for i=1,-5,-1 do
-    newarg[i]=arg[i]
-  end
-  environment.initializearguments(newarg)
-  environment.originalarguments=mark(newarg)
-  environment.rawarguments=mark(arg)
-  arg={} 
+ end
+ for i=1,-5,-1 do
+  newarg[i]=arg[i]
+ end
+ environment.initializearguments(newarg)
+ environment.originalarguments=mark(newarg)
+ environment.rawarguments=mark(arg)
+ arg={} 
 end
 
 
@@ -11962,17 +15437,18 @@
 
 package.loaded["luat-env"] = package.loaded["luat-env"] or true
 
--- original size: 5820, stripped down to: 4155
+-- original size: 6134, stripped down to: 4118
 
  if not modules then modules={} end modules ['luat-env']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 rawset,rawget,loadfile,assert=rawset,rawget,loadfile,assert
-local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local rawset,rawget,loadfile=rawset,rawget,loadfile
+local gsub=string.gsub
+local trace_locating=false  trackers.register("resolvers.locating",function(v) trace_locating=v end)
 local report_lua=logs.reporter("resolvers","lua")
 local luautilities=utilities.lua
 local luasuffixes=luautilities.suffixes
@@ -11980,133 +15456,146 @@
 environment=environment or {}
 local environment=environment
 local mt={
-  __index=function(_,k)
-    if k=="version" then
-      local version=texgettoks and texgettoks("contextversiontoks")
-      if version and version~="" then
-        rawset(environment,"version",version)
-        return version
-      else
-        return "unknown"
-      end
-    elseif k=="kind" then
-      local kind=texgettoks and texgettoks("contextkindtoks")
-      if kind and kind~="" then
-        rawset(environment,"kind",kind)
-        return kind
-      else
-        return "unknown"
-      end
-    elseif k=="jobname" or k=="formatname" then
-      local name=tex and tex[k]
-      if name or name=="" then
-        rawset(environment,k,name)
-        return name
-      else
-        return "unknown"
-      end
-    elseif k=="outputfilename" then
-      local name=environment.jobname
-      rawset(environment,k,name)
-      return name
-    end
+ __index=function(_,k)
+  if k=="version" then
+   local version=texgettoks and texgettoks("contextversiontoks")
+   if version and version~="" then
+    rawset(environment,"version",version)
+    return version
+   else
+    return "unknown"
+   end
+  elseif k=="kind" then
+   local kind=texgettoks and texgettoks("contextkindtoks")
+   if kind and kind~="" then
+    rawset(environment,"kind",kind)
+    return kind
+   else
+    return "unknown"
+   end
+  elseif k=="jobname" or k=="formatname" then
+   local name=tex and tex[k]
+   if name or name=="" then
+    rawset(environment,k,name)
+    return name
+   else
+    return "unknown"
+   end
+  elseif k=="outputfilename" then
+   local name=environment.jobname
+   rawset(environment,k,name)
+   return name
   end
+ end
 }
 setmetatable(environment,mt)
 function environment.texfile(filename)
-  return resolvers.findfile(filename,'tex')
+ return resolvers.findfile(filename,'tex')
 end
 function environment.luafile(filename) 
-  local resolved=resolvers.findfile(filename,'tex') or ""
-  if resolved~="" then
-    return resolved
-  end
-  resolved=resolvers.findfile(filename,'texmfscripts') or ""
-  if resolved~="" then
-    return resolved
-  end
-  return resolvers.findfile(filename,'luatexlibs') or ""
+ local resolved=resolvers.findfile(filename,'tex') or ""
+ if resolved~="" then
+  return resolved
+ end
+ resolved=resolvers.findfile(filename,'texmfscripts') or ""
+ if resolved~="" then
+  return resolved
+ end
+ return resolvers.findfile(filename,'luatexlibs') or ""
 end
-local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end)
+local stripindeed=false  directives.register("system.compile.strip",function(v) stripindeed=v end)
 local function strippable(filename)
-  if stripindeed then
-    local modu=modules[file.nameonly(filename)]
-    return modu and modu.dataonly
-  else
-    return false
-  end
+ if stripindeed then
+  local modu=modules[file.nameonly(filename)]
+  return modu and modu.dataonly
+ else
+  return false
+ end
 end
 function environment.luafilechunk(filename,silent,macros) 
-  filename=file.replacesuffix(filename,"lua")
-  local fullname=environment.luafile(filename)
-  if fullname and fullname~="" then
-    local data=luautilities.loadedluacode(fullname,strippable,filename,macros)
-    if not silent then
-      report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
-    end
-    return data
-  else
-    if not silent then
-      report_lua("unknown file %a",filename)
-    end
-    return nil
+ filename=file.replacesuffix(filename,"lua")
+ local fullname=environment.luafile(filename)
+ if fullname and fullname~="" then
+  local data=luautilities.loadedluacode(fullname,strippable,filename,macros)
+  if not silent then
+   report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
   end
+  return data
+ else
+  if not silent then
+   report_lua("unknown file %a",filename)
+  end
+  return nil
+ end
 end
 function environment.loadluafile(filename,version)
-  local lucname,luaname,chunk
-  local basename=file.removesuffix(filename)
-  if basename==filename then
-    luaname=file.addsuffix(basename,luasuffixes.lua)
-    lucname=file.addsuffix(basename,luasuffixes.luc)
-  else
-    luaname=basename 
-    lucname=nil
+ local lucname,luaname,chunk
+ local basename=file.removesuffix(filename)
+ if basename==filename then
+  luaname=file.addsuffix(basename,luasuffixes.lua)
+  lucname=file.addsuffix(basename,luasuffixes.luc)
+ else
+  luaname=filename 
+  lucname=nil
+ end
+ local fullname=(lucname and environment.luafile(lucname)) or ""
+ if fullname~="" then
+  if trace_locating then
+   report_lua("loading %a",fullname)
   end
-  local fullname=(lucname and environment.luafile(lucname)) or ""
-  if fullname~="" then
+  chunk=loadfile(fullname) 
+ end
+ if chunk then
+  chunk()
+  if version then
+   local v=version 
+   if modules and modules[filename] then
+    v=modules[filename].version 
+   elseif versions and versions[filename] then
+    v=versions[filename]  
+   end
+   if v==version then
+    return true
+   else
     if trace_locating then
-      report_lua("loading %a",fullname)
+     report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
     end
-    chunk=loadfile(fullname) 
+    environment.loadluafile(filename)
+   end
+  else
+   return true
   end
-  if chunk then
-    assert(chunk)()
-    if version then
-      local v=version 
-      if modules and modules[filename] then
-        v=modules[filename].version 
-      elseif versions and versions[filename] then
-        v=versions[filename]    
-      end
-      if v==version then
-        return true
-      else
-        if trace_locating then
-          report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
-        end
-        environment.loadluafile(filename)
-      end
-    else
-      return true
-    end
+ end
+ fullname=(luaname and environment.luafile(luaname)) or ""
+ if fullname~="" then
+  if trace_locating then
+   report_lua("loading %a",fullname)
   end
-  fullname=(luaname and environment.luafile(luaname)) or ""
-  if fullname~="" then
-    if trace_locating then
-      report_lua("loading %a",fullname)
-    end
-    chunk=loadfile(fullname) 
-    if not chunk then
-      if trace_locating then
-        report_lua("unknown file %a",filename)
-      end
-    else
-      assert(chunk)()
-      return true
-    end
+  chunk=loadfile(fullname) 
+  if not chunk then
+   if trace_locating then
+    report_lua("unknown file %a",filename)
+   end
+  else
+   chunk()
+   return true
   end
-  return false
+ end
+ return false
 end
+environment.filenames=setmetatable({},{
+ __index=function(t,k)
+  local v=environment.files[k]
+  if v then
+   return (gsub(v,"%.+$",""))
+  end
+ end,
+ __newindex=function(t,k)
+ end,
+ __len=function(t)
+  return #environment.files
+ end,
+} )
 
 
 end -- of closure
@@ -12115,16 +15604,16 @@
 
 package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
 
--- original size: 60383, stripped down to: 38562
+-- original size: 60383, stripped down to: 35698
 
 if not modules then modules={} end modules ['lxml-tab']={
-  version=1.001,
-  comment="this module is the basis for the lxml-* ones",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
-local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end)
+local trace_entities=false  trackers.register("xml.entities",function(v) trace_entities=v end)
 local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end
 if lpeg.setmaxstack then lpeg.setmaxstack(1000) end 
 xml=xml or {}
@@ -12142,17 +15631,17 @@
 local check=P(false)
 local parse=check
 function xml.registerns(namespace,pattern) 
-  check=check+C(P(lower(pattern)))/namespace
-  parse=P { P(check)+1*V(1) }
+ check=check+C(P(lower(pattern)))/namespace
+ parse=P { P(check)+1*V(1) }
 end
 function xml.checkns(namespace,url)
-  local ns=lpegmatch(parse,lower(url))
-  if ns and namespace~=ns then
-    xml.xmlns[namespace]=ns
-  end
+ local ns=lpegmatch(parse,lower(url))
+ if ns and namespace~=ns then
+  xml.xmlns[namespace]=ns
+ end
 end
 function xml.resolvens(url)
-   return lpegmatch(parse,lower(url)) or ""
+  return lpegmatch(parse,lower(url)) or ""
 end
 end
 local nsremap,resolvens=xml.xmlns,xml.resolvens
@@ -12170,661 +15659,661 @@
 local handle_any_entity_dtd
 local handle_any_entity_text
 local function preparexmlstate(settings)
-  if settings then
-    linenumbers=settings.linenumbers
-    stack={}
-    level=0
-    top={}
-    at={}
-    mt={}
-    dt={}
-    nt=0  
-    xmlns={}
-    errorstr=nil
-    strip=settings.strip_cm_and_dt
-    utfize=settings.utfize_entities
-    resolve=settings.resolve_entities      
-    resolve_predefined=settings.resolve_predefined_entities 
-    unify_predefined=settings.unify_predefined_entities  
-    cleanup=settings.text_cleanup
-    entities=settings.entities or {}
-    currentfilename=settings.currentresource
-    currentline=1
-    parameters={}
-    reported_at_errors={}
-    dcache={}
-    hcache={}
-    acache={}
-    if utfize==nil then
-      settings.utfize_entities=true
-      utfize=true
-    end
-    if resolve_predefined==nil then
-      settings.resolve_predefined_entities=true
-      resolve_predefined=true
-    end
-  else
-    linenumbers=false
-    stack=nil
-    level=nil
-    top=nil
-    at=nil
-    mt=nil
-    dt=nil
-    nt=nil
-    xmlns=nil
-    errorstr=nil
-    strip=nil
-    utfize=nil
-    resolve=nil
-    resolve_predefined=nil
-    unify_predefined=nil
-    cleanup=nil
-    entities=nil
-    parameters=nil
-    reported_at_errors=nil
-    dcache=nil
-    hcache=nil
-    acache=nil
-    currentfilename=nil
-    currentline=1
+ if settings then
+  linenumbers=settings.linenumbers
+  stack={}
+  level=0
+  top={}
+  at={}
+  mt={}
+  dt={}
+  nt=0   
+  xmlns={}
+  errorstr=nil
+  strip=settings.strip_cm_and_dt
+  utfize=settings.utfize_entities
+  resolve=settings.resolve_entities   
+  resolve_predefined=settings.resolve_predefined_entities 
+  unify_predefined=settings.unify_predefined_entities   
+  cleanup=settings.text_cleanup
+  entities=settings.entities or {}
+  currentfilename=settings.currentresource
+  currentline=1
+  parameters={}
+  reported_at_errors={}
+  dcache={}
+  hcache={}
+  acache={}
+  if utfize==nil then
+   settings.utfize_entities=true
+   utfize=true
   end
+  if resolve_predefined==nil then
+   settings.resolve_predefined_entities=true
+   resolve_predefined=true
+  end
+ else
+  linenumbers=false
+  stack=nil
+  level=nil
+  top=nil
+  at=nil
+  mt=nil
+  dt=nil
+  nt=nil
+  xmlns=nil
+  errorstr=nil
+  strip=nil
+  utfize=nil
+  resolve=nil
+  resolve_predefined=nil
+  unify_predefined=nil
+  cleanup=nil
+  entities=nil
+  parameters=nil
+  reported_at_errors=nil
+  dcache=nil
+  hcache=nil
+  acache=nil
+  currentfilename=nil
+  currentline=1
+ end
 end
 local function initialize_mt(root)
-  mt={ __index=root } 
+ mt={ __index=root } 
 end
 function xml.setproperty(root,k,v)
-  getmetatable(root).__index[k]=v
+ getmetatable(root).__index[k]=v
 end
 function xml.checkerror(top,toclose)
-  return "" 
+ return "" 
 end
 local checkns=xml.checkns
 local function add_attribute(namespace,tag,value)
-  if cleanup and value~="" then
-    value=cleanup(value) 
-  end
-  if tag=="xmlns" then
-    xmlns[#xmlns+1]=resolvens(value)
-    at[tag]=value
-  elseif namespace=="" then
-    at[tag]=value
-  elseif namespace=="xmlns" then
-    checkns(tag,value)
-    at["xmlns:"..tag]=value
-  else
-    at[namespace..":"..tag]=value
-  end
+ if cleanup and value~="" then
+  value=cleanup(value) 
+ end
+ if tag=="xmlns" then
+  xmlns[#xmlns+1]=resolvens(value)
+  at[tag]=value
+ elseif namespace=="" then
+  at[tag]=value
+ elseif namespace=="xmlns" then
+  checkns(tag,value)
+  at["xmlns:"..tag]=value
+ else
+  at[namespace..":"..tag]=value
+ end
 end
 local function add_empty(spacing,namespace,tag)
-  if spacing~="" then
-    nt=nt+1
-    dt[nt]=spacing
-  end
-  local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
-  top=stack[level]
-  dt=top.dt
-  nt=#dt+1
-  local t=linenumbers and {
-    ns=namespace or "",
-    rn=resolved,
-    tg=tag,
-    at=at,
-    dt={},
-    ni=nt,
-    cf=currentfilename,
-    cl=currentline,
-    __p__=top,
-  } or {
-    ns=namespace or "",
-    rn=resolved,
-    tg=tag,
-    at=at,
-    dt={},
-    ni=nt,
-    __p__=top,
-  }
-  dt[nt]=t
-  setmetatable(t,mt)
-  if at.xmlns then
-    remove(xmlns)
-  end
-  at={}
+ if spacing~="" then
+  nt=nt+1
+  dt[nt]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top=stack[level]
+ dt=top.dt
+ nt=#dt+1
+ local t=linenumbers and {
+  ns=namespace or "",
+  rn=resolved,
+  tg=tag,
+  at=at,
+  dt={},
+  ni=nt,
+  cf=currentfilename,
+  cl=currentline,
+  __p__=top,
+ } or {
+  ns=namespace or "",
+  rn=resolved,
+  tg=tag,
+  at=at,
+  dt={},
+  ni=nt,
+  __p__=top,
+ }
+ dt[nt]=t
+ setmetatable(t,mt)
+ if at.xmlns then
+  remove(xmlns)
+ end
+ at={}
 end
 local function add_begin(spacing,namespace,tag)
-  if spacing~="" then
-    nt=nt+1
-    dt[nt]=spacing
-  end
-  local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
-  dt={}
-  top=linenumbers and {
-    ns=namespace or "",
-    rn=resolved,
-    tg=tag,
-    at=at,
-    dt=dt,
-    ni=nil,
-    cf=currentfilename,
-    cl=currentline,
-    __p__=stack[level],
-  } or {
-    ns=namespace or "",
-    rn=resolved,
-    tg=tag,
-    at=at,
-    dt=dt,
-    ni=nil,
-    __p__=stack[level],
-  }
-  setmetatable(top,mt)
-  nt=0
-  level=level+1
-  stack[level]=top
-  at={}
+ if spacing~="" then
+  nt=nt+1
+  dt[nt]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ dt={}
+ top=linenumbers and {
+  ns=namespace or "",
+  rn=resolved,
+  tg=tag,
+  at=at,
+  dt=dt,
+  ni=nil,
+  cf=currentfilename,
+  cl=currentline,
+  __p__=stack[level],
+ } or {
+  ns=namespace or "",
+  rn=resolved,
+  tg=tag,
+  at=at,
+  dt=dt,
+  ni=nil,
+  __p__=stack[level],
+ }
+ setmetatable(top,mt)
+ nt=0
+ level=level+1
+ stack[level]=top
+ at={}
 end
 local function add_end(spacing,namespace,tag)
-  if spacing~="" then
-    nt=nt+1
-    dt[nt]=spacing
-  end
-  local toclose=stack[level]
-  level=level-1
-  top=stack[level]
-  if level<1 then
-    errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
-    report_xml(errorstr)
-  elseif toclose.tg~=tag then 
-    errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
-    report_xml(errorstr)
-  end
-  dt=top.dt
-  nt=#dt+1
-  dt[nt]=toclose
-  toclose.ni=nt 
-  if toclose.at.xmlns then
-    remove(xmlns)
-  end
+ if spacing~="" then
+  nt=nt+1
+  dt[nt]=spacing
+ end
+ local toclose=stack[level]
+ level=level-1
+ top=stack[level]
+ if level<1 then
+  errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
+  report_xml(errorstr)
+ elseif toclose.tg~=tag then 
+  errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
+  report_xml(errorstr)
+ end
+ dt=top.dt
+ nt=#dt+1
+ dt[nt]=toclose
+ toclose.ni=nt 
+ if toclose.at.xmlns then
+  remove(xmlns)
+ end
 end
 local function add_text(text)
-  if text=="" then
-    return
-  end
-  if cleanup then
-    if nt>0 then
-      local s=dt[nt]
-      if type(s)=="string" then
-        dt[nt]=s..cleanup(text)
-      else
-        nt=nt+1
-        dt[nt]=cleanup(text)
-      end
-    else
-      nt=1
-      dt[1]=cleanup(text)
-    end
+ if text=="" then
+  return
+ end
+ if cleanup then
+  if nt>0 then
+   local s=dt[nt]
+   if type(s)=="string" then
+    dt[nt]=s..cleanup(text)
+   else
+    nt=nt+1
+    dt[nt]=cleanup(text)
+   end
   else
-    if nt>0 then
-      local s=dt[nt]
-      if type(s)=="string" then
-        dt[nt]=s..text
-      else
-        nt=nt+1
-        dt[nt]=text
-      end
-    else
-      nt=1
-      dt[1]=text
-    end
+   nt=1
+   dt[1]=cleanup(text)
   end
-end
-local function add_special(what,spacing,text)
-  if spacing~="" then
+ else
+  if nt>0 then
+   local s=dt[nt]
+   if type(s)=="string" then
+    dt[nt]=s..text
+   else
     nt=nt+1
-    dt[nt]=spacing
-  end
-  if strip and (what=="@cm@" or what=="@dt@") then
+    dt[nt]=text
+   end
   else
-    nt=nt+1
-    dt[nt]=linenumbers and {
-      special=true,
-      ns="",
-      tg=what,
-      ni=nil,
-      dt={ text },
-      cf=currentfilename,
-      cl=currentline,
-    } or {
-      special=true,
-      ns="",
-      tg=what,
-      ni=nil,
-      dt={ text },
-    }
+   nt=1
+   dt[1]=text
   end
+ end
 end
+local function add_special(what,spacing,text)
+ if spacing~="" then
+  nt=nt+1
+  dt[nt]=spacing
+ end
+ if strip and (what=="@cm@" or what=="@dt@") then
+ else
+  nt=nt+1
+  dt[nt]=linenumbers and {
+   special=true,
+   ns="",
+   tg=what,
+   ni=nil,
+   dt={ text },
+   cf=currentfilename,
+   cl=currentline,
+  } or {
+   special=true,
+   ns="",
+   tg=what,
+   ni=nil,
+   dt={ text },
+  }
+ end
+end
 local function set_message(txt)
-  errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","")
+ errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","")
 end
 local function attribute_value_error(str)
-  if not reported_at_errors[str] then
-    report_xml("invalid attribute value %a",str)
-    reported_at_errors[str]=true
-    at._error_=str
-  end
-  return str
+ if not reported_at_errors[str] then
+  report_xml("invalid attribute value %a",str)
+  reported_at_errors[str]=true
+  at._error_=str
+ end
+ return str
 end
 local function attribute_specification_error(str)
-  if not reported_at_errors[str] then
-    report_xml("invalid attribute specification %a",str)
-    reported_at_errors[str]=true
-    at._error_=str
-  end
-  return str
+ if not reported_at_errors[str] then
+  report_xml("invalid attribute specification %a",str)
+  reported_at_errors[str]=true
+  at._error_=str
+ end
+ return str
 end
 do
-  local badentity="&" 
-  xml.placeholders={
-    unknown_dec_entity=function(str) return str=="" and badentity or formatters["&%s;"](str) end,
-    unknown_hex_entity=function(str) return formatters["&#x%s;"](str) end,
-    unknown_any_entity=function(str) return formatters["&#x%s;"](str) end,
-  }
-  local function fromhex(s)
-    local n=tonumber(s,16)
-    if n then
-      return utfchar(n)
-    else
-      return formatters["h:%s"](s),true
-    end
+ local badentity="&" 
+ xml.placeholders={
+  unknown_dec_entity=function(str) return str=="" and badentity or formatters["&%s;"](str) end,
+  unknown_hex_entity=function(str) return formatters["&#x%s;"](str) end,
+  unknown_any_entity=function(str) return formatters["&#x%s;"](str) end,
+ }
+ local function fromhex(s)
+  local n=tonumber(s,16)
+  if n then
+   return utfchar(n)
+  else
+   return formatters["h:%s"](s),true
   end
-  local function fromdec(s)
-    local n=tonumber(s)
-    if n then
-      return utfchar(n)
-    else
-      return formatters["d:%s"](s),true
-    end
+ end
+ local function fromdec(s)
+  local n=tonumber(s)
+  if n then
+   return utfchar(n)
+  else
+   return formatters["d:%s"](s),true
   end
-  local p_rest=(1-P(";"))^0
-  local p_many=P(1)^0
-  local parsedentity=P("&#")*(P("x")*(p_rest/fromhex)+(p_rest/fromdec))*P(";")*P(-1)+P ("#")*(P("x")*(p_many/fromhex)+(p_many/fromdec))
-  xml.parsedentitylpeg=parsedentity
-  local predefined_unified={
-    [38]="&",
-    [42]=""",
-    [47]="'",
-    [74]="<",
-    [76]=">",
-  }
-  local predefined_simplified={
-    [38]="&",amp="&",
-    [42]='"',quot='"',
-    [47]="'",apos="'",
-    [74]="<",lt="<",
-    [76]=">",gt=">",
-  }
-  local nofprivates=0xF0000 
-  local privates_u={ 
-    [ [[&]] ]="&",
-    [ [["]] ]=""",
-    [ [[']] ]="'",
-    [ [[<]] ]="<",
-    [ [[>]] ]=">",
-  }
-  local privates_p={ 
-  }
-  local privates_s={ 
-    [ [["]] ]="&U+22;",
-    [ [[#]] ]="&U+23;",
-    [ [[$]] ]="&U+24;",
-    [ [[%]] ]="&U+25;",
-    [ [[&]] ]="&U+26;",
-    [ [[']] ]="&U+27;",
-    [ [[<]] ]="&U+3C;",
-    [ [[>]] ]="&U+3E;",
-    [ [[\]] ]="&U+5C;",
-    [ [[{]] ]="&U+7B;",
-    [ [[|]] ]="&U+7C;",
-    [ [[}]] ]="&U+7D;",
-    [ [[~]] ]="&U+7E;",
-  }
-  local privates_x={ 
-    [ [["]] ]="&U+22;",
-    [ [[#]] ]="&U+23;",
-    [ [[$]] ]="&U+24;",
-    [ [[%]] ]="&U+25;",
-    [ [[']] ]="&U+27;",
-    [ [[\]] ]="&U+5C;",
-    [ [[{]] ]="&U+7B;",
-    [ [[|]] ]="&U+7C;",
-    [ [[}]] ]="&U+7D;",
-    [ [[~]] ]="&U+7E;",
-  }
-  local privates_n={ 
-  }
-  local escaped=utf.remapper(privates_u,"dynamic")
-  local unprivatized=utf.remapper(privates_p,"dynamic")
-  local unspecialized=utf.remapper(privates_s,"dynamic")
-  local despecialized=utf.remapper(privates_x,"dynamic")
-  xml.unprivatized=unprivatized
-  xml.unspecialized=unspecialized
-  xml.despecialized=despecialized
-  xml.escaped=escaped
-  local function unescaped(s)
-    local p=privates_n[s]
-    if not p then
-      nofprivates=nofprivates+1
-      p=utfchar(nofprivates)
-      privates_n[s]=p
-      s="&"..s..";" 
-      privates_u[p]=s
-      privates_p[p]=s
-      privates_s[p]=s
+ end
+ local p_rest=(1-P(";"))^0
+ local p_many=P(1)^0
+ local parsedentity=P("&#")*(P("x")*(p_rest/fromhex)+(p_rest/fromdec))*P(";")*P(-1)+P ("#")*(P("x")*(p_many/fromhex)+(p_many/fromdec))
+ xml.parsedentitylpeg=parsedentity
+ local predefined_unified={
+  [38]="&",
+  [42]=""",
+  [47]="'",
+  [74]="<",
+  [76]=">",
+ }
+ local predefined_simplified={
+  [38]="&",amp="&",
+  [42]='"',quot='"',
+  [47]="'",apos="'",
+  [74]="<",lt="<",
+  [76]=">",gt=">",
+ }
+ local nofprivates=0xF0000 
+ local privates_u={ 
+  [ [[&]] ]="&",
+  [ [["]] ]=""",
+  [ [[']] ]="'",
+  [ [[<]] ]="<",
+  [ [[>]] ]=">",
+ }
+ local privates_p={ 
+ }
+ local privates_s={ 
+  [ [["]] ]="&U+22;",
+  [ [[#]] ]="&U+23;",
+  [ [[$]] ]="&U+24;",
+  [ [[%]] ]="&U+25;",
+  [ [[&]] ]="&U+26;",
+  [ [[']] ]="&U+27;",
+  [ [[<]] ]="&U+3C;",
+  [ [[>]] ]="&U+3E;",
+  [ [[\]] ]="&U+5C;",
+  [ [[{]] ]="&U+7B;",
+  [ [[|]] ]="&U+7C;",
+  [ [[}]] ]="&U+7D;",
+  [ [[~]] ]="&U+7E;",
+ }
+ local privates_x={ 
+  [ [["]] ]="&U+22;",
+  [ [[#]] ]="&U+23;",
+  [ [[$]] ]="&U+24;",
+  [ [[%]] ]="&U+25;",
+  [ [[']] ]="&U+27;",
+  [ [[\]] ]="&U+5C;",
+  [ [[{]] ]="&U+7B;",
+  [ [[|]] ]="&U+7C;",
+  [ [[}]] ]="&U+7D;",
+  [ [[~]] ]="&U+7E;",
+ }
+ local privates_n={ 
+ }
+ local escaped=utf.remapper(privates_u,"dynamic")
+ local unprivatized=utf.remapper(privates_p,"dynamic")
+ local unspecialized=utf.remapper(privates_s,"dynamic")
+ local despecialized=utf.remapper(privates_x,"dynamic")
+ xml.unprivatized=unprivatized
+ xml.unspecialized=unspecialized
+ xml.despecialized=despecialized
+ xml.escaped=escaped
+ local function unescaped(s)
+  local p=privates_n[s]
+  if not p then
+   nofprivates=nofprivates+1
+   p=utfchar(nofprivates)
+   privates_n[s]=p
+   s="&"..s..";" 
+   privates_u[p]=s
+   privates_p[p]=s
+   privates_s[p]=s
+  end
+  return p
+ end
+ xml.privatetoken=unescaped
+ xml.privatecodes=privates_n
+ xml.specialcodes=privates_s
+ function xml.addspecialcode(key,value)
+  privates_s[key]=value or "&"..s..";"
+ end
+ handle_hex_entity=function(str)
+  local h=hcache[str]
+  if not h then
+   local n=tonumber(str,16)
+   h=unify_predefined and predefined_unified[n]
+   if h then
+    if trace_entities then
+     report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
     end
-    return p
+   elseif utfize then
+    h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
+    if not n then
+     report_xml("utfize, ignoring hex entity &#x%s;",str)
+    elseif trace_entities then
+     report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
+    end
+   else
+    if trace_entities then
+     report_xml("found entity &#x%s;",str)
+    end
+    h="&#x"..str..";"
+   end
+   hcache[str]=h
   end
-  xml.privatetoken=unescaped
-  xml.privatecodes=privates_n
-  xml.specialcodes=privates_s
-  function xml.addspecialcode(key,value)
-    privates_s[key]=value or "&"..s..";"
-  end
-  handle_hex_entity=function(str)
-    local h=hcache[str]
-    if not h then
-      local n=tonumber(str,16)
-      h=unify_predefined and predefined_unified[n]
-      if h then
-        if trace_entities then
-          report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
-        end
-      elseif utfize then
-        h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
-        if not n then
-          report_xml("utfize, ignoring hex entity &#x%s;",str)
-        elseif trace_entities then
-          report_xml("utfize, converting hex entity &#x%s; into %a",str,h)
-        end
-      else
-        if trace_entities then
-          report_xml("found entity &#x%s;",str)
-        end
-        h="&#x"..str..";"
-      end
-      hcache[str]=h
+  return h
+ end
+ handle_dec_entity=function(str)
+  local d=dcache[str]
+  if not d then
+   local n=tonumber(str)
+   d=unify_predefined and predefined_unified[n]
+   if d then
+    if trace_entities then
+     report_xml("utfize, converting dec entity &#%s; into %a",str,d)
     end
-    return h
+   elseif utfize then
+    d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
+    if not n then
+     report_xml("utfize, ignoring dec entity &#%s;",str)
+    elseif trace_entities then
+     report_xml("utfize, converting dec entity &#%s; into %a",str,d)
+    end
+   else
+    if trace_entities then
+     report_xml("found entity &#%s;",str)
+    end
+    d="&#"..str..";"
+   end
+   dcache[str]=d
   end
-  handle_dec_entity=function(str)
-    local d=dcache[str]
-    if not d then
-      local n=tonumber(str)
-      d=unify_predefined and predefined_unified[n]
-      if d then
-        if trace_entities then
-          report_xml("utfize, converting dec entity &#%s; into %a",str,d)
-        end
-      elseif utfize then
-        d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
-        if not n then
-          report_xml("utfize, ignoring dec entity &#%s;",str)
-        elseif trace_entities then
-          report_xml("utfize, converting dec entity &#%s; into %a",str,d)
-        end
-      else
-        if trace_entities then
-          report_xml("found entity &#%s;",str)
-        end
-        d="&#"..str..";"
-      end
-      dcache[str]=d
+  return d
+ end
+ handle_any_entity_dtd=function(str)
+  if resolve then
+   local a=resolve_predefined and predefined_simplified[str] 
+   if a then
+    if trace_entities then
+     report_xml("resolving entity &%s; to predefined %a",str,a)
     end
-    return d
-  end
-  handle_any_entity_dtd=function(str)
-    if resolve then
-      local a=resolve_predefined and predefined_simplified[str] 
-      if a then
-        if trace_entities then
-          report_xml("resolving entity &%s; to predefined %a",str,a)
-        end
-      else
-        if type(resolve)=="function" then
-          a=resolve(str,entities) or entities[str]
-        else
-          a=entities[str]
-        end
-        if a then
-          if type(a)=="function" then
-            if trace_entities then
-              report_xml("expanding entity &%s; to function call",str)
-            end
-            a=a(str) or ""
-          end
-          a=lpegmatch(parsedentity,a) or a 
-          if trace_entities then
-            report_xml("resolving entity &%s; to internal %a",str,a)
-          end
-        else
-          local unknown_any_entity=placeholders.unknown_any_entity
-          if unknown_any_entity then
-            a=unknown_any_entity(str) or ""
-          end
-          if a then
-            if trace_entities then
-              report_xml("resolving entity &%s; to external %s",str,a)
-            end
-          else
-            if trace_entities then
-              report_xml("keeping entity &%s;",str)
-            end
-            if str=="" then
-              a=badentity
-            else
-              a="&"..str..";"
-            end
-          end
-        end
+   else
+    if type(resolve)=="function" then
+     a=resolve(str,entities) or entities[str]
+    else
+     a=entities[str]
+    end
+    if a then
+     if type(a)=="function" then
+      if trace_entities then
+       report_xml("expanding entity &%s; to function call",str)
       end
-      return a
+      a=a(str) or ""
+     end
+     a=lpegmatch(parsedentity,a) or a 
+     if trace_entities then
+      report_xml("resolving entity &%s; to internal %a",str,a)
+     end
     else
-      local a=acache[str]
-      if not a then
-        a=resolve_predefined and predefined_simplified[str]
-        if a then
-          acache[str]=a
-          if trace_entities then
-            report_xml("entity &%s; becomes %a",str,a)
-          end
-        elseif str=="" then
-          if trace_entities then
-            report_xml("invalid entity &%s;",str)
-          end
-          a=badentity
-          acache[str]=a
-        else
-          if trace_entities then
-            report_xml("entity &%s; is made private",str)
-          end
-          a=unescaped(str)
-          acache[str]=a
-        end
+     local unknown_any_entity=placeholders.unknown_any_entity
+     if unknown_any_entity then
+      a=unknown_any_entity(str) or ""
+     end
+     if a then
+      if trace_entities then
+       report_xml("resolving entity &%s; to external %s",str,a)
       end
-      return a
-    end
-  end
-  handle_any_entity_text=function(str)
-    if resolve then
-      local a=resolve_predefined and predefined_simplified[str]
-      if a then
-        if trace_entities then
-          report_xml("resolving entity &%s; to predefined %a",str,a)
-        end
+     else
+      if trace_entities then
+       report_xml("keeping entity &%s;",str)
+      end
+      if str=="" then
+       a=badentity
       else
-        if type(resolve)=="function" then
-          a=resolve(str,entities) or entities[str]
-        else
-          a=entities[str]
-        end
-        if a then
-          if type(a)=="function" then
-            if trace_entities then
-              report_xml("expanding entity &%s; to function call",str)
-            end
-            a=a(str) or ""
-          end
-          a=lpegmatch(grammar_parsed_text_two,a) or a
-          if type(a)=="number" then
-            return ""
-          else
-            a=lpegmatch(parsedentity,a) or a 
-            if trace_entities then
-              report_xml("resolving entity &%s; to internal %a",str,a)
-            end
-          end
-          if trace_entities then
-            report_xml("resolving entity &%s; to internal %a",str,a)
-          end
-        else
-          local unknown_any_entity=placeholders.unknown_any_entity
-          if unknown_any_entity then
-            a=unknown_any_entity(str) or ""
-          end
-          if a then
-            if trace_entities then
-              report_xml("resolving entity &%s; to external %s",str,a)
-            end
-          else
-            if trace_entities then
-              report_xml("keeping entity &%s;",str)
-            end
-            if str=="" then
-              a=badentity
-            else
-              a="&"..str..";"
-            end
-          end
-        end
+       a="&"..str..";"
       end
-      return a
-    else
-      local a=acache[str]
-      if not a then
-        a=resolve_predefined and predefined_simplified[str]
-        if a then
-          acache[str]=a
-          if trace_entities then
-            report_xml("entity &%s; becomes %a",str,a)
-          end
-        elseif str=="" then
-          if trace_entities then
-            report_xml("invalid entity &%s;",str)
-          end
-          a=badentity
-          acache[str]=a
-        else
-          if trace_entities then
-            report_xml("entity &%s; is made private",str)
-          end
-          a=unescaped(str)
-          acache[str]=a
-        end
-      end
-      return a
+     end
     end
-  end
-  local p_rest=(1-P(";"))^1
-  local spec={
-    [0x23]="\\Ux{23}",
-    [0x24]="\\Ux{24}",
-    [0x25]="\\Ux{25}",
-    [0x5C]="\\Ux{5C}",
-    [0x7B]="\\Ux{7B}",
-    [0x7C]="\\Ux{7C}",
-    [0x7D]="\\Ux{7D}",
-    [0x7E]="\\Ux{7E}",
-  }
-  local hash=table.setmetatableindex(spec,function(t,k)
-    local v=utfchar(k)
-    t[k]=v
-    return v
-  end)
-  local function fromuni(s)
-    local n=tonumber(s,16)
-    if n then
-      return hash[n]
+   end
+   return a
+  else
+   local a=acache[str]
+   if not a then
+    a=resolve_predefined and predefined_simplified[str]
+    if a then
+     acache[str]=a
+     if trace_entities then
+      report_xml("entity &%s; becomes %a",str,a)
+     end
+    elseif str=="" then
+     if trace_entities then
+      report_xml("invalid entity &%s;",str)
+     end
+     a=badentity
+     acache[str]=a
     else
-      return formatters["u:%s"](s),true
+     if trace_entities then
+      report_xml("entity &%s; is made private",str)
+     end
+     a=unescaped(str)
+     acache[str]=a
     end
+   end
+   return a
   end
-  local function fromhex(s)
-    local n=tonumber(s,16)
-    if n then
-      return hash[n]
-    else
-      return formatters["h:%s"](s),true
+ end
+ handle_any_entity_text=function(str)
+  if resolve then
+   local a=resolve_predefined and predefined_simplified[str]
+   if a then
+    if trace_entities then
+     report_xml("resolving entity &%s; to predefined %a",str,a)
     end
-  end
-  local function fromdec(s)
-    local n=tonumber(s)
-    if n then
-      return hash[n]
+   else
+    if type(resolve)=="function" then
+     a=resolve(str,entities) or entities[str]
     else
-      return formatters["d:%s"](s),true
+     a=entities[str]
     end
-  end
-  local reparsedentity=P("U+")*(p_rest/fromuni)+P("#")*(
-      P("x")*(p_rest/fromhex)+p_rest/fromdec
-    )
-  local hash=table.setmetatableindex(function(t,k)
-    local v=utfchar(k)
-    t[k]=v
-    return v
-  end)
-  local function fromuni(s)
-    local n=tonumber(s,16)
-    if n then
-      return hash[n]
+    if a then
+     if type(a)=="function" then
+      if trace_entities then
+       report_xml("expanding entity &%s; to function call",str)
+      end
+      a=a(str) or ""
+     end
+     a=lpegmatch(grammar_parsed_text_two,a) or a
+     if type(a)=="number" then
+      return ""
+     else
+      a=lpegmatch(parsedentity,a) or a 
+      if trace_entities then
+       report_xml("resolving entity &%s; to internal %a",str,a)
+      end
+     end
+     if trace_entities then
+      report_xml("resolving entity &%s; to internal %a",str,a)
+     end
     else
-      return formatters["u:%s"](s),true
+     local unknown_any_entity=placeholders.unknown_any_entity
+     if unknown_any_entity then
+      a=unknown_any_entity(str) or ""
+     end
+     if a then
+      if trace_entities then
+       report_xml("resolving entity &%s; to external %s",str,a)
+      end
+     else
+      if trace_entities then
+       report_xml("keeping entity &%s;",str)
+      end
+      if str=="" then
+       a=badentity
+      else
+       a="&"..str..";"
+      end
+     end
     end
-  end
-  local function fromhex(s)
-    local n=tonumber(s,16)
-    if n then
-      return hash[n]
+   end
+   return a
+  else
+   local a=acache[str]
+   if not a then
+    a=resolve_predefined and predefined_simplified[str]
+    if a then
+     acache[str]=a
+     if trace_entities then
+      report_xml("entity &%s; becomes %a",str,a)
+     end
+    elseif str=="" then
+     if trace_entities then
+      report_xml("invalid entity &%s;",str)
+     end
+     a=badentity
+     acache[str]=a
     else
-      return formatters["h:%s"](s),true
+     if trace_entities then
+      report_xml("entity &%s; is made private",str)
+     end
+     a=unescaped(str)
+     acache[str]=a
     end
+   end
+   return a
   end
-  local function fromdec(s)
-    local n=tonumber(s)
-    if n then
-      return hash[n]
-    else
-      return formatters["d:%s"](s),true
-    end
+ end
+ local p_rest=(1-P(";"))^1
+ local spec={
+  [0x23]="\\Ux{23}",
+  [0x24]="\\Ux{24}",
+  [0x25]="\\Ux{25}",
+  [0x5C]="\\Ux{5C}",
+  [0x7B]="\\Ux{7B}",
+  [0x7C]="\\Ux{7C}",
+  [0x7D]="\\Ux{7D}",
+  [0x7E]="\\Ux{7E}",
+ }
+ local hash=table.setmetatableindex(spec,function(t,k)
+  local v=utfchar(k)
+  t[k]=v
+  return v
+ end)
+ local function fromuni(s)
+  local n=tonumber(s,16)
+  if n then
+   return hash[n]
+  else
+   return formatters["u:%s"](s),true
   end
-  local unescapedentity=P("U+")*(p_rest/fromuni)+P("#")*(
-      P("x")*(p_rest/fromhex)+p_rest/fromdec
-    )
-  xml.reparsedentitylpeg=reparsedentity  
-  xml.unescapedentitylpeg=unescapedentity 
+ end
+ local function fromhex(s)
+  local n=tonumber(s,16)
+  if n then
+   return hash[n]
+  else
+   return formatters["h:%s"](s),true
+  end
+ end
+ local function fromdec(s)
+  local n=tonumber(s)
+  if n then
+   return hash[n]
+  else
+   return formatters["d:%s"](s),true
+  end
+ end
+ local reparsedentity=P("U+")*(p_rest/fromuni)+P("#")*(
+   P("x")*(p_rest/fromhex)+p_rest/fromdec
+  )
+ local hash=table.setmetatableindex(function(t,k)
+  local v=utfchar(k)
+  t[k]=v
+  return v
+ end)
+ local function fromuni(s)
+  local n=tonumber(s,16)
+  if n then
+   return hash[n]
+  else
+   return formatters["u:%s"](s),true
+  end
+ end
+ local function fromhex(s)
+  local n=tonumber(s,16)
+  if n then
+   return hash[n]
+  else
+   return formatters["h:%s"](s),true
+  end
+ end
+ local function fromdec(s)
+  local n=tonumber(s)
+  if n then
+   return hash[n]
+  else
+   return formatters["d:%s"](s),true
+  end
+ end
+ local unescapedentity=P("U+")*(p_rest/fromuni)+P("#")*(
+   P("x")*(p_rest/fromhex)+p_rest/fromdec
+  )
+ xml.reparsedentitylpeg=reparsedentity   
+ xml.unescapedentitylpeg=unescapedentity  
 end
 local escaped=xml.escaped
 local unescaped=xml.unescaped
 local placeholders=xml.placeholders
 local function handle_end_entity(str)
-  report_xml("error in entity, %a found without ending %a",str,";")
-  return str
+ report_xml("error in entity, %a found without ending %a",str,";")
+ return str
 end
 local function handle_crap_error(chr)
-  report_xml("error in parsing, unexpected %a found ",chr)
-  add_text(chr)
-  return chr
+ report_xml("error in parsing, unexpected %a found ",chr)
+ add_text(chr)
+ return chr
 end
 local function handlenewline()
-  currentline=currentline+1
+ currentline=currentline+1
 end
 local spacetab=S(' \t')
 local space=S(' \r\n\t')
@@ -12849,141 +16338,141 @@
 local spacing_nl=Cs((space_nl)^0)
 local anything_nl=newline+P(1)
 local function weirdentity(k,v)
-  if trace_entities then
-    report_xml("registering %s entity %a as %a","weird",k,v)
-  end
-  parameters[k]=v
+ if trace_entities then
+  report_xml("registering %s entity %a as %a","weird",k,v)
+ end
+ parameters[k]=v
 end
 local function normalentity(k,v)
-  if trace_entities then
-    report_xml("registering %s entity %a as %a","normal",k,v)
-  end
-  entities[k]=v
+ if trace_entities then
+  report_xml("registering %s entity %a as %a","normal",k,v)
+ end
+ entities[k]=v
 end
 local function systementity(k,v,n)
-  if trace_entities then
-    report_xml("registering %s entity %a as %a","system",k,v)
-  end
-  entities[k]=v
+ if trace_entities then
+  report_xml("registering %s entity %a as %a","system",k,v)
+ end
+ entities[k]=v
 end
 local function publicentity(k,v,n)
-  if trace_entities then
-    report_xml("registering %s entity %a as %a","public",k,v)
-  end
-  entities[k]=v
+ if trace_entities then
+  report_xml("registering %s entity %a as %a","public",k,v)
+ end
+ entities[k]=v
 end
 local function entityfile(pattern,k,v,n)
-  if n then
-    local okay,data
-    if resolvers then
-      okay,data=resolvers.loadbinfile(n)
-    else
-      data=io.loaddata(n)
-      okay=data and data~=""
-    end
-    if okay then
-      if trace_entities then
-        report_xml("loading public entities %a as %a from %a",k,v,n)
-      end
-      lpegmatch(pattern,data)
-      return
-    end
+ if n then
+  local okay,data
+  if resolvers then
+   okay,data=resolvers.loadbinfile(n)
+  else
+   data=io.loaddata(n)
+   okay=data and data~=""
   end
-  report_xml("ignoring public entities %a as %a from %a",k,v,n)
+  if okay then
+   if trace_entities then
+    report_xml("loading public entities %a as %a from %a",k,v,n)
+   end
+   lpegmatch(pattern,data)
+   return
+  end
+ end
+ report_xml("ignoring public entities %a as %a from %a",k,v,n)
 end
 local function install(spacenewline,spacing,anything)
-  local anyentitycontent=(1-open-semicolon-space-close-ampersand)^0
-  local hexentitycontent=R("AF","af","09")^1
-  local decentitycontent=R("09")^1
-  local parsedentity=P("#")/""*(
-                  P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
-                )+(anyentitycontent/handle_any_entity_dtd) 
-  local parsedentity_text=P("#")/""*(
-                  P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
-                )+(anyentitycontent/handle_any_entity_text) 
-  local entity=(ampersand/"")*parsedentity*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity)
-  local entity_text=(ampersand/"")*parsedentity_text*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity)
-  local text_unparsed=Cs((anything-open)^1)
-  local text_parsed=(Cs((anything-open-ampersand)^1)/add_text+Cs(entity_text)/add_text)^1
-  local somespace=(spacenewline)^1
-  local optionalspace=(spacenewline)^0
-  local value=(squote*Cs((entity+(anything-squote))^0)*squote)+(dquote*Cs((entity+(anything-dquote))^0)*dquote) 
-  local endofattributes=slash*close+close 
-  local whatever=space*name*optionalspace*equal
-  local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error
-  local attributevalue=value+wrongvalue
-  local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute
-  local attributes=(attribute+somespace^-1*(((anything-endofattributes)^1)/attribute_specification_error))^0
-  local parsedtext=text_parsed  
-  local unparsedtext=text_unparsed/add_text
-  local balanced=P { "["*((anything-S"[]")+V(1))^0*"]" } 
-  local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty
-  local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin
-  local endelement=(spacing*open*slash*name*optionalspace*close)/add_end
-  local begincomment=open*P("!--")
-  local endcomment=P("--")*close
-  local begininstruction=open*P("?")
-  local endinstruction=P("?")*close
-  local begincdata=open*P("![CDATA[")
-  local endcdata=P("]]")*close
-  local someinstruction=C((anything-endinstruction)^0)
-  local somecomment=C((anything-endcomment  )^0)
-  local somecdata=C((anything-endcdata   )^0)
-  local begindoctype=open*P("!DOCTYPE")
-  local enddoctype=close
-  local beginset=P("[")
-  local endset=P("]")
-  local wrdtypename=C((anything-somespace-P(";"))^1)
-  local doctypename=C((anything-somespace-close)^0)
-  local elementdoctype=optionalspace*P("<!ELEMENT")*(anything-close)^0*close
-  local basiccomment=begincomment*((anything-endcomment)^0)*endcomment
-  local weirdentitytype=P("%")*(somespace*doctypename*somespace*value)/weirdentity
-  local normalentitytype=(doctypename*somespace*value)/normalentity
-  local publicentitytype=(doctypename*somespace*P("PUBLIC")*somespace*value)/publicentity
-  local systementitytype=(doctypename*somespace*P("SYSTEM")*somespace*value*somespace*P("NDATA")*somespace*doctypename)/systementity
-  local entitydoctype=optionalspace*P("<!ENTITY")*somespace*(systementitytype+publicentitytype+normalentitytype+weirdentitytype)*optionalspace*close
-  local publicentityfile=(doctypename*somespace*P("PUBLIC")*somespace*value*(somespace*value)^0)/function(...)
-    entityfile(entitydoctype,...)
-  end
-  local function weirdresolve(s)
-    lpegmatch(entitydoctype,parameters[s])
-  end
-  local function normalresolve(s)
-    lpegmatch(entitydoctype,entities[s])
-  end
-  local entityresolve=P("%")*(wrdtypename/weirdresolve )*P(";")+P("&")*(wrdtypename/normalresolve)*P(";")
-  entitydoctype=entitydoctype+entityresolve
-  local doctypeset=beginset*optionalspace*P(elementdoctype+entitydoctype+entityresolve+basiccomment+space)^0*optionalspace*endset
-  local definitiondoctype=doctypename*somespace*doctypeset
-  local publicdoctype=doctypename*somespace*P("PUBLIC")*somespace*value*somespace*value*somespace*doctypeset
-  local systemdoctype=doctypename*somespace*P("SYSTEM")*somespace*value*somespace*doctypeset
-  local simpledoctype=(anything-close)^1 
-  local somedoctype=C((somespace*(
+ local anyentitycontent=(1-open-semicolon-space-close-ampersand)^0
+ local hexentitycontent=R("AF","af","09")^1
+ local decentitycontent=R("09")^1
+ local parsedentity=P("#")/""*(
+         P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
+        )+(anyentitycontent/handle_any_entity_dtd) 
+ local parsedentity_text=P("#")/""*(
+         P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
+        )+(anyentitycontent/handle_any_entity_text) 
+ local entity=(ampersand/"")*parsedentity*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity)
+ local entity_text=(ampersand/"")*parsedentity_text*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity)
+ local text_unparsed=Cs((anything-open)^1)
+ local text_parsed=(Cs((anything-open-ampersand)^1)/add_text+Cs(entity_text)/add_text)^1
+ local somespace=(spacenewline)^1
+ local optionalspace=(spacenewline)^0
+ local value=(squote*Cs((entity+(anything-squote))^0)*squote)+(dquote*Cs((entity+(anything-dquote))^0)*dquote) 
+ local endofattributes=slash*close+close 
+ local whatever=space*name*optionalspace*equal
+ local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error
+ local attributevalue=value+wrongvalue
+ local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute
+ local attributes=(attribute+somespace^-1*(((anything-endofattributes)^1)/attribute_specification_error))^0
+ local parsedtext=text_parsed   
+ local unparsedtext=text_unparsed/add_text
+ local balanced=P { "["*((anything-S"[]")+V(1))^0*"]" } 
+ local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty
+ local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin
+ local endelement=(spacing*open*slash*name*optionalspace*close)/add_end
+ local begincomment=open*P("!--")
+ local endcomment=P("--")*close
+ local begininstruction=open*P("?")
+ local endinstruction=P("?")*close
+ local begincdata=open*P("![CDATA[")
+ local endcdata=P("]]")*close
+ local someinstruction=C((anything-endinstruction)^0)
+ local somecomment=C((anything-endcomment )^0)
+ local somecdata=C((anything-endcdata   )^0)
+ local begindoctype=open*P("!DOCTYPE")
+ local enddoctype=close
+ local beginset=P("[")
+ local endset=P("]")
+ local wrdtypename=C((anything-somespace-P(";"))^1)
+ local doctypename=C((anything-somespace-close)^0)
+ local elementdoctype=optionalspace*P("<!ELEMENT")*(anything-close)^0*close
+ local basiccomment=begincomment*((anything-endcomment)^0)*endcomment
+ local weirdentitytype=P("%")*(somespace*doctypename*somespace*value)/weirdentity
+ local normalentitytype=(doctypename*somespace*value)/normalentity
+ local publicentitytype=(doctypename*somespace*P("PUBLIC")*somespace*value)/publicentity
+ local systementitytype=(doctypename*somespace*P("SYSTEM")*somespace*value*somespace*P("NDATA")*somespace*doctypename)/systementity
+ local entitydoctype=optionalspace*P("<!ENTITY")*somespace*(systementitytype+publicentitytype+normalentitytype+weirdentitytype)*optionalspace*close
+ local publicentityfile=(doctypename*somespace*P("PUBLIC")*somespace*value*(somespace*value)^0)/function(...)
+  entityfile(entitydoctype,...)
+ end
+ local function weirdresolve(s)
+  lpegmatch(entitydoctype,parameters[s])
+ end
+ local function normalresolve(s)
+  lpegmatch(entitydoctype,entities[s])
+ end
+ local entityresolve=P("%")*(wrdtypename/weirdresolve )*P(";")+P("&")*(wrdtypename/normalresolve)*P(";")
+ entitydoctype=entitydoctype+entityresolve
+ local doctypeset=beginset*optionalspace*P(elementdoctype+entitydoctype+entityresolve+basiccomment+space)^0*optionalspace*endset
+ local definitiondoctype=doctypename*somespace*doctypeset
+ local publicdoctype=doctypename*somespace*P("PUBLIC")*somespace*value*somespace*value*somespace*doctypeset
+ local systemdoctype=doctypename*somespace*P("SYSTEM")*somespace*value*somespace*doctypeset
+ local simpledoctype=(anything-close)^1 
+ local somedoctype=C((somespace*(
 publicentityfile+publicdoctype+systemdoctype+definitiondoctype+simpledoctype)*optionalspace)^0)
-  local instruction=(spacing*begininstruction*someinstruction*endinstruction)/function(...) add_special("@pi@",...) end
-  local comment=(spacing*begincomment*somecomment*endcomment  )/function(...) add_special("@cm@",...) end
-  local cdata=(spacing*begincdata*somecdata*endcdata   )/function(...) add_special("@cd@",...) end
-  local doctype=(spacing*begindoctype*somedoctype*enddoctype  )/function(...) add_special("@dt@",...) end
-  local crap_parsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata-ampersand
-  local crap_unparsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata
-  local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error
-  local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error
-  local unparsedcrap=Cs((crap_unparsed       )^1)/handle_crap_error
-  local trailer=space^0*(text_unparsed/set_message)^0
-  local grammar_parsed_text_one=P { "preamble",
-    preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0,
-  }
-  local grammar_parsed_text_two=P { "followup",
-    followup=V("parent")*trailer,
-    parent=beginelement*V("children")^0*endelement,
-    children=parsedtext+V("parent")+emptyelement+comment+cdata+instruction+parsedcrap,
-  }
-  local grammar_unparsed_text=P { "preamble",
-    preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer,
-    parent=beginelement*V("children")^0*endelement,
-    children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction+unparsedcrap,
-  }
-  return grammar_parsed_text_one,grammar_parsed_text_two,grammar_unparsed_text
+ local instruction=(spacing*begininstruction*someinstruction*endinstruction)/function(...) add_special("@pi@",...) end
+ local comment=(spacing*begincomment*somecomment*endcomment )/function(...) add_special("@cm@",...) end
+ local cdata=(spacing*begincdata*somecdata*endcdata   )/function(...) add_special("@cd@",...) end
+ local doctype=(spacing*begindoctype*somedoctype*enddoctype )/function(...) add_special("@dt@",...) end
+ local crap_parsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata-ampersand
+ local crap_unparsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata
+ local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error
+ local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error
+ local unparsedcrap=Cs((crap_unparsed     )^1)/handle_crap_error
+ local trailer=space^0*(text_unparsed/set_message)^0
+ local grammar_parsed_text_one=P { "preamble",
+  preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0,
+ }
+ local grammar_parsed_text_two=P { "followup",
+  followup=V("parent")*trailer,
+  parent=beginelement*V("children")^0*endelement,
+  children=parsedtext+V("parent")+emptyelement+comment+cdata+instruction+parsedcrap,
+ }
+ local grammar_unparsed_text=P { "preamble",
+  preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer,
+  parent=beginelement*V("children")^0*endelement,
+  children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction+unparsedcrap,
+ }
+ return grammar_parsed_text_one,grammar_parsed_text_two,grammar_unparsed_text
 end
 grammar_parsed_text_one_nop,
 grammar_parsed_text_two_nop,
@@ -12992,450 +16481,450 @@
 grammar_parsed_text_two_yes,
 grammar_unparsed_text_yes=install(space_nl,spacing_nl,anything_nl)
 local function _xmlconvert_(data,settings,detail)
-  settings=settings or {} 
-  preparexmlstate(settings)
-  if settings.linenumbers then
-    grammar_parsed_text_one=grammar_parsed_text_one_yes
-    grammar_parsed_text_two=grammar_parsed_text_two_yes
-    grammar_unparsed_text=grammar_unparsed_text_yes
+ settings=settings or {} 
+ preparexmlstate(settings)
+ if settings.linenumbers then
+  grammar_parsed_text_one=grammar_parsed_text_one_yes
+  grammar_parsed_text_two=grammar_parsed_text_two_yes
+  grammar_unparsed_text=grammar_unparsed_text_yes
+ else
+  grammar_parsed_text_one=grammar_parsed_text_one_nop
+  grammar_parsed_text_two=grammar_parsed_text_two_nop
+  grammar_unparsed_text=grammar_unparsed_text_nop
+ end
+ local preprocessor=settings.preprocessor
+ if data and data~="" and type(preprocessor)=="function" then
+  data=preprocessor(data,settings) or data 
+ end
+ if settings.parent_root then
+  mt=getmetatable(settings.parent_root)
+ else
+  initialize_mt(top)
+ end
+ level=level+1
+ stack[level]=top
+ top.dt={}
+ dt=top.dt
+ nt=0
+ if not data or data=="" then
+  errorstr="empty xml file"
+ elseif data==true then
+  errorstr=detail or "problematic xml file"
+ elseif utfize or resolve then
+  local m=lpegmatch(grammar_parsed_text_one,data)
+  if m then
+   m=lpegmatch(grammar_parsed_text_two,data,m)
+  end
+  if m then
   else
-    grammar_parsed_text_one=grammar_parsed_text_one_nop
-    grammar_parsed_text_two=grammar_parsed_text_two_nop
-    grammar_unparsed_text=grammar_unparsed_text_nop
+   errorstr="invalid xml file - parsed text"
   end
-  local preprocessor=settings.preprocessor
-  if data and data~="" and type(preprocessor)=="function" then
-    data=preprocessor(data,settings) or data 
-  end
-  if settings.parent_root then
-    mt=getmetatable(settings.parent_root)
+ elseif type(data)=="string" then
+  if lpegmatch(grammar_unparsed_text,data) then
+   errorstr=""
   else
-    initialize_mt(top)
+   errorstr="invalid xml file - unparsed text"
   end
-  level=level+1
-  stack[level]=top
-  top.dt={}
-  dt=top.dt
-  nt=0
-  if not data or data=="" then
-    errorstr="empty xml file"
-  elseif data==true then
-    errorstr=detail or "problematic xml file"
-  elseif utfize or resolve then
-    local m=lpegmatch(grammar_parsed_text_one,data)
-    if m then
-      m=lpegmatch(grammar_parsed_text_two,data,m)
-    end
-    if m then
-    else
-      errorstr="invalid xml file - parsed text"
-    end
-  elseif type(data)=="string" then
-    if lpegmatch(grammar_unparsed_text,data) then
-      errorstr=""
-    else
-      errorstr="invalid xml file - unparsed text"
-    end
+ else
+  errorstr="invalid xml file - no text at all"
+ end
+ local result
+ if errorstr and errorstr~="" then
+  result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } }
+  setmetatable(result,mt)
+  setmetatable(result.dt[1],mt)
+  setmetatable(stack,mt)
+  local errorhandler=settings.error_handler
+  if errorhandler==false then
   else
-    errorstr="invalid xml file - no text at all"
-  end
-  local result
-  if errorstr and errorstr~="" then
-    result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } }
-    setmetatable(result,mt)
-    setmetatable(result.dt[1],mt)
-    setmetatable(stack,mt)
-    local errorhandler=settings.error_handler
-    if errorhandler==false then
+   errorhandler=errorhandler or xml.errorhandler
+   if errorhandler then
+    local currentresource=settings.currentresource
+    if currentresource and currentresource~="" then
+     xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr),currentresource)
     else
-      errorhandler=errorhandler or xml.errorhandler
-      if errorhandler then
-        local currentresource=settings.currentresource
-        if currentresource and currentresource~="" then
-          xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr),currentresource)
-        else
-          xml.errorhandler(formatters["load error: %s"](errorstr))
-        end
-      end
+     xml.errorhandler(formatters["load error: %s"](errorstr))
     end
-  else
-    result=stack[1]
+   end
   end
-  if not settings.no_root then
-    result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings }
-    setmetatable(result,mt)
-    local rdt=result.dt
-    for k=1,#rdt do
-      local v=rdt[k]
-      if type(v)=="table" and not v.special then 
-        result.ri=k 
-        v.__p__=result 
-        break
-      end
-    end
+ else
+  result=stack[1]
+ end
+ if not settings.no_root then
+  result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings }
+  setmetatable(result,mt)
+  local rdt=result.dt
+  for k=1,#rdt do
+   local v=rdt[k]
+   if type(v)=="table" and not v.special then 
+    result.ri=k 
+    v.__p__=result  
+    break
+   end
   end
-  if errorstr and errorstr~="" then
-    result.error=true
-  else
-    errorstr=nil
-  end
-  result.statistics={
-    errormessage=errorstr,
-    entities={
-      decimals=dcache,
-      hexadecimals=hcache,
-      names=acache,
-      intermediates=parameters,
-    }
+ end
+ if errorstr and errorstr~="" then
+  result.error=true
+ else
+  errorstr=nil
+ end
+ result.statistics={
+  errormessage=errorstr,
+  entities={
+   decimals=dcache,
+   hexadecimals=hcache,
+   names=acache,
+   intermediates=parameters,
   }
-  preparexmlstate() 
-  return result
+ }
+ preparexmlstate() 
+ return result
 end
 local function xmlconvert(data,settings)
-  local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
-  if ok then
-    return result
-  elseif type(result)=="string" then
-    return _xmlconvert_(true,settings,result)
-  else
-    return _xmlconvert_(true,settings)
-  end
+ local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+  return result
+ elseif type(result)=="string" then
+  return _xmlconvert_(true,settings,result)
+ else
+  return _xmlconvert_(true,settings)
+ end
 end
 xml.convert=xmlconvert
 function xml.inheritedconvert(data,xmldata) 
-  local settings=xmldata.settings
-  if settings then
-    settings.parent_root=xmldata 
-  end
-  local xc=xmlconvert(data,settings)
-  return xc
+ local settings=xmldata.settings
+ if settings then
+  settings.parent_root=xmldata 
+ end
+ local xc=xmlconvert(data,settings)
+ return xc
 end
 function xml.is_valid(root)
-  return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er
+ return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er
 end
 function xml.package(tag,attributes,data)
-  local ns,tg=match(tag,"^(.-):?([^:]+)$")
-  local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} }
-  setmetatable(t,mt)
-  return t
+ local ns,tg=match(tag,"^(.-):?([^:]+)$")
+ local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} }
+ setmetatable(t,mt)
+ return t
 end
 function xml.is_valid(root)
-  return root and not root.error
+ return root and not root.error
 end
 xml.errorhandler=report_xml
 function xml.load(filename,settings)
-  local data=""
-  if type(filename)=="string" then
-    local f=io.open(filename,'r') 
-    if f then
-      data=f:read("*all") 
-      f:close()
-    end
-  elseif filename then 
-    data=filename:read("*all") 
+ local data=""
+ if type(filename)=="string" then
+  local f=io.open(filename,'r') 
+  if f then
+   data=f:read("*all") 
+   f:close()
   end
-  if settings then
-    settings.currentresource=filename
-    local result=xmlconvert(data,settings)
-    settings.currentresource=nil
-    return result
-  else
-    return xmlconvert(data,{ currentresource=filename })
-  end
+ elseif filename then 
+  data=filename:read("*all") 
+ end
+ if settings then
+  settings.currentresource=filename
+  local result=xmlconvert(data,settings)
+  settings.currentresource=nil
+  return result
+ else
+  return xmlconvert(data,{ currentresource=filename })
+ end
 end
 local no_root={ no_root=true }
 function xml.toxml(data)
-  if type(data)=="string" then
-    local root={ xmlconvert(data,no_root) }
-    return (#root>1 and root) or root[1]
-  else
-    return data
-  end
+ if type(data)=="string" then
+  local root={ xmlconvert(data,no_root) }
+  return (#root>1 and root) or root[1]
+ else
+  return data
+ end
 end
 local function copy(old,p)
-  if old then
-    local new={}
-    for k,v in next,old do
-      local t=type(v)=="table"
-      if k=="at" then
-        local t={}
-        for k,v in next,v do
-          t[k]=v
-        end
-        new[k]=t
-      elseif k=="dt" then
-        v.__p__=nil
-        v=copy(v,new)
-        new[k]=v
-        v.__p__=p
-      else
-        new[k]=v 
-      end
+ if old then
+  local new={}
+  for k,v in next,old do
+   local t=type(v)=="table"
+   if k=="at" then
+    local t={}
+    for k,v in next,v do
+     t[k]=v
     end
-    local mt=getmetatable(old)
-    if mt then
-      setmetatable(new,mt)
-    end
-    return new
-  else
-    return {}
+    new[k]=t
+   elseif k=="dt" then
+    v.__p__=nil
+    v=copy(v,new)
+    new[k]=v
+    v.__p__=p
+   else
+    new[k]=v 
+   end
   end
+  local mt=getmetatable(old)
+  if mt then
+   setmetatable(new,mt)
+  end
+  return new
+ else
+  return {}
+ end
 end
 xml.copy=copy
 function xml.checkbom(root) 
-  if root.ri then
-    local dt=root.dt
-    for k=1,#dt do
-      local v=dt[k]
-      if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then
-        return
-      end
-    end
-    insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } )
-    insert(dt,2,"\n" )
+ if root.ri then
+  local dt=root.dt
+  for k=1,#dt do
+   local v=dt[k]
+   if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then
+    return
+   end
   end
+  insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } )
+  insert(dt,2,"\n" )
+ end
 end
 local f_attribute=formatters['%s=%q']
 local function verbose_element(e,handlers,escape) 
-  local handle=handlers.handle
-  local serialize=handlers.serialize
-  local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
-  local ats=eat and next(eat) and {}
-  if ats then
-    local n=0
-    for k in next,eat do
-      n=n+1
-      ats[n]=k
-    end
-    if n==1 then
-      local k=ats[1]
-      ats=f_attribute(k,escaped(eat[k]))
-    else
-      sort(ats)
-      for i=1,n do
-        local k=ats[i]
-        ats[i]=f_attribute(k,escaped(eat[k]))
-      end
-      ats=concat(ats," ")
-    end
+ local handle=handlers.handle
+ local serialize=handlers.serialize
+ local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
+ local ats=eat and next(eat) and {}
+ if ats then
+  local n=0
+  for k in next,eat do
+   n=n+1
+   ats[n]=k
   end
-  if ern and trace_entities and ern~=ens then
-    ens=ern
+  if n==1 then
+   local k=ats[1]
+   ats=f_attribute(k,escaped(eat[k]))
+  else
+   sort(ats)
+   for i=1,n do
+    local k=ats[i]
+    ats[i]=f_attribute(k,escaped(eat[k]))
+   end
+   ats=concat(ats," ")
   end
-  local n=edt and #edt
-  if ens~="" then
-    if n and n>0 then
-      if ats then
-        handle("<",ens,":",etg," ",ats,">")
-      else
-        handle("<",ens,":",etg,">")
-      end
-      for i=1,n do
-        local e=edt[i]
-        if type(e)=="string" then
-          handle(escaped(e))
-        else
-          serialize(e,handlers)
-        end
-      end
-      handle("</",ens,":",etg,">")
+ end
+ if ern and trace_entities and ern~=ens then
+  ens=ern
+ end
+ local n=edt and #edt
+ if ens~="" then
+  if n and n>0 then
+   if ats then
+    handle("<",ens,":",etg," ",ats,">")
+   else
+    handle("<",ens,":",etg,">")
+   end
+   for i=1,n do
+    local e=edt[i]
+    if type(e)=="string" then
+     handle(escaped(e))
     else
-      if ats then
-        handle("<",ens,":",etg," ",ats,"/>")
-      else
-        handle("<",ens,":",etg,"/>")
-      end
+     serialize(e,handlers)
     end
+   end
+   handle("</",ens,":",etg,">")
   else
-    if n and n>0 then
-      if ats then
-        handle("<",etg," ",ats,">")
-      else
-        handle("<",etg,">")
-      end
-      for i=1,n do
-        local e=edt[i]
-        if type(e)=="string" then
-          handle(escaped(e)) 
-        else
-          serialize(e,handlers)
-        end
-      end
-      handle("</",etg,">")
+   if ats then
+    handle("<",ens,":",etg," ",ats,"/>")
+   else
+    handle("<",ens,":",etg,"/>")
+   end
+  end
+ else
+  if n and n>0 then
+   if ats then
+    handle("<",etg," ",ats,">")
+   else
+    handle("<",etg,">")
+   end
+   for i=1,n do
+    local e=edt[i]
+    if type(e)=="string" then
+     handle(escaped(e)) 
     else
-      if ats then
-        handle("<",etg," ",ats,"/>")
-      else
-        handle("<",etg,"/>")
-      end
+     serialize(e,handlers)
     end
+   end
+   handle("</",etg,">")
+  else
+   if ats then
+    handle("<",etg," ",ats,"/>")
+   else
+    handle("<",etg,"/>")
+   end
   end
+ end
 end
 local function verbose_pi(e,handlers)
-  handlers.handle("<?",e.dt[1],"?>")
+ handlers.handle("<?",e.dt[1],"?>")
 end
 local function verbose_comment(e,handlers)
-  handlers.handle("<!--",e.dt[1],"-->")
+ handlers.handle("<!--",e.dt[1],"-->")
 end
 local function verbose_cdata(e,handlers)
-  handlers.handle("<![CDATA[",e.dt[1],"]]>")
+ handlers.handle("<![CDATA[",e.dt[1],"]]>")
 end
 local function verbose_doctype(e,handlers)
-  handlers.handle("<!DOCTYPE",e.dt[1],">") 
+ handlers.handle("<!DOCTYPE",e.dt[1],">") 
 end
 local function verbose_root(e,handlers)
-  handlers.serialize(e.dt,handlers)
+ handlers.serialize(e.dt,handlers)
 end
 local function verbose_text(e,handlers)
-  handlers.handle(escaped(e))
+ handlers.handle(escaped(e))
 end
 local function verbose_document(e,handlers)
-  local serialize=handlers.serialize
-  local functions=handlers.functions
-  for i=1,#e do
-    local ei=e[i]
-    if type(ei)=="string" then
-      functions["@tx@"](ei,handlers)
-    else
-      serialize(ei,handlers)
-    end
+ local serialize=handlers.serialize
+ local functions=handlers.functions
+ for i=1,#e do
+  local ei=e[i]
+  if type(ei)=="string" then
+   functions["@tx@"](ei,handlers)
+  else
+   serialize(ei,handlers)
   end
+ end
 end
 local function serialize(e,handlers,...)
-  if e then
-    local initialize=handlers.initialize
-    local finalize=handlers.finalize
-    local functions=handlers.functions
-    if initialize then
-      local state=initialize(...)
-      if not state==true then
-        return state
-      end
-    end
-    local etg=e.tg
-    if etg then
-      (functions[etg] or functions["@el@"])(e,handlers)
-    else
-      functions["@dc@"](e,handlers) 
-    end
-    if finalize then
-      return finalize()
-    end
+ if e then
+  local initialize=handlers.initialize
+  local finalize=handlers.finalize
+  local functions=handlers.functions
+  if initialize then
+   local state=initialize(...)
+   if not state==true then
+    return state
+   end
   end
+  local etg=e.tg
+  if etg then
+   (functions[etg] or functions["@el@"])(e,handlers)
+  else
+   functions["@dc@"](e,handlers) 
+  end
+  if finalize then
+   return finalize()
+  end
+ end
 end
 local function xserialize(e,handlers)
-  if e then
-    local functions=handlers.functions
-    local etg=e.tg
-    if etg then
-      (functions[etg] or functions["@el@"])(e,handlers)
-    else
-      functions["@dc@"](e,handlers)
-    end
+ if e then
+  local functions=handlers.functions
+  local etg=e.tg
+  if etg then
+   (functions[etg] or functions["@el@"])(e,handlers)
+  else
+   functions["@dc@"](e,handlers)
   end
+ end
 end
 local handlers={}
 local function newhandlers(settings)
-  local t=table.copy(handlers[settings and settings.parent or "verbose"] or {}) 
-  if settings then
-    for k,v in next,settings do
-      if type(v)=="table" then
-        local tk=t[k] if not tk then tk={} t[k]=tk end
-        for kk,vv in next,v do
-          tk[kk]=vv
-        end
-      else
-        t[k]=v
-      end
+ local t=table.copy(handlers[settings and settings.parent or "verbose"] or {}) 
+ if settings then
+  for k,v in next,settings do
+   if type(v)=="table" then
+    local tk=t[k] if not tk then tk={} t[k]=tk end
+    for kk,vv in next,v do
+     tk[kk]=vv
     end
-    if settings.name then
-      handlers[settings.name]=t
-    end
+   else
+    t[k]=v
+   end
   end
-  utilities.storage.mark(t)
-  return t
+  if settings.name then
+   handlers[settings.name]=t
+  end
+ end
+ utilities.storage.mark(t)
+ return t
 end
 local nofunction=function() end
 function xml.sethandlersfunction(handler,name,fnc)
-  handler.functions[name]=fnc or nofunction
+ handler.functions[name]=fnc or nofunction
 end
 function xml.gethandlersfunction(handler,name)
-  return handler.functions[name]
+ return handler.functions[name]
 end
 function xml.gethandlers(name)
-  return handlers[name]
+ return handlers[name]
 end
 newhandlers {
-  name="verbose",
-  initialize=false,
-  finalize=false,
-  serialize=xserialize,
-  handle=print,
-  functions={
-    ["@dc@"]=verbose_document,
-    ["@dt@"]=verbose_doctype,
-    ["@rt@"]=verbose_root,
-    ["@el@"]=verbose_element,
-    ["@pi@"]=verbose_pi,
-    ["@cm@"]=verbose_comment,
-    ["@cd@"]=verbose_cdata,
-    ["@tx@"]=verbose_text,
-  }
+ name="verbose",
+ initialize=false,
+ finalize=false,
+ serialize=xserialize,
+ handle=print,
+ functions={
+  ["@dc@"]=verbose_document,
+  ["@dt@"]=verbose_doctype,
+  ["@rt@"]=verbose_root,
+  ["@el@"]=verbose_element,
+  ["@pi@"]=verbose_pi,
+  ["@cm@"]=verbose_comment,
+  ["@cd@"]=verbose_cdata,
+  ["@tx@"]=verbose_text,
+ }
 }
 local result
 local xmlfilehandler=newhandlers {
-  name="file",
-  initialize=function(name)
-    result=io.open(name,"wb")
-    return result
-  end,
-  finalize=function()
-    result:close()
-    return true
-  end,
-  handle=function(...)
-    result:write(...)
-  end,
+ name="file",
+ initialize=function(name)
+  result=io.open(name,"wb")
+  return result
+ end,
+ finalize=function()
+  result:close()
+  return true
+ end,
+ handle=function(...)
+  result:write(...)
+ end,
 }
 function xml.save(root,name)
-  serialize(root,xmlfilehandler,name)
+ serialize(root,xmlfilehandler,name)
 end
 local result,r,threshold={},0,512
 local xmlstringhandler=newhandlers {
-  name="string",
-  initialize=function()
-    r=0
-    return result
-  end,
-  finalize=function()
-    local done=concat(result,"",1,r)
-    r=0
-    if r>threshold then
-      result={}
-    end
-    return done
-  end,
-  handle=function(...)
-    for i=1,select("#",...) do
-      r=r+1
-      result[r]=select(i,...)
-    end
-  end,
+ name="string",
+ initialize=function()
+  r=0
+  return result
+ end,
+ finalize=function()
+  local done=concat(result,"",1,r)
+  r=0
+  if r>threshold then
+   result={}
+  end
+  return done
+ end,
+ handle=function(...)
+  for i=1,select("#",...) do
+   r=r+1
+   result[r]=select(i,...)
+  end
+ end,
 }
 local function xmltostring(root) 
-  if not root then
-    return ""
-  elseif type(root)=="string" then
-    return root
-  else 
-    return serialize(root,xmlstringhandler) or ""
-  end
+ if not root then
+  return ""
+ elseif type(root)=="string" then
+  return root
+ else 
+  return serialize(root,xmlstringhandler) or ""
+ end
 end
 local function __tostring(root) 
-  return (root and xmltostring(root)) or ""
+ return (root and xmltostring(root)) or ""
 end
 initialize_mt=function(root) 
-  mt={ __tostring=__tostring,__index=root }
+ mt={ __tostring=__tostring,__index=root }
 end
 xml.defaulthandlers=handlers
 xml.newhandlers=newhandlers
@@ -13442,126 +16931,126 @@
 xml.serialize=serialize
 xml.tostring=xmltostring
 local function xmlstring(e,handle)
-  if not handle or (e.special and e.tg~="@rt@") then
-  elseif e.tg then
-    local edt=e.dt
-    if edt then
-      for i=1,#edt do
-        xmlstring(edt[i],handle)
-      end
-    end
-  else
-    handle(e)
+ if not handle or (e.special and e.tg~="@rt@") then
+ elseif e.tg then
+  local edt=e.dt
+  if edt then
+   for i=1,#edt do
+    xmlstring(edt[i],handle)
+   end
   end
+ else
+  handle(e)
+ end
 end
 xml.string=xmlstring
 function xml.settings(e)
-  while e do
-    local s=e.settings
-    if s then
-      return s
-    else
-      e=e.__p__
-    end
+ while e do
+  local s=e.settings
+  if s then
+   return s
+  else
+   e=e.__p__
   end
-  return nil
+ end
+ return nil
 end
 function xml.root(e)
-  local r=e
-  while e do
-    e=e.__p__
-    if e then
-      r=e
-    end
+ local r=e
+ while e do
+  e=e.__p__
+  if e then
+   r=e
   end
-  return r
+ end
+ return r
 end
 function xml.parent(root)
-  return root.__p__
+ return root.__p__
 end
 function xml.body(root)
-  return root.ri and root.dt[root.ri] or root 
+ return root.ri and root.dt[root.ri] or root 
 end
 function xml.name(root)
-  if not root then
-    return ""
-  end
-  local ns=root.ns
-  local tg=root.tg
-  if ns=="" then
-    return tg
-  else
-    return ns..":"..tg
-  end
+ if not root then
+  return ""
+ end
+ local ns=root.ns
+ local tg=root.tg
+ if ns=="" then
+  return tg
+ else
+  return ns..":"..tg
+ end
 end
 function xml.erase(dt,k)
-  if dt then
-    if k then
-      dt[k]=""
-    else for k=1,#dt do
-      dt[1]={ "" }
-    end end
-  end
+ if dt then
+  if k then
+   dt[k]=""
+  else for k=1,#dt do
+   dt[1]={ "" }
+  end end
+ end
 end
 function xml.assign(dt,k,root)
-  if dt and k then
-    dt[k]=type(root)=="table" and xml.body(root) or root
-    return dt[k]
-  else
-    return xml.body(root)
-  end
+ if dt and k then
+  dt[k]=type(root)=="table" and xml.body(root) or root
+  return dt[k]
+ else
+  return xml.body(root)
+ end
 end
 function xml.tocdata(e,wrapper) 
-  local whatever=type(e)=="table" and xmltostring(e.dt) or e or ""
-  if wrapper then
-    whatever=formatters["<%s>%s</%s>"](wrapper,whatever,wrapper)
-  end
-  local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e }
-  setmetatable(t,getmetatable(e))
-  e.dt={ t }
+ local whatever=type(e)=="table" and xmltostring(e.dt) or e or ""
+ if wrapper then
+  whatever=formatters["<%s>%s</%s>"](wrapper,whatever,wrapper)
+ end
+ local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e }
+ setmetatable(t,getmetatable(e))
+ e.dt={ t }
 end
 function xml.makestandalone(root)
-  if root.ri then
-    local dt=root.dt
-    for k=1,#dt do
-      local v=dt[k]
-      if type(v)=="table" and v.special and v.tg=="@pi@" then
-        local txt=v.dt[1]
-        if find(txt,"xml.*version=") then
-          v.dt[1]=txt.." standalone='yes'"
-          break
-        end
-      end
+ if root.ri then
+  local dt=root.dt
+  for k=1,#dt do
+   local v=dt[k]
+   if type(v)=="table" and v.special and v.tg=="@pi@" then
+    local txt=v.dt[1]
+    if find(txt,"xml.*version=") then
+     v.dt[1]=txt.." standalone='yes'"
+     break
     end
+   end
   end
-  return root
+ end
+ return root
 end
 function xml.kind(e)
-  local dt=e and e.dt
-  if dt then
-    local n=#dt
-    if n==1 then
-      local d=dt[1]
-      if d.special then
-        local tg=d.tg
-        if tg=="@cd@" then
-          return "cdata"
-        elseif tg=="@cm" then
-          return "comment"
-        elseif tg=="@pi@" then
-          return "instruction"
-        elseif tg=="@dt@" then
-          return "declaration"
-        end
-      elseif type(d)=="string" then
-        return "text"
-      end
-      return "element"
-    elseif n>0 then
-      return "mixed"
+ local dt=e and e.dt
+ if dt then
+  local n=#dt
+  if n==1 then
+   local d=dt[1]
+   if d.special then
+    local tg=d.tg
+    if tg=="@cd@" then
+     return "cdata"
+    elseif tg=="@cm" then
+     return "comment"
+    elseif tg=="@pi@" then
+     return "instruction"
+    elseif tg=="@dt@" then
+     return "declaration"
     end
+   elseif type(d)=="string" then
+    return "text"
+   end
+   return "element"
+  elseif n>0 then
+   return "mixed"
   end
-  return "empty"
+ end
+ return "empty"
 end
 
 
@@ -13571,14 +17060,14 @@
 
 package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
 
--- original size: 53301, stripped down to: 32477
+-- original size: 55145, stripped down to: 30992
 
 if not modules then modules={} end modules ['lxml-lpt']={
-  version=1.001,
-  comment="this module is the basis for the lxml-* ones",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local concat,remove,insert=table.concat,table.remove,table.insert
 local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select
@@ -13591,21 +17080,21 @@
 local trace_lprofile=false
 local report_lpath=logs.reporter("xml","lpath")
 if trackers then
-  trackers.register("xml.path",function(v)
-    trace_lpath=v
-  end)
-  trackers.register("xml.parse",function(v)
-    trace_lparse=v
-  end)
-  trackers.register("xml.profile",function(v)
-    trace_lpath=v
-    trace_lparse=v
-    trace_lprofile=v
-  end)
+ trackers.register("xml.path",function(v)
+  trace_lpath=v
+ end)
+ trackers.register("xml.parse",function(v)
+  trace_lparse=v
+ end)
+ trackers.register("xml.profile",function(v)
+  trace_lpath=v
+  trace_lparse=v
+  trace_lprofile=v
+ end)
 end
 local xml=xml
-local lpathcalls=0 function xml.lpathcalls () return lpathcalls end
-local lpathcached=0 function xml.lpathcached() return lpathcached end
+local lpathcalls=0  function xml.lpathcalls () return lpathcalls  end
+local lpathcached=0  function xml.lpathcached() return lpathcached end
 xml.functions=xml.functions or {} 
 local functions=xml.functions
 xml.expressions=xml.expressions or {} 
@@ -13619,14 +17108,14 @@
 finalizers.xml=finalizers.xml or {}
 finalizers.tex=finalizers.tex or {}
 local function fallback (t,name)
-  local fn=finalizers[name]
-  if fn then
-    t[name]=fn
-  else
-    report_lpath("unknown sub finalizer %a",name)
-    fn=function() end
-  end
-  return fn
+ local fn=finalizers[name]
+ if fn then
+  t[name]=fn
+ else
+  report_lpath("unknown sub finalizer %a",name)
+  fn=function() end
+ end
+ return fn
 end
 setmetatableindex(finalizers.xml,fallback)
 setmetatableindex(finalizers.tex,fallback)
@@ -13633,202 +17122,257 @@
 xml.defaultprotocol="xml"
 local apply_axis={}
 apply_axis['root']=function(list)
-  local collected={}
-  for l=1,#list do
-    local ll=list[l]
-    local rt=ll
-    while ll do
-      ll=ll.__p__
-      if ll then
-        rt=ll
-      end
-    end
-    collected[l]=rt
+ local collected={}
+ for l=1,#list do
+  local ll=list[l]
+  local rt=ll
+  while ll do
+   ll=ll.__p__
+   if ll then
+    rt=ll
+   end
   end
-  return collected
+  collected[l]=rt
+ end
+ return collected
 end
 apply_axis['self']=function(list)
-  return list
+ return list
 end
 apply_axis['child']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    local dt=ll.dt
-    if dt then 
-      local en=0
-      for k=1,#dt do
-        local dk=dt[k]
-        if dk.tg then
-          c=c+1
-          collected[c]=dk
-          dk.ni=k 
-          en=en+1
-          dk.ei=en
-        end
-      end
-      ll.en=en
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  local dt=ll.dt
+  if dt then 
+   local n=#dt
+   if n==0 then
+    ll.en=0
+   elseif n==1 then
+    local dk=dt[1]
+    if dk.tg then
+     c=c+1
+     collected[c]=dk
+     dk.ni=1 
+     dk.ei=1
+     ll.en=1
     end
+   else
+    local en=0
+    for k=1,#dt do
+     local dk=dt[k]
+     if dk.tg then
+      c=c+1
+      en=en+1
+      collected[c]=dk
+      dk.ni=k 
+      dk.ei=en
+     end
+    end
+    ll.en=en
+   end
   end
-  return collected
+ end
+ return collected
 end
 local function collect(list,collected,c)
-  local dt=list.dt
-  if dt then
-    local en=0
-    for k=1,#dt do
-      local dk=dt[k]
-      if dk.tg then
-        c=c+1
-        collected[c]=dk
-        dk.ni=k 
-        en=en+1
-        dk.ei=en
-        c=collect(dk,collected,c)
-      end
+ local dt=list.dt
+ if dt then
+  local n=#dt
+  if n==0 then
+   list.en=0
+  elseif n==1 then
+   local dk=dt[1]
+   if dk.tg then
+    c=c+1
+    collected[c]=dk
+    dk.ni=1 
+    dk.ei=1
+    c=collect(dk,collected,c)
+    list.en=1
+   else
+    list.en=0
+   end
+  else
+   local en=0
+   for k=1,n do
+    local dk=dt[k]
+    if dk.tg then
+     c=c+1
+     en=en+1
+     collected[c]=dk
+     dk.ni=k 
+     dk.ei=en
+     c=collect(dk,collected,c)
     end
-    list.en=en
+   end
+   list.en=en
   end
-  return c
+ end
+ return c
 end
 apply_axis['descendant']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    c=collect(list[l],collected,c)
-  end
-  return collected
+ local collected={}
+ local c=0
+ for l=1,#list do
+  c=collect(list[l],collected,c)
+ end
+ return collected
 end
 local function collect(list,collected,c)
-  local dt=list.dt
-  if dt then
-    local en=0
-    for k=1,#dt do
-      local dk=dt[k]
-      if dk.tg then
-        c=c+1
-        collected[c]=dk
-        dk.ni=k 
-        en=en+1
-        dk.ei=en
-        c=collect(dk,collected,c)
-      end
+ local dt=list.dt
+ if dt then
+  local n=#dt
+  if n==0 then
+   list.en=0
+  elseif n==1 then
+   local dk=dt[1]
+   if dk.tg then
+    c=c+1
+    collected[c]=dk
+    dk.ni=1 
+    dk.ei=1
+    c=collect(dk,collected,c)
+    list.en=1
+   end
+  else
+   local en=0
+   for k=1,#dt do
+    local dk=dt[k]
+    if dk.tg then
+     c=c+1
+     en=en+1
+     collected[c]=dk
+     dk.ni=k 
+     dk.ei=en
+     c=collect(dk,collected,c)
     end
-    list.en=en
+   end
+   list.en=en
   end
-  return c
+ end
+ return c
 end
 apply_axis['descendant-or-self']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    if ll.special~=true then 
-      c=c+1
-      collected[c]=ll
-    end
-    c=collect(ll,collected,c)
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  if ll.special~=true then 
+   c=c+1
+   collected[c]=ll
   end
-  return collected
+  c=collect(ll,collected,c)
+ end
+ return collected
 end
 apply_axis['ancestor']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    while ll do
-      ll=ll.__p__
-      if ll then
-        c=c+1
-        collected[c]=ll
-      end
-    end
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  while ll do
+   ll=ll.__p__
+   if ll then
+    c=c+1
+    collected[c]=ll
+   end
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['ancestor-or-self']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  c=c+1
+  collected[c]=ll
+  while ll do
+   ll=ll.__p__
+   if ll then
     c=c+1
     collected[c]=ll
-    while ll do
-      ll=ll.__p__
-      if ll then
-        c=c+1
-        collected[c]=ll
-      end
-    end
+   end
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['parent']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local pl=list[l].__p__
-    if pl then
-      c=c+1
-      collected[c]=pl
-    end
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local pl=list[l].__p__
+  if pl then
+   c=c+1
+   collected[c]=pl
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['attribute']=function(list)
-  return {}
+ return {}
 end
 apply_axis['namespace']=function(list)
-  return {}
+ return {}
 end
 apply_axis['following']=function(list)
-  return {}
+ return {}
 end
 apply_axis['preceding']=function(list)
-  return {}
+ return {}
 end
 apply_axis['following-sibling']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    local p=ll.__p__
-    local d=p.dt
-    for i=ll.ni+1,#d do
-      local di=d[i]
-      if type(di)=="table" then
-        c=c+1
-        collected[c]=di
-      end
-    end
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  local p=ll.__p__
+  local d=p.dt
+  for i=ll.ni+1,#d do
+   local di=d[i]
+   if type(di)=="table" then
+    c=c+1
+    collected[c]=di
+   end
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['preceding-sibling']=function(list)
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    local p=ll.__p__
-    local d=p.dt
-    for i=1,ll.ni-1 do
-      local di=d[i]
-      if type(di)=="table" then
-        c=c+1
-        collected[c]=di
-      end
-    end
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  local p=ll.__p__
+  local d=p.dt
+  for i=1,ll.ni-1 do
+   local di=d[i]
+   if type(di)=="table" then
+    c=c+1
+    collected[c]=di
+   end
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['reverse-sibling']=function(list) 
-  local collected,c={},0
-  for l=1,#list do
-    local ll=list[l]
-    local p=ll.__p__
-    local d=p.dt
-    for i=ll.ni-1,1,-1 do
-      local di=d[i]
-      if type(di)=="table" then
-        c=c+1
-        collected[c]=di
-      end
-    end
+ local collected={}
+ local c=0
+ for l=1,#list do
+  local ll=list[l]
+  local p=ll.__p__
+  local d=p.dt
+  for i=ll.ni-1,1,-1 do
+   local di=d[i]
+   if type(di)=="table" then
+    c=c+1
+    collected[c]=di
+   end
   end
-  return collected
+ end
+ return collected
 end
 apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self']
 apply_axis['auto-descendant']=apply_axis['descendant']
@@ -13836,131 +17380,148 @@
 apply_axis['auto-self']=apply_axis['self']
 apply_axis['initial-child']=apply_axis['child']
 local function apply_nodes(list,directive,nodes)
-  local maxn=#nodes
-  if maxn==3 then 
-    local nns,ntg=nodes[2],nodes[3]
-    if not nns and not ntg then 
+ local maxn=#nodes
+ if maxn==3 then 
+  local nns=nodes[2]
+  local ntg=nodes[3]
+  if not nns and not ntg then 
+   if directive then
+    return list
+   else
+    return {}
+   end
+  else
+   local collected={}
+   local c=0
+   local m=0
+   local p=nil
+   if not nns then 
+    for l=1,#list do
+     local ll=list[l]
+     local ltg=ll.tg
+     if ltg then
       if directive then
-        return list
-      else
-        return {}
+       if ntg==ltg then
+        local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+        c=c+1
+        collected[c]=ll
+        ll.mi=m
+       end
+      elseif ntg~=ltg then
+       local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+       c=c+1
+       collected[c]=ll
+       ll.mi=m
       end
-    else
-      local collected,c,m,p={},0,0,nil
-      if not nns then 
-        for l=1,#list do
-          local ll=list[l]
-          local ltg=ll.tg
-          if ltg then
-            if directive then
-              if ntg==ltg then
-                local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-                c=c+1
-                collected[c],ll.mi=ll,m
-              end
-            elseif ntg~=ltg then
-              local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-              c=c+1
-              collected[c],ll.mi=ll,m
-            end
-          end
-        end
-      elseif not ntg then 
-        for l=1,#list do
-          local ll=list[l]
-          local lns=ll.rn or ll.ns
-          if lns then
-            if directive then
-              if lns==nns then
-                local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-                c=c+1
-                collected[c],ll.mi=ll,m
-              end
-            elseif lns~=nns then
-              local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-              c=c+1
-              collected[c],ll.mi=ll,m
-            end
-          end
-        end
-      else 
-        for l=1,#list do
-          local ll=list[l]
-          local ltg=ll.tg
-          if ltg then
-            local lns=ll.rn or ll.ns
-            local ok=ltg==ntg and lns==nns
-            if directive then
-              if ok then
-                local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-                c=c+1
-                collected[c],ll.mi=ll,m
-              end
-            elseif not ok then
-              local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-              c=c+1
-              collected[c],ll.mi=ll,m
-            end
-          end
-        end
+     end
+    end
+   elseif not ntg then 
+    for l=1,#list do
+     local ll=list[l]
+     local lns=ll.rn or ll.ns
+     if lns then
+      if directive then
+       if lns==nns then
+        local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+        c=c+1
+        collected[c]=ll
+        ll.mi=m
+       end
+      elseif lns~=nns then
+       local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+       c=c+1
+       collected[c]=ll
+       ll.mi=m
       end
-      return collected
+     end
     end
-  else
-    local collected,c,m,p={},0,0,nil
+   else 
     for l=1,#list do
-      local ll=list[l]
-      local ltg=ll.tg
-      if ltg then
-        local lns=ll.rn or ll.ns
-        local ok=false
-        for n=1,maxn,3 do
-          local nns,ntg=nodes[n+1],nodes[n+2]
-          ok=(not ntg or ltg==ntg) and (not nns or lns==nns)
-          if ok then
-            break
-          end
-        end
-        if directive then
-          if ok then
-            local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-            c=c+1
-            collected[c],ll.mi=ll,m
-          end
-        elseif not ok then
-          local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
-          c=c+1
-          collected[c],ll.mi=ll,m
-        end
+     local ll=list[l]
+     local ltg=ll.tg
+     if ltg then
+      local lns=ll.rn or ll.ns
+      local ok=ltg==ntg and lns==nns
+      if directive then
+       if ok then
+        local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+        c=c+1
+        collected[c]=ll
+        ll.mi=m
+       end
+      elseif not ok then
+       local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+       c=c+1
+       collected[c]=ll
+       ll.mi=m
       end
+     end
     end
-    return collected
+   end
+   return collected
   end
-end
-local quit_expression=false
-local function apply_expression(list,expression,order)
-  local collected,c={},0
-  quit_expression=false
+ else
+  local collected={}
+  local c=0
+  local m=0
+  local p=nil
   for l=1,#list do
-    local ll=list[l]
-    if expression(list,ll,l,order) then 
+   local ll=list[l]
+   local ltg=ll.tg
+   if ltg then
+    local lns=ll.rn or ll.ns
+    local ok=false
+    for n=1,maxn,3 do
+     local nns=nodes[n+1]
+     local ntg=nodes[n+2]
+     ok=(not ntg or ltg==ntg) and (not nns or lns==nns)
+     if ok then
+      break
+     end
+    end
+    if directive then
+     if ok then
+      local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
       c=c+1
       collected[c]=ll
+      ll.mi=m
+     end
+    elseif not ok then
+     local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end
+     c=c+1
+     collected[c]=ll
+     ll.mi=m
     end
-    if quit_expression then
-      break
-    end
+   end
   end
   return collected
+ end
 end
-local function apply_selector(list,specification)
-  if xml.applyselector then
-    apply_selector=xml.applyselector
-    return apply_selector(list,specification)
-  else
-    return list
+local quit_expression=false
+local function apply_expression(list,expression,order)
+ local collected={}
+ local c=0
+ quit_expression=false
+ for l=1,#list do
+  local ll=list[l]
+  if expression(list,ll,l,order) then 
+   c=c+1
+   collected[c]=ll
   end
+  if quit_expression then
+   break
+  end
+ end
+ return collected
 end
+local function apply_selector(list,specification)
+ if xml.applyselector then
+  apply_selector=xml.applyselector
+  return apply_selector(list,specification)
+ else
+  return list
+ end
+end
 local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb
 local spaces=S(" \n\r\t\f")^0
 local lp_space=S(" \n\r\t\f")
@@ -13970,24 +17531,24 @@
 local lp_or=P("|")/" or "
 local lp_and=P("&")/" and "
 local builtin={
-  text="(ll.dt[1] or '')",
-  content="ll.dt",
-  name="((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)",
-  tag="ll.tg",
-  position="l",
-  firstindex="1",
-  firstelement="1",
-  first="1",
-  lastindex="(#ll.__p__.dt or 1)",
-  lastelement="(ll.__p__.en or 1)",
-  last="#list",
-  rootposition="order",
-  order="order",
-  element="(ll.ei or 1)",
-  index="(ll.ni or 1)",
-  match="(ll.mi or 1)",
-  namespace="ll.ns",
-  ns="ll.ns",
+ text="(ll.dt[1] or '')",
+ content="ll.dt",
+ name="((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)",
+ tag="ll.tg",
+ position="l",
+ firstindex="1",
+ firstelement="1",
+ first="1",
+ lastindex="(#ll.__p__.dt or 1)",
+ lastelement="(ll.__p__.en or 1)",
+ last="#list",
+ rootposition="order",
+ order="order",
+ element="(ll.ei or 1)",
+ index="(ll.ni or 1)",
+ match="(ll.mi or 1)",
+ namespace="ll.ns",
+ ns="ll.ns",
 }
 local lp_builtin=lpeg.utfchartabletopattern(builtin)/builtin*((spaces*P("(")*spaces*P(")"))/"")
 local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
@@ -13997,11 +17558,11 @@
 local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
 local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
 local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t) 
-  if expressions[t] then
-    return "expr."..t.."("
-  else
-    return "expr.error("
-  end
+ if expressions[t] then
+  return "expr."..t.."("
+ else
+  return "expr.error("
+ end
 end
 local lparent=P("(")
 local rparent=P(")")
@@ -14014,24 +17575,24 @@
 local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"'))
 local cleaner
 local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s)
-  if expressions[t] then
-    s=s and s~="" and lpegmatch(cleaner,s)
-    if s and s~="" then
-      return "expr."..t.."(ll,"..s..")"
-    else
-      return "expr."..t.."(ll)"
-    end
+ if expressions[t] then
+  s=s and s~="" and lpegmatch(cleaner,s)
+  if s and s~="" then
+   return "expr."..t.."(ll,"..s..")"
   else
-    return "expr.error("..t..")"
+   return "expr."..t.."(ll)"
   end
+ else
+  return "expr.error("..t..")"
+ end
 end
 local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+
-  lp_child+lp_any
+ lp_child+lp_any
 local converter=Cs (
-  lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0
+ lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0
 )
 cleaner=Cs ((
-  lp_reserved+lp_number+lp_string+1 )^1 )
+ lp_reserved+lp_number+lp_string+1 )^1 )
 local template_e=[[
     local expr = xml.expressions
     return function(list,ll,l,order)
@@ -14047,75 +17608,75 @@
 local template_f_n=[[
     return xml.finalizers['%s']['%s']
 ]]
-local register_last_match={ kind="axis",axis="last-match"       } 
-local register_self={ kind="axis",axis="self"          } 
-local register_parent={ kind="axis",axis="parent"         } 
-local register_descendant={ kind="axis",axis="descendant"       } 
-local register_child={ kind="axis",axis="child"          } 
+local register_last_match={ kind="axis",axis="last-match"     } 
+local register_self={ kind="axis",axis="self"     } 
+local register_parent={ kind="axis",axis="parent"      } 
+local register_descendant={ kind="axis",axis="descendant"     } 
+local register_child={ kind="axis",axis="child"       } 
 local register_descendant_or_self={ kind="axis",axis="descendant-or-self"   } 
-local register_root={ kind="axis",axis="root"          } 
-local register_ancestor={ kind="axis",axis="ancestor"        } 
-local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self"    } 
-local register_attribute={ kind="axis",axis="attribute"        } 
-local register_namespace={ kind="axis",axis="namespace"        } 
-local register_following={ kind="axis",axis="following"        } 
+local register_root={ kind="axis",axis="root"     } 
+local register_ancestor={ kind="axis",axis="ancestor"    } 
+local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self"  } 
+local register_attribute={ kind="axis",axis="attribute"      } 
+local register_namespace={ kind="axis",axis="namespace"      } 
+local register_following={ kind="axis",axis="following"      } 
 local register_following_sibling={ kind="axis",axis="following-sibling"    } 
-local register_preceding={ kind="axis",axis="preceding"        } 
+local register_preceding={ kind="axis",axis="preceding"      } 
 local register_preceding_sibling={ kind="axis",axis="preceding-sibling"    } 
-local register_reverse_sibling={ kind="axis",axis="reverse-sibling"     } 
+local register_reverse_sibling={ kind="axis",axis="reverse-sibling"   } 
 local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" } 
-local register_auto_descendant={ kind="axis",axis="auto-descendant"     } 
-local register_auto_self={ kind="axis",axis="auto-self"        } 
-local register_auto_child={ kind="axis",axis="auto-child"       } 
-local register_initial_child={ kind="axis",axis="initial-child"      } 
+local register_auto_descendant={ kind="axis",axis="auto-descendant"   } 
+local register_auto_self={ kind="axis",axis="auto-self"      } 
+local register_auto_child={ kind="axis",axis="auto-child"     } 
+local register_initial_child={ kind="axis",axis="initial-child"     } 
 local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } }
 local skip={}
 local function errorrunner_e(str,cnv)
-  if not skip[str] then
-    report_lpath("error in expression: %s => %s",str,cnv)
-    skip[str]=cnv or str
-  end
-  return false
+ if not skip[str] then
+  report_lpath("error in expression: %s => %s",str,cnv)
+  skip[str]=cnv or str
+ end
+ return false
 end
 local function errorrunner_f(str,arg)
-  report_lpath("error in finalizer: %s(%s)",str,arg or "")
-  return false
+ report_lpath("error in finalizer: %s(%s)",str,arg or "")
+ return false
 end
 local function register_nodes(nodetest,nodes)
-  return { kind="nodes",nodetest=nodetest,nodes=nodes }
+ return { kind="nodes",nodetest=nodetest,nodes=nodes }
 end
 local function register_selector(specification)
-  return { kind="selector",specification=specification }
+ return { kind="selector",specification=specification }
 end
 local function register_expression(expression)
-  local converted=lpegmatch(converter,expression)
-  local runner=load(format(template_e,converted))
-  runner=(runner and runner()) or function() errorrunner_e(expression,converted) end
-  return { kind="expression",expression=expression,converted=converted,evaluator=runner }
+ local converted=lpegmatch(converter,expression)
+ local runner=load(format(template_e,converted))
+ runner=(runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind="expression",expression=expression,converted=converted,evaluator=runner }
 end
 local function register_finalizer(protocol,name,arguments)
-  local runner
-  if arguments and arguments~="" then
-    runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
-  else
-    runner=load(format(template_f_n,protocol or xml.defaultprotocol,name))
-  end
-  runner=(runner and runner()) or function() errorrunner_f(name,arguments) end
-  return { kind="finalizer",name=name,arguments=arguments,finalizer=runner }
+ local runner
+ if arguments and arguments~="" then
+  runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+  runner=load(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner=(runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind="finalizer",name=name,arguments=arguments,finalizer=runner }
 end
 local expression=P { "ex",
-  ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]",
-  sq="'"*(1-S("'"))^0*"'",
-  dq='"'*(1-S('"'))^0*'"',
+ ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]",
+ sq="'"*(1-S("'"))^0*"'",
+ dq='"'*(1-S('"'))^0*'"',
 }
 local arguments=P { "ar",
-  ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")",
-  nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end,
-  sq=P("'")*(1-P("'"))^0*P("'"),
-  dq=P('"')*(1-P('"'))^0*P('"'),
+ ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")",
+ nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end,
+ sq=P("'")*(1-P("'"))^0*P("'"),
+ dq=P('"')*(1-P('"'))^0*P('"'),
 }
 local function register_error(str)
-  return { kind="error",error=format("unparsed: %s",str) }
+ return { kind="error",error=format("unparsed: %s",str) }
 end
 local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes) 
 local special_2=P("/")*Cc(register_auto_self)
@@ -14123,367 +17684,368 @@
 local no_nextcolon=P(-1)+#(1-P(":")) 
 local no_nextlparent=P(-1)+#(1-P("(")) 
 local pathparser=Ct { "patterns",
-  patterns=spaces*V("protocol")*spaces*(
-               (V("special")*spaces*P(-1)                             )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 )
-              ),
-  protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"),
-  step=((V("shortcuts")+V("selector")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0,
-  axis=V("last_match")+V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child),
-  special=special_1+special_2+special_3,
-  initial=(P("/")*spaces*Cc(register_initial_child))^-1,
-  error=(P(1)^1)/register_error,
-  shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor")+V("s_lastmatch"),
-  shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0,
-  s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self),
-  s_descendant=P("**")*Cc(register_descendant),
-  s_child=P("*")*no_nextcolon*Cc(register_child),
-  s_parent=P("..")*Cc(register_parent),
-  s_self=P("." )*Cc(register_self),
-  s_root=P("^^")*Cc(register_root),
-  s_ancestor=P("^")*Cc(register_ancestor),
-  s_lastmatch=P("=")*Cc(register_last_match),
-  descendant=P("descendant::")*Cc(register_descendant),
-  child=P("child::")*Cc(register_child),
-  parent=P("parent::")*Cc(register_parent),
-  self=P("self::")*Cc(register_self),
-  root=P('root::')*Cc(register_root),
-  ancestor=P('ancestor::')*Cc(register_ancestor),
-  descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self),
-  ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self),
-  following=P('following::')*Cc(register_following),
-  following_sibling=P('following-sibling::')*Cc(register_following_sibling),
-  preceding=P('preceding::')*Cc(register_preceding),
-  preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling),
-  reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling),
-  last_match=P('last-match::')*Cc(register_last_match),
-  selector=P("{")*C((1-P("}"))^1)*P("}")/register_selector,
-  nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes,
-  expressions=expression/register_expression,
-  letters=R("az")^1,
-  name=(1-S("/[]()|:*!"))^1,
-  negate=P("!")*Cc(false),
-  nodefunction=V("negate")+P("not")*Cc(false)+Cc(true),
-  nodetest=V("negate")+Cc(true),
-  nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))),
-  wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent,
-  nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces,
-  finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer,
+ patterns=spaces*V("protocol")*spaces*(
+         (V("special")*spaces*P(-1)               )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 )
+         ),
+ protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"),
+ step=((V("shortcuts")+V("selector")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0,
+ axis=V("last_match")+V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child),
+ special=special_1+special_2+special_3,
+ initial=(P("/")*spaces*Cc(register_initial_child))^-1,
+ error=(P(1)^1)/register_error,
+ shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor")+V("s_lastmatch"),
+ shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0,
+ s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self),
+ s_descendant=P("**")*Cc(register_descendant),
+ s_child=P("*")*no_nextcolon*Cc(register_child),
+ s_parent=P("..")*Cc(register_parent),
+ s_self=P("." )*Cc(register_self),
+ s_root=P("^^")*Cc(register_root),
+ s_ancestor=P("^")*Cc(register_ancestor),
+ s_lastmatch=P("=")*Cc(register_last_match),
+ descendant=P("descendant::")*Cc(register_descendant),
+ child=P("child::")*Cc(register_child),
+ parent=P("parent::")*Cc(register_parent),
+ self=P("self::")*Cc(register_self),
+ root=P('root::')*Cc(register_root),
+ ancestor=P('ancestor::')*Cc(register_ancestor),
+ descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self),
+ ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self),
+ following=P('following::')*Cc(register_following),
+ following_sibling=P('following-sibling::')*Cc(register_following_sibling),
+ preceding=P('preceding::')*Cc(register_preceding),
+ preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling),
+ reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling),
+ last_match=P('last-match::')*Cc(register_last_match),
+ selector=P("{")*C((1-P("}"))^1)*P("}")/register_selector,
+ nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes,
+ expressions=expression/register_expression,
+ letters=R("az")^1,
+ name=(1-S("/[]()|:*!"))^1,
+ negate=P("!")*Cc(false),
+ nodefunction=V("negate")+P("not")*Cc(false)+Cc(true),
+ nodetest=V("negate")+Cc(true),
+ nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))),
+ wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent,
+ nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces,
+ finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer,
 }
 xmlpatterns.pathparser=pathparser
 local cache={}
 local function nodesettostring(set,nodetest)
-  local t={}
-  for i=1,#set,3 do
-    local directive,ns,tg=set[i],set[i+1],set[i+2]
-    if not ns or ns=="" then ns="*" end
-    if not tg or tg=="" then tg="*" end
-    tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
-    t[#t+1]=(directive and tg) or format("not(%s)",tg)
-  end
-  if nodetest==false then
-    return format("not(%s)",concat(t,"|"))
-  else
-    return concat(t,"|")
-  end
+ local t={}
+ for i=1,#set,3 do
+  local directive,ns,tg=set[i],set[i+1],set[i+2]
+  if not ns or ns=="" then ns="*" end
+  if not tg or tg=="" then tg="*" end
+  tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+  t[#t+1]=(directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest==false then
+  return format("not(%s)",concat(t,"|"))
+ else
+  return concat(t,"|")
+ end
 end
 local function tagstostring(list)
-  if #list==0 then
-    return "no elements"
-  else
-    local t={}
-    for i=1,#list do
-      local li=list[i]
-      local ns,tg=li.ns,li.tg
-      if not ns or ns=="" then ns="*" end
-      if not tg or tg=="" then tg="*" end
-      t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
-    end
-    return concat(t," ")
+ if #list==0 then
+  return "no elements"
+ else
+  local t={}
+  for i=1,#list do
+   local li=list[i]
+   local ns=li.ns
+   local tg=li.tg
+   if not ns or ns=="" then ns="*" end
+   if not tg or tg=="" then tg="*" end
+   t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
   end
+  return concat(t," ")
+ end
 end
 xml.nodesettostring=nodesettostring
 local lpath 
 local function lshow(parsed)
-  if type(parsed)=="string" then
-    parsed=lpath(parsed)
-  end
-  report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
-    table.serialize(parsed,false))
+ if type(parsed)=="string" then
+  parsed=lpath(parsed)
+ end
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
+  table.serialize(parsed,false))
 end
 xml.lshow=lshow
 local function add_comment(p,str)
-  local pc=p.comment
-  if not pc then
-    p.comment={ str }
-  else
-    pc[#pc+1]=str
-  end
+ local pc=p.comment
+ if not pc then
+  p.comment={ str }
+ else
+  pc[#pc+1]=str
+ end
 end
 lpath=function (pattern) 
-  lpathcalls=lpathcalls+1
-  if type(pattern)=="table" then
-    return pattern
+ lpathcalls=lpathcalls+1
+ if type(pattern)=="table" then
+  return pattern
+ else
+  local parsed=cache[pattern]
+  if parsed then
+   lpathcached=lpathcached+1
   else
-    local parsed=cache[pattern]
-    if parsed then
-      lpathcached=lpathcached+1
+   parsed=lpegmatch(pathparser,pattern)
+   if parsed then
+    parsed.pattern=pattern
+    local np=#parsed
+    if np==0 then
+     parsed={ pattern=pattern,register_self,state="parsing error" }
+     report_lpath("parsing error in pattern: %s",pattern)
+     lshow(parsed)
     else
-      parsed=lpegmatch(pathparser,pattern)
-      if parsed then
-        parsed.pattern=pattern
-        local np=#parsed
-        if np==0 then
-          parsed={ pattern=pattern,register_self,state="parsing error" }
-          report_lpath("parsing error in pattern: %s",pattern)
-          lshow(parsed)
-        else
-          local pi=parsed[1]
-          if pi.axis=="auto-child" then
-            if false then
-              add_comment(parsed,"auto-child replaced by auto-descendant-or-self")
-              parsed[1]=register_auto_descendant_or_self
-            else
-              add_comment(parsed,"auto-child replaced by auto-descendant")
-              parsed[1]=register_auto_descendant
-            end
-          elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then
-            add_comment(parsed,"initial-child removed") 
-            remove(parsed,1)
-          end
-          local np=#parsed 
-          if np>1 then
-            local pnp=parsed[np]
-            if pnp.kind=="nodes" and pnp.nodetest==true then
-              local nodes=pnp.nodes
-              if nodes[1]==true and nodes[2]==false and nodes[3]==false then
-                add_comment(parsed,"redundant final wildcard filter removed")
-                remove(parsed,np)
-              end
-            end
-          end
-        end
+     local pi=parsed[1]
+     if pi.axis=="auto-child" then
+      if false then
+       add_comment(parsed,"auto-child replaced by auto-descendant-or-self")
+       parsed[1]=register_auto_descendant_or_self
       else
-        parsed={ pattern=pattern }
+       add_comment(parsed,"auto-child replaced by auto-descendant")
+       parsed[1]=register_auto_descendant
       end
-      cache[pattern]=parsed
-      if trace_lparse and not trace_lprofile then
-        lshow(parsed)
+     elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then
+      add_comment(parsed,"initial-child removed") 
+      remove(parsed,1)
+     end
+     local np=#parsed 
+     if np>1 then
+      local pnp=parsed[np]
+      if pnp.kind=="nodes" and pnp.nodetest==true then
+       local nodes=pnp.nodes
+       if nodes[1]==true and nodes[2]==false and nodes[3]==false then
+        add_comment(parsed,"redundant final wildcard filter removed")
+        remove(parsed,np)
+       end
       end
+     end
     end
-    return parsed
+   else
+    parsed={ pattern=pattern }
+   end
+   cache[pattern]=parsed
+   if trace_lparse and not trace_lprofile then
+    lshow(parsed)
+   end
   end
+  return parsed
+ end
 end
 xml.lpath=lpath
 do
-  local profiled={}
-  xml.profiled=profiled
-  local lastmatch=nil 
-  local keepmatch=nil 
-  if directives then
-    directives.register("xml.path.keeplastmatch",function(v)
-      keepmatch=v
-      lastmatch=nil
-    end)
+ local profiled={}
+ xml.profiled=profiled
+ local lastmatch=nil  
+ local keepmatch=nil  
+ if directives then
+  directives.register("xml.path.keeplastmatch",function(v)
+   keepmatch=v
+   lastmatch=nil
+  end)
+ end
+ apply_axis["last-match"]=function()
+  return lastmatch or {}
+ end
+ local function profiled_apply(list,parsed,nofparsed,order)
+  local p=profiled[parsed.pattern]
+  if p then
+   p.tested=p.tested+1
+  else
+   p={ tested=1,matched=0,finalized=0 }
+   profiled[parsed.pattern]=p
   end
-  apply_axis["last-match"]=function()
-    return lastmatch or {}
-  end
-  local function profiled_apply(list,parsed,nofparsed,order)
-    local p=profiled[parsed.pattern]
-    if p then
-      p.tested=p.tested+1
-    else
-      p={ tested=1,matched=0,finalized=0 }
-      profiled[parsed.pattern]=p
-    end
-    local collected=list
-    for i=1,nofparsed do
-      local pi=parsed[i]
-      local kind=pi.kind
-      if kind=="axis" then
-        collected=apply_axis[pi.axis](collected)
-      elseif kind=="nodes" then
-        collected=apply_nodes(collected,pi.nodetest,pi.nodes)
-      elseif kind=="expression" then
-        collected=apply_expression(collected,pi.evaluator,order)
-      elseif kind=="selector" then
-        collected=apply_selector(collected,pi.specification)
-      elseif kind=="finalizer" then
-        collected=pi.finalizer(collected) 
-        p.matched=p.matched+1
-        p.finalized=p.finalized+1
-        return collected
-      end
-      if not collected or #collected==0 then
-        local pn=i<nofparsed and parsed[nofparsed]
-        if pn and pn.kind=="finalizer" then
-          collected=pn.finalizer(collected) 
-          p.finalized=p.finalized+1
-          return collected
-        end
-        return nil
-      end
-    end
-    if collected then
-      p.matched=p.matched+1
-    end
+  local collected=list
+  for i=1,nofparsed do
+   local pi=parsed[i]
+   local kind=pi.kind
+   if kind=="axis" then
+    collected=apply_axis[pi.axis](collected)
+   elseif kind=="nodes" then
+    collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+   elseif kind=="expression" then
+    collected=apply_expression(collected,pi.evaluator,order)
+   elseif kind=="selector" then
+    collected=apply_selector(collected,pi.specification)
+   elseif kind=="finalizer" then
+    collected=pi.finalizer(collected) 
+    p.matched=p.matched+1
+    p.finalized=p.finalized+1
     return collected
-  end
-  local function traced_apply(list,parsed,nofparsed,order)
-    if trace_lparse then
-      lshow(parsed)
+   end
+   if not collected or #collected==0 then
+    local pn=i<nofparsed and parsed[nofparsed]
+    if pn and pn.kind=="finalizer" then
+     collected=pn.finalizer(collected) 
+     p.finalized=p.finalized+1
+     return collected
     end
-    report_lpath("collecting: %s",parsed.pattern)
-    report_lpath("root tags : %s",tagstostring(list))
-    report_lpath("order     : %s",order or "unset")
-    local collected=list
-    for i=1,nofparsed do
-      local pi=parsed[i]
-      local kind=pi.kind
-      if kind=="axis" then
-        collected=apply_axis[pi.axis](collected)
-        report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
-      elseif kind=="nodes" then
-        collected=apply_nodes(collected,pi.nodetest,pi.nodes)
-        report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
-      elseif kind=="expression" then
-        collected=apply_expression(collected,pi.evaluator,order)
-        report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
-      elseif kind=="selector" then
-        collected=apply_selector(collected,pi.specification)
-        report_lpath("% 10i : se : %s ",(collected and #collected) or 0,pi.specification)
-      elseif kind=="finalizer" then
-        collected=pi.finalizer(collected)
-        report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
-        return collected
-      end
-      if not collected or #collected==0 then
-        local pn=i<nofparsed and parsed[nofparsed]
-        if pn and pn.kind=="finalizer" then
-          collected=pn.finalizer(collected)
-          report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
-          return collected
-        end
-        return nil
-      end
-    end
-    return collected
+    return nil
+   end
   end
-  local function normal_apply(list,parsed,nofparsed,order)
-    local collected=list
-    for i=1,nofparsed do
-      local pi=parsed[i]
-      local kind=pi.kind
-      if kind=="axis" then
-        local axis=pi.axis
-        if axis~="self" then
-          collected=apply_axis[axis](collected)
-        end
-      elseif kind=="nodes" then
-        collected=apply_nodes(collected,pi.nodetest,pi.nodes)
-      elseif kind=="expression" then
-        collected=apply_expression(collected,pi.evaluator,order)
-      elseif kind=="selector" then
-        collected=apply_selector(collected,pi.specification)
-      elseif kind=="finalizer" then
-        return pi.finalizer(collected)
-      end
-      if not collected or #collected==0 then
-        local pf=i<nofparsed and parsed[nofparsed].finalizer
-        if pf then
-          return pf(collected) 
-        end
-        return nil
-      end
-    end
-    return collected
+  if collected then
+   p.matched=p.matched+1
   end
-  local apply=normal_apply
-  if trackers then
-    trackers.register("xml.path,xml.parse,xml.profile",function()
-      if trace_lprofile then
-        apply=profiled_apply
-      elseif trace_lpath then
-        apply=traced_apply
-      else
-        apply=normal_apply
-      end
-    end)
+  return collected
+ end
+ local function traced_apply(list,parsed,nofparsed,order)
+  if trace_lparse then
+   lshow(parsed)
   end
-  function xml.applylpath(list,pattern)
-    if not list then
-      lastmatch=nil
-      return
+  report_lpath("collecting: %s",parsed.pattern)
+  report_lpath("root tags : %s",tagstostring(list))
+  report_lpath("order     : %s",order or "unset")
+  local collected=list
+  for i=1,nofparsed do
+   local pi=parsed[i]
+   local kind=pi.kind
+   if kind=="axis" then
+    collected=apply_axis[pi.axis](collected)
+    report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
+   elseif kind=="nodes" then
+    collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+    report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
+   elseif kind=="expression" then
+    collected=apply_expression(collected,pi.evaluator,order)
+    report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
+   elseif kind=="selector" then
+    collected=apply_selector(collected,pi.specification)
+    report_lpath("% 10i : se : %s ",(collected and #collected) or 0,pi.specification)
+   elseif kind=="finalizer" then
+    collected=pi.finalizer(collected)
+    report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+    return collected
+   end
+   if not collected or #collected==0 then
+    local pn=i<nofparsed and parsed[nofparsed]
+    if pn and pn.kind=="finalizer" then
+     collected=pn.finalizer(collected)
+     report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
+     return collected
     end
-    local parsed=cache[pattern]
-    if parsed then
-      lpathcalls=lpathcalls+1
-      lpathcached=lpathcached+1
-    elseif type(pattern)=="table" then
-      lpathcalls=lpathcalls+1
-      parsed=pattern
-    else
-      parsed=lpath(pattern) or pattern
+    return nil
+   end
+  end
+  return collected
+ end
+ local function normal_apply(list,parsed,nofparsed,order)
+  local collected=list
+  for i=1,nofparsed do
+   local pi=parsed[i]
+   local kind=pi.kind
+   if kind=="axis" then
+    local axis=pi.axis
+    if axis~="self" then
+     collected=apply_axis[axis](collected)
     end
-    if not parsed then
-      lastmatch=nil
-      return
+   elseif kind=="nodes" then
+    collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+   elseif kind=="expression" then
+    collected=apply_expression(collected,pi.evaluator,order)
+   elseif kind=="selector" then
+    collected=apply_selector(collected,pi.specification)
+   elseif kind=="finalizer" then
+    return pi.finalizer(collected)
+   end
+   if not collected or #collected==0 then
+    local pf=i<nofparsed and parsed[nofparsed].finalizer
+    if pf then
+     return pf(collected) 
     end
-    local nofparsed=#parsed
-    if nofparsed==0 then
-      lastmatch=nil
-      return 
-    end
-    local collected=apply({ list },parsed,nofparsed,list.mi)
-    lastmatch=keepmatch and collected or nil
-    return collected
+    return nil
+   end
   end
-  function xml.lastmatch()
-    return lastmatch
+  return collected
+ end
+ local apply=normal_apply
+ if trackers then
+  trackers.register("xml.path,xml.parse,xml.profile",function()
+   if trace_lprofile then
+    apply=profiled_apply
+   elseif trace_lpath then
+    apply=traced_apply
+   else
+    apply=normal_apply
+   end
+  end)
+ end
+ function xml.applylpath(list,pattern)
+  if not list then
+   lastmatch=nil
+   return
   end
-  local stack={}
-  function xml.pushmatch()
-    insert(stack,lastmatch)
+  local parsed=cache[pattern]
+  if parsed then
+   lpathcalls=lpathcalls+1
+   lpathcached=lpathcached+1
+  elseif type(pattern)=="table" then
+   lpathcalls=lpathcalls+1
+   parsed=pattern
+  else
+   parsed=lpath(pattern) or pattern
   end
-  function xml.popmatch()
-    lastmatch=remove(stack)
+  if not parsed then
+   lastmatch=nil
+   return
   end
+  local nofparsed=#parsed
+  if nofparsed==0 then
+   lastmatch=nil
+   return 
+  end
+  local collected=apply({ list },parsed,nofparsed,list.mi)
+  lastmatch=keepmatch and collected or nil
+  return collected
+ end
+ function xml.lastmatch()
+  return lastmatch
+ end
+ local stack={}
+ function xml.pushmatch()
+  insert(stack,lastmatch)
+ end
+ function xml.popmatch()
+  lastmatch=remove(stack)
+ end
 end
 local applylpath=xml.applylpath
 function xml.filter(root,pattern) 
-  return applylpath(root,pattern)
+ return applylpath(root,pattern)
 end
 expressions.child=function(e,pattern)
-  return applylpath(e,pattern) 
+ return applylpath(e,pattern) 
 end
 expressions.count=function(e,pattern) 
-  local collected=applylpath(e,pattern) 
-  return pattern and (collected and #collected) or 0
+ local collected=applylpath(e,pattern) 
+ return pattern and (collected and #collected) or 0
 end
 expressions.oneof=function(s,...)
-  for i=1,select("#",...) do
-    if s==select(i,...) then
-      return true
-    end
+ for i=1,select("#",...) do
+  if s==select(i,...) then
+   return true
   end
-  return false
+ end
+ return false
 end
 expressions.error=function(str)
-  xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
-  return false
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
+ return false
 end
 expressions.undefined=function(s)
-  return s==nil
+ return s==nil
 end
 expressions.quit=function(s)
-  if s or s==nil then
-    quit_expression=true
-  end
-  return true
+ if s or s==nil then
+  quit_expression=true
+ end
+ return true
 end
 expressions.print=function(...)
-  print(...)
-  return true
+ print(...)
+ return true
 end
 expressions.find=find
 expressions.upper=upper
@@ -14491,233 +18053,238 @@
 expressions.number=tonumber
 expressions.boolean=toboolean
 function expressions.contains(str,pattern)
-  local t=type(str)
-  if t=="string" then
-    if find(str,pattern) then
-      return true
-    end
-  elseif t=="table" then
-    for i=1,#str do
-      local d=str[i]
-      if type(d)=="string" and find(d,pattern) then
-        return true
-      end
-    end
+ local t=type(str)
+ if t=="string" then
+  if find(str,pattern) then
+   return true
   end
-  return false
+ elseif t=="table" then
+  for i=1,#str do
+   local d=str[i]
+   if type(d)=="string" and find(d,pattern) then
+    return true
+   end
+  end
+ end
+ return false
 end
 function xml.expressions.idstring(str)
-  return type(str)=="string" and gsub(str,"^#","") or ""
+ return type(str)=="string" and gsub(str,"^#","") or ""
 end
 local function traverse(root,pattern,handle)
-  local collected=applylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      local e=collected[c]
-      local r=e.__p__
-      handle(r,r.dt,e.ni)
-    end
+ local collected=applylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   local e=collected[c]
+   local r=e.__p__
+   handle(r,r.dt,e.ni)
   end
+ end
 end
 local function selection(root,pattern,handle)
-  local collected=applylpath(root,pattern)
-  if collected then
-    if handle then
-      for c=1,#collected do
-        handle(collected[c])
-      end
-    else
-      return collected
-    end
+ local collected=applylpath(root,pattern)
+ if collected then
+  if handle then
+   for c=1,#collected do
+    handle(collected[c])
+   end
+  else
+   return collected
   end
+ end
 end
-xml.traverse=traverse      
+xml.traverse=traverse     
 xml.selection=selection
 local function dofunction(collected,fnc,...)
-  if collected then
-    local f=functions[fnc]
-    if f then
-      for c=1,#collected do
-        f(collected[c],...)
-      end
-    else
-      report_lpath("unknown function %a",fnc)
-    end
+ if collected then
+  local f=functions[fnc]
+  if f then
+   for c=1,#collected do
+    f(collected[c],...)
+   end
+  else
+   report_lpath("unknown function %a",fnc)
   end
+ end
 end
 finalizers.xml["function"]=dofunction
 finalizers.tex["function"]=dofunction
 expressions.text=function(e,n)
-  local rdt=e.__p__.dt
-  return rdt and rdt[n] or ""
+ local rdt=e.__p__.dt
+ return rdt and rdt[n] or ""
 end
 expressions.name=function(e,n) 
-  local found=false
-  n=tonumber(n) or 0
-  if n==0 then
-    found=type(e)=="table" and e
-  elseif n<0 then
-    local d,k=e.__p__.dt,e.ni
-    for i=k-1,1,-1 do
-      local di=d[i]
-      if type(di)=="table" then
-        if n==-1 then
-          found=di
-          break
-        else
-          n=n+1
-        end
-      end
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+  found=type(e)=="table" and e
+ elseif n<0 then
+  local d=e.__p__.dt
+  local k=e.ni
+  for i=k-1,1,-1 do
+   local di=d[i]
+   if type(di)=="table" then
+    if n==-1 then
+     found=di
+     break
+    else
+     n=n+1
     end
-  else
-    local d,k=e.__p__.dt,e.ni
-    for i=k+1,#d,1 do
-      local di=d[i]
-      if type(di)=="table" then
-        if n==1 then
-          found=di
-          break
-        else
-          n=n-1
-        end
-      end
-    end
+   end
   end
-  if found then
-    local ns,tg=found.rn or found.ns or "",found.tg
-    if ns~="" then
-      return ns..":"..tg
+ else
+  local d=e.__p__.dt
+  local k=e.ni
+  for i=k+1,#d,1 do
+   local di=d[i]
+   if type(di)=="table" then
+    if n==1 then
+     found=di
+     break
     else
-      return tg
+     n=n-1
     end
+   end
+  end
+ end
+ if found then
+  local ns=found.rn or found.ns or ""
+  local tg=found.tg
+  if ns~="" then
+   return ns..":"..tg
   else
-    return ""
+   return tg
   end
+ else
+  return ""
+ end
 end
 expressions.tag=function(e,n) 
-  if not e then
-    return ""
+ if not e then
+  return ""
+ else
+  local found=false
+  n=tonumber(n) or 0
+  if n==0 then
+   found=(type(e)=="table") and e 
+  elseif n<0 then
+   local d=e.__p__.dt
+   local k=e.ni
+   for i=k-1,1,-1 do
+    local di=d[i]
+    if type(di)=="table" then
+     if n==-1 then
+      found=di
+      break
+     else
+      n=n+1
+     end
+    end
+   end
   else
-    local found=false
-    n=tonumber(n) or 0
-    if n==0 then
-      found=(type(e)=="table") and e 
-    elseif n<0 then
-      local d,k=e.__p__.dt,e.ni
-      for i=k-1,1,-1 do
-        local di=d[i]
-        if type(di)=="table" then
-          if n==-1 then
-            found=di
-            break
-          else
-            n=n+1
-          end
-        end
-      end
-    else
-      local d,k=e.__p__.dt,e.ni
-      for i=k+1,#d,1 do
-        local di=d[i]
-        if type(di)=="table" then
-          if n==1 then
-            found=di
-            break
-          else
-            n=n-1
-          end
-        end
-      end
+   local d=e.__p__.dt
+   local k=e.ni
+   for i=k+1,#d,1 do
+    local di=d[i]
+    if type(di)=="table" then
+     if n==1 then
+      found=di
+      break
+     else
+      n=n-1
+     end
     end
-    return (found and found.tg) or ""
+   end
   end
+  return (found and found.tg) or ""
+ end
 end
 local dummy=function() end
 function xml.elements(root,pattern,reverse) 
-  local collected=applylpath(root,pattern)
-  if not collected then
-    return dummy
+ local collected=applylpath(root,pattern)
+ if not collected then
+  return dummy
+ end
+ local n=#collected
+ if n==0 then
+  return dummy
+ end
+ if reverse then
+  local c=n+1
+  return function()
+   if c>1 then
+    c=c-1
+    local e=collected[c]
+    local r=e.__p__
+    return r,r.dt,e.ni
+   end
   end
-  local n=#collected
-  if n==0 then
-    return dummy
+ else
+  local c=0
+  return function()
+   if c<n then
+    c=c+1
+    local e=collected[c]
+    local r=e.__p__
+    return r,r.dt,e.ni
+   end
   end
-  if reverse then
-    local c=n+1
-    return function()
-      if c>1 then
-        c=c-1
-        local e=collected[c]
-        local r=e.__p__
-        return r,r.dt,e.ni
-      end
-    end
-  else
-    local c=0
-    return function()
-      if c<n then
-        c=c+1
-        local e=collected[c]
-        local r=e.__p__
-        return r,r.dt,e.ni
-      end
-    end
-  end
+ end
 end
 function xml.collected(root,pattern,reverse) 
-  local collected=applylpath(root,pattern)
-  if not collected then
-    return dummy
+ local collected=applylpath(root,pattern)
+ if not collected then
+  return dummy
+ end
+ local n=#collected
+ if n==0 then
+  return dummy
+ end
+ if reverse then
+  local c=n+1
+  return function()
+   if c>1 then
+    c=c-1
+    return collected[c]
+   end
   end
-  local n=#collected
-  if n==0 then
-    return dummy
+ else
+  local c=0
+  return function()
+   if c<n then
+    c=c+1
+    return collected[c]
+   end
   end
-  if reverse then
-    local c=n+1
-    return function()
-      if c>1 then
-        c=c-1
-        return collected[c]
-      end
-    end
-  else
-    local c=0
-    return function()
-      if c<n then
-        c=c+1
-        return collected[c]
-      end
-    end
-  end
+ end
 end
 function xml.inspect(collection,pattern)
-  pattern=pattern or "."
-  for e in xml.collected(collection,pattern or ".") do
-    report_lpath("pattern: %s\n\n%s\n",pattern,xml.tostring(e))
-  end
+ pattern=pattern or "."
+ for e in xml.collected(collection,pattern or ".") do
+  report_lpath("pattern: %s\n\n%s\n",pattern,xml.tostring(e))
+ end
 end
 local function split(e) 
-  local dt=e.dt
-  if dt then
-    for i=1,#dt do
-      local dti=dt[i]
-      if type(dti)=="string" then
-        dti=gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
-        dti=gsub(dti,"[\n\r]+","\n\n")
-        dt[i]=dti
-      else
-        split(dti)
-      end
-    end
+ local dt=e.dt
+ if dt then
+  for i=1,#dt do
+   local dti=dt[i]
+   if type(dti)=="string" then
+    dti=gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+    dti=gsub(dti,"[\n\r]+","\n\n")
+    dt[i]=dti
+   else
+    split(dti)
+   end
   end
-  return e
+ end
+ return e
 end
 function xml.finalizers.paragraphs(c)
-  for i=1,#c do
-    split(c[i])
-  end
-  return c
+ for i=1,#c do
+  split(c[i])
+ end
+ return c
 end
 
 
@@ -14727,14 +18294,14 @@
 
 package.loaded["lxml-mis"] = package.loaded["lxml-mis"] or true
 
--- original size: 3574, stripped down to: 1863
+-- original size: 3574, stripped down to: 1808
 
 if not modules then modules={} end modules ['lxml-mis']={
-  version=1.001,
-  comment="this module is the basis for the lxml-* ones",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local xml,lpeg,string=xml,lpeg,string
 local type=type
@@ -14745,26 +18312,26 @@
 lpegpatterns.xml=lpegpatterns.xml or {}
 local xmlpatterns=lpegpatterns.xml
 local function xmlgsub(t,old,new) 
-  local dt=t.dt
-  if dt then
-    for k=1,#dt do
-      local v=dt[k]
-      if type(v)=="string" then
-        dt[k]=gsub(v,old,new)
-      else
-        xmlgsub(v,old,new)
-      end
-    end
+ local dt=t.dt
+ if dt then
+  for k=1,#dt do
+   local v=dt[k]
+   if type(v)=="string" then
+    dt[k]=gsub(v,old,new)
+   else
+    xmlgsub(v,old,new)
+   end
   end
+ end
 end
 function xml.stripleadingspaces(dk,d,k) 
-  if d and k then
-    local dkm=d[k-1]
-    if dkm and type(dkm)=="string" then
-      local s=match(dkm,"\n(%s+)")
-      xmlgsub(dk,"\n"..rep(" ",#s),"\n")
-    end
+ if d and k then
+  local dkm=d[k-1]
+  if dkm and type(dkm)=="string" then
+   local s=match(dkm,"\n(%s+)")
+   xmlgsub(dk,"\n"..rep(" ",#s),"\n")
   end
+ end
 end
 local normal=(1-S("<&>"))^0
 local special=P("<")/"<"+P(">")/">"+P("&")/"&"
@@ -14776,17 +18343,17 @@
 xmlpatterns.escaped=escaped
 xmlpatterns.unescaped=unescaped
 xmlpatterns.cleansed=cleansed
-function xml.escaped (str) return lpegmatch(escaped,str)  end
+function xml.escaped  (str) return lpegmatch(escaped,str)   end
 function xml.unescaped(str) return lpegmatch(unescaped,str) end
-function xml.cleansed (str) return lpegmatch(cleansed,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str)  end
 function xml.fillin(root,pattern,str,check)
-  local e=xml.first(root,pattern)
-  if e then
-    local n=#e.dt
-    if not check or n==0 or (n==1 and e.dt[1]=="") then
-      e.dt={ str }
-    end
+ local e=xml.first(root,pattern)
+ if e then
+  local n=#e.dt
+  if not check or n==0 or (n==1 and e.dt[1]=="") then
+   e.dt={ str }
   end
+ end
 end
 
 
@@ -14796,17 +18363,17 @@
 
 package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
 
--- original size: 30650, stripped down to: 21793
+-- original size: 30771, stripped down to: 19680
 
 if not modules then modules={} end modules ['lxml-aux']={
-  version=1.001,
-  comment="this module is the basis for the lxml-* ones",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
-local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
-local trace_inclusions=false trackers.register("lxml.inclusions",function(v) trace_inclusions=v end)
+local trace_manipulations=false  trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local trace_inclusions=false  trackers.register("lxml.inclusions",function(v) trace_inclusions=v end)
 local report_xml=logs.reporter("xml")
 local xml=xml
 local xmlcopy,xmlname=xml.copy,xml.name
@@ -14819,308 +18386,313 @@
 local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
 local striplinepatterns=utilities.strings.striplinepatterns
 local function report(what,pattern,c,e)
-  report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+ report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
 end
 local function withelements(e,handle,depth)
-  if e and handle then
-    local edt=e.dt
-    if edt then
-      depth=depth or 0
-      for i=1,#edt do
-        local e=edt[i]
-        if type(e)=="table" then
-          handle(e,depth)
-          withelements(e,handle,depth+1)
-        end
-      end
+ if e and handle then
+  local edt=e.dt
+  if edt then
+   depth=depth or 0
+   for i=1,#edt do
+    local e=edt[i]
+    if type(e)=="table" then
+     handle(e,depth)
+     withelements(e,handle,depth+1)
     end
+   end
   end
+ end
 end
 xml.withelements=withelements
 function xml.withelement(e,n,handle) 
-  if e and n~=0 and handle then
-    local edt=e.dt
-    if edt then
-      if n>0 then
-        for i=1,#edt do
-          local ei=edt[i]
-          if type(ei)=="table" then
-            if n==1 then
-              handle(ei)
-              return
-            else
-              n=n-1
-            end
-          end
-        end
-      elseif n<0 then
-        for i=#edt,1,-1 do
-          local ei=edt[i]
-          if type(ei)=="table" then
-            if n==-1 then
-              handle(ei)
-              return
-            else
-              n=n+1
-            end
-          end
-        end
+ if e and n~=0 and handle then
+  local edt=e.dt
+  if edt then
+   if n>0 then
+    for i=1,#edt do
+     local ei=edt[i]
+     if type(ei)=="table" then
+      if n==1 then
+       handle(ei)
+       return
+      else
+       n=n-1
       end
+     end
     end
-  end
-end
-function xml.each(root,pattern,handle,reverse)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    if handle then
-      if reverse then
-        for c=#collected,1,-1 do
-          handle(collected[c])
-        end
+   elseif n<0 then
+    for i=#edt,1,-1 do
+     local ei=edt[i]
+     if type(ei)=="table" then
+      if n==-1 then
+       handle(ei)
+       return
       else
-        for c=1,#collected do
-          handle(collected[c])
-        end
+       n=n+1
       end
+     end
     end
-    return collected
+   end
   end
+ end
 end
-function xml.processattributes(root,pattern,handle)
-  local collected=xmlapplylpath(root,pattern)
-  if collected and handle then
+function xml.each(root,pattern,handle,reverse)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  if handle then
+   if reverse then
+    for c=#collected,1,-1 do
+     handle(collected[c])
+    end
+   else
     for c=1,#collected do
-      handle(collected[c].at)
+     handle(collected[c])
     end
+   end
   end
   return collected
+ end
 end
+function xml.processattributes(root,pattern,handle)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and handle then
+  for c=1,#collected do
+   handle(collected[c].at)
+  end
+ end
+ return collected
+end
 function xml.collect(root,pattern)
-  return xmlapplylpath(root,pattern)
+ return xmlapplylpath(root,pattern)
 end
 function xml.collecttexts(root,pattern,flatten) 
-  local collected=xmlapplylpath(root,pattern)
-  if collected and flatten then
-    local xmltostring=xml.tostring
-    for c=1,#collected do
-      collected[c]=xmltostring(collected[c].dt)
-    end
+ local collected=xmlapplylpath(root,pattern)
+ if collected and flatten then
+  local xmltostring=xml.tostring
+  for c=1,#collected do
+   collected[c]=xmltostring(collected[c].dt)
   end
-  return collected or {}
+ end
+ return collected or {}
 end
 function xml.collect_tags(root,pattern,nonamespace)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    local t,n={},0
-    for c=1,#collected do
-      local e=collected[c]
-      local ns,tg=e.ns,e.tg
-      n=n+1
-      if nonamespace then
-        t[n]=tg
-      elseif ns=="" then
-        t[n]=tg
-      else
-        t[n]=ns..":"..tg
-      end
-    end
-    return t
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  local t={}
+  local n=0
+  for c=1,#collected do
+   local e=collected[c]
+   local ns=e.ns
+   local tg=e.tg
+   n=n+1
+   if nonamespace then
+    t[n]=tg
+   elseif ns=="" then
+    t[n]=tg
+   else
+    t[n]=ns..":"..tg
+   end
   end
+  return t
+ end
 end
 local no_root={ no_root=true }
 local function redo_ni(d)
-  for k=1,#d do
-    local dk=d[k]
-    if type(dk)=="table" then
-      dk.ni=k
-    end
+ for k=1,#d do
+  local dk=d[k]
+  if type(dk)=="table" then
+   dk.ni=k
   end
+ end
 end
 xml.reindex=redo_ni
 local function xmltoelement(whatever,root)
-  if not whatever then
-    return nil
-  end
-  local element
-  if type(whatever)=="string" then
-    element=xmlinheritedconvert(whatever,root) 
-  else
-    element=whatever 
-  end
-  if element.error then
-    return whatever 
-  end
-  if element then
-  end
-  return element
+ if not whatever then
+  return nil
+ end
+ local element
+ if type(whatever)=="string" then
+  element=xmlinheritedconvert(whatever,root) 
+ else
+  element=whatever 
+ end
+ if element.error then
+  return whatever 
+ end
+ if element then
+ end
+ return element
 end
 xml.toelement=xmltoelement
 local function copiedelement(element,newparent)
-  if type(element)=="string" then
-    return element
-  else
-    element=xmlcopy(element).dt
-    if newparent and type(element)=="table" then
-      element.__p__=newparent
-    end
-    return element
+ if type(element)=="string" then
+  return element
+ else
+  element=xmlcopy(element).dt
+  if newparent and type(element)=="table" then
+   element.__p__=newparent
   end
+  return element
+ end
 end
 function xml.delete(root,pattern)
-  if not pattern or pattern=="" then
-    local p=root.__p__
+ if not pattern or pattern=="" then
+  local p=root.__p__
+  if p then
+   if trace_manipulations then
+    report('deleting',"--",c,root)
+   end
+   local d=p.dt
+   remove(d,root.ni)
+   redo_ni(d) 
+  end
+ else
+  local collected=xmlapplylpath(root,pattern)
+  if collected then
+   for c=1,#collected do
+    local e=collected[c]
+    local p=e.__p__
     if p then
-      if trace_manipulations then
-        report('deleting',"--",c,root)
+     if trace_manipulations then
+      report('deleting',pattern,c,e)
+     end
+     local d=p.dt
+     local ni=e.ni
+     if ni<=#d then
+      if false then
+       p.dt[ni]=""
+      else
+       remove(d,ni)
+       redo_ni(d) 
       end
-      local d=p.dt
-      remove(d,root.ni)
-      redo_ni(d) 
+     else
+     end
     end
-  else
-    local collected=xmlapplylpath(root,pattern)
-    if collected then
-      for c=1,#collected do
-        local e=collected[c]
-        local p=e.__p__
-        if p then
-          if trace_manipulations then
-            report('deleting',pattern,c,e)
-          end
-          local d=p.dt
-          local ni=e.ni
-          if ni<=#d then
-            if false then
-              p.dt[ni]=""
-            else
-              remove(d,ni)
-              redo_ni(d) 
-            end
-          else
-          end
-        end
-      end
-    end
+   end
   end
+ end
 end
 function xml.replace(root,pattern,whatever)
-  local element=root and xmltoelement(whatever,root)
-  local collected=element and xmlapplylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      local e=collected[c]
-      local p=e.__p__
-      if p then
-        if trace_manipulations then
-          report('replacing',pattern,c,e)
-        end
-        local d=p.dt
-        local n=e.ni
-        local t=copiedelement(element,p)
-        if type(t)=="table" then
-          d[n]=t[1]
-          for i=2,#t do
-            n=n+1
-            insert(d,n,t[i])
-          end
-        else
-          d[n]=t
-        end
-        redo_ni(d) 
-      end
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   local e=collected[c]
+   local p=e.__p__
+   if p then
+    if trace_manipulations then
+     report('replacing',pattern,c,e)
     end
+    local d=p.dt
+    local n=e.ni
+    local t=copiedelement(element,p)
+    if type(t)=="table" then
+     d[n]=t[1]
+     for i=2,#t do
+      n=n+1
+      insert(d,n,t[i])
+     end
+    else
+     d[n]=t
+    end
+    redo_ni(d) 
+   end
   end
+ end
 end
 local function wrap(e,wrapper)
-  local t={
-    rn=e.rn,
-    tg=e.tg,
-    ns=e.ns,
-    at=e.at,
-    dt=e.dt,
-    __p__=e,
-  }
-  setmetatable(t,getmetatable(e))
-  e.rn=wrapper.rn or e.rn or ""
-  e.tg=wrapper.tg or e.tg or ""
-  e.ns=wrapper.ns or e.ns or ""
-  e.at=fastcopy(wrapper.at)
-  e.dt={ t }
+ local t={
+  rn=e.rn,
+  tg=e.tg,
+  ns=e.ns,
+  at=e.at,
+  dt=e.dt,
+  __p__=e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn=wrapper.rn or e.rn or ""
+ e.tg=wrapper.tg or e.tg or ""
+ e.ns=wrapper.ns or e.ns or ""
+ e.at=fastcopy(wrapper.at)
+ e.dt={ t }
 end
 function xml.wrap(root,pattern,whatever)
-  if whatever then
-    local wrapper=xmltoelement(whatever,root)
-    local collected=xmlapplylpath(root,pattern)
-    if collected then
-      for c=1,#collected do
-        local e=collected[c]
-        if trace_manipulations then
-          report('wrapping',pattern,c,e)
-        end
-        wrap(e,wrapper)
-      end
+ if whatever then
+  local wrapper=xmltoelement(whatever,root)
+  local collected=xmlapplylpath(root,pattern)
+  if collected then
+   for c=1,#collected do
+    local e=collected[c]
+    if trace_manipulations then
+     report('wrapping',pattern,c,e)
     end
-  else
-    wrap(root,xmltoelement(pattern))
+    wrap(e,wrapper)
+   end
   end
+ else
+  wrap(root,xmltoelement(pattern))
+ end
 end
 local function inject_element(root,pattern,whatever,prepend)
-  local element=root and xmltoelement(whatever,root)
-  local collected=element and xmlapplylpath(root,pattern)
-  local function inject_e(e)
-    local r=e.__p__
-    local d,k,rri=r.dt,e.ni,r.ri
-    local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt)
-    if edt then
-      local be,af
-      local cp=copiedelement(element,e)
-      if prepend then
-        be,af=cp,edt
-      else
-        be,af=edt,cp
-      end
-      local bn=#be
-      for i=1,#af do
-        bn=bn+1
-        be[bn]=af[i]
-      end
-      if rri then
-        r.dt[rri].dt=be
-      else
-        d[k].dt=be
-      end
-      redo_ni(d)
-    end
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function inject_e(e)
+  local r=e.__p__
+  local d=r.dt
+  local k=e.ni
+  local rri=r.ri
+  local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt)
+  if edt then
+   local be,af
+   local cp=copiedelement(element,e)
+   if prepend then
+    be,af=cp,edt
+   else
+    be,af=edt,cp
+   end
+   local bn=#be
+   for i=1,#af do
+    bn=bn+1
+    be[bn]=af[i]
+   end
+   if rri then
+    r.dt[rri].dt=be
+   else
+    d[k].dt=be
+   end
+   redo_ni(d)
   end
-  if not collected then
-  elseif collected.tg then
-    inject_e(collected)
-  else
-    for c=1,#collected do
-      inject_e(collected[c])
-    end
+ end
+ if not collected then
+ elseif collected.tg then
+  inject_e(collected)
+ else
+  for c=1,#collected do
+   inject_e(collected[c])
   end
+ end
 end
 local function insert_element(root,pattern,whatever,before) 
-  local element=root and xmltoelement(whatever,root)
-  local collected=element and xmlapplylpath(root,pattern)
-  local function insert_e(e)
-    local r=e.__p__
-    local d,k=r.dt,e.ni
-    if not before then
-      k=k+1
-    end
-    insert(d,k,copiedelement(element,r))
-    redo_ni(d)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function insert_e(e)
+  local r=e.__p__
+  local d=r.dt
+  local k=e.ni
+  if not before then
+   k=k+1
   end
-  if not collected then
-  elseif collected.tg then
-    insert_e(collected)
-  else
-    for c=1,#collected do
-      insert_e(collected[c])
-    end
+  insert(d,k,copiedelement(element,r))
+  redo_ni(d)
+ end
+ if not collected then
+ elseif collected.tg then
+  insert_e(collected)
+ else
+  for c=1,#collected do
+   insert_e(collected[c])
   end
+ end
 end
 xml.insert_element=insert_element
 xml.insertafter=insert_element
@@ -15128,124 +18700,124 @@
 xml.injectafter=inject_element
 xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
 local function include(xmldata,pattern,attribute,recursive,loaddata,level)
-  pattern=pattern or 'include'
-  loaddata=loaddata or io.loaddata
-  local collected=xmlapplylpath(xmldata,pattern)
-  if collected then
-    if not level then
-      level=1
-    end
-    for c=1,#collected do
-      local ek=collected[c]
-      local name=nil
-      local ekdt=ek.dt
-      if ekdt then
-        local ekat=ek.at
-        local ekrt=ek.__p__
-        if ekrt then
-          local epdt=ekrt.dt
-          if not attribute or attribute=="" then
-            name=(type(ekdt)=="table" and ekdt[1]) or ekdt 
-          end
-          if not name then
-            for a in gmatch(attribute or "href","([^|]+)") do
-              name=ekat[a]
-              if name then
-                break
-              end
-            end
-          end
-          local data=nil
-          if name and name~="" then
-            local d,n=loaddata(name)
-            data=d or ""
-            name=n or name
-            if trace_inclusions then
-              report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
-            end
-          end
-          if not data or data=="" then
-            epdt[ek.ni]="" 
-          elseif ekat["parse"]=="text" then
-            epdt[ek.ni]=xml.escaped(data) 
-          else
+ pattern=pattern or 'include'
+ loaddata=loaddata or io.loaddata
+ local collected=xmlapplylpath(xmldata,pattern)
+ if collected then
+  if not level then
+   level=1
+  end
+  for c=1,#collected do
+   local ek=collected[c]
+   local name=nil
+   local ekdt=ek.dt
+   if ekdt then
+    local ekat=ek.at
+    local ekrt=ek.__p__
+    if ekrt then
+     local epdt=ekrt.dt
+     if not attribute or attribute=="" then
+      name=(type(ekdt)=="table" and ekdt[1]) or ekdt 
+     end
+     if not name then
+      for a in gmatch(attribute or "href","([^|]+)") do
+       name=ekat[a]
+       if name then
+        break
+       end
+      end
+     end
+     local data=nil
+     if name and name~="" then
+      local d,n=loaddata(name)
+      data=d or ""
+      name=n or name
+      if trace_inclusions then
+       report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
+      end
+     end
+     if not data or data=="" then
+      epdt[ek.ni]="" 
+     elseif ekat["parse"]=="text" then
+      epdt[ek.ni]=xml.escaped(data) 
+     else
 local settings=xmldata.settings
 local savedresource=settings.currentresource
 settings.currentresource=name
-            local xi=xmlinheritedconvert(data,xmldata)
-            if not xi then
-              epdt[ek.ni]="" 
-            else
-              if recursive then
-                include(xi,pattern,attribute,recursive,loaddata,level+1)
-              end
-              local child=xml.body(xi) 
-              child.__p__=ekrt
-              child.__f__=name 
+      local xi=xmlinheritedconvert(data,xmldata)
+      if not xi then
+       epdt[ek.ni]="" 
+      else
+       if recursive then
+        include(xi,pattern,attribute,recursive,loaddata,level+1)
+       end
+       local child=xml.body(xi) 
+       child.__p__=ekrt
+       child.__f__=name 
 child.cf=name
-              epdt[ek.ni]=child
-              local settings=xmldata.settings
-              local inclusions=settings and settings.inclusions
-              if inclusions then
-                inclusions[#inclusions+1]=name
-              elseif settings then
-                settings.inclusions={ name }
-              else
-                settings={ inclusions={ name } }
-                xmldata.settings=settings
-              end
-              if child.er then
-                local badinclusions=settings.badinclusions
-                if badinclusions then
-                  badinclusions[#badinclusions+1]=name
-                else
-                  settings.badinclusions={ name }
-                end
-              end
-            end
-settings.currentresource=savedresource
-          end
+       epdt[ek.ni]=child
+       local settings=xmldata.settings
+       local inclusions=settings and settings.inclusions
+       if inclusions then
+        inclusions[#inclusions+1]=name
+       elseif settings then
+        settings.inclusions={ name }
+       else
+        settings={ inclusions={ name } }
+        xmldata.settings=settings
+       end
+       if child.er then
+        local badinclusions=settings.badinclusions
+        if badinclusions then
+         badinclusions[#badinclusions+1]=name
+        else
+         settings.badinclusions={ name }
         end
+       end
       end
+settings.currentresource=savedresource
+     end
     end
+   end
   end
+ end
 end
 xml.include=include
 function xml.inclusion(e,default)
-  while e do
-    local f=e.__f__
-    if f then
-      return f
-    else
-      e=e.__p__
-    end
+ while e do
+  local f=e.__f__
+  if f then
+   return f
+  else
+   e=e.__p__
   end
-  return default
+ end
+ return default
 end
 local function getinclusions(key,e,sorted)
-  while e do
-    local settings=e.settings
-    if settings then
-      local inclusions=settings[key]
-      if inclusions then
-        inclusions=table.unique(inclusions) 
-        if sorted then
-          table.sort(inclusions) 
-        end
-        return inclusions 
-      else
-        e=e.__p__
-      end
-    else
-      e=e.__p__
+ while e do
+  local settings=e.settings
+  if settings then
+   local inclusions=settings[key]
+   if inclusions then
+    inclusions=table.unique(inclusions) 
+    if sorted then
+     table.sort(inclusions) 
     end
+    return inclusions 
+   else
+    e=e.__p__
+   end
+  else
+   e=e.__p__
   end
+ end
 end
 function xml.inclusions(e,sorted)
-  return getinclusions("inclusions",e,sorted)
+ return getinclusions("inclusions",e,sorted)
 end
 function xml.badinclusions(e,sorted)
-  return getinclusions("badinclusions",e,sorted)
+ return getinclusions("badinclusions",e,sorted)
 end
 local b_collapser=lpegpatterns.b_collapser
 local m_collapser=lpegpatterns.m_collapser
@@ -15254,194 +18826,194 @@
 local m_stripper=lpegpatterns.m_stripper
 local e_stripper=lpegpatterns.e_stripper
 local function stripelement(e,nolines,anywhere)
-  local edt=e.dt
-  if edt then
-    local n=#edt
-    if n==0 then
-      return e 
-    elseif anywhere then
-      local t={}
-      local m=0
-      for e=1,n do
-        local str=edt[e]
-        if type(str)~="string" then
-          m=m+1
-          t[m]=str
-        elseif str~="" then
-          if nolines then
-            str=lpegmatch((n==1 and b_collapser) or (n==m and e_collapser) or m_collapser,str)
-          else
-            str=lpegmatch((n==1 and b_stripper) or (n==m and e_stripper) or m_stripper,str)
-          end
-          if str~="" then
-            m=m+1
-            t[m]=str
-          end
-        end
-      end
-      e.dt=t
+ local edt=e.dt
+ if edt then
+  local n=#edt
+  if n==0 then
+   return e 
+  elseif anywhere then
+   local t={}
+   local m=0
+   for e=1,n do
+    local str=edt[e]
+    if type(str)~="string" then
+     m=m+1
+     t[m]=str
+    elseif str~="" then
+     if nolines then
+      str=lpegmatch((n==1 and b_collapser) or (n==m and e_collapser) or m_collapser,str)
+     else
+      str=lpegmatch((n==1 and b_stripper) or (n==m and e_stripper) or m_stripper,str)
+     end
+     if str~="" then
+      m=m+1
+      t[m]=str
+     end
+    end
+   end
+   e.dt=t
+  else
+   local str=edt[1]
+   if type(str)=="string" then
+    if str~="" then
+     str=lpegmatch(nolines and b_collapser or b_stripper,str)
+    end
+    if str=="" then
+     remove(edt,1)
+     n=n-1
     else
-      local str=edt[1]
-      if type(str)=="string" then
-        if str~="" then
-          str=lpegmatch(nolines and b_collapser or b_stripper,str)
-        end
-        if str=="" then
-          remove(edt,1)
-          n=n-1
-        else
-          edt[1]=str
-        end
+     edt[1]=str
+    end
+   end
+   if n>0 then
+    str=edt[n]
+    if type(str)=="string" then
+     if str=="" then
+      remove(edt)
+     else
+      str=lpegmatch(nolines and e_collapser or e_stripper,str)
+      if str=="" then
+       remove(edt)
+      else
+       edt[n]=str
       end
-      if n>0 then
-        str=edt[n]
-        if type(str)=="string" then
-          if str=="" then
-            remove(edt)
-          else
-            str=lpegmatch(nolines and e_collapser or e_stripper,str)
-            if str=="" then
-              remove(edt)
-            else
-              edt[n]=str
-            end
-          end
-        end
-      end
+     end
     end
+   end
   end
-  return e 
+ end
+ return e 
 end
 xml.stripelement=stripelement
 function xml.strip(root,pattern,nolines,anywhere) 
-  local collected=xmlapplylpath(root,pattern) 
-  if collected then
-    for i=1,#collected do
-      stripelement(collected[i],nolines,anywhere)
-    end
+ local collected=xmlapplylpath(root,pattern) 
+ if collected then
+  for i=1,#collected do
+   stripelement(collected[i],nolines,anywhere)
   end
+ end
 end
 local function renamespace(root,oldspace,newspace) 
-  local ndt=#root.dt
-  for i=1,ndt or 0 do
-    local e=root[i]
-    if type(e)=="table" then
-      if e.ns==oldspace then
-        e.ns=newspace
-        if e.rn then
-          e.rn=newspace
-        end
-      end
-      local edt=e.dt
-      if edt then
-        renamespace(edt,oldspace,newspace)
-      end
+ local ndt=#root.dt
+ for i=1,ndt or 0 do
+  local e=root[i]
+  if type(e)=="table" then
+   if e.ns==oldspace then
+    e.ns=newspace
+    if e.rn then
+     e.rn=newspace
     end
+   end
+   local edt=e.dt
+   if edt then
+    renamespace(edt,oldspace,newspace)
+   end
   end
+ end
 end
 xml.renamespace=renamespace
 function xml.remaptag(root,pattern,newtg)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      collected[c].tg=newtg
-    end
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   collected[c].tg=newtg
   end
+ end
 end
 function xml.remapnamespace(root,pattern,newns)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      collected[c].ns=newns
-    end
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   collected[c].ns=newns
   end
+ end
 end
 function xml.checknamespace(root,pattern,newns)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      local e=collected[c]
-      if (not e.rn or e.rn=="") and e.ns=="" then
-        e.rn=newns
-      end
-    end
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   local e=collected[c]
+   if (not e.rn or e.rn=="") and e.ns=="" then
+    e.rn=newns
+   end
   end
+ end
 end
 function xml.remapname(root,pattern,newtg,newns,newrn)
-  local collected=xmlapplylpath(root,pattern)
-  if collected then
-    for c=1,#collected do
-      local e=collected[c]
-      e.tg,e.ns,e.rn=newtg,newns,newrn
-    end
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+  for c=1,#collected do
+   local e=collected[c]
+   e.tg,e.ns,e.rn=newtg,newns,newrn
   end
+ end
 end
 function xml.cdatatotext(e)
-  local dt=e.dt
-  if #dt==1 then
-    local first=dt[1]
-    if first.tg=="@cd@" then
-      e.dt=first.dt
-    end
-  else
+ local dt=e.dt
+ if #dt==1 then
+  local first=dt[1]
+  if first.tg=="@cd@" then
+   e.dt=first.dt
   end
+ else
+ end
 end
 function xml.texttocdata(e) 
-  local dt=e.dt
-  local s=xml.tostring(dt) 
-  e.tg="@cd@"
-  e.special=true
-  e.ns=""
-  e.rn=""
-  e.dt={ s }
-  e.at=nil
+ local dt=e.dt
+ local s=xml.tostring(dt) 
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
 end
 function xml.elementtocdata(e) 
-  local dt=e.dt
-  local s=xml.tostring(e) 
-  e.tg="@cd@"
-  e.special=true
-  e.ns=""
-  e.rn=""
-  e.dt={ s }
-  e.at=nil
+ local dt=e.dt
+ local s=xml.tostring(e) 
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
 end
 xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" } 
 local entities=characters and characters.entities or nil
 local builtinentities=xml.builtinentities
 function xml.addentitiesdoctype(root,option) 
-  if not entities then
-    require("char-ent")
-    entities=characters.entities
-  end
-  if entities and root and root.tg=="@rt@" and root.statistics then
-    local list={}
-    local hexify=option=="hexadecimal"
-    for k,v in table.sortedhash(root.statistics.entities.names) do
-      if not builtinentities[k] then
-        local e=entities[k]
-        if not e then
-          e=format("[%s]",k)
-        elseif hexify then
-          e=format("&#%05X;",utfbyte(k))
-        end
-        list[#list+1]=format("  <!ENTITY %s %q >",k,e)
-      end
+ if not entities then
+  require("char-ent")
+  entities=characters.entities
+ end
+ if entities and root and root.tg=="@rt@" and root.statistics then
+  local list={}
+  local hexify=option=="hexadecimal"
+  for k,v in table.sortedhash(root.statistics.entities.names) do
+   if not builtinentities[k] then
+    local e=entities[k]
+    if not e then
+     e=format("[%s]",k)
+    elseif hexify then
+     e=format("&#%05X;",utfbyte(k))
     end
-    local dt=root.dt
-    local n=dt[1].tg=="@pi@" and 2 or 1
-    if #list>0 then
-      insert(dt,n,{ "\n" })
-      insert(dt,n,{
-        tg="@dt@",
-        dt={ format("Something [\n%s\n] ",concat(list)) },
-        ns="",
-        special=true,
-      })
-      insert(dt,n,{ "\n\n" })
-    else
-    end
+    list[#list+1]=format("  <!ENTITY %s %q >",k,e)
+   end
   end
+  local dt=root.dt
+  local n=dt[1].tg=="@pi@" and 2 or 1
+  if #list>0 then
+   insert(dt,n,{ "\n" })
+   insert(dt,n,{
+      tg="@dt@",
+      dt={ format("Something [\n%s\n] ",concat(list)) },
+      ns="",
+      special=true,
+   })
+   insert(dt,n,{ "\n\n" })
+  else
+  end
+ end
 end
 xml.all=xml.each
 xml.insert=xml.insertafter
@@ -15451,239 +19023,241 @@
 xml.process=xml.each
 xml.obsolete=xml.obsolete or {}
 local obsolete=xml.obsolete
-xml.strip_whitespace=xml.strip         obsolete.strip_whitespace=xml.strip
-xml.collect_elements=xml.collect        obsolete.collect_elements=xml.collect
-xml.delete_element=xml.delete        obsolete.delete_element=xml.delete
-xml.replace_element=xml.replace        obsolete.replace_element=xml.replace
-xml.each_element=xml.each         obsolete.each_element=xml.each
-xml.process_elements=xml.process        obsolete.process_elements=xml.process
-xml.insert_element_after=xml.insertafter      obsolete.insert_element_after=xml.insertafter
-xml.insert_element_before=xml.insertbefore     obsolete.insert_element_before=xml.insertbefore
-xml.inject_element_after=xml.injectafter      obsolete.inject_element_after=xml.injectafter
-xml.inject_element_before=xml.injectbefore     obsolete.inject_element_before=xml.injectbefore
-xml.process_attributes=xml.processattributes   obsolete.process_attributes=xml.processattributes
-xml.collect_texts=xml.collecttexts     obsolete.collect_texts=xml.collecttexts
-xml.inject_element=xml.inject        obsolete.inject_element=xml.inject
-xml.remap_tag=xml.remaptag       obsolete.remap_tag=xml.remaptag
-xml.remap_name=xml.remapname       obsolete.remap_name=xml.remapname
-xml.remap_namespace=xml.remapnamespace    obsolete.remap_namespace=xml.remapnamespace
+xml.strip_whitespace=xml.strip     obsolete.strip_whitespace=xml.strip
+xml.collect_elements=xml.collect      obsolete.collect_elements=xml.collect
+xml.delete_element=xml.delete    obsolete.delete_element=xml.delete
+xml.replace_element=xml.replace      obsolete.replace_element=xml.replace
+xml.each_element=xml.each      obsolete.each_element=xml.each
+xml.process_elements=xml.process      obsolete.process_elements=xml.process
+xml.insert_element_after=xml.insertafter     obsolete.insert_element_after=xml.insertafter
+xml.insert_element_before=xml.insertbefore    obsolete.insert_element_before=xml.insertbefore
+xml.inject_element_after=xml.injectafter     obsolete.inject_element_after=xml.injectafter
+xml.inject_element_before=xml.injectbefore    obsolete.inject_element_before=xml.injectbefore
+xml.process_attributes=xml.processattributes  obsolete.process_attributes=xml.processattributes
+xml.collect_texts=xml.collecttexts    obsolete.collect_texts=xml.collecttexts
+xml.inject_element=xml.inject    obsolete.inject_element=xml.inject
+xml.remap_tag=xml.remaptag     obsolete.remap_tag=xml.remaptag
+xml.remap_name=xml.remapname    obsolete.remap_name=xml.remapname
+xml.remap_namespace=xml.remapnamespace  obsolete.remap_namespace=xml.remapnamespace
 function xml.cdata(e)
-  if e then
-    local dt=e.dt
-    if dt and #dt==1 then
-      local first=dt[1]
-      return first.tg=="@cd@" and first.dt[1] or ""
-    end
+ if e then
+  local dt=e.dt
+  if dt and #dt==1 then
+   local first=dt[1]
+   return first.tg=="@cd@" and first.dt[1] or ""
   end
-  return ""
+ end
+ return ""
 end
 function xml.finalizers.xml.cdata(collected)
-  if collected then
-    local e=collected[1]
-    if e then
-      local dt=e.dt
-      if dt and #dt==1 then
-        local first=dt[1]
-        return first.tg=="@cd@" and first.dt[1] or ""
-      end
-    end
+ if collected then
+  local e=collected[1]
+  if e then
+   local dt=e.dt
+   if dt and #dt==1 then
+    local first=dt[1]
+    return first.tg=="@cd@" and first.dt[1] or ""
+   end
   end
-  return ""
+ end
+ return ""
 end
 function xml.insertcomment(e,str,n)
-  insert(e.dt,n or 1,{
-    tg="@cm@",
-    ns="",
-    special=true,
-    at={},
-    dt={ str },
-  })
+ insert(e.dt,n or 1,{
+  tg="@cm@",
+  ns="",
+  special=true,
+  at={},
+  dt={ str },
+ })
 end
 function xml.insertcdata(e,str,n)
-  insert(e.dt,n or 1,{
-    tg="@cd@",
-    ns="",
-    special=true,
-    at={},
-    dt={ str },
-  })
+ insert(e.dt,n or 1,{
+  tg="@cd@",
+  ns="",
+  special=true,
+  at={},
+  dt={ str },
+ })
 end
 function xml.setcomment(e,str,n)
-  e.dt={ {
-    tg="@cm@",
-    ns="",
-    special=true,
-    at={},
-    dt={ str },
-  } }
+ e.dt={ {
+  tg="@cm@",
+  ns="",
+  special=true,
+  at={},
+  dt={ str },
+ } }
 end
 function xml.setcdata(e,str)
-  e.dt={ {
-    tg="@cd@",
-    ns="",
-    special=true,
-    at={},
-    dt={ str },
-  } }
+ e.dt={ {
+  tg="@cd@",
+  ns="",
+  special=true,
+  at={},
+  dt={ str },
+ } }
 end
 function xml.separate(x,pattern)
-  local collected=xmlapplylpath(x,pattern)
-  if collected then
-    for c=1,#collected do
-      local e=collected[c]
-      local d=e.dt
-      if d==x then
-        report_xml("warning: xml.separate changes root")
-        x=d
+ local collected=xmlapplylpath(x,pattern)
+ if collected then
+  for c=1,#collected do
+   local e=collected[c]
+   local d=e.dt
+   if d==x then
+    report_xml("warning: xml.separate changes root")
+    x=d
+   end
+   local t={ "\n" }
+   local n=1
+   local i=1
+   local nd=#d
+   while i<=nd do
+    while i<=nd do
+     local di=d[i]
+     if type(di)=="string" then
+      if di=="\n" or find(di,"^%s+$") then 
+       i=i+1
+      else
+       d[i]=strip(di)
+       break
       end
-      local t,n={ "\n" },1
-      local i,nd=1,#d
-      while i<=nd do
-        while i<=nd do
-          local di=d[i]
-          if type(di)=="string" then
-            if di=="\n" or find(di,"^%s+$") then 
-              i=i+1
-            else
-              d[i]=strip(di)
-              break
-            end
-          else
-            break
-          end
-        end
-        if i>nd then
-          break
-        end
-        t[n+1]="\n"
-        t[n+2]=d[i]
-        t[n+3]="\n"
-        n=n+3
-        i=i+1
-      end
-      t[n+1]="\n"
-      setmetatable(t,getmetatable(d))
-      e.dt=t
+     else
+      break
+     end
     end
+    if i>nd then
+     break
+    end
+    t[n+1]="\n"
+    t[n+2]=d[i]
+    t[n+3]="\n"
+    n=n+3
+    i=i+1
+   end
+   t[n+1]="\n"
+   setmetatable(t,getmetatable(d))
+   e.dt=t
   end
-  return x
+ end
+ return x
 end
 local helpers=xml.helpers or {}
 xml.helpers=helpers
 local function normal(e,action)
-  local edt=e.dt
-  if edt then
-    for i=1,#edt do
-      local str=edt[i]
-      if type(str)=="string" and str~="" then
-        edt[i]=action(str)
-      end
-    end
+ local edt=e.dt
+ if edt then
+  for i=1,#edt do
+   local str=edt[i]
+   if type(str)=="string" and str~="" then
+    edt[i]=action(str)
+   end
   end
+ end
 end
 local function recurse(e,action)
-  local edt=e.dt
-  if edt then
-    for i=1,#edt do
-      local str=edt[i]
-      if type(str)~="string" then
-        recurse(str,action) 
-      elseif str~="" then
-        edt[i]=action(str)
-      end
-    end
+ local edt=e.dt
+ if edt then
+  for i=1,#edt do
+   local str=edt[i]
+   if type(str)~="string" then
+    recurse(str,action) 
+   elseif str~="" then
+    edt[i]=action(str)
+   end
   end
+ end
 end
 function helpers.recursetext(collected,action,recursive)
-  if recursive then
-    for i=1,#collected do
-      recurse(collected[i],action)
-    end
-  else
-    for i=1,#collected do
-      normal(collected[i],action)
-    end
+ if recursive then
+  for i=1,#collected do
+   recurse(collected[i],action)
   end
+ else
+  for i=1,#collected do
+     normal(collected[i],action)
+  end
+ end
 end
 local specials={
-  ["@rt@"]="root",
-  ["@pi@"]="instruction",
-  ["@cm@"]="comment",
-  ["@dt@"]="declaration",
-  ["@cd@"]="cdata",
+ ["@rt@"]="root",
+ ["@pi@"]="instruction",
+ ["@cm@"]="comment",
+ ["@dt@"]="declaration",
+ ["@cd@"]="cdata",
 }
 local function convert(x,strip,flat)
-  local ns=x.ns
-  local tg=x.tg
-  local at=x.at
-  local dt=x.dt
-  local node=flat and {
-    [0]=(not x.special and (ns~="" and ns..":"..tg or tg)) or nil,
-  } or {
-    _namespace=ns~="" and ns or nil,
-    _tag=not x.special and tg or nil,
-    _type=specials[tg] or "_element",
-  }
-  if at then
-    for k,v in next,at do
-      node[k]=v
-    end
+ local ns=x.ns
+ local tg=x.tg
+ local at=x.at
+ local dt=x.dt
+ local node=flat and {
+  [0]=(not x.special and (ns~="" and ns..":"..tg or tg)) or nil,
+ } or {
+  _namespace=ns~="" and ns or nil,
+  _tag=not x.special and tg or nil,
+  _type=specials[tg] or "_element",
+ }
+ if at then
+  for k,v in next,at do
+   node[k]=v
   end
-  local n=0
-  for i=1,#dt do
-    local di=dt[i]
-    if type(di)=="table" then
-      if flat and di.special then
-      else
-        di=convert(di,strip,flat)
-        if di then
-          n=n+1
-          node[n]=di
-        end
-      end
-    elseif strip then
-      di=lpegmatch(strip,di)
-      if di~="" then
-        n=n+1
-        node[n]=di
-      end
-    else
-      n=n+1
-      node[n]=di
+ end
+ local n=0
+ for i=1,#dt do
+  local di=dt[i]
+  if type(di)=="table" then
+   if flat and di.special then
+   else
+    di=convert(di,strip,flat)
+    if di then
+     n=n+1
+     node[n]=di
     end
+   end
+  elseif strip then
+   di=lpegmatch(strip,di)
+   if di~="" then
+    n=n+1
+    node[n]=di
+   end
+  else
+   n=n+1
+   node[n]=di
   end
-  if next(node) then
-    return node
-  end
+ end
+ if next(node) then
+  return node
+ end
 end
 function xml.totable(x,strip,flat)
-  if type(x)=="table" then
-    if strip then
-      strip=striplinepatterns[strip]
-    end
-    return convert(x,strip,flat)
+ if type(x)=="table" then
+  if strip then
+   strip=striplinepatterns[strip]
   end
+  return convert(x,strip,flat)
+ end
 end
 function xml.rename(e,namespace,name,attributes)
-  if type(e)~="table" or not e.tg then
-    return
-  end
-  if type(name)=="table" then
-    attributes=name
-    name=namespace
-    namespace=""
-  elseif type(name)~="string" then
-    attributes={}
-    name=namespace
-    namespace=""
-  end
-  if type(attributes)~="table" then
-    attributes={}
-  end
-  e.ns=namespace
-  e.rn=namespace
-  e.tg=name
-  e.at=attributes
+ if type(e)~="table" or not e.tg then
+  return
+ end
+ if type(name)=="table" then
+  attributes=name
+  name=namespace
+  namespace=""
+ elseif type(name)~="string" then
+  attributes={}
+  name=namespace
+  namespace=""
+ end
+ if type(attributes)~="table" then
+  attributes={}
+ end
+ e.ns=namespace
+ e.rn=namespace
+ e.tg=name
+ e.at=attributes
 end
 
 
@@ -15693,14 +19267,14 @@
 
 package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true
 
--- original size: 11096, stripped down to: 8243
+-- original size: 11096, stripped down to: 7702
 
 if not modules then modules={} end modules ['lxml-xml']={
-  version=1.001,
-  comment="this module is the basis for the lxml-* ones",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local tonumber,next=tonumber,next
 local concat=table.concat
@@ -15712,241 +19286,241 @@
 local xmlserialize=xml.serialize
 local xmlcollected=xml.collected
 local xmlnewhandlers=xml.newhandlers
-local reparsedentity=xml.reparsedentitylpeg  
+local reparsedentity=xml.reparsedentitylpeg   
 local unescapedentity=xml.unescapedentitylpeg
 local parsedentity=reparsedentity
 local function first(collected) 
-  return collected and collected[1]
+ return collected and collected[1]
 end
 local function last(collected)
-  return collected and collected[#collected]
+ return collected and collected[#collected]
 end
 local function all(collected)
-  return collected
+ return collected
 end
 local reverse=table.reversed
 local function attribute(collected,name)
-  if collected and #collected>0 then
-    local at=collected[1].at
-    return at and at[name]
-  end
+ if collected and #collected>0 then
+  local at=collected[1].at
+  return at and at[name]
+ end
 end
 local function att(id,name)
-  local at=id.at
-  return at and at[name]
+ local at=id.at
+ return at and at[name]
 end
 local function count(collected)
-  return collected and #collected or 0
+ return collected and #collected or 0
 end
 local function position(collected,n)
-  if not collected then
-    return 0
-  end
-  local nc=#collected
-  if nc==0 then
-    return 0
-  end
-  n=tonumber(n) or 0
-  if n<0 then
-    return collected[nc+n+1]
-  elseif n>0 then
-    return collected[n]
-  else
-    return collected[1].mi or 0
-  end
+ if not collected then
+  return 0
+ end
+ local nc=#collected
+ if nc==0 then
+  return 0
+ end
+ n=tonumber(n) or 0
+ if n<0 then
+  return collected[nc+n+1]
+ elseif n>0 then
+  return collected[n]
+ else
+  return collected[1].mi or 0
+ end
 end
 local function match(collected)
-  return collected and #collected>0 and collected[1].mi or 0 
+ return collected and #collected>0 and collected[1].mi or 0 
 end
 local function index(collected)
-  return collected and #collected>0 and collected[1].ni or 0 
+ return collected and #collected>0 and collected[1].ni or 0 
 end
 local function attributes(collected,arguments)
-  if collected and #collected>0 then
-    local at=collected[1].at
-    if arguments then
-      return at[arguments]
-    elseif next(at) then
-      return at 
-    end
+ if collected and #collected>0 then
+  local at=collected[1].at
+  if arguments then
+   return at[arguments]
+  elseif next(at) then
+   return at 
   end
+ end
 end
 local function chainattribute(collected,arguments) 
-  if collected and #collected>0 then
-    local e=collected[1]
-    while e do
-      local at=e.at
-      if at then
-        local a=at[arguments]
-        if a then
-          return a
-        end
-      else
-        break 
-      end
-      e=e.__p__
+ if collected and #collected>0 then
+  local e=collected[1]
+  while e do
+   local at=e.at
+   if at then
+    local a=at[arguments]
+    if a then
+     return a
     end
+   else
+    break 
+   end
+   e=e.__p__
   end
-  return ""
+ end
+ return ""
 end
 local function raw(collected) 
-  if collected and #collected>0 then
-    local e=collected[1] or collected
-    return e and xmltostring(e) or "" 
-  else
-    return ""
-  end
+ if collected and #collected>0 then
+  local e=collected[1] or collected
+  return e and xmltostring(e) or "" 
+ else
+  return ""
+ end
 end
 local xmltexthandler=xmlnewhandlers {
-  name="string",
-  initialize=function()
-    result={}
-    return result
-  end,
-  finalize=function()
-    return concat(result)
-  end,
-  handle=function(...)
-    result[#result+1]=concat {... }
-  end,
-  escape=false,
+ name="string",
+ initialize=function()
+  result={}
+  return result
+ end,
+ finalize=function()
+  return concat(result)
+ end,
+ handle=function(...)
+  result[#result+1]=concat {... }
+ end,
+ escape=false,
 }
 local function xmltotext(root)
-  local dt=root.dt
-  if not dt then
-    return ""
-  end
-  local nt=#dt 
-  if nt==0 then
-    return ""
-  elseif nt==1 and type(dt[1])=="string" then
-    return dt[1] 
-  else
-    return xmlserialize(root,xmltexthandler) or ""
-  end
+ local dt=root.dt
+ if not dt then
+  return ""
+ end
+ local nt=#dt 
+ if nt==0 then
+  return ""
+ elseif nt==1 and type(dt[1])=="string" then
+  return dt[1] 
+ else
+  return xmlserialize(root,xmltexthandler) or ""
+ end
 end
 function xml.serializetotext(root)
-  return root and xmlserialize(root,xmltexthandler) or ""
+ return root and xmlserialize(root,xmltexthandler) or ""
 end
 local function text(collected) 
-  if collected then 
-    local e=collected[1] or collected 
-    return e and xmltotext(e) or ""
-  else
-    return ""
-  end
+ if collected then 
+  local e=collected[1] or collected 
+  return e and xmltotext(e) or ""
+ else
+  return ""
+ end
 end
 local function texts(collected)
-  if not collected then
-    return {} 
+ if not collected then
+  return {} 
+ end
+ local nc=#collected
+ if nc==0 then
+  return {} 
+ end
+ local t,n={},0
+ for c=1,nc do
+  local e=collected[c]
+  if e and e.dt then
+   n=n+1
+   t[n]=e.dt
   end
-  local nc=#collected
-  if nc==0 then
-    return {} 
-  end
-  local t,n={},0
-  for c=1,nc do
-    local e=collected[c]
-    if e and e.dt then
-      n=n+1
-      t[n]=e.dt
-    end
-  end
-  return t
+ end
+ return t
 end
 local function tag(collected,n)
-  if not collected then
-    return
-  end
-  local nc=#collected
-  if nc==0 then
-    return
-  end
-  local c
-  if n==0 or not n then
-    c=collected[1]
-  elseif n>1 then
-    c=collected[n]
-  else
-    c=collected[nc-n+1]
-  end
-  return c and c.tg
+ if not collected then
+  return
+ end
+ local nc=#collected
+ if nc==0 then
+  return
+ end
+ local c
+ if n==0 or not n then
+  c=collected[1]
+ elseif n>1 then
+  c=collected[n]
+ else
+  c=collected[nc-n+1]
+ end
+ return c and c.tg
 end
 local function name(collected,n)
-  if not collected then
-    return
-  end
-  local nc=#collected
-  if nc==0 then
-    return
-  end
-  local c
-  if n==0 or not n then
-    c=collected[1]
-  elseif n>1 then
-    c=collected[n]
-  else
-    c=collected[nc-n+1]
-  end
-  if not c then
-  elseif c.ns=="" then
-    return c.tg
-  else
-    return c.ns..":"..c.tg
-  end
+ if not collected then
+  return
+ end
+ local nc=#collected
+ if nc==0 then
+  return
+ end
+ local c
+ if n==0 or not n then
+  c=collected[1]
+ elseif n>1 then
+  c=collected[n]
+ else
+  c=collected[nc-n+1]
+ end
+ if not c then
+ elseif c.ns=="" then
+  return c.tg
+ else
+  return c.ns..":"..c.tg
+ end
 end
 local function tags(collected,nonamespace)
-  if not collected then
-    return
+ if not collected then
+  return
+ end
+ local nc=#collected
+ if nc==0 then
+  return
+ end
+ local t,n={},0
+ for c=1,nc do
+  local e=collected[c]
+  local ns,tg=e.ns,e.tg
+  n=n+1
+  if nonamespace or ns=="" then
+   t[n]=tg
+  else
+   t[n]=ns..":"..tg
   end
-  local nc=#collected
-  if nc==0 then
-    return
-  end
-  local t,n={},0
-  for c=1,nc do
-    local e=collected[c]
-    local ns,tg=e.ns,e.tg
-    n=n+1
-    if nonamespace or ns=="" then
-      t[n]=tg
-    else
-      t[n]=ns..":"..tg
-    end
-  end
-  return t
+ end
+ return t
 end
 local function empty(collected,spacesonly)
-  if not collected then
-    return true
-  end
-  local nc=#collected
-  if nc==0 then
-    return true
-  end
-  for c=1,nc do
-    local e=collected[c]
-    if e then
-      local edt=e.dt
-      if edt then
-        local n=#edt
-        if n==1 then
-          local edk=edt[1]
-          local typ=type(edk)
-          if typ=="table" then
-            return false
-          elseif edk~="" then
-            return false
-          elseif spacesonly and not find(edk,"%S") then
-            return false
-          end
-        elseif n>1 then
-          return false
-        end
-      end
+ if not collected then
+  return true
+ end
+ local nc=#collected
+ if nc==0 then
+  return true
+ end
+ for c=1,nc do
+  local e=collected[c]
+  if e then
+   local edt=e.dt
+   if edt then
+    local n=#edt
+    if n==1 then
+     local edk=edt[1]
+     local typ=type(edk)
+     if typ=="table" then
+      return false
+     elseif edk~="" then
+      return false
+     elseif spacesonly and not find(edk,"%S") then
+      return false
+     end
+    elseif n>1 then
+     return false
     end
+   end
   end
-  return true
+ end
+ return true
 end
 finalizers.first=first
 finalizers.last=last
@@ -15969,124 +19543,124 @@
 finalizers.tags=tags
 finalizers.empty=empty
 function xml.first(id,pattern)
-  return first(xmlfilter(id,pattern))
+ return first(xmlfilter(id,pattern))
 end
 function xml.last(id,pattern)
-  return last(xmlfilter(id,pattern))
+ return last(xmlfilter(id,pattern))
 end
 function xml.count(id,pattern)
-  return count(xmlfilter(id,pattern))
+ return count(xmlfilter(id,pattern))
 end
 function xml.attribute(id,pattern,a,default)
-  return attribute(xmlfilter(id,pattern),a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
 end
 function xml.raw(id,pattern)
-  if pattern then
-    return raw(xmlfilter(id,pattern))
-  else
-    return raw(id)
-  end
+ if pattern then
+  return raw(xmlfilter(id,pattern))
+ else
+  return raw(id)
+ end
 end
 function xml.text(id,pattern) 
-  if pattern then
-    local collected=xmlfilter(id,pattern)
-    return collected and #collected>0 and xmltotext(collected[1]) or ""
-  elseif id then
-    return xmltotext(id) or ""
-  else
-    return ""
-  end
+ if pattern then
+  local collected=xmlfilter(id,pattern)
+  return collected and #collected>0 and xmltotext(collected[1]) or ""
+ elseif id then
+  return xmltotext(id) or ""
+ else
+  return ""
+ end
 end
 function xml.pure(id,pattern)
-  if pattern then
-    local collected=xmlfilter(id,pattern)
-    if collected and #collected>0 then
-      parsedentity=unescapedentity
-      local s=collected and #collected>0 and xmltotext(collected[1]) or ""
-      parsedentity=reparsedentity
-      return s
-    else
-      return ""
-    end
+ if pattern then
+  local collected=xmlfilter(id,pattern)
+  if collected and #collected>0 then
+   parsedentity=unescapedentity
+   local s=collected and #collected>0 and xmltotext(collected[1]) or ""
+   parsedentity=reparsedentity
+   return s
   else
-    parsedentity=unescapedentity
-    local s=xmltotext(id) or ""
-    parsedentity=reparsedentity
-    return s
+   return ""
   end
+ else
+  parsedentity=unescapedentity
+  local s=xmltotext(id) or ""
+  parsedentity=reparsedentity
+  return s
+ end
 end
 xml.content=text
 function xml.position(id,pattern,n) 
-  return position(xmlfilter(id,pattern),n)
+ return position(xmlfilter(id,pattern),n)
 end
 function xml.match(id,pattern) 
-  return match(xmlfilter(id,pattern))
+ return match(xmlfilter(id,pattern))
 end
 function xml.empty(id,pattern,spacesonly)
-  return empty(xmlfilter(id,pattern),spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
 end
 xml.all=xml.filter
 xml.index=xml.position
 xml.found=xml.filter
 local function totable(x)
-  local t={}
-  for e in xmlcollected(x[1] or x,"/*") do
-    t[e.tg]=xmltostring(e.dt) or ""
-  end
-  return next(t) and t or nil
+ local t={}
+ for e in xmlcollected(x[1] or x,"/*") do
+  t[e.tg]=xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
 end
 xml.table=totable
 finalizers.table=totable
 local function textonly(e,t)
-  if e then
-    local edt=e.dt
-    if edt then
-      for i=1,#edt do
-        local e=edt[i]
-        if type(e)=="table" then
-          textonly(e,t)
-        else
-          t[#t+1]=e
-        end
-      end
+ if e then
+  local edt=e.dt
+  if edt then
+   for i=1,#edt do
+    local e=edt[i]
+    if type(e)=="table" then
+     textonly(e,t)
+    else
+     t[#t+1]=e
     end
+   end
   end
-  return t
+ end
+ return t
 end
 function xml.textonly(e) 
-  return concat(textonly(e,{}))
+ return concat(textonly(e,{}))
 end
 function finalizers.lowerall(collected)
-  for c=1,#collected do
-    local e=collected[c]
-    if not e.special then
-      e.tg=lower(e.tg)
-      local eat=e.at
-      if eat then
-        local t={}
-        for k,v in next,eat do
-          t[lower(k)]=v
-        end
-        e.at=t
-      end
+ for c=1,#collected do
+  local e=collected[c]
+  if not e.special then
+   e.tg=lower(e.tg)
+   local eat=e.at
+   if eat then
+    local t={}
+    for k,v in next,eat do
+     t[lower(k)]=v
     end
+    e.at=t
+   end
   end
+ end
 end
 function finalizers.upperall(collected)
-  for c=1,#collected do
-    local e=collected[c]
-    if not e.special then
-      e.tg=upper(e.tg)
-      local eat=e.at
-      if eat then
-        local t={}
-        for k,v in next,eat do
-          t[upper(k)]=v
-        end
-        e.at=t
-      end
+ for c=1,#collected do
+  local e=collected[c]
+  if not e.special then
+   e.tg=upper(e.tg)
+   local eat=e.at
+   if eat then
+    local t={}
+    for k,v in next,eat do
+     t[upper(k)]=v
     end
+    e.at=t
+   end
   end
+ end
 end
 
 
@@ -16096,14 +19670,14 @@
 
 package.loaded["trac-xml"] = package.loaded["trac-xml"] or true
 
--- original size: 6407, stripped down to: 4965
+-- original size: 6407, stripped down to: 4640
 
 if not modules then modules={} end modules ['trac-xml']={
-  version=1.001,
-  comment="companion to trac-log.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
 }
 local formatters=string.formatters
 local reporters=logs.reporters
@@ -16112,152 +19686,152 @@
 local xmltext=xml.text
 local xmlfirst=xml.first
 local function showhelp(specification,...)
-  local root=xml.convert(specification.helpinfo or "")
-  if not root then
-    return
-  end
-  local xs=xml.gethandlers("string")
-  xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
-  xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end)
-  local wantedcategories=select("#",...)==0 and true or table.tohash {... }
-  local nofcategories=xml.count(root,"/application/flags/category")
-  local report=specification.report
-  for category in xmlcollected(root,"/application/flags/category") do
-    local categoryname=category.at.name or ""
-    if wantedcategories==true or wantedcategories[categoryname] then
-      if nofcategories>1 then
-        report("%s options:",categoryname)
-        report()
-      end
-      for subcategory in xmlcollected(category,"/subcategory") do
-        for flag in xmlcollected(subcategory,"/flag") do
-          local name=flag.at.name
-          local value=flag.at.value
-          local short=xmltext(xmlfirst(flag,"/short"))
-          if value then
-            report("--%-20s %s",formatters["%s=%s"](name,value),short)
-          else
-            report("--%-20s %s",name,short)
-          end
-        end
-        report()
-      end
+ local root=xml.convert(specification.helpinfo or "")
+ if not root then
+  return
+ end
+ local xs=xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories=select("#",...)==0 and true or table.tohash {... }
+ local nofcategories=xml.count(root,"/application/flags/category")
+ local report=specification.report
+ for category in xmlcollected(root,"/application/flags/category") do
+  local categoryname=category.at.name or ""
+  if wantedcategories==true or wantedcategories[categoryname] then
+   if nofcategories>1 then
+    report("%s options:",categoryname)
+    report()
+   end
+   for subcategory in xmlcollected(category,"/subcategory") do
+    for flag in xmlcollected(subcategory,"/flag") do
+     local name=flag.at.name
+     local value=flag.at.value
+     local short=xmltext(xmlfirst(flag,"/short"))
+     if value then
+      report("--%-20s %s",formatters["%s=%s"](name,value),short)
+     else
+      report("--%-20s %s",name,short)
+     end
     end
+    report()
+   end
   end
-  for category in xmlcollected(root,"/application/examples/category") do
-    local title=xmltext(xmlfirst(category,"/title"))
-    if title and title~="" then
-      report()
-      report(title)
-      report()
-    end
-    for subcategory in xmlcollected(category,"/subcategory") do
-      for example in xmlcollected(subcategory,"/example") do
-        local command=xmltext(xmlfirst(example,"/command"))
-        local comment=xmltext(xmlfirst(example,"/comment"))
-        report(command)
-      end
-      report()
-    end
+ end
+ for category in xmlcollected(root,"/application/examples/category") do
+  local title=xmltext(xmlfirst(category,"/title"))
+  if title and title~="" then
+   report()
+   report(title)
+   report()
   end
-  for comment in xmlcollected(root,"/application/comments/comment") do
-    local comment=xmltext(comment)
-    report()
-    report(comment)
-    report()
+  for subcategory in xmlcollected(category,"/subcategory") do
+   for example in xmlcollected(subcategory,"/example") do
+    local command=xmltext(xmlfirst(example,"/command"))
+    local comment=xmltext(xmlfirst(example,"/comment"))
+    report(command)
+   end
+   report()
   end
+ end
+ for comment in xmlcollected(root,"/application/comments/comment") do
+  local comment=xmltext(comment)
+  report()
+  report(comment)
+  report()
+ end
 end
 local reporthelp=reporters.help
 local exporthelp=reporters.export
 local function xmlfound(t)
-  local helpinfo=t.helpinfo
-  if type(helpinfo)=="table" then
-    return false
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="table" then
+  return false
+ end
+ if type(helpinfo)~="string" then
+  helpinfo="Warning: no helpinfo found."
+  t.helpinfo=helpinfo
+  return false
+ end
+ if string.find(helpinfo,".xml$") then
+  local ownscript=environment.ownscript
+  local helpdata=false
+  if ownscript then
+   local helpfile=file.join(file.pathpart(ownscript),helpinfo)
+   helpdata=io.loaddata(helpfile)
+   if helpdata=="" then
+    helpdata=false
+   end
   end
-  if type(helpinfo)~="string" then
-    helpinfo="Warning: no helpinfo found."
-    t.helpinfo=helpinfo
-    return false
+  if not helpdata then
+   local helpfile=resolvers.findfile(helpinfo,"tex")
+   helpdata=helpfile and io.loaddata(helpfile)
   end
-  if string.find(helpinfo,".xml$") then
-    local ownscript=environment.ownscript
-    local helpdata=false
-    if ownscript then
-      local helpfile=file.join(file.pathpart(ownscript),helpinfo)
-      helpdata=io.loaddata(helpfile)
-      if helpdata=="" then
-        helpdata=false
-      end
-    end
-    if not helpdata then
-      local helpfile=resolvers.findfile(helpinfo,"tex")
-      helpdata=helpfile and io.loaddata(helpfile)
-    end
-    if helpdata and helpdata~="" then
-      helpinfo=helpdata
-    else
-      helpinfo=formatters["Warning: help file %a is not found."](helpinfo)
-    end
+  if helpdata and helpdata~="" then
+   helpinfo=helpdata
+  else
+   helpinfo=formatters["Warning: help file %a is not found."](helpinfo)
   end
-  t.helpinfo=helpinfo
-  return string.find(t.helpinfo,"^<%?xml") and true or false
+ end
+ t.helpinfo=helpinfo
+ return string.find(t.helpinfo,"^<%?xml") and true or false
 end
 function reporters.help(t,...)
-  if xmlfound(t) then
-    showhelp(t,...)
-  else
-    reporthelp(t,...)
-  end
+ if xmlfound(t) then
+  showhelp(t,...)
+ else
+  reporthelp(t,...)
+ end
 end
 function reporters.export(t,methods,filename)
-  if not xmlfound(t) then
-    return exporthelp(t)
-  end
-  if not methods or methods=="" then
-    methods=environment.arguments["exporthelp"]
-  end
-  if not filename or filename=="" then
-    filename=environment.files[1]
-  end
-  dofile(resolvers.findfile("trac-exp.lua","tex"))
-  local exporters=logs.exporters
-  if not exporters or not methods then
-    return exporthelp(t)
-  end
-  if methods=="all" then
-    methods=table.keys(exporters)
-  elseif type(methods)=="string" then
-    methods=utilities.parsers.settings_to_array(methods)
-  else
-    return exporthelp(t)
-  end
-  if type(filename)~="string" or filename=="" then
-    filename=false
-  elseif file.pathpart(filename)=="" then
-    t.report("export file %a will not be saved on the current path (safeguard)",filename)
-    return
-  end
-  for i=1,#methods do
-    local method=methods[i]
-    local exporter=exporters[method]
-    if exporter then
-      local result=exporter(t,method)
-      if result and result~="" then
-        if filename then
-          local fullname=file.replacesuffix(filename,method)
-          t.report("saving export in %a",fullname)
-          dir.mkdirs(file.pathpart(fullname))
-          io.savedata(fullname,result)
-        else
-          reporters.lines(t,result)
-        end
-      else
-        t.report("no output from exporter %a",method)
-      end
+ if not xmlfound(t) then
+  return exporthelp(t)
+ end
+ if not methods or methods=="" then
+  methods=environment.arguments["exporthelp"]
+ end
+ if not filename or filename=="" then
+  filename=environment.files[1]
+ end
+ dofile(resolvers.findfile("trac-exp.lua","tex"))
+ local exporters=logs.exporters
+ if not exporters or not methods then
+  return exporthelp(t)
+ end
+ if methods=="all" then
+  methods=table.keys(exporters)
+ elseif type(methods)=="string" then
+  methods=utilities.parsers.settings_to_array(methods)
+ else
+  return exporthelp(t)
+ end
+ if type(filename)~="string" or filename=="" then
+  filename=false
+ elseif file.pathpart(filename)=="" then
+  t.report("export file %a will not be saved on the current path (safeguard)",filename)
+  return
+ end
+ for i=1,#methods do
+  local method=methods[i]
+  local exporter=exporters[method]
+  if exporter then
+   local result=exporter(t,method)
+   if result and result~="" then
+    if filename then
+     local fullname=file.replacesuffix(filename,method)
+     t.report("saving export in %a",fullname)
+     dir.mkdirs(file.pathpart(fullname))
+     io.savedata(fullname,result)
     else
-      t.report("unknown exporter %a",method)
+     reporters.lines(t,result)
     end
+   else
+    t.report("no output from exporter %a",method)
+   end
+  else
+   t.report("unknown exporter %a",method)
   end
+ end
 end
 
 
@@ -16267,14 +19841,14 @@
 
 package.loaded["data-ini"] = package.loaded["data-ini"] or true
 
--- original size: 11099, stripped down to: 7516
+-- original size: 11099, stripped down to: 7152
 
 if not modules then modules={} end modules ['data-ini']={
-  version=1.001,
-  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",
+ version=1.001,
+ 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 next,type,getmetatable,rawset=next,type,getmetatable,rawset
 local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
@@ -16281,9 +19855,9 @@
 local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
 local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
 local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
-local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
-local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
-local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_locating=false  trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false  trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false  trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
 local report_initialization=logs.reporter("resolvers","initialization")
 resolvers=resolvers or {}
 local resolvers=resolvers
@@ -16290,126 +19864,126 @@
 texconfig.kpse_init=false
 texconfig.shell_escape='t'
 if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then
-  local default_texmfcnf=kpse.default_texmfcnf()
-  default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
-  default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
-  default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
-  default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:")
-  environment.default_texmfcnf=default_texmfcnf
+ local default_texmfcnf=kpse.default_texmfcnf()
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
+ default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:")
+ environment.default_texmfcnf=default_texmfcnf
 end
 kpse={ original=kpse }
 setmetatable(kpse,{
-  __index=function(kp,name)
-    report_initialization("fatal error: kpse library is accessed (key: %s)",name)
-    os.exit()
-  end
+ __index=function(kp,name)
+  report_initialization("fatal error: kpse library is accessed (key: %s)",name)
+  os.exit()
+ end
 } )
 do
-  local osfontdir=osgetenv("OSFONTDIR")
-  if osfontdir and osfontdir~="" then
-  elseif osname=="windows" then
-    ossetenv("OSFONTDIR","c:/windows/fonts//")
-  elseif osname=="macosx" then
-    ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
-  end
+ local osfontdir=osgetenv("OSFONTDIR")
+ if osfontdir and osfontdir~="" then
+ elseif osname=="windows" then
+  ossetenv("OSFONTDIR","c:/windows/fonts//")
+ elseif osname=="macosx" then
+  ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ end
 end
 do
-  local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or ''
-  if not homedir or homedir=="" then
-    homedir=char(127) 
-  end
-  homedir=file.collapsepath(homedir)
-  ossetenv("HOME",homedir) 
-  ossetenv("USERPROFILE",homedir) 
-  environment.homedir=homedir
+ local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or ''
+ if not homedir or homedir=="" then
+  homedir=char(127) 
+ end
+ homedir=file.collapsepath(homedir)
+ ossetenv("HOME",homedir) 
+ ossetenv("USERPROFILE",homedir) 
+ environment.homedir=homedir
 end
 do
-  local args=environment.originalarguments or arg 
-  if not environment.ownmain then
-    environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ local args=environment.originalarguments or arg 
+ if not environment.ownmain then
+  environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+ local ownbin=environment.ownbin  or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+ local ownpath=environment.ownpath or os.selfdir
+ ownbin=file.collapsepath(ownbin)
+ ownpath=file.collapsepath(ownpath)
+ if not ownpath or ownpath=="" or ownpath=="unset" then
+  ownpath=args[-1] or arg[-1]
+  ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+  if not ownpath or ownpath=="" then
+   ownpath=args[-0] or arg[-0]
+   ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
   end
-  local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
-  local ownpath=environment.ownpath or os.selfdir
-  ownbin=file.collapsepath(ownbin)
-  ownpath=file.collapsepath(ownpath)
-  if not ownpath or ownpath=="" or ownpath=="unset" then
-    ownpath=args[-1] or arg[-1]
-    ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
-    if not ownpath or ownpath=="" then
-      ownpath=args[-0] or arg[-0]
-      ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
-    end
-    local binary=ownbin
-    if not ownpath or ownpath=="" then
-      ownpath=ownpath and filedirname(binary)
-    end
-    if not ownpath or ownpath=="" then
-      if os.binsuffix~="" then
-        binary=file.replacesuffix(binary,os.binsuffix)
+  local binary=ownbin
+  if not ownpath or ownpath=="" then
+   ownpath=ownpath and filedirname(binary)
+  end
+  if not ownpath or ownpath=="" then
+   if os.binsuffix~="" then
+    binary=file.replacesuffix(binary,os.binsuffix)
+   end
+   local path=osgetenv("PATH")
+   if path then
+    for p in gmatch(path,"[^"..io.pathseparator.."]+") do
+     local b=filejoin(p,binary)
+     if lfs.isfile(b) then
+      local olddir=lfs.currentdir()
+      if lfs.chdir(p) then
+       local pp=lfs.currentdir()
+       if trace_locating and p~=pp then
+        report_initialization("following symlink %a to %a",p,pp)
+       end
+       ownpath=pp
+       lfs.chdir(olddir)
+      else
+       if trace_locating then
+        report_initialization("unable to check path %a",p)
+       end
+       ownpath=p
       end
-      local path=osgetenv("PATH")
-      if path then
-        for p in gmatch(path,"[^"..io.pathseparator.."]+") do
-          local b=filejoin(p,binary)
-          if lfs.isfile(b) then
-            local olddir=lfs.currentdir()
-            if lfs.chdir(p) then
-              local pp=lfs.currentdir()
-              if trace_locating and p~=pp then
-                report_initialization("following symlink %a to %a",p,pp)
-              end
-              ownpath=pp
-              lfs.chdir(olddir)
-            else
-              if trace_locating then
-                report_initialization("unable to check path %a",p)
-              end
-              ownpath=p
-            end
-            break
-          end
-        end
-      end
+      break
+     end
     end
-    if not ownpath or ownpath=="" then
-      ownpath="."
-      report_initialization("forcing fallback to ownpath %a",ownpath)
-    elseif trace_locating then
-      report_initialization("using ownpath %a",ownpath)
-    end
+   end
   end
-  environment.ownbin=ownbin
-  environment.ownpath=ownpath
+  if not ownpath or ownpath=="" then
+   ownpath="."
+   report_initialization("forcing fallback to ownpath %a",ownpath)
+  elseif trace_locating then
+   report_initialization("using ownpath %a",ownpath)
+  end
+ end
+ environment.ownbin=ownbin
+ environment.ownpath=ownpath
 end
 resolvers.ownpath=environment.ownpath
 function resolvers.getownpath()
-  return environment.ownpath
+ return environment.ownpath
 end
 do
-  local ownpath=environment.ownpath or dir.current()
-  if ownpath then
-    ossetenv('SELFAUTOLOC',file.collapsepath(ownpath))
-    ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/.."))
-    ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../.."))
-  else
-    report_initialization("error: unable to locate ownpath")
-    os.exit()
-  end
+ local ownpath=environment.ownpath or dir.current()
+ if ownpath then
+  ossetenv('SELFAUTOLOC',file.collapsepath(ownpath))
+  ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/.."))
+  ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../.."))
+ else
+  report_initialization("error: unable to locate ownpath")
+  os.exit()
+ end
 end
-local texos=environment.texos  or osgetenv("TEXOS")
+local texos=environment.texos   or osgetenv("TEXOS")
 local texmfos=environment.texmfos or osgetenv('SELFAUTODIR')
 if not texos or texos=="" then
-  texos=file.basename(texmfos)
+ texos=file.basename(texmfos)
 end
 ossetenv('TEXMFOS',texmfos)   
-ossetenv('TEXOS',texos)    
-ossetenv('SELFAUTOSYSTEM',os.platform) 
+ossetenv('TEXOS',texos)  
+ossetenv('SELFAUTOSYSTEM',os.platform)  
 environment.texos=texos
 environment.texmfos=texmfos
 local texroot=environment.texroot or osgetenv("TEXROOT")
 if not texroot or texroot=="" then
-  texroot=osgetenv('SELFAUTOPARENT')
-  ossetenv('TEXROOT',texroot)
+ texroot=osgetenv('SELFAUTOPARENT')
+ ossetenv('TEXROOT',texroot)
 end
 environment.texroot=file.collapsepath(texroot)
 local prefixes=utilities.storage.allocate()
@@ -16418,30 +19992,30 @@
 local abstract={}
 local dynamic={}
 function resolvers.resetresolve(str)
-  resolved,abstract={},{}
+ resolved,abstract={},{}
 end
 function resolvers.allprefixes(separator)
-  local all=table.sortedkeys(prefixes)
-  if separator then
-    for i=1,#all do
-      all[i]=all[i]..":"
-    end
+ local all=table.sortedkeys(prefixes)
+ if separator then
+  for i=1,#all do
+   all[i]=all[i]..":"
   end
-  return all
+ end
+ return all
 end
 local function _resolve_(method,target)
-  local action=prefixes[method]
-  if action then
-    return action(target)
-  else
-    return method..":"..target
-  end
+ local action=prefixes[method]
+ if action then
+  return action(target)
+ else
+  return method..":"..target
+ end
 end
 function resolvers.unresolve(str)
-  return abstract[str] or str
+ return abstract[str] or str
 end
 function resolvers.setdynamic(str)
-  dynamic[str]=true
+ dynamic[str]=true
 end
 local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
 local prefix=C(R("az")^2)*P(":")
@@ -16450,65 +20024,65 @@
 local p_resolve=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
 local p_simple=prefix*P(-1)
 local function resolve(str) 
-  if type(str)=="table" then
-    local res={}
-    for i=1,#str do
-      res[i]=resolve(str[i])
-    end
-    return res
+ if type(str)=="table" then
+  local res={}
+  for i=1,#str do
+   res[i]=resolve(str[i])
   end
-  local res=resolved[str]
-  if res then
-    return res
+  return res
+ end
+ local res=resolved[str]
+ if res then
+  return res
+ end
+ local simple=lpegmatch(p_simple,str)
+ local action=prefixes[simple]
+ if action then
+  local res=action(res)
+  if not dynamic[simple] then
+   resolved[simple]=res
+   abstract[res]=simple
   end
-  local simple=lpegmatch(p_simple,str)
-  local action=prefixes[simple]
-  if action then
-    local res=action(res)
-    if not dynamic[simple] then
-      resolved[simple]=res
-      abstract[res]=simple
-    end
-    return res
-  end
-  res=lpegmatch(p_resolve,str)
-  resolved[str]=res
-  abstract[res]=str
   return res
+ end
+ res=lpegmatch(p_resolve,str)
+ resolved[str]=res
+ abstract[res]=str
+ return res
 end
 resolvers.resolve=resolve
 if type(osuname)=="function" then
-  for k,v in next,osuname() do
-    if not prefixes[k] then
-      prefixes[k]=function() return v end
-    end
+ for k,v in next,osuname() do
+  if not prefixes[k] then
+   prefixes[k]=function() return v end
   end
+ end
 end
 if ostype=="unix" then
-  local pattern
-  local function makepattern(t,k,v)
-    if t then
-      rawset(t,k,v)
-    end
-    local colon=P(":")
-    for k,v in table.sortedpairs(prefixes) do
-      if p then
-        p=P(k)+p
-      else
-        p=P(k)
-      end
-    end
-    pattern=Cs((p*colon+colon/";"+P(1))^0)
+ local pattern
+ local function makepattern(t,k,v)
+  if t then
+   rawset(t,k,v)
   end
-  makepattern()
-  table.setmetatablenewindex(prefixes,makepattern)
-  function resolvers.repath(str)
-    return lpegmatch(pattern,str)
+  local colon=P(":")
+  for k,v in table.sortedpairs(prefixes) do
+   if p then
+    p=P(k)+p
+   else
+    p=P(k)
+   end
   end
+  pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ table.setmetatablenewindex(prefixes,makepattern)
+ function resolvers.repath(str)
+  return lpegmatch(pattern,str)
+ end
 else 
-  function resolvers.repath(str)
-    return str
-  end
+ function resolvers.repath(str)
+  return str
+ end
 end
 
 
@@ -16518,14 +20092,14 @@
 
 package.loaded["data-exp"] = package.loaded["data-exp"] or true
 
--- original size: 18105, stripped down to: 11207
+-- original size: 18105, stripped down to: 10389
 
 if not modules then modules={} end modules ['data-exp']={
-  version=1.001,
-  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",
+ version=1.001,
+ 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 format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub
 local concat,sort=table.concat,table.sort
@@ -16535,21 +20109,21 @@
 local type,next=type,next
 local isdir=lfs.isdir
 local collapsepath,joinpath,basename=file.collapsepath,file.join,file.basename
-local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
-local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
-local trace_globbing=true  trackers.register("resolvers.globbing",function(v) trace_globbing=v end)
+local trace_locating=false  trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_expansions=false  trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_globbing=true   trackers.register("resolvers.globbing",function(v) trace_globbing=v end)
 local report_expansions=logs.reporter("resolvers","expansions")
 local report_globbing=logs.reporter("resolvers","globbing")
 local resolvers=resolvers
 local resolveprefix=resolvers.resolve
 local function f_both(a,b)
-  local t,n={},0
-  for sb in gmatch(b,"[^,]+") do       
-    for sa in gmatch(a,"[^,]+") do     
-      n=n+1;t[n]=sa..sb
-    end
+ local t,n={},0
+ for sb in gmatch(b,"[^,]+") do     
+  for sa in gmatch(a,"[^,]+") do    
+   n=n+1;t[n]=sa..sb
   end
-  return concat(t,",")
+ end
+ return concat(t,",")
 end
 local comma=P(",")
 local nocomma=(1-comma)^1
@@ -16559,7 +20133,7 @@
 local both=Cs(((C(nocomma)*Carg(1))/function(a,b) return lpegmatch(before,b,1,a) end+docomma)^0)
 local function f_first (a,b) return lpegmatch(after,b,1,a) end
 local function f_second(a,b) return lpegmatch(before,a,1,b) end
-local function f_both (a,b) return lpegmatch(both,b,1,a) end
+local function f_both  (a,b) return lpegmatch(both,b,1,a) end
 local left=P("{")
 local right=P("}")
 local var=P((1-S("{}" ))^0)
@@ -16572,141 +20146,141 @@
 local stripper_1=lpeg.stripper ("{}@")
 local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },}
 local function splitpathexpr(str,newlist,validate) 
-  if trace_expansions then
-    report_expansions("expanding variable %a",str)
-  end
-  local t,ok,done=newlist or {},false,false
-  local n=#t
-  str=lpegmatch(replacer_1,str)
+ if trace_expansions then
+  report_expansions("expanding variable %a",str)
+ end
+ local t,ok,done=newlist or {},false,false
+ local n=#t
+ str=lpegmatch(replacer_1,str)
+ repeat
+  local old=str
   repeat
-    local old=str
-    repeat
-      local old=str
-      str=lpegmatch(l_first,str)
-    until old==str
-    repeat
-      local old=str
-      str=lpegmatch(l_second,str)
-    until old==str
-    repeat
-      local old=str
-      str=lpegmatch(l_both,str)
-    until old==str
-    repeat
-      local old=str
-      str=lpegmatch(l_rest,str)
-    until old==str
-  until old==str 
-  str=lpegmatch(stripper_1,str)
-  if validate then
-    for s in gmatch(str,"[^,]+") do
-      s=validate(s)
-      if s then
-        n=n+1
-        t[n]=s
-      end
-    end
-  else
-    for s in gmatch(str,"[^,]+") do
-      n=n+1
-      t[n]=s
-    end
+   local old=str
+   str=lpegmatch(l_first,str)
+  until old==str
+  repeat
+   local old=str
+   str=lpegmatch(l_second,str)
+  until old==str
+  repeat
+   local old=str
+   str=lpegmatch(l_both,str)
+  until old==str
+  repeat
+   local old=str
+   str=lpegmatch(l_rest,str)
+  until old==str
+ until old==str 
+ str=lpegmatch(stripper_1,str)
+ if validate then
+  for s in gmatch(str,"[^,]+") do
+   s=validate(s)
+   if s then
+    n=n+1
+    t[n]=s
+   end
   end
-  if trace_expansions then
-    for k=1,#t do
-      report_expansions("% 4i: %s",k,t[k])
-    end
+ else
+  for s in gmatch(str,"[^,]+") do
+   n=n+1
+   t[n]=s
   end
-  return t
+ end
+ if trace_expansions then
+  for k=1,#t do
+   report_expansions("% 4i: %s",k,t[k])
+  end
+ end
+ return t
 end
 local function validate(s)
-  s=collapsepath(s) 
-  return s~="" and not find(s,"^!*unset/*$") and s
+ s=collapsepath(s) 
+ return s~="" and not find(s,"^!*unset/*$") and s
 end
 resolvers.validatedpath=validate 
 function resolvers.expandedpathfromlist(pathlist)
-  local newlist={}
-  for k=1,#pathlist do
-    splitpathexpr(pathlist[k],newlist,validate)
-  end
-  return newlist
+ local newlist={}
+ for k=1,#pathlist do
+  splitpathexpr(pathlist[k],newlist,validate)
+ end
+ return newlist
 end
 local usedhomedir=nil
-local donegation=(P("!")/""   )^0
+local donegation=(P("!")/""  )^0
 local doslashes=(P("\\")/"/"+1)^0
 local function expandedhome()
-  if not usedhomedir then
-    usedhomedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
-    if usedhomedir=="~" or usedhomedir=="" or not isdir(usedhomedir) then
-      if trace_expansions then
-        report_expansions("no home dir set, ignoring dependent path using current path")
-      end
-      usedhomedir="."
-    end
+ if not usedhomedir then
+  usedhomedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+  if usedhomedir=="~" or usedhomedir=="" or not isdir(usedhomedir) then
+   if trace_expansions then
+    report_expansions("no home dir set, ignoring dependent path using current path")
+   end
+   usedhomedir="."
   end
-  return usedhomedir
+ end
+ return usedhomedir
 end
 local dohome=((P("~")+P("$HOME")+P("%HOME%"))/expandedhome)^0
 local cleanup=Cs(donegation*dohome*doslashes)
 resolvers.cleanpath=function(str)
-  return str and lpegmatch(cleanup,str) or ""
+ return str and lpegmatch(cleanup,str) or ""
 end
 local expandhome=P("~")/"$HOME"
 local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
 local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
-local dostring=(expandhome+1       )^0
+local dostring=(expandhome+1     )^0
 local stripper=Cs(
-  lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer
+ lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer
 )
 function resolvers.checkedvariable(str) 
-  return type(str)=="string" and lpegmatch(stripper,str) or str
+ return type(str)=="string" and lpegmatch(stripper,str) or str
 end
 local cache={}
 local splitter=lpeg.tsplitat(";") 
 local backslashswapper=lpeg.replacer("\\","/")
 local function splitconfigurationpath(str) 
-  if str then
-    local found=cache[str]
-    if not found then
-      if str=="" then
-        found={}
-      else
-        local split=lpegmatch(splitter,lpegmatch(backslashswapper,str)) 
-        found={}
-        local noffound=0
-        for i=1,#split do
-          local s=split[i]
-          if not find(s,"^{*unset}*") then
-            noffound=noffound+1
-            found[noffound]=s
-          end
-        end
-        if trace_expansions then
-          report_expansions("splitting path specification %a",str)
-          for k=1,noffound do
-            report_expansions("% 4i: %s",k,found[k])
-          end
-        end
-        cache[str]=found
-      end
+ if str then
+  local found=cache[str]
+  if not found then
+   if str=="" then
+    found={}
+   else
+    local split=lpegmatch(splitter,lpegmatch(backslashswapper,str)) 
+    found={}
+    local noffound=0
+    for i=1,#split do
+     local s=split[i]
+     if not find(s,"^{*unset}*") then
+      noffound=noffound+1
+      found[noffound]=s
+     end
     end
-    return found
+    if trace_expansions then
+     report_expansions("splitting path specification %a",str)
+     for k=1,noffound do
+      report_expansions("% 4i: %s",k,found[k])
+     end
+    end
+    cache[str]=found
+   end
   end
+  return found
+ end
 end
 resolvers.splitconfigurationpath=splitconfigurationpath
 function resolvers.splitpath(str)
-  if type(str)=='table' then
-    return str
-  else
-    return splitconfigurationpath(str)
-  end
+ if type(str)=='table' then
+  return str
+ else
+  return splitconfigurationpath(str)
+ end
 end
 function resolvers.joinpath(str)
-  if type(str)=='table' then
-    return joinpath(str)
-  else
-    return str
-  end
+ if type(str)=='table' then
+  return joinpath(str)
+ else
+  return str
+ end
 end
 local attributes,directory=lfs.attributes,lfs.dir
 local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
@@ -16719,201 +20293,201 @@
 local nofsharedscans=0
 local addcasecraptoo=true
 local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
-  local full=path=="" and spec or (spec..path..'/')
-  local dirlist={}
-  local nofdirs=0
-  local pattern=tolerant and lessweird or weird
-  local filelist={}
-  local noffiles=0
-  for name in directory(full) do
-    if not lpegmatch(pattern,name) then
-      local mode=attributes(full..name,"mode")
-      if mode=="file" then
-        n=n+1
-        noffiles=noffiles+1
-        filelist[noffiles]=name
-      elseif mode=="directory" then
-        m=m+1
-        nofdirs=nofdirs+1
-        if path~="" then
-          dirlist[nofdirs]=path.."/"..name
-        else
-          dirlist[nofdirs]=name
-        end
-      end
+ local full=path=="" and spec or (spec..path..'/')
+ local dirlist={}
+ local nofdirs=0
+ local pattern=tolerant and lessweird or weird
+ local filelist={}
+ local noffiles=0
+ for name in directory(full) do
+  if not lpegmatch(pattern,name) then
+   local mode=attributes(full..name,"mode")
+   if mode=="file" then
+    n=n+1
+    noffiles=noffiles+1
+    filelist[noffiles]=name
+   elseif mode=="directory" then
+    m=m+1
+    nofdirs=nofdirs+1
+    if path~="" then
+     dirlist[nofdirs]=path.."/"..name
+    else
+     dirlist[nofdirs]=name
     end
+   end
   end
-  if noffiles>0 then
-    sort(filelist)
-    for i=1,noffiles do
-      local name=filelist[i]
-      local lower=lower(name)
-      local paths=files[lower]
-      if paths then
-        if onlyone then
-        else
-          if name~=lower then
-            local rl=remap[lower]
-            if not rl then
-              remap[lower]=name
-              r=r+1
-            elseif trace_globbing and rl~=name then
-              report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
-            end
-            if addcasecraptoo then
-              local paths=files[name]
-              if not paths then
-                files[name]=path
-              elseif type(paths)=="string" then
-                files[name]={ paths,path }
-              else
-                paths[#paths+1]=path
-              end
-            end
-          end
-          if type(paths)=="string" then
-            files[lower]={ paths,path }
-          else
-            paths[#paths+1]=path
-          end
-        end
-      else 
-        files[lower]=path
-        if name~=lower then
-          local rl=remap[lower]
-          if not rl then
-            remap[lower]=name
-            r=r+1
-          elseif trace_globbing and rl~=name then
-            report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
-          end
-        end
+ end
+ if noffiles>0 then
+  sort(filelist)
+  for i=1,noffiles do
+   local name=filelist[i]
+   local lower=lower(name)
+   local paths=files[lower]
+   if paths then
+    if onlyone then
+    else
+     if name~=lower then
+      local rl=remap[lower]
+      if not rl then
+       remap[lower]=name
+       r=r+1
+      elseif trace_globbing and rl~=name then
+       report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
       end
+      if addcasecraptoo then
+       local paths=files[name]
+       if not paths then
+        files[name]=path
+       elseif type(paths)=="string" then
+        files[name]={ paths,path }
+       else
+        paths[#paths+1]=path
+       end
+      end
+     end
+     if type(paths)=="string" then
+      files[lower]={ paths,path }
+     else
+      paths[#paths+1]=path
+     end
     end
-  end
-  if nofdirs>0 then
-    sort(dirlist)
-    for i=1,nofdirs do
-      files,remap,n,m,r=scan(files,remap,spec,dirlist[i],n,m,r,onlyonce,tolerant)
+   else 
+    files[lower]=path
+    if name~=lower then
+     local rl=remap[lower]
+     if not rl then
+      remap[lower]=name
+      r=r+1
+     elseif trace_globbing and rl~=name then
+      report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+     end
     end
+   end
   end
-  scancache[sub(full,1,-2)]=files
-  return files,remap,n,m,r
+ end
+ if nofdirs>0 then
+  sort(dirlist)
+  for i=1,nofdirs do
+   files,remap,n,m,r=scan(files,remap,spec,dirlist[i],n,m,r,onlyonce,tolerant)
+  end
+ end
+ scancache[sub(full,1,-2)]=files
+ return files,remap,n,m,r
 end
 function resolvers.scanfiles(path,branch,usecache,onlyonce,tolerant)
-  local realpath=resolveprefix(path)
-  if usecache then
-    local content=fullcache[realpath]
-    if content then
-      if trace_locating then
-        report_expansions("using cached scan of path %a, branch %a",path,branch or path)
-      end
-      nofsharedscans=nofsharedscans+1
-      return content
-    end
+ local realpath=resolveprefix(path)
+ if usecache then
+  local content=fullcache[realpath]
+  if content then
+   if trace_locating then
+    report_expansions("using cached scan of path %a, branch %a",path,branch or path)
+   end
+   nofsharedscans=nofsharedscans+1
+   return content
   end
-  statistics.starttiming(timer)
+ end
+ statistics.starttiming(timer)
+ if trace_locating then
+  report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local content
+ if isdir(realpath) then
+  local files,remap,n,m,r=scan({},{},realpath..'/',"",0,0,0,onlyonce,tolerant)
+  content={
+   metadata={
+    path=path,
+    files=n,
+    directories=m,
+    remappings=r,
+   },
+   files=files,
+   remap=remap,
+  }
   if trace_locating then
-    report_expansions("scanning path %a, branch %a",path,branch or path)
+   report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
   end
-  local content
-  if isdir(realpath) then
-    local files,remap,n,m,r=scan({},{},realpath..'/',"",0,0,0,onlyonce,tolerant)
-    content={
-      metadata={
-        path=path,
-        files=n,
-        directories=m,
-        remappings=r,
-      },
-      files=files,
-      remap=remap,
-    }
-    if trace_locating then
-      report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
-    end
-  else
-    content={
-      metadata={
-        path=path,
-        files=0,
-        directories=0,
-        remappings=0,
-      },
-      files={},
-      remap={},
-    }
-    if trace_locating then
-      report_expansions("invalid path %a",realpath)
-    end
+ else
+  content={
+   metadata={
+    path=path,
+    files=0,
+    directories=0,
+    remappings=0,
+   },
+   files={},
+   remap={},
+  }
+  if trace_locating then
+   report_expansions("invalid path %a",realpath)
   end
-  if usecache then
-    scanned[#scanned+1]=realpath
-    fullcache[realpath]=content
-  end
-  nofscans=nofscans+1
-  statistics.stoptiming(timer)
-  return content
+ end
+ if usecache then
+  scanned[#scanned+1]=realpath
+  fullcache[realpath]=content
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return content
 end
 function resolvers.simplescanfiles(path,branch,usecache)
-  return resolvers.scanfiles(path,branch,usecache,true,true) 
+ return resolvers.scanfiles(path,branch,usecache,true,true) 
 end
 function resolvers.scandata()
-  table.sort(scanned)
-  return {
-    n=nofscans,
-    shared=nofsharedscans,
-    time=statistics.elapsedtime(timer),
-    paths=scanned,
-  }
+ table.sort(scanned)
+ return {
+  n=nofscans,
+  shared=nofsharedscans,
+  time=statistics.elapsedtime(timer),
+  paths=scanned,
+ }
 end
 function resolvers.get_from_content(content,path,name) 
-  if not content then
-    return
+ if not content then
+  return
+ end
+ local files=content.files
+ if not files then
+  return
+ end
+ local remap=content.remap
+ if not remap then
+  return
+ end
+ if name then
+  local used=lower(name)
+  return path,remap[used] or used
+ else
+  local name=path
+  local used=lower(name)
+  local path=files[used]
+  if path then
+   return path,remap[used] or used
   end
-  local files=content.files
-  if not files then
-    return
-  end
-  local remap=content.remap
-  if not remap then
-    return
-  end
-  if name then
-    local used=lower(name)
-    return path,remap[used] or used
-  else
-    local name=path
-    local used=lower(name)
-    local path=files[used]
-    if path then
-      return path,remap[used] or used
-    end
-  end
+ end
 end
 local nothing=function() end
 function resolvers.filtered_from_content(content,pattern)
-  if content and type(pattern)=="string" then
-    local pattern=lower(pattern)
-    local files=content.files 
-    local remap=content.remap
-    if files and remap then
-      local f=sortedkeys(files)
-      local n=#f
-      local i=0
-      local function iterator()
-        while i<n do
-          i=i+1
-          local k=f[i]
-          if find(k,pattern) then
-            return files[k],remap and remap[k] or k
-          end
-        end
-      end
-      return iterator
+ if content and type(pattern)=="string" then
+  local pattern=lower(pattern)
+  local files=content.files 
+  local remap=content.remap
+  if files and remap then
+   local f=sortedkeys(files)
+   local n=#f
+   local i=0
+   local function iterator()
+    while i<n do
+     i=i+1
+     local k=f[i]
+     if find(k,pattern) then
+      return files[k],remap and remap[k] or k
+     end
     end
+   end
+   return iterator
   end
-  return nothing
+ end
+ return nothing
 end
 
 
@@ -16923,14 +20497,14 @@
 
 package.loaded["data-env"] = package.loaded["data-env"] or true
 
--- original size: 9360, stripped down to: 6903
+-- original size: 9360, stripped down to: 6312
 
 if not modules then modules={} end modules ['data-env']={
-  version=1.001,
-  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",
+ version=1.001,
+ 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 lower,gsub=string.lower,string.gsub
 local next=next
@@ -16950,255 +20524,255 @@
 resolvers.usertypes=usertypes
 local luasuffixes=utilities.lua.suffixes
 local relations=allocate { 
-  core={
-    ofm={ 
-      names={ "ofm","omega font metric","omega font metrics" },
-      variable='OFMFONTS',
-      suffixes={ 'ofm','tfm' },
-    },
-    ovf={ 
-      names={ "ovf","omega virtual font","omega virtual fonts" },
-      variable='OVFFONTS',
-      suffixes={ 'ovf','vf' },
-    },
-    tfm={
-      names={ "tfm","tex font metric","tex font metrics" },
-      variable='TFMFONTS',
-      suffixes={ 'tfm' },
-    },
-    vf={
-      names={ "vf","virtual font","virtual fonts" },
-      variable='VFFONTS',
-      suffixes={ 'vf' },
-    },
-    otf={
-      names={ "otf","opentype","opentype font","opentype fonts"},
-      variable='OPENTYPEFONTS',
-      suffixes={ 'otf' },
-    },
-    ttf={
-      names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" },
-      variable='TTFONTS',
-      suffixes={ 'ttf','ttc','dfont' },
-    },
-    afm={
-      names={ "afm","adobe font metric","adobe font metrics" },
-      variable="AFMFONTS",
-      suffixes={ "afm" },
-    },
-    pfb={
-      names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" },
-      variable='T1FONTS',
-      suffixes={ 'pfb','pfa' },
-    },
-    fea={
-      names={ "fea","font feature","font features","font feature file","font feature files" },
-      variable='FONTFEATURES',
-      suffixes={ 'fea' },
-    },
-    cid={
-      names={ "cid","cid map","cid maps","cid file","cid files" },
-      variable='FONTCIDMAPS',
-      suffixes={ 'cid','cidmap' },
-    },
-    fmt={
-      names={ "fmt","format","tex format" },
-      variable='TEXFORMATS',
-      suffixes={ 'fmt' },
-    },
-    mem={ 
-      names={ 'mem',"metapost format" },
-      variable='MPMEMS',
-      suffixes={ 'mem' },
-    },
-    mp={
-      names={ "mp" },
-      variable='MPINPUTS',
-      suffixes={ 'mp','mpvi','mpiv','mpii' },
-      usertype=true,
-    },
-    tex={
-      names={ "tex" },
-      variable='TEXINPUTS',
-      suffixes={ "tex","mkvi","mkiv","mkii","cld","lfg","xml" },
-      usertype=true,
-    },
-    icc={
-      names={ "icc","icc profile","icc profiles" },
-      variable='ICCPROFILES',
-      suffixes={ 'icc' },
-    },
-    texmfscripts={
-      names={ "texmfscript","texmfscripts","script","scripts" },
-      variable='TEXMFSCRIPTS',
-      suffixes={ 'lua','rb','pl','py' },
-    },
-    lua={
-      names={ "lua" },
-      variable='LUAINPUTS',
-      suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
-      usertype=true,
-    },
-    lib={
-      names={ "lib" },
-      variable='CLUAINPUTS',
-      suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' },
-    },
-    bib={
-      names={ 'bib' },
-      variable='BIBINPUTS',
-      suffixes={ 'bib' },
-      usertype=true,
-    },
-    bst={
-      names={ 'bst' },
-      variable='BSTINPUTS',
-      suffixes={ 'bst' },
-      usertype=true,
-    },
-    fontconfig={
-      names={ 'fontconfig','fontconfig file','fontconfig files' },
-      variable='FONTCONFIG_PATH',
-    },
-    pk={
-      names={ "pk" },
-      variable='PKFONTS',
-      suffixes={ 'pk' },
-    },
+ core={
+  ofm={ 
+   names={ "ofm","omega font metric","omega font metrics" },
+   variable='OFMFONTS',
+   suffixes={ 'ofm','tfm' },
   },
-  obsolete={
-    enc={
-      names={ "enc","enc files","enc file","encoding files","encoding file" },
-      variable='ENCFONTS',
-      suffixes={ 'enc' },
-    },
-    map={
-      names={ "map","map files","map file" },
-      variable='TEXFONTMAPS',
-      suffixes={ 'map' },
-    },
-    lig={
-      names={ "lig files","lig file","ligature file","ligature files" },
-      variable='LIGFONTS',
-      suffixes={ 'lig' },
-    },
-    opl={
-      names={ "opl" },
-      variable='OPLFONTS',
-      suffixes={ 'opl' },
-    },
-    ovp={
-      names={ "ovp" },
-      variable='OVPFONTS',
-      suffixes={ 'ovp' },
-    },
+  ovf={ 
+   names={ "ovf","omega virtual font","omega virtual fonts" },
+   variable='OVFFONTS',
+   suffixes={ 'ovf','vf' },
   },
-  kpse={ 
-    base={
-      names={ 'base',"metafont format" },
-      variable='MFBASES',
-      suffixes={ 'base','bas' },
-    },
-    cmap={
-      names={ 'cmap','cmap files','cmap file' },
-      variable='CMAPFONTS',
-      suffixes={ 'cmap' },
-    },
-    cnf={
-      names={ 'cnf' },
-      suffixes={ 'cnf' },
-    },
-    web={
-      names={ 'web' },
-      suffixes={ 'web','ch' }
-    },
-    cweb={
-      names={ 'cweb' },
-      suffixes={ 'w','web','ch' },
-    },
-    gf={
-      names={ 'gf' },
-      suffixes={ '<resolution>gf' },
-    },
-    mf={
-      names={ 'mf' },
-      variable='MFINPUTS',
-      suffixes={ 'mf' },
-    },
-    mft={
-      names={ 'mft' },
-      suffixes={ 'mft' },
-    },
-    pk={
-      names={ 'pk' },
-      suffixes={ '<resolution>pk' },
-    },
+  tfm={
+   names={ "tfm","tex font metric","tex font metrics" },
+   variable='TFMFONTS',
+   suffixes={ 'tfm' },
   },
+  vf={
+   names={ "vf","virtual font","virtual fonts" },
+   variable='VFFONTS',
+   suffixes={ 'vf' },
+  },
+  otf={
+   names={ "otf","opentype","opentype font","opentype fonts"},
+   variable='OPENTYPEFONTS',
+   suffixes={ 'otf' },
+  },
+  ttf={
+   names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" },
+   variable='TTFONTS',
+   suffixes={ 'ttf','ttc','dfont' },
+  },
+  afm={
+   names={ "afm","adobe font metric","adobe font metrics" },
+   variable="AFMFONTS",
+   suffixes={ "afm" },
+  },
+  pfb={
+   names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" },
+   variable='T1FONTS',
+   suffixes={ 'pfb','pfa' },
+  },
+  fea={
+   names={ "fea","font feature","font features","font feature file","font feature files" },
+   variable='FONTFEATURES',
+   suffixes={ 'fea' },
+  },
+  cid={
+   names={ "cid","cid map","cid maps","cid file","cid files" },
+   variable='FONTCIDMAPS',
+   suffixes={ 'cid','cidmap' },
+  },
+  fmt={
+   names={ "fmt","format","tex format" },
+   variable='TEXFORMATS',
+   suffixes={ 'fmt' },
+  },
+  mem={ 
+   names={ 'mem',"metapost format" },
+   variable='MPMEMS',
+   suffixes={ 'mem' },
+  },
+  mp={
+   names={ "mp" },
+   variable='MPINPUTS',
+   suffixes={ 'mp','mpvi','mpiv','mpii' },
+   usertype=true,
+  },
+  tex={
+   names={ "tex" },
+   variable='TEXINPUTS',
+   suffixes={ "tex","mkvi","mkiv","mkii","cld","lfg","xml" },
+   usertype=true,
+  },
+  icc={
+   names={ "icc","icc profile","icc profiles" },
+   variable='ICCPROFILES',
+   suffixes={ 'icc' },
+  },
+  texmfscripts={
+   names={ "texmfscript","texmfscripts","script","scripts" },
+   variable='TEXMFSCRIPTS',
+   suffixes={ 'lua','rb','pl','py' },
+  },
+  lua={
+   names={ "lua" },
+   variable='LUAINPUTS',
+   suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+   usertype=true,
+  },
+  lib={
+   names={ "lib" },
+   variable='CLUAINPUTS',
+   suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' },
+  },
+  bib={
+   names={ 'bib' },
+   variable='BIBINPUTS',
+   suffixes={ 'bib' },
+   usertype=true,
+  },
+  bst={
+   names={ 'bst' },
+   variable='BSTINPUTS',
+   suffixes={ 'bst' },
+   usertype=true,
+  },
+  fontconfig={
+   names={ 'fontconfig','fontconfig file','fontconfig files' },
+   variable='FONTCONFIG_PATH',
+  },
+  pk={
+   names={ "pk" },
+   variable='PKFONTS',
+   suffixes={ 'pk' },
+  },
+ },
+ obsolete={
+  enc={
+   names={ "enc","enc files","enc file","encoding files","encoding file" },
+   variable='ENCFONTS',
+   suffixes={ 'enc' },
+  },
+  map={
+   names={ "map","map files","map file" },
+   variable='TEXFONTMAPS',
+   suffixes={ 'map' },
+  },
+  lig={
+   names={ "lig files","lig file","ligature file","ligature files" },
+   variable='LIGFONTS',
+   suffixes={ 'lig' },
+  },
+  opl={
+   names={ "opl" },
+   variable='OPLFONTS',
+   suffixes={ 'opl' },
+  },
+  ovp={
+   names={ "ovp" },
+   variable='OVPFONTS',
+   suffixes={ 'ovp' },
+  },
+ },
+ kpse={ 
+  base={
+   names={ 'base',"metafont format" },
+   variable='MFBASES',
+   suffixes={ 'base','bas' },
+  },
+  cmap={
+   names={ 'cmap','cmap files','cmap file' },
+   variable='CMAPFONTS',
+   suffixes={ 'cmap' },
+  },
+  cnf={
+   names={ 'cnf' },
+   suffixes={ 'cnf' },
+  },
+  web={
+   names={ 'web' },
+   suffixes={ 'web','ch' }
+  },
+  cweb={
+   names={ 'cweb' },
+   suffixes={ 'w','web','ch' },
+  },
+  gf={
+   names={ 'gf' },
+   suffixes={ '<resolution>gf' },
+  },
+  mf={
+   names={ 'mf' },
+   variable='MFINPUTS',
+   suffixes={ 'mf' },
+  },
+  mft={
+   names={ 'mft' },
+   suffixes={ 'mft' },
+  },
+  pk={
+   names={ 'pk' },
+   suffixes={ '<resolution>pk' },
+  },
+ },
 }
 resolvers.relations=relations
 function resolvers.updaterelations()
-  for category,categories in next,relations do
-    for name,relation in next,categories do
-      local rn=relation.names
-      local rv=relation.variable
-      if rn and rv then
-        local rs=relation.suffixes
-        local ru=relation.usertype
-        for i=1,#rn do
-          local rni=lower(gsub(rn[i]," ",""))
-          formats[rni]=rv
-          if rs then
-            suffixes[rni]=rs
-            for i=1,#rs do
-              local rsi=rs[i]
-              suffixmap[rsi]=rni
-            end
-          end
-        end
-        if ru then
-          usertypes[name]=true
-        end
+ for category,categories in next,relations do
+  for name,relation in next,categories do
+   local rn=relation.names
+   local rv=relation.variable
+   if rn and rv then
+    local rs=relation.suffixes
+    local ru=relation.usertype
+    for i=1,#rn do
+     local rni=lower(gsub(rn[i]," ",""))
+     formats[rni]=rv
+     if rs then
+      suffixes[rni]=rs
+      for i=1,#rs do
+       local rsi=rs[i]
+       suffixmap[rsi]=rni
       end
+     end
     end
+    if ru then
+     usertypes[name]=true
+    end
+   end
   end
+ end
 end
 resolvers.updaterelations() 
 local function simplified(t,k)
-  return k and rawget(t,lower(gsub(k," ",""))) or nil
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
 end
 setmetatableindex(formats,simplified)
 setmetatableindex(suffixes,simplified)
 setmetatableindex(suffixmap,simplified)
 function resolvers.suffixofformat(str)
-  local s=suffixes[str]
-  return s and s[1] or ""
+ local s=suffixes[str]
+ return s and s[1] or ""
 end
 function resolvers.suffixofformat(str)
-  return suffixes[str] or {}
+ return suffixes[str] or {}
 end
 for name,format in next,formats do
-  dangerous[name]=true 
+ dangerous[name]=true 
 end
 dangerous.tex=nil
 function resolvers.formatofvariable(str)
-  return formats[str] or ''
+ return formats[str] or ''
 end
 function resolvers.formatofsuffix(str) 
-  return suffixmap[suffixonly(str)] or 'tex' 
+ return suffixmap[suffixonly(str)] or 'tex' 
 end
 function resolvers.variableofformat(str)
-  return formats[str] or ''
+ return formats[str] or ''
 end
 function resolvers.variableofformatorsuffix(str)
-  local v=formats[str]
-  if v then
-    return v
-  end
-  v=suffixmap[suffixonly(str)]
-  if v then
-    return formats[v]
-  end
-  return ''
+ local v=formats[str]
+ if v then
+  return v
+ end
+ v=suffixmap[suffixonly(str)]
+ if v then
+  return formats[v]
+ end
+ return ''
 end
 
 
@@ -17208,14 +20782,14 @@
 
 package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
 
--- original size: 16116, stripped down to: 11459
+-- original size: 16116, stripped down to: 10782
 
 if not modules then modules={} end modules ['data-tmp']={
-  version=1.100,
-  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"
+ version=1.100,
+ 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 format,lower,gsub,concat=string.format,string.lower,string.gsub,table.concat
 local concat=table.concat
@@ -17223,19 +20797,19 @@
 local addsuffix,is_writable,is_readable=file.addsuffix,file.is_writable,file.is_readable
 local formatters=string.formatters
 local next,type=next,type
-local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
-local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_locating=false  trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_cache=false  trackers.register("resolvers.cache",function(v) trace_cache=v end)
 local report_caches=logs.reporter("resolvers","caches")
 local report_resolvers=logs.reporter("resolvers","caching")
 local resolvers=resolvers
 local cleanpath=resolvers.cleanpath
-local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
-local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
+local directive_cleanup=false  directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
+local directive_strip=false  directives.register("system.compile.strip",function(v) directive_strip=v end)
 local compile=utilities.lua.compile
 function utilities.lua.compile(luafile,lucfile,cleanup,strip)
-  if cleanup==nil then cleanup=directive_cleanup end
-  if strip==nil then strip=directive_strip  end
-  return compile(luafile,lucfile,cleanup,strip)
+ if cleanup==nil then cleanup=directive_cleanup end
+ if strip==nil then strip=directive_strip   end
+ return compile(luafile,lucfile,cleanup,strip)
 end
 caches=caches or {}
 local caches=caches
@@ -17250,324 +20824,324 @@
 caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
 local writable,readables,usedreadables=nil,{},{}
 local function identify()
-  local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE") 
-  if texmfcaches then
-    for k=1,#texmfcaches do
-      local cachepath=texmfcaches[k]
-      if cachepath~="" then
-        cachepath=resolvers.resolve(cachepath)
-        cachepath=resolvers.cleanpath(cachepath)
-        cachepath=file.collapsepath(cachepath)
-        local valid=isdir(cachepath)
-        if valid then
-          if is_readable(cachepath) then
-            readables[#readables+1]=cachepath
-            if not writable and is_writable(cachepath) then
-              writable=cachepath
-            end
-          end
-        elseif not writable and caches.force then
-          local cacheparent=file.dirname(cachepath)
-          if is_writable(cacheparent) and true then 
-            if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then
-              mkdirs(cachepath)
-              if isdir(cachepath) and is_writable(cachepath) then
-                report_caches("path %a created",cachepath)
-                writable=cachepath
-                readables[#readables+1]=cachepath
-              end
-            end
-          end
-        end
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE") 
+ if texmfcaches then
+  for k=1,#texmfcaches do
+   local cachepath=texmfcaches[k]
+   if cachepath~="" then
+    cachepath=resolvers.resolve(cachepath)
+    cachepath=resolvers.cleanpath(cachepath)
+    cachepath=file.collapsepath(cachepath)
+    local valid=isdir(cachepath)
+    if valid then
+     if is_readable(cachepath) then
+      readables[#readables+1]=cachepath
+      if not writable and is_writable(cachepath) then
+       writable=cachepath
       end
+     end
+    elseif not writable and caches.force then
+     local cacheparent=file.dirname(cachepath)
+     if is_writable(cacheparent) and true then 
+      if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then
+       mkdirs(cachepath)
+       if isdir(cachepath) and is_writable(cachepath) then
+        report_caches("path %a created",cachepath)
+        writable=cachepath
+        readables[#readables+1]=cachepath
+       end
+      end
+     end
     end
+   end
   end
-  local texmfcaches=caches.defaults
-  if texmfcaches then
-    for k=1,#texmfcaches do
-      local cachepath=texmfcaches[k]
-      cachepath=resolvers.expansion(cachepath) 
-      if cachepath~="" then
-        cachepath=resolvers.resolve(cachepath)
-        cachepath=resolvers.cleanpath(cachepath)
-        local valid=isdir(cachepath)
-        if valid and is_readable(cachepath) then
-          if not writable and is_writable(cachepath) then
-            readables[#readables+1]=cachepath
-            writable=cachepath
-            break
-          end
-        end
-      end
+ end
+ local texmfcaches=caches.defaults
+ if texmfcaches then
+  for k=1,#texmfcaches do
+   local cachepath=texmfcaches[k]
+   cachepath=resolvers.expansion(cachepath) 
+   if cachepath~="" then
+    cachepath=resolvers.resolve(cachepath)
+    cachepath=resolvers.cleanpath(cachepath)
+    local valid=isdir(cachepath)
+    if valid and is_readable(cachepath) then
+     if not writable and is_writable(cachepath) then
+      readables[#readables+1]=cachepath
+      writable=cachepath
+      break
+     end
     end
+   end
   end
-  if not writable then
-    report_caches("fatal error: there is no valid writable cache path defined")
-    os.exit()
-  elseif #readables==0 then
-    report_caches("fatal error: there is no valid readable cache path defined")
-    os.exit()
+ end
+ if not writable then
+  report_caches("fatal error: there is no valid writable cache path defined")
+  os.exit()
+ elseif #readables==0 then
+  report_caches("fatal error: there is no valid readable cache path defined")
+  os.exit()
+ end
+ writable=dir.expandname(resolvers.cleanpath(writable))
+ local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash() 
+ if tree then
+  caches.tree=tree
+  writable=mkdirs(writable,base,more,tree)
+  for i=1,#readables do
+   readables[i]=file.join(readables[i],base,more,tree)
   end
-  writable=dir.expandname(resolvers.cleanpath(writable))
-  local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash() 
-  if tree then
-    caches.tree=tree
-    writable=mkdirs(writable,base,more,tree)
-    for i=1,#readables do
-      readables[i]=file.join(readables[i],base,more,tree)
-    end
-  else
-    writable=mkdirs(writable,base,more)
-    for i=1,#readables do
-      readables[i]=file.join(readables[i],base,more)
-    end
+ else
+  writable=mkdirs(writable,base,more)
+  for i=1,#readables do
+   readables[i]=file.join(readables[i],base,more)
   end
-  if trace_cache then
-    for i=1,#readables do
-      report_caches("using readable path %a (order %s)",readables[i],i)
-    end
-    report_caches("using writable path %a",writable)
+ end
+ if trace_cache then
+  for i=1,#readables do
+   report_caches("using readable path %a (order %s)",readables[i],i)
   end
-  identify=function()
-    return writable,readables
-  end
+  report_caches("using writable path %a",writable)
+ end
+ identify=function()
   return writable,readables
+ end
+ return writable,readables
 end
 function caches.usedpaths(separator)
-  local writable,readables=identify()
-  if #readables>1 then
-    local result={}
-    local done={}
-    for i=1,#readables do
-      local readable=readables[i]
-      if readable==writable then
-        done[readable]=true
-        result[#result+1]=formatters["readable+writable: %a"](readable)
-      elseif usedreadables[i] then
-        done[readable]=true
-        result[#result+1]=formatters["readable: %a"](readable)
-      end
-    end
-    if not done[writable] then
-      result[#result+1]=formatters["writable: %a"](writable)
-    end
-    return concat(result,separator or " | ")
-  else
-    return writable or "?"
+ local writable,readables=identify()
+ if #readables>1 then
+  local result={}
+  local done={}
+  for i=1,#readables do
+   local readable=readables[i]
+   if readable==writable then
+    done[readable]=true
+    result[#result+1]=formatters["readable+writable: %a"](readable)
+   elseif usedreadables[i] then
+    done[readable]=true
+    result[#result+1]=formatters["readable: %a"](readable)
+   end
   end
+  if not done[writable] then
+   result[#result+1]=formatters["writable: %a"](writable)
+  end
+  return concat(result,separator or " | ")
+ else
+  return writable or "?"
+ end
 end
 function caches.configfiles()
-  return concat(resolvers.configurationfiles(),";")
+ return concat(resolvers.configurationfiles(),";")
 end
 function caches.hashed(tree)
-  tree=gsub(tree,"[\\/]+$","")
-  tree=lower(tree)
-  local hash=md5.hex(tree)
-  if trace_cache or trace_locating then
-    report_caches("hashing tree %a, hash %a",tree,hash)
-  end
-  return hash
+ tree=gsub(tree,"[\\/]+$","")
+ tree=lower(tree)
+ local hash=md5.hex(tree)
+ if trace_cache or trace_locating then
+  report_caches("hashing tree %a, hash %a",tree,hash)
+ end
+ return hash
 end
 function caches.treehash()
-  local tree=caches.configfiles()
-  if not tree or tree=="" then
-    return false
-  else
-    return caches.hashed(tree)
-  end
+ local tree=caches.configfiles()
+ if not tree or tree=="" then
+  return false
+ else
+  return caches.hashed(tree)
+ end
 end
 local r_cache,w_cache={},{} 
 local function getreadablepaths(...)
-  local tags={... }
-  local hash=concat(tags,"/")
-  local done=r_cache[hash]
-  if not done then
-    local writable,readables=identify() 
-    if #tags>0 then
-      done={}
-      for i=1,#readables do
-        done[i]=file.join(readables[i],...)
-      end
-    else
-      done=readables
-    end
-    r_cache[hash]=done
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=r_cache[hash]
+ if not done then
+  local writable,readables=identify() 
+  if #tags>0 then
+   done={}
+   for i=1,#readables do
+    done[i]=file.join(readables[i],...)
+   end
+  else
+   done=readables
   end
-  return done
+  r_cache[hash]=done
+ end
+ return done
 end
 local function getwritablepath(...)
-  local tags={... }
-  local hash=concat(tags,"/")
-  local done=w_cache[hash]
-  if not done then
-    local writable,readables=identify() 
-    if #tags>0 then
-      done=mkdirs(writable,...)
-    else
-      done=writable
-    end
-    w_cache[hash]=done
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=w_cache[hash]
+ if not done then
+  local writable,readables=identify() 
+  if #tags>0 then
+   done=mkdirs(writable,...)
+  else
+   done=writable
   end
-  return done
+  w_cache[hash]=done
+ end
+ return done
 end
 caches.getreadablepaths=getreadablepaths
 caches.getwritablepath=getwritablepath
 function caches.getfirstreadablefile(filename,...)
-  local fullname,path=caches.setfirstwritablefile(filename,...)
+ local fullname,path=caches.setfirstwritablefile(filename,...)
+ if is_readable(fullname) then
+  return fullname,path 
+ end
+ local rd=getreadablepaths(...)
+ for i=1,#rd do
+  local path=rd[i]
+  local fullname=file.join(path,filename)
   if is_readable(fullname) then
-    return fullname,path 
+   usedreadables[i]=true
+   return fullname,path 
   end
-  local rd=getreadablepaths(...)
-  for i=1,#rd do
-    local path=rd[i]
-    local fullname=file.join(path,filename)
-    if is_readable(fullname) then
-      usedreadables[i]=true
-      return fullname,path 
-    end
-  end
-  return fullname,path 
+ end
+ return fullname,path 
 end
 function caches.setfirstwritablefile(filename,...)
-  local wr=getwritablepath(...)
-  local fullname=file.join(wr,filename)
-  return fullname,wr
+ local wr=getwritablepath(...)
+ local fullname=file.join(wr,filename)
+ return fullname,wr
 end
 function caches.define(category,subcategory) 
-  return function()
-    return getwritablepath(category,subcategory)
-  end
+ return function()
+  return getwritablepath(category,subcategory)
+ end
 end
 function caches.setluanames(path,name)
-  return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc)
+ return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc)
 end
 function caches.loaddata(readables,name,writable)
-  if type(readables)=="string" then
-    readables={ readables }
+ if type(readables)=="string" then
+  readables={ readables }
+ end
+ for i=1,#readables do
+  local path=readables[i]
+  local loader=false
+  local tmaname,tmcname=caches.setluanames(path,name)
+  if isfile(tmcname) then
+   loader=loadfile(tmcname)
   end
-  for i=1,#readables do
-    local path=readables[i]
-    local loader=false
-    local tmaname,tmcname=caches.setluanames(path,name)
-    if isfile(tmcname) then
-      loader=loadfile(tmcname)
-    end
-    if not loader and isfile(tmaname) then
-      local tmacrap,tmcname=caches.setluanames(writable,name)
-      if isfile(tmcname) then
-        loader=loadfile(tmcname)
-      end
-      utilities.lua.compile(tmaname,tmcname)
-      if isfile(tmcname) then
-        loader=loadfile(tmcname)
-      end
-      if not loader then
-        loader=loadfile(tmaname)
-      end
-    end
-    if loader then
-      loader=loader()
-      collectgarbage("step")
-      return loader
-    end
+  if not loader and isfile(tmaname) then
+   local tmacrap,tmcname=caches.setluanames(writable,name)
+   if isfile(tmcname) then
+    loader=loadfile(tmcname)
+   end
+   utilities.lua.compile(tmaname,tmcname)
+   if isfile(tmcname) then
+    loader=loadfile(tmcname)
+   end
+   if not loader then
+    loader=loadfile(tmaname)
+   end
   end
-  return false
+  if loader then
+   loader=loader()
+   collectgarbage("step")
+   return loader
+  end
+ end
+ return false
 end
 function caches.is_writable(filepath,filename)
-  local tmaname,tmcname=caches.setluanames(filepath,filename)
-  return is_writable(tmaname)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ return is_writable(tmaname)
 end
 local saveoptions={ compact=true }
 function caches.savedata(filepath,filename,data,raw)
-  local tmaname,tmcname=caches.setluanames(filepath,filename)
-  data.cache_uuid=os.uuid()
-  if caches.direct then
-    file.savedata(tmaname,table.serialize(data,true,saveoptions))
-  else
-    table.tofile(tmaname,data,true,saveoptions)
-  end
-  utilities.lua.compile(tmaname,tmcname)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ data.cache_uuid=os.uuid()
+ if caches.direct then
+  file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ else
+  table.tofile(tmaname,data,true,saveoptions)
+ end
+ utilities.lua.compile(tmaname,tmcname)
 end
 local content_state={}
 function caches.contentstate()
-  return content_state or {}
+ return content_state or {}
 end
 function caches.loadcontent(cachename,dataname,filename)
-  if not filename then
-    local name=caches.hashed(cachename)
-    local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
-    filename=file.join(path,name)
-  end
-  local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
-  if blob then
-    local data=blob()
-    if data and data.content then
-      if data.type==dataname then
-        if data.version==resolvers.cacheversion then
-          content_state[#content_state+1]=data.uuid
-          if trace_locating then
-            report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
-          end
-          return data.content
-        else
-          report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
-        end
-      else
-        report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
-      end
-    elseif trace_locating then
-      report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
+ if not filename then
+  local name=caches.hashed(cachename)
+  local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+  filename=file.join(path,name)
+ end
+ local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
+ if blob then
+  local data=blob()
+  if data and data.content then
+   if data.type==dataname then
+    if data.version==resolvers.cacheversion then
+     content_state[#content_state+1]=data.uuid
+     if trace_locating then
+      report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
+     end
+     return data.content
+    else
+     report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
     end
+   else
+    report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
+   end
   elseif trace_locating then
-    report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+   report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
   end
+ elseif trace_locating then
+  report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+ end
 end
 function caches.collapsecontent(content)
-  for k,v in next,content do
-    if type(v)=="table" and #v==1 then
-      content[k]=v[1]
-    end
+ for k,v in next,content do
+  if type(v)=="table" and #v==1 then
+   content[k]=v[1]
   end
+ end
 end
 function caches.savecontent(cachename,dataname,content,filename)
-  if not filename then
-    local name=caches.hashed(cachename)
-    local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
-    filename=file.join(path,name) 
-  end
-  local luaname=addsuffix(filename,luasuffixes.lua)
-  local lucname=addsuffix(filename,luasuffixes.luc)
+ if not filename then
+  local name=caches.hashed(cachename)
+  local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+  filename=file.join(path,name) 
+ end
+ local luaname=addsuffix(filename,luasuffixes.lua)
+ local lucname=addsuffix(filename,luasuffixes.luc)
+ if trace_locating then
+  report_resolvers("preparing %a for %a",dataname,cachename)
+ end
+ local data={
+  type=dataname,
+  root=cachename,
+  version=resolvers.cacheversion,
+  date=os.date("%Y-%m-%d"),
+  time=os.date("%H:%M:%S"),
+  content=content,
+  uuid=os.uuid(),
+ }
+ local ok=io.savedata(luaname,table.serialize(data,true))
+ if ok then
   if trace_locating then
-    report_resolvers("preparing %a for %a",dataname,cachename)
+   report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
   end
-  local data={
-    type=dataname,
-    root=cachename,
-    version=resolvers.cacheversion,
-    date=os.date("%Y-%m-%d"),
-    time=os.date("%H:%M:%S"),
-    content=content,
-    uuid=os.uuid(),
-  }
-  local ok=io.savedata(luaname,table.serialize(data,true))
-  if ok then
-    if trace_locating then
-      report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
-    end
-    if utilities.lua.compile(luaname,lucname) then
-      if trace_locating then
-        report_resolvers("%a compiled to %a",dataname,lucname)
-      end
-      return true
-    else
-      if trace_locating then
-        report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
-      end
-      os.remove(lucname)
-    end
-  elseif trace_locating then
-    report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+  if utilities.lua.compile(luaname,lucname) then
+   if trace_locating then
+    report_resolvers("%a compiled to %a",dataname,lucname)
+   end
+   return true
+  else
+   if trace_locating then
+    report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
+   end
+   os.remove(lucname)
   end
+ elseif trace_locating then
+  report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+ end
 end
 
 
@@ -17577,14 +21151,14 @@
 
 package.loaded["data-met"] = package.loaded["data-met"] or true
 
--- original size: 5310, stripped down to: 3980
+-- original size: 5310, stripped down to: 3784
 
 if not modules then modules={} end modules ['data-met']={
-  version=1.100,
-  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"
+ version=1.100,
+ 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 find,format=string.find,string.format
 local sequenced=table.sequenced
@@ -17598,86 +21172,86 @@
 local resolvers=resolvers
 local registered={}
 local function splitmethod(filename) 
-  if not filename then
-    return { scheme="unknown",original=filename }
-  end
-  if type(filename)=="table" then
-    return filename 
-  end
-  filename=file.collapsepath(filename,".") 
-  if not find(filename,"://",1,true) then
-    return { scheme="file",path=filename,original=filename,filename=filename }
-  end
-  local specification=url.hashed(filename)
-  if not specification.scheme or specification.scheme=="" then
-    return { scheme="file",path=filename,original=filename,filename=filename }
-  else
-    return specification
-  end
+ if not filename then
+  return { scheme="unknown",original=filename }
+ end
+ if type(filename)=="table" then
+  return filename 
+ end
+ filename=file.collapsepath(filename,".") 
+ if not find(filename,"://",1,true) then
+  return { scheme="file",path=filename,original=filename,filename=filename }
+ end
+ local specification=url.hashed(filename)
+ if not specification.scheme or specification.scheme=="" then
+  return { scheme="file",path=filename,original=filename,filename=filename }
+ else
+  return specification
+ end
 end
 resolvers.splitmethod=splitmethod
 local function methodhandler(what,first,...) 
-  local method=registered[what]
-  if method then
-    local how,namespace=method.how,method.namespace
-    if how=="uri" or how=="url" then
-      local specification=splitmethod(first)
-      local scheme=specification.scheme
-      local resolver=namespace and namespace[scheme]
-      if resolver then
-        if trace_methods then
-          report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
-        end
-        return resolver(specification,...)
-      else
-        resolver=namespace.default or namespace.file
-        if resolver then
-          if trace_methods then
-            report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
-          end
-          return resolver(specification,...)
-        elseif trace_methods then
-          report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
-        end
-      end
-    elseif how=="tag" then
-      local resolver=namespace and namespace[first]
-      if resolver then
-        if trace_methods then
-          report_methods("resolving, method %a, how %a, tag %a",what,how,first)
-        end
-        return resolver(...)
-      else
-        resolver=namespace.default or namespace.file
-        if resolver then
-          if trace_methods then
-            report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
-          end
-          return resolver(...)
-        elseif trace_methods then
-          report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
-        end
-      end
+ local method=registered[what]
+ if method then
+  local how,namespace=method.how,method.namespace
+  if how=="uri" or how=="url" then
+   local specification=splitmethod(first)
+   local scheme=specification.scheme
+   local resolver=namespace and namespace[scheme]
+   if resolver then
+    if trace_methods then
+     report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
     end
-  else
-    report_methods("resolving, invalid method %a")
+    return resolver(specification,...)
+   else
+    resolver=namespace.default or namespace.file
+    if resolver then
+     if trace_methods then
+      report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
+     end
+     return resolver(specification,...)
+    elseif trace_methods then
+     report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
+    end
+   end
+  elseif how=="tag" then
+   local resolver=namespace and namespace[first]
+   if resolver then
+    if trace_methods then
+     report_methods("resolving, method %a, how %a, tag %a",what,how,first)
+    end
+    return resolver(...)
+   else
+    resolver=namespace.default or namespace.file
+    if resolver then
+     if trace_methods then
+      report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
+     end
+     return resolver(...)
+    elseif trace_methods then
+     report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
+    end
+   end
   end
+ else
+  report_methods("resolving, invalid method %a")
+ end
 end
 resolvers.methodhandler=methodhandler
 function resolvers.registermethod(name,namespace,how)
-  registered[name]={ how=how or "tag",namespace=namespace }
-  namespace["byscheme"]=function(scheme,filename,...)
-    if scheme=="file" then
-      return methodhandler(name,filename,...)
-    else
-      return methodhandler(name,addurlscheme(filename,scheme),...)
-    end
+ registered[name]={ how=how or "tag",namespace=namespace }
+ namespace["byscheme"]=function(scheme,filename,...)
+  if scheme=="file" then
+   return methodhandler(name,filename,...)
+  else
+   return methodhandler(name,addurlscheme(filename,scheme),...)
   end
+ end
 end
-local concatinators=allocate { notfound=file.join    } 
-local locators=allocate { notfound=function() end } 
-local hashers=allocate { notfound=function() end } 
-local generators=allocate { notfound=function() end } 
+local concatinators=allocate { notfound=file.join    }  
+local locators=allocate { notfound=function() end  }  
+local hashers=allocate { notfound=function() end  }  
+local generators=allocate { notfound=function() end  }  
 resolvers.concatinators=concatinators
 resolvers.locators=locators
 resolvers.hashers=hashers
@@ -17695,17 +21269,17 @@
 
 package.loaded["data-res"] = package.loaded["data-res"] or true
 
--- original size: 68263, stripped down to: 47789
+-- original size: 68195, stripped down to: 43680
 
 if not modules then modules={} end modules ['data-res']={
-  version=1.001,
-  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",
+ version=1.001,
+ 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 gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
-local concat,insert,remove,sortedkeys,sortedhash=table.concat,table.insert,table.remove,table.sortedkeys,table.sortedhash
+local concat,insert,remove=table.concat,table.insert,table.remove
 local next,type,rawget=next,type,rawget
 local os=os
 local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
@@ -17727,11 +21301,11 @@
 local isdir=lfs.isdir
 local setmetatableindex=table.setmetatableindex
 local luasuffixes=utilities.lua.suffixes
-local trace_locating=false trackers .register("resolvers.locating",function(v) trace_locating=v end)
-local trace_detail=false trackers .register("resolvers.details",function(v) trace_detail=v end)
-local trace_expansions=false trackers .register("resolvers.expansions",function(v) trace_expansions=v end)
-local trace_paths=false trackers .register("resolvers.paths",function(v) trace_paths=v end)
-local resolve_otherwise=true  directives.register("resolvers.otherwise",function(v) resolve_otherwise=v end)
+local trace_locating=false  trackers  .register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false  trackers  .register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false  trackers  .register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_paths=false  trackers  .register("resolvers.paths",function(v) trace_paths=v end)
+local resolve_otherwise=true   directives.register("resolvers.otherwise",function(v) resolve_otherwise=v end)
 local report_resolving=logs.reporter("resolvers","resolving")
 local resolvers=resolvers
 local expandedpathfromlist=resolvers.expandedpathfromlist
@@ -17752,15 +21326,15 @@
 resolvers.luacnffallback="contextcnf.lua"
 resolvers.luacnfstate="unknown"
 if environment.default_texmfcnf then
-  resolvers.luacnfspec="home:texmf/web2c;"..environment.default_texmfcnf 
+ resolvers.luacnfspec="home:texmf/web2c;"..environment.default_texmfcnf 
 else
-  resolvers.luacnfspec=concat ({
-    "home:texmf/web2c",
-    "selfautoparent:/texmf-local/web2c",
-    "selfautoparent:/texmf-context/web2c",
-    "selfautoparent:/texmf-dist/web2c",
-    "selfautoparent:/texmf/web2c",
-  },";")
+ resolvers.luacnfspec=concat ({
+  "home:texmf/web2c",
+  "selfautoparent:/texmf-local/web2c",
+  "selfautoparent:/texmf-context/web2c",
+  "selfautoparent:/texmf-dist/web2c",
+  "selfautoparent:/texmf/web2c",
+ },";")
 end
 local unset_variable="unset"
 local formats=resolvers.formats
@@ -17771,24 +21345,24 @@
 resolvers.defaultsuffixes={ "tex" } 
 local instance=nil
 function resolvers.setenv(key,value,raw)
-  if instance then
-    instance.environment[key]=value
-    ossetenv(key,raw and value or resolveprefix(value))
-  end
+ if instance then
+  instance.environment[key]=value
+  ossetenv(key,raw and value or resolveprefix(value))
+ end
 end
 local function getenv(key)
-  local value=rawget(instance.environment,key)
-  if value and value~="" then
-    return value
-  else
-    local e=osgetenv(key)
-    return e~=nil and e~="" and checkedvariable(e) or ""
-  end
+ local value=rawget(instance.environment,key)
+ if value and value~="" then
+  return value
+ else
+  local e=osgetenv(key)
+  return e~=nil and e~="" and checkedvariable(e) or ""
+ end
 end
 resolvers.getenv=getenv
 resolvers.env=getenv
 local function resolvevariable(k)
-  return instance.expansions[k]
+ return instance.expansions[k]
 end
 local dollarstripper=lpeg.stripper("$")
 local inhibitstripper=P("!")^0*Cs(P(1)^0)
@@ -17802,1506 +21376,1506 @@
 local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
 local variableresolver=Cs((variable+P(1))^0)
 local function expandedvariable(var)
-  return lpegmatch(variableexpander,var) or var
+ return lpegmatch(variableexpander,var) or var
 end
 function resolvers.reset()
-  if trace_locating then
-    report_resolving("creating instance")
-  end
-  local environment={}
-  local variables={}
-  local expansions={}
-  local order={}
-  instance={
-    environment=environment,
-    variables=variables,
-    expansions=expansions,
-    order=order,
-    files={},
-    setups={},
-    found={},
-    foundintrees={},
-    hashes={},
-    hashed={},
-    pathlists=false,
-    specification={},
-    lists={},
-    data={},
-    fakepaths={},
-    remember=true,
-    diskcache=true,
-    renewcache=false,
-    renewtree=false,
-    loaderror=false,
-    savelists=true,
-    pattern=nil,
-    force_suffixes=true,
-    pathstack={},
-  }
-  setmetatableindex(variables,function(t,k)
-    local v
-    for i=1,#order do
-      v=order[i][k]
-      if v~=nil then
-        t[k]=v
-        return v
-      end
-    end
-    if v==nil then
-      v=""
-    end
+ if trace_locating then
+  report_resolving("creating instance")
+ end
+ local environment={}
+ local variables={}
+ local expansions={}
+ local order={}
+ instance={
+  environment=environment,
+  variables=variables,
+  expansions=expansions,
+  order=order,
+  files={},
+  setups={},
+  found={},
+  foundintrees={},
+  hashes={},
+  hashed={},
+  pathlists=false,
+  specification={},
+  lists={},
+  data={},
+  fakepaths={},
+  remember=true,
+  diskcache=true,
+  renewcache=false,
+  renewtree=false,
+  loaderror=false,
+  savelists=true,
+  pattern=nil,
+  force_suffixes=true,
+  pathstack={},
+ }
+ setmetatableindex(variables,function(t,k)
+  local v
+  for i=1,#order do
+   v=order[i][k]
+   if v~=nil then
     t[k]=v
     return v
-  end)
-  setmetatableindex(environment,function(t,k)
-    local v=osgetenv(k)
-    if v==nil then
-      v=variables[k]
-    end
-    if v~=nil then
-      v=checkedvariable(v) or ""
-    end
-    v=resolvers.repath(v) 
-    t[k]=v
-    return v
-  end)
-  setmetatableindex(expansions,function(t,k)
-    local v=environment[k]
-    if type(v)=="string" then
-      v=lpegmatch(variableresolver,v)
-      v=lpegmatch(variablecleaner,v)
-    end
-    t[k]=v
-    return v
-  end)
+   end
+  end
+  if v==nil then
+   v=""
+  end
+  t[k]=v
+  return v
+ end)
+ setmetatableindex(environment,function(t,k)
+  local v=osgetenv(k)
+  if v==nil then
+   v=variables[k]
+  end
+  if v~=nil then
+   v=checkedvariable(v) or ""
+  end
+  v=resolvers.repath(v) 
+  t[k]=v
+  return v
+ end)
+ setmetatableindex(expansions,function(t,k)
+  local v=environment[k]
+  if type(v)=="string" then
+   v=lpegmatch(variableresolver,v)
+   v=lpegmatch(variablecleaner,v)
+  end
+  t[k]=v
+  return v
+ end)
 end
 function resolvers.initialized()
-  return instance~=nil
+ return instance~=nil
 end
 local function reset_hashes()
-  instance.lists={}
-  instance.pathlists=false
-  instance.found={}
+ instance.lists={}
+ instance.pathlists=false
+ instance.found={}
 end
 local function reset_caches()
-  instance.lists={}
-  instance.pathlists=false
+ instance.lists={}
+ instance.pathlists=false
 end
 local slash=P("/")
 local pathexpressionpattern=Cs (
-  Cc("^")*(
-    Cc("%")*S(".-")+slash^2*P(-1)/"/.*"
+ Cc("^")*(
+  Cc("%")*S(".-")+slash^2*P(-1)/"/.*"
 +slash^2/"/"+(1-slash)*P(-1)*Cc("/")+P(1)
-  )^1*Cc("$") 
+ )^1*Cc("$") 
 )
 local cache={}
 local function makepathexpression(str)
-  if str=="." then
-    return "^%./$"
-  else
-    local c=cache[str]
-    if not c then
-      c=lpegmatch(pathexpressionpattern,str)
-      cache[str]=c
-    end
-    return c
+ if str=="." then
+  return "^%./$"
+ else
+  local c=cache[str]
+  if not c then
+   c=lpegmatch(pathexpressionpattern,str)
+   cache[str]=c
   end
+  return c
+ end
 end
 local function reportcriticalvariables(cnfspec)
-  if trace_locating then
-    for i=1,#resolvers.criticalvars do
-      local k=resolvers.criticalvars[i]
-      local v=resolvers.getenv(k) or "unknown" 
-      report_resolving("variable %a set to %a",k,v)
-    end
-    report_resolving()
-    if cnfspec then
-      report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec)
-    end
-    report_resolving()
+ if trace_locating then
+  for i=1,#resolvers.criticalvars do
+   local k=resolvers.criticalvars[i]
+   local v=resolvers.getenv(k) or "unknown" 
+   report_resolving("variable %a set to %a",k,v)
   end
-  reportcriticalvariables=function() end
+  report_resolving()
+  if cnfspec then
+   report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec)
+  end
+  report_resolving()
+ end
+ reportcriticalvariables=function() end
 end
 local function identify_configuration_files()
-  local specification=instance.specification
-  if #specification==0 then
-    local cnfspec=getenv("TEXMFCNF")
-    if cnfspec=="" then
-      cnfspec=resolvers.luacnfspec
-      resolvers.luacnfstate="default"
-    else
-      resolvers.luacnfstate="environment"
+ local specification=instance.specification
+ if #specification==0 then
+  local cnfspec=getenv("TEXMFCNF")
+  if cnfspec=="" then
+   cnfspec=resolvers.luacnfspec
+   resolvers.luacnfstate="default"
+  else
+   resolvers.luacnfstate="environment"
+  end
+  reportcriticalvariables(cnfspec)
+  local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec))
+  local function locatecnf(luacnfname,kind)
+   for i=1,#cnfpaths do
+    local filepath=cnfpaths[i]
+    local filename=collapsepath(filejoin(filepath,luacnfname))
+    local realname=resolveprefix(filename)
+    if trace_locating then
+     local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/")
+     local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
+     report_resolving("looking for %s %a on %s path %a from specification %a",
+      kind,luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
     end
-    reportcriticalvariables(cnfspec)
-    local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec))
-    local function locatecnf(luacnfname,kind)
-      for i=1,#cnfpaths do
-        local filepath=cnfpaths[i]
-        local filename=collapsepath(filejoin(filepath,luacnfname))
-        local realname=resolveprefix(filename)
-        if trace_locating then
-          local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/")
-          local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
-          report_resolving("looking for %s %a on %s path %a from specification %a",
-            kind,luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
-        end
-        if isfile(realname) then
-          specification[#specification+1]=filename 
-          if trace_locating then
-            report_resolving("found %s configuration file %a",kind,realname)
-          end
-        end
-      end
+    if isfile(realname) then
+     specification[#specification+1]=filename 
+     if trace_locating then
+      report_resolving("found %s configuration file %a",kind,realname)
+     end
     end
-    locatecnf(resolvers.luacnfname,"regular")
-    if #specification==0 then
-      locatecnf(resolvers.luacnffallback,"fallback")
-    end
-    if trace_locating then
-      report_resolving()
-    end
-  elseif trace_locating then
-    report_resolving("configuration files already identified")
+   end
   end
+  locatecnf(resolvers.luacnfname,"regular")
+  if #specification==0 then
+   locatecnf(resolvers.luacnffallback,"fallback")
+  end
+  if trace_locating then
+   report_resolving()
+  end
+ elseif trace_locating then
+  report_resolving("configuration files already identified")
+ end
 end
 local function load_configuration_files()
-  local specification=instance.specification
-  if #specification>0 then
-    local luacnfname=resolvers.luacnfname
-    for i=1,#specification do
-      local filename=specification[i]
-      local pathname=filedirname(filename)
-      local filename=filejoin(pathname,luacnfname)
-      local realname=resolveprefix(filename) 
-      local blob=loadfile(realname)
-      if blob then
-        local setups=instance.setups
-        local data=blob()
-        local parent=data and data.parent
-        if parent then
-          local filename=filejoin(pathname,parent)
-          local realname=resolveprefix(filename) 
-          local blob=loadfile(realname)
-          if blob then
-            local parentdata=blob()
-            if parentdata then
-              report_resolving("loading configuration file %a",filename)
-              data=table.merged(parentdata,data)
-            end
-          end
-        end
-        data=data and data.content
-        if data then
-          if trace_locating then
-            report_resolving("loading configuration file %a",filename)
-            report_resolving()
-          end
-          local variables=data.variables or {}
-          local warning=false
-          for k,v in next,data do
-            local variant=type(v)
-            if variant=="table" then
-              initializesetter(filename,k,v)
-            elseif variables[k]==nil then
-              if trace_locating and not warning then
-                report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
-                  k,resolveprefix(filename))
-                warning=true
-              end
-              variables[k]=v
-            end
-          end
-          setups[pathname]=variables
-          if resolvers.luacnfstate=="default" then
-            local cnfspec=variables["TEXMFCNF"]
-            if cnfspec then
-              if trace_locating then
-                report_resolving("reloading configuration due to TEXMF redefinition")
-              end
-              resolvers.setenv("TEXMFCNF",cnfspec)
-              instance.specification={}
-              identify_configuration_files()
-              load_configuration_files()
-              resolvers.luacnfstate="configuration"
-              break
-            end
-          end
-        else
-          if trace_locating then
-            report_resolving("skipping configuration file %a (no content)",filename)
-          end
-          setups[pathname]={}
-          instance.loaderror=true
-        end
-      elseif trace_locating then
-        report_resolving("skipping configuration file %a (no valid format)",filename)
+ local specification=instance.specification
+ if #specification>0 then
+  local luacnfname=resolvers.luacnfname
+  for i=1,#specification do
+   local filename=specification[i]
+   local pathname=filedirname(filename)
+   local filename=filejoin(pathname,luacnfname)
+   local realname=resolveprefix(filename) 
+   local blob=loadfile(realname)
+   if blob then
+    local setups=instance.setups
+    local data=blob()
+    local parent=data and data.parent
+    if parent then
+     local filename=filejoin(pathname,parent)
+     local realname=resolveprefix(filename) 
+     local blob=loadfile(realname)
+     if blob then
+      local parentdata=blob()
+      if parentdata then
+       report_resolving("loading configuration file %a",filename)
+       data=table.merged(parentdata,data)
       end
-      instance.order[#instance.order+1]=instance.setups[pathname]
-      if instance.loaderror then
-        break
+     end
+    end
+    data=data and data.content
+    if data then
+     if trace_locating then
+      report_resolving("loading configuration file %a",filename)
+      report_resolving()
+     end
+     local variables=data.variables or {}
+     local warning=false
+     for k,v in next,data do
+      local variant=type(v)
+      if variant=="table" then
+       initializesetter(filename,k,v)
+      elseif variables[k]==nil then
+       if trace_locating and not warning then
+        report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
+         k,resolveprefix(filename))
+        warning=true
+       end
+       variables[k]=v
       end
+     end
+     setups[pathname]=variables
+     if resolvers.luacnfstate=="default" then
+      local cnfspec=variables["TEXMFCNF"]
+      if cnfspec then
+       if trace_locating then
+        report_resolving("reloading configuration due to TEXMF redefinition")
+       end
+       resolvers.setenv("TEXMFCNF",cnfspec)
+       instance.specification={}
+       identify_configuration_files()
+       load_configuration_files()
+       resolvers.luacnfstate="configuration"
+       break
+      end
+     end
+    else
+     if trace_locating then
+      report_resolving("skipping configuration file %a (no content)",filename)
+     end
+     setups[pathname]={}
+     instance.loaderror=true
     end
-  elseif trace_locating then
-    report_resolving("warning: no lua configuration files found")
+   elseif trace_locating then
+    report_resolving("skipping configuration file %a (no valid format)",filename)
+   end
+   instance.order[#instance.order+1]=instance.setups[pathname]
+   if instance.loaderror then
+    break
+   end
   end
+ elseif trace_locating then
+  report_resolving("warning: no lua configuration files found")
+ end
 end
 function resolvers.configurationfiles()
-  return instance.specification or {}
+ return instance.specification or {}
 end
 local function load_file_databases()
-  instance.loaderror=false
-  instance.files={}
-  if not instance.renewcache then
-    local hashes=instance.hashes
-    for k=1,#hashes do
-      local hash=hashes[k]
-      resolvers.hashers.byscheme(hash.type,hash.name)
-      if instance.loaderror then break end
-    end
+ instance.loaderror=false
+ instance.files={}
+ if not instance.renewcache then
+  local hashes=instance.hashes
+  for k=1,#hashes do
+   local hash=hashes[k]
+   resolvers.hashers.byscheme(hash.type,hash.name)
+   if instance.loaderror then break end
   end
+ end
 end
 local function locate_file_databases()
-  local texmfpaths=resolvers.expandedpathlist("TEXMF")
-  if #texmfpaths>0 then
-    for i=1,#texmfpaths do
-      local path=collapsepath(texmfpaths[i])
-      path=gsub(path,"/+$","") 
-      local stripped=lpegmatch(inhibitstripper,path) 
-      if stripped~="" then
-        local runtime=stripped==path
-        path=cleanpath(path)
-        local spec=resolvers.splitmethod(stripped)
-        if runtime and (spec.noscheme or spec.scheme=="file") then
-          stripped="tree:///"..stripped
-        elseif spec.scheme=="cache" or spec.scheme=="file" then
-          stripped=spec.path
-        end
-        if trace_locating then
-          if runtime then
-            report_resolving("locating list of %a (runtime) (%s)",path,stripped)
-          else
-            report_resolving("locating list of %a (cached)",path)
-          end
-        end
-        methodhandler('locators',stripped)
-      end
+ local texmfpaths=resolvers.expandedpathlist("TEXMF")
+ if #texmfpaths>0 then
+  for i=1,#texmfpaths do
+   local path=collapsepath(texmfpaths[i])
+   path=gsub(path,"/+$","") 
+   local stripped=lpegmatch(inhibitstripper,path) 
+   if stripped~="" then
+    local runtime=stripped==path
+    path=cleanpath(path)
+    local spec=resolvers.splitmethod(stripped)
+    if runtime and (spec.noscheme or spec.scheme=="file") then
+     stripped="tree:///"..stripped
+    elseif spec.scheme=="cache" or spec.scheme=="file" then
+     stripped=spec.path
     end
     if trace_locating then
-      report_resolving()
+     if runtime then
+      report_resolving("locating list of %a (runtime) (%s)",path,stripped)
+     else
+      report_resolving("locating list of %a (cached)",path)
+     end
     end
-  elseif trace_locating then
-    report_resolving("no texmf paths are defined (using TEXMF)")
+    methodhandler('locators',stripped)
+   end
   end
-end
-local function generate_file_databases()
-  local hashes=instance.hashes
-  for k=1,#hashes do
-    local hash=hashes[k]
-    methodhandler('generators',hash.name)
-  end
   if trace_locating then
-    report_resolving()
+   report_resolving()
   end
+ elseif trace_locating then
+  report_resolving("no texmf paths are defined (using TEXMF)")
+ end
 end
+local function generate_file_databases()
+ local hashes=instance.hashes
+ for k=1,#hashes do
+  local hash=hashes[k]
+  methodhandler('generators',hash.name)
+ end
+ if trace_locating then
+  report_resolving()
+ end
+end
 local function save_file_databases() 
-  for i=1,#instance.hashes do
-    local hash=instance.hashes[i]
-    local cachename=hash.name
-    if hash.cache then
-      local content=instance.files[cachename]
-      caches.collapsecontent(content)
-      if trace_locating then
-        report_resolving("saving tree %a",cachename)
-      end
-      caches.savecontent(cachename,"files",content)
-    elseif trace_locating then
-      report_resolving("not saving runtime tree %a",cachename)
-    end
+ for i=1,#instance.hashes do
+  local hash=instance.hashes[i]
+  local cachename=hash.name
+  if hash.cache then
+   local content=instance.files[cachename]
+   caches.collapsecontent(content)
+   if trace_locating then
+    report_resolving("saving tree %a",cachename)
+   end
+   caches.savecontent(cachename,"files",content)
+  elseif trace_locating then
+   report_resolving("not saving runtime tree %a",cachename)
   end
+ end
 end
 function resolvers.renew(hashname)
-  if hashname and hashname~="" then
-    local expanded=resolvers.expansion(hashname) or ""
-    if expanded~="" then
-      if trace_locating then
-        report_resolving("identifying tree %a from %a",expanded,hashname)
-      end
-      hashname=expanded
-    else
-      if trace_locating then
-        report_resolving("identifying tree %a",hashname)
-      end
-    end
-    local realpath=resolveprefix(hashname)
-    if isdir(realpath) then
-      if trace_locating then
-        report_resolving("using path %a",realpath)
-      end
-      methodhandler('generators',hashname)
-      local content=instance.files[hashname]
-      caches.collapsecontent(content)
-      if trace_locating then
-        report_resolving("saving tree %a",hashname)
-      end
-      caches.savecontent(hashname,"files",content)
-    else
-      report_resolving("invalid path %a",realpath)
-    end
+ if hashname and hashname~="" then
+  local expanded=resolvers.expansion(hashname) or ""
+  if expanded~="" then
+   if trace_locating then
+    report_resolving("identifying tree %a from %a",expanded,hashname)
+   end
+   hashname=expanded
+  else
+   if trace_locating then
+    report_resolving("identifying tree %a",hashname)
+   end
   end
+  local realpath=resolveprefix(hashname)
+  if isdir(realpath) then
+   if trace_locating then
+    report_resolving("using path %a",realpath)
+   end
+   methodhandler('generators',hashname)
+   local content=instance.files[hashname]
+   caches.collapsecontent(content)
+   if trace_locating then
+    report_resolving("saving tree %a",hashname)
+   end
+   caches.savecontent(hashname,"files",content)
+  else
+   report_resolving("invalid path %a",realpath)
+  end
+ end
 end
 local function load_databases()
-  locate_file_databases()
-  if instance.diskcache and not instance.renewcache then
-    load_file_databases()
-    if instance.loaderror then
-      generate_file_databases()
-      save_file_databases()
-    end
-  else
-    generate_file_databases()
-    if instance.renewcache then
-      save_file_databases()
-    end
+ locate_file_databases()
+ if instance.diskcache and not instance.renewcache then
+  load_file_databases()
+  if instance.loaderror then
+   generate_file_databases()
+   save_file_databases()
   end
+ else
+  generate_file_databases()
+  if instance.renewcache then
+   save_file_databases()
+  end
+ end
 end
 function resolvers.appendhash(type,name,cache)
-  if not instance.hashed[name] then
-    if trace_locating then
-      report_resolving("hash %a appended",name)
-    end
-    insert(instance.hashes,{ type=type,name=name,cache=cache } )
-    instance.hashed[name]=cache
+ if not instance.hashed[name] then
+  if trace_locating then
+   report_resolving("hash %a appended",name)
   end
+  insert(instance.hashes,{ type=type,name=name,cache=cache } )
+  instance.hashed[name]=cache
+ end
 end
 function resolvers.prependhash(type,name,cache)
-  if not instance.hashed[name] then
-    if trace_locating then
-      report_resolving("hash %a prepended",name)
-    end
-    insert(instance.hashes,1,{ type=type,name=name,cache=cache } )
-    instance.hashed[name]=cache
+ if not instance.hashed[name] then
+  if trace_locating then
+   report_resolving("hash %a prepended",name)
   end
+  insert(instance.hashes,1,{ type=type,name=name,cache=cache } )
+  instance.hashed[name]=cache
+ end
 end
 function resolvers.extendtexmfvariable(specification) 
-  local t=resolvers.splitpath(getenv("TEXMF")) 
-  insert(t,1,specification)
-  local newspec=concat(t,",") 
-  if instance.environment["TEXMF"] then
-    instance.environment["TEXMF"]=newspec
-  elseif instance.variables["TEXMF"] then
-    instance.variables["TEXMF"]=newspec
-  else
-  end
-  reset_hashes()
+ local t=resolvers.splitpath(getenv("TEXMF")) 
+ insert(t,1,specification)
+ local newspec=concat(t,",") 
+ if instance.environment["TEXMF"] then
+  instance.environment["TEXMF"]=newspec
+ elseif instance.variables["TEXMF"] then
+  instance.variables["TEXMF"]=newspec
+ else
+ end
+ reset_hashes()
 end
 function resolvers.splitexpansions()
-  local ie=instance.expansions
-  for k,v in next,ie do
-    local t,tn,h,p={},0,{},splitconfigurationpath(v)
-    for kk=1,#p do
-      local vv=p[kk]
-      if vv~="" and not h[vv] then
-        tn=tn+1
-        t[tn]=vv
-        h[vv]=true
-      end
-    end
-    if #t>1 then
-      ie[k]=t
-    else
-      ie[k]=t[1]
-    end
+ local ie=instance.expansions
+ for k,v in next,ie do
+  local t,tn,h,p={},0,{},splitconfigurationpath(v)
+  for kk=1,#p do
+   local vv=p[kk]
+   if vv~="" and not h[vv] then
+    tn=tn+1
+    t[tn]=vv
+    h[vv]=true
+   end
   end
+  if #t>1 then
+   ie[k]=t
+  else
+   ie[k]=t[1]
+  end
+ end
 end
 function resolvers.datastate()
-  return caches.contentstate()
+ return caches.contentstate()
 end
 function resolvers.variable(name)
-  local name=name and lpegmatch(dollarstripper,name)
-  local result=name and instance.variables[name]
-  return result~=nil and result or ""
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.variables[name]
+ return result~=nil and result or ""
 end
 function resolvers.expansion(name)
-  local name=name and lpegmatch(dollarstripper,name)
-  local result=name and instance.expansions[name]
-  return result~=nil and result or ""
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.expansions[name]
+ return result~=nil and result or ""
 end
 function resolvers.unexpandedpathlist(str)
-  local pth=resolvers.variable(str)
-  local lst=resolvers.splitpath(pth)
-  return expandedpathfromlist(lst)
+ local pth=resolvers.variable(str)
+ local lst=resolvers.splitpath(pth)
+ return expandedpathfromlist(lst)
 end
 function resolvers.unexpandedpath(str)
-  return joinpath(resolvers.unexpandedpathlist(str))
+ return joinpath(resolvers.unexpandedpathlist(str))
 end
 function resolvers.pushpath(name)
-  local pathstack=instance.pathstack
-  local lastpath=pathstack[#pathstack]
-  local pluspath=filedirname(name)
-  if lastpath then
-    lastpath=collapsepath(filejoin(lastpath,pluspath))
-  else
-    lastpath=collapsepath(pluspath)
-  end
-  insert(pathstack,lastpath)
-  if trace_paths then
-    report_resolving("pushing path %a",lastpath)
-  end
+ local pathstack=instance.pathstack
+ local lastpath=pathstack[#pathstack]
+ local pluspath=filedirname(name)
+ if lastpath then
+  lastpath=collapsepath(filejoin(lastpath,pluspath))
+ else
+  lastpath=collapsepath(pluspath)
+ end
+ insert(pathstack,lastpath)
+ if trace_paths then
+  report_resolving("pushing path %a",lastpath)
+ end
 end
 function resolvers.poppath()
-  local pathstack=instance.pathstack
-  if trace_paths and #pathstack>0 then
-    report_resolving("popping path %a",pathstack[#pathstack])
-  end
-  remove(pathstack)
+ local pathstack=instance.pathstack
+ if trace_paths and #pathstack>0 then
+  report_resolving("popping path %a",pathstack[#pathstack])
+ end
+ remove(pathstack)
 end
 function resolvers.stackpath()
-  local pathstack=instance.pathstack
-  local currentpath=pathstack[#pathstack]
-  return currentpath~="" and currentpath or nil
+ local pathstack=instance.pathstack
+ local currentpath=pathstack[#pathstack]
+ return currentpath~="" and currentpath or nil
 end
 local done={}
 function resolvers.resetextrapaths()
-  local ep=instance.extra_paths
-  if not ep then
-    done={}
-    instance.extra_paths={}
-  elseif #ep>0 then
-    done={}
-    reset_caches()
-  end
+ local ep=instance.extra_paths
+ if not ep then
+  done={}
+  instance.extra_paths={}
+ elseif #ep>0 then
+  done={}
+  reset_caches()
+ end
 end
 function resolvers.getextrapaths()
-  return instance.extra_paths or {}
+ return instance.extra_paths or {}
 end
 function resolvers.registerextrapath(paths,subpaths)
-  if not subpaths or subpaths=="" then
-    if not paths or path=="" then
-      return 
-    elseif done[paths] then
-      return 
-    end
+ if not subpaths or subpaths=="" then
+  if not paths or path=="" then
+   return 
+  elseif done[paths] then
+   return 
   end
-  local paths=settings_to_array(paths)
-  local subpaths=settings_to_array(subpaths)
-  local ep=instance.extra_paths or {}
-  local oldn=#ep
-  local newn=oldn
-  local nofpaths=#paths
-  local nofsubpaths=#subpaths
-  if nofpaths>0 then
-    if nofsubpaths>0 then
-      for i=1,nofpaths do
-        local p=paths[i]
-        for j=1,nofsubpaths do
-          local s=subpaths[j]
-          local ps=p.."/"..s
-          if not done[ps] then
-            newn=newn+1
-            ep[newn]=cleanpath(ps)
-            done[ps]=true
-          end
-        end
-      end
-    else
-      for i=1,nofpaths do
-        local p=paths[i]
-        if not done[p] then
-          newn=newn+1
-          ep[newn]=cleanpath(p)
-          done[p]=true
-        end
-      end
+ end
+ local paths=settings_to_array(paths)
+ local subpaths=settings_to_array(subpaths)
+ local ep=instance.extra_paths or {}
+ local oldn=#ep
+ local newn=oldn
+ local nofpaths=#paths
+ local nofsubpaths=#subpaths
+ if nofpaths>0 then
+  if nofsubpaths>0 then
+   for i=1,nofpaths do
+    local p=paths[i]
+    for j=1,nofsubpaths do
+     local s=subpaths[j]
+     local ps=p.."/"..s
+     if not done[ps] then
+      newn=newn+1
+      ep[newn]=cleanpath(ps)
+      done[ps]=true
+     end
     end
-  elseif nofsubpaths>0 then
-    for i=1,oldn do
-      for j=1,nofsubpaths do
-        local s=subpaths[j]
-        local ps=ep[i].."/"..s
-        if not done[ps] then
-          newn=newn+1
-          ep[newn]=cleanpath(ps)
-          done[ps]=true
-        end
-      end
+   end
+  else
+   for i=1,nofpaths do
+    local p=paths[i]
+    if not done[p] then
+     newn=newn+1
+     ep[newn]=cleanpath(p)
+     done[p]=true
     end
+   end
   end
-  if newn>0 then
-    instance.extra_paths=ep 
+ elseif nofsubpaths>0 then
+  for i=1,oldn do
+   for j=1,nofsubpaths do
+    local s=subpaths[j]
+    local ps=ep[i].."/"..s
+    if not done[ps] then
+     newn=newn+1
+     ep[newn]=cleanpath(ps)
+     done[ps]=true
+    end
+   end
   end
-  if newn~=oldn then
-    reset_caches()
-  end
+ end
+ if newn>0 then
+  instance.extra_paths=ep 
+ end
+ if newn~=oldn then
+  reset_caches()
+ end
 end
 function resolvers.pushextrapath(path)
-  local paths=settings_to_array(path)
-  if instance.extra_stack then
-    insert(instance.extra_stack,1,paths)
-  else
-    instance.extra_stack={ paths }
-  end
-  reset_caches()
+ local paths=settings_to_array(path)
+ if instance.extra_stack then
+  insert(instance.extra_stack,1,paths)
+ else
+  instance.extra_stack={ paths }
+ end
+ reset_caches()
 end
 function resolvers.popextrapath()
-  if instance.extra_stack then
-    reset_caches()
-    return remove(instance.extra_stack,1)
-  end
+ if instance.extra_stack then
+  reset_caches()
+  return remove(instance.extra_stack,1)
+ end
 end
 local function made_list(instance,list,extra_too)
-  local done={}
-  local new={}
-  local newn=0
-  local function add(p)
-    for k=1,#p do
-      local v=p[k]
-      if not done[v] then
-        done[v]=true
-        newn=newn+1
-        new[newn]=v
-      end
-    end
+ local done={}
+ local new={}
+ local newn=0
+ local function add(p)
+  for k=1,#p do
+   local v=p[k]
+   if not done[v] then
+    done[v]=true
+    newn=newn+1
+    new[newn]=v
+   end
   end
-  for k=1,#list do
-    local v=list[k]
-    if done[v] then
-    elseif find(v,"^[%.%/]$") then
-      done[v]=true
-      newn=newn+1
-      new[newn]=v
-    else
-      break
-    end
+ end
+ for k=1,#list do
+  local v=list[k]
+  if done[v] then
+  elseif find(v,"^[%.%/]$") then
+   done[v]=true
+   newn=newn+1
+   new[newn]=v
+  else
+   break
   end
-  if extra_too then
-    local es=instance.extra_stack
-    if es and #es>0 then
-      for k=1,#es do
-        add(es[k])
-      end
-    end
-    local ep=instance.extra_paths
-    if ep and #ep>0 then
-      add(ep)
-    end
+ end
+ if extra_too then
+  local es=instance.extra_stack
+  if es and #es>0 then
+   for k=1,#es do
+    add(es[k])
+   end
   end
-  add(list)
-  return new
+  local ep=instance.extra_paths
+  if ep and #ep>0 then
+   add(ep)
+  end
+ end
+ add(list)
+ return new
 end
 function resolvers.cleanpathlist(str)
-  local t=resolvers.expandedpathlist(str)
-  if t then
-    for i=1,#t do
-      t[i]=collapsepath(cleanpath(t[i]))
-    end
+ local t=resolvers.expandedpathlist(str)
+ if t then
+  for i=1,#t do
+   t[i]=collapsepath(cleanpath(t[i]))
   end
-  return t
+ end
+ return t
 end
 function resolvers.expandpath(str)
-  return joinpath(resolvers.expandedpathlist(str))
+ return joinpath(resolvers.expandedpathlist(str))
 end
 function resolvers.expandedpathlist(str,extra_too)
-  if not str then
-    return {}
-  elseif instance.savelists then 
-    str=lpegmatch(dollarstripper,str)
-    local lists=instance.lists
-    local lst=lists[str]
-    if not lst then
-      local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
-      lst=expandedpathfromlist(l)
-      lists[str]=lst
-    end
-    return lst
-  else
-    local lst=resolvers.splitpath(resolvers.expansion(str))
-    return made_list(instance,expandedpathfromlist(lst),extra_too)
+ if not str then
+  return {}
+ elseif instance.savelists then 
+  str=lpegmatch(dollarstripper,str)
+  local lists=instance.lists
+  local lst=lists[str]
+  if not lst then
+   local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
+   lst=expandedpathfromlist(l)
+   lists[str]=lst
   end
+  return lst
+ else
+  local lst=resolvers.splitpath(resolvers.expansion(str))
+  return made_list(instance,expandedpathfromlist(lst),extra_too)
+ end
 end
 function resolvers.expandedpathlistfromvariable(str) 
-  str=lpegmatch(dollarstripper,str)
-  local tmp=resolvers.variableofformatorsuffix(str)
-  return resolvers.expandedpathlist(tmp~="" and tmp or str)
+ str=lpegmatch(dollarstripper,str)
+ local tmp=resolvers.variableofformatorsuffix(str)
+ return resolvers.expandedpathlist(tmp~="" and tmp or str)
 end
 function resolvers.expandpathfromvariable(str)
-  return joinpath(resolvers.expandedpathlistfromvariable(str))
+ return joinpath(resolvers.expandedpathlistfromvariable(str))
 end
 function resolvers.cleanedpathlist(v) 
-  local t=resolvers.expandedpathlist(v)
-  for i=1,#t do
-    t[i]=resolvers.resolve(resolvers.cleanpath(t[i]))
-  end
-  return t
+ local t=resolvers.expandedpathlist(v)
+ for i=1,#t do
+  t[i]=resolvers.resolve(resolvers.cleanpath(t[i]))
+ end
+ return t
 end
 function resolvers.expandbraces(str) 
-  local pth=expandedpathfromlist(resolvers.splitpath(str))
-  return joinpath(pth)
+ local pth=expandedpathfromlist(resolvers.splitpath(str))
+ return joinpath(pth)
 end
 function resolvers.registerfilehash(name,content,someerror)
-  if content then
-    instance.files[name]=content
-  else
-    instance.files[name]={}
-    if somerror==true then 
-      instance.loaderror=someerror
-    end
+ if content then
+  instance.files[name]=content
+ else
+  instance.files[name]={}
+  if somerror==true then 
+   instance.loaderror=someerror
   end
+ end
 end
 function resolvers.getfilehashes()
-  return instance and instance.files or {}
+ return instance and instance.files or {}
 end
 function resolvers.gethashes()
-  return instance and instance.hashes or {}
+ return instance and instance.hashes or {}
 end
 function resolvers.renewcache()
-  if instance then
-    instance.renewcache=true
-  end
+ if instance then
+  instance.renewcache=true
+ end
 end
 local function isreadable(name)
-  local readable=isfile(name) 
-  if trace_detail then
-    if readable then
-      report_resolving("file %a is readable",name)
-    else
-      report_resolving("file %a is not readable",name)
-    end
+ local readable=isfile(name) 
+ if trace_detail then
+  if readable then
+   report_resolving("file %a is readable",name)
+  else
+   report_resolving("file %a is not readable",name)
   end
-  return readable
+ end
+ return readable
 end
 local function collect_files(names) 
-  local filelist={}      
-  local noffiles=0
-  local function check(hash,root,pathname,path,basename,name)
-    if not pathname or find(path,pathname) then
-      local variant=hash.type
-      local search=filejoin(root,path,name) 
-      local result=methodhandler('concatinators',variant,root,path,name)
-      if trace_detail then
-        report_resolving("match: variant %a, search %a, result %a",variant,search,result)
-      end
-      noffiles=noffiles+1
-      filelist[noffiles]={ variant,search,result }
-    end
+ local filelist={}   
+ local noffiles=0
+ local function check(hash,root,pathname,path,basename,name)
+  if not pathname or find(path,pathname) then
+   local variant=hash.type
+   local search=filejoin(root,path,name) 
+   local result=methodhandler('concatinators',variant,root,path,name)
+   if trace_detail then
+    report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+   end
+   noffiles=noffiles+1
+   filelist[noffiles]={ variant,search,result }
   end
-  for k=1,#names do
-    local filename=names[k]
+ end
+ for k=1,#names do
+  local filename=names[k]
+  if trace_detail then
+   report_resolving("checking name %a",filename)
+  end
+  local basename=filebasename(filename)
+  local pathname=filedirname(filename)
+  if pathname=="" or find(pathname,"^%.") then
+   pathname=false
+  else
+   pathname=gsub(pathname,"%*",".*")
+   pathname="/"..pathname.."$"
+  end
+  local hashes=instance.hashes
+  for h=1,#hashes do
+   local hash=hashes[h]
+   local hashname=hash.name
+   local content=hashname and instance.files[hashname]
+   if content then
     if trace_detail then
-      report_resolving("checking name %a",filename)
+     report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
     end
-    local basename=filebasename(filename)
-    local pathname=filedirname(filename)
-    if pathname=="" or find(pathname,"^%.") then
-      pathname=false
-    else
-      pathname=gsub(pathname,"%*",".*")
-      pathname="/"..pathname.."$"
-    end
-    local hashes=instance.hashes
-    for h=1,#hashes do
-      local hash=hashes[h]
-      local hashname=hash.name
-      local content=hashname and instance.files[hashname]
-      if content then
-        if trace_detail then
-          report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
-        end
-        local path,name=lookup(content,basename)
-        if path then
-          local metadata=content.metadata
-          local realroot=metadata and metadata.path or hashname
-          if type(path)=="string" then
-            check(hash,realroot,pathname,path,basename,name)
-          else
-            for i=1,#path do
-              check(hash,realroot,pathname,path[i],basename,name)
-            end
-          end
-        end
-      elseif trace_locating then
-        report_resolving("no match in %a (%s)",hashname,basename)
+    local path,name=lookup(content,basename)
+    if path then
+     local metadata=content.metadata
+     local realroot=metadata and metadata.path or hashname
+     if type(path)=="string" then
+      check(hash,realroot,pathname,path,basename,name)
+     else
+      for i=1,#path do
+       check(hash,realroot,pathname,path[i],basename,name)
       end
+     end
     end
+   elseif trace_locating then
+    report_resolving("no match in %a (%s)",hashname,basename)
+   end
   end
-  return noffiles>0 and filelist or nil
+ end
+ return noffiles>0 and filelist or nil
 end
 local fit={}
 function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
-  local foundintrees=instance.foundintrees
-  if usedmethod=="direct" and filename==foundname and fit[foundname] then
-  else
-    local collapsed=collapsepath(foundname,true)
-    local t={
-      filename=filename,
-      format=format~="" and format  or nil,
-      filetype=filetype~="" and filetype or nil,
-      usedmethod=usedmethod,
-      foundname=foundname,
-      fullname=collapsed,
-    }
-    fit[foundname]=t
-    foundintrees[#foundintrees+1]=t
-  end
+ local foundintrees=instance.foundintrees
+ if usedmethod=="direct" and filename==foundname and fit[foundname] then
+ else
+  local collapsed=collapsepath(foundname,true)
+  local t={
+   filename=filename,
+   format=format~="" and format   or nil,
+   filetype=filetype~="" and filetype or nil,
+   usedmethod=usedmethod,
+   foundname=foundname,
+   fullname=collapsed,
+  }
+  fit[foundname]=t
+  foundintrees[#foundintrees+1]=t
+ end
 end
 function resolvers.foundintrees()
-  return instance.foundintrees or {}
+ return instance.foundintrees or {}
 end
 function resolvers.foundintree(fullname)
-  local f=fit[fullname]
-  return f and f.usedmethod=="database"
+ local f=fit[fullname]
+ return f and f.usedmethod=="database"
 end
 local function can_be_dir(name) 
-  local fakepaths=instance.fakepaths
-  if not fakepaths[name] then
-    if isdir(name) then
-      fakepaths[name]=1 
-    else
-      fakepaths[name]=2 
-    end
+ local fakepaths=instance.fakepaths
+ if not fakepaths[name] then
+  if isdir(name) then
+   fakepaths[name]=1 
+  else
+   fakepaths[name]=2 
   end
-  return fakepaths[name]==1
+ end
+ return fakepaths[name]==1
 end
 local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$"))
 local collect_instance_files
 local function find_analyze(filename,askedformat,allresults)
-  local filetype=''
-  local filesuffix=suffixonly(filename)
-  local wantedfiles={}
-  wantedfiles[#wantedfiles+1]=filename
-  if askedformat=="" then
-    if filesuffix=="" or not suffixmap[filesuffix] then
-      local defaultsuffixes=resolvers.defaultsuffixes
-      local formatofsuffix=resolvers.formatofsuffix
-      for i=1,#defaultsuffixes do
-        local forcedname=filename..'.'..defaultsuffixes[i]
-        wantedfiles[#wantedfiles+1]=forcedname
-        filetype=formatofsuffix(forcedname)
-        if trace_locating then
-          report_resolving("forcing filetype %a",filetype)
-        end
-      end
-    else
-      filetype=resolvers.formatofsuffix(filename)
-      if trace_locating then
-        report_resolving("using suffix based filetype %a",filetype)
-      end
+ local filetype=''
+ local filesuffix=suffixonly(filename)
+ local wantedfiles={}
+ wantedfiles[#wantedfiles+1]=filename
+ if askedformat=="" then
+  if filesuffix=="" or not suffixmap[filesuffix] then
+   local defaultsuffixes=resolvers.defaultsuffixes
+   local formatofsuffix=resolvers.formatofsuffix
+   for i=1,#defaultsuffixes do
+    local forcedname=filename..'.'..defaultsuffixes[i]
+    wantedfiles[#wantedfiles+1]=forcedname
+    filetype=formatofsuffix(forcedname)
+    if trace_locating then
+     report_resolving("forcing filetype %a",filetype)
     end
+   end
   else
-    if filesuffix=="" or not suffixmap[filesuffix] then
-      local format_suffixes=suffixes[askedformat]
-      if format_suffixes then
-        for i=1,#format_suffixes do
-          wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i]
-        end
-      end
+   filetype=resolvers.formatofsuffix(filename)
+   if trace_locating then
+    report_resolving("using suffix based filetype %a",filetype)
+   end
+  end
+ else
+  if filesuffix=="" or not suffixmap[filesuffix] then
+   local format_suffixes=suffixes[askedformat]
+   if format_suffixes then
+    for i=1,#format_suffixes do
+     wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i]
     end
-    filetype=askedformat
-    if trace_locating then
-      report_resolving("using given filetype %a",filetype)
-    end
+   end
   end
-  return filetype,wantedfiles
+  filetype=askedformat
+  if trace_locating then
+   report_resolving("using given filetype %a",filetype)
+  end
+ end
+ return filetype,wantedfiles
 end
 local function find_direct(filename,allresults)
-  if not dangerous[askedformat] and isreadable(filename) then
-    if trace_detail then
-      report_resolving("file %a found directly",filename)
-    end
-    return "direct",{ filename }
+ if not dangerous[askedformat] and isreadable(filename) then
+  if trace_detail then
+   report_resolving("file %a found directly",filename)
   end
+  return "direct",{ filename }
+ end
 end
 local function find_wildcard(filename,allresults)
-  if find(filename,'*',1,true) then
-    if trace_locating then
-      report_resolving("checking wildcard %a",filename)
-    end
-    local result=resolvers.findwildcardfiles(filename)
-    if result then
-      return "wildcard",result
-    end
+ if find(filename,'*',1,true) then
+  if trace_locating then
+   report_resolving("checking wildcard %a",filename)
   end
+  local result=resolvers.findwildcardfiles(filename)
+  if result then
+   return "wildcard",result
+  end
+ end
 end
 local function find_qualified(filename,allresults,askedformat,alsostripped) 
-  if not is_qualified_path(filename) then
-    return
+ if not is_qualified_path(filename) then
+  return
+ end
+ if trace_locating then
+  report_resolving("checking qualified name %a",filename)
+ end
+ if isreadable(filename) then
+  if trace_detail then
+   report_resolving("qualified file %a found",filename)
   end
-  if trace_locating then
-    report_resolving("checking qualified name %a",filename)
-  end
-  if isreadable(filename) then
-    if trace_detail then
-      report_resolving("qualified file %a found",filename)
+  return "qualified",{ filename }
+ end
+ if trace_detail then
+  report_resolving("locating qualified file %a",filename)
+ end
+ local forcedname,suffix="",suffixonly(filename)
+ if suffix=="" then 
+  local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat]
+  if format_suffixes then
+   for i=1,#format_suffixes do
+    local s=format_suffixes[i]
+    forcedname=filename.."."..s
+    if isreadable(forcedname) then
+     if trace_locating then
+      report_resolving("no suffix, forcing format filetype %a",s)
+     end
+     return "qualified",{ forcedname }
     end
-    return "qualified",{ filename }
+   end
   end
-  if trace_detail then
-    report_resolving("locating qualified file %a",filename)
+ end
+ if alsostripped and suffix and suffix~="" then
+  local basename=filebasename(filename)
+  local pattern=lpegmatch(preparetreepattern,filename)
+  local savedformat=askedformat
+  local format=savedformat or ""
+  if format=="" then
+   askedformat=resolvers.formatofsuffix(suffix)
   end
-  local forcedname,suffix="",suffixonly(filename)
-  if suffix=="" then 
-    local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat]
-    if format_suffixes then
-      for i=1,#format_suffixes do
-        local s=format_suffixes[i]
-        forcedname=filename.."."..s
-        if isreadable(forcedname) then
-          if trace_locating then
-            report_resolving("no suffix, forcing format filetype %a",s)
-          end
-          return "qualified",{ forcedname }
-        end
-      end
-    end
+  if not format then
+   askedformat="othertextfiles" 
   end
-  if alsostripped and suffix and suffix~="" then
-    local basename=filebasename(filename)
-    local pattern=lpegmatch(preparetreepattern,filename)
-    local savedformat=askedformat
-    local format=savedformat or ""
-    if format=="" then
-      askedformat=resolvers.formatofsuffix(suffix)
+  if basename~=filename then
+   local resolved=collect_instance_files(basename,askedformat,allresults)
+   if #resolved==0 then
+    local lowered=lower(basename)
+    if filename~=lowered then
+     resolved=collect_instance_files(lowered,askedformat,allresults)
     end
-    if not format then
-      askedformat="othertextfiles" 
+   end
+   resolvers.format=savedformat
+   if #resolved>0 then
+    local result={}
+    for r=1,#resolved do
+     local rr=resolved[r]
+     if find(rr,pattern) then
+      result[#result+1]=rr
+     end
     end
-    if basename~=filename then
-      local resolved=collect_instance_files(basename,askedformat,allresults)
-      if #resolved==0 then
-        local lowered=lower(basename)
-        if filename~=lowered then
-          resolved=collect_instance_files(lowered,askedformat,allresults)
-        end
-      end
-      resolvers.format=savedformat
-      if #resolved>0 then
-        local result={}
-        for r=1,#resolved do
-          local rr=resolved[r]
-          if find(rr,pattern) then
-            result[#result+1]=rr
-          end
-        end
-        if #result>0 then
-          return "qualified",result
-        end
-      end
+    if #result>0 then
+     return "qualified",result
     end
+   end
   end
+ end
 end
 local function check_subpath(fname)
-  if isreadable(fname) then
-    if trace_detail then
-      report_resolving("found %a by deep scanning",fname)
-    end
-    return fname
+ if isreadable(fname) then
+  if trace_detail then
+   report_resolving("found %a by deep scanning",fname)
   end
+  return fname
+ end
 end
 local function makepathlist(list,filetype)
-  local typespec=resolvers.variableofformat(filetype)
-  local pathlist=resolvers.expandedpathlist(typespec,filetype and usertypes[filetype]) 
-  local entry={}
-  if pathlist and #pathlist>0 then
-    for k=1,#pathlist do
-      local path=pathlist[k]
-      local prescanned=find(path,'^!!')
-      local resursive=find(path,'//$')
-      local pathname=lpegmatch(inhibitstripper,path)
-      local expression=makepathexpression(pathname)
-      local barename=gsub(pathname,"/+$","")
-      barename=resolveprefix(barename)
-      local scheme=url.hasscheme(barename)
-      local schemename=gsub(barename,"%.%*$",'')
-      entry[k]={
-        path=path,
-        pathname=pathname,
-        prescanned=prescanned,
-        recursive=recursive,
-        expression=expression,
-        barename=barename,
-        scheme=scheme,
-        schemename=schemename,
-      }
-    end
-    entry.typespec=typespec
-    list[filetype]=entry
-  else
-    list[filetype]=false
+ local typespec=resolvers.variableofformat(filetype)
+ local pathlist=resolvers.expandedpathlist(typespec,filetype and usertypes[filetype]) 
+ local entry={}
+ if pathlist and #pathlist>0 then
+  for k=1,#pathlist do
+   local path=pathlist[k]
+   local prescanned=find(path,'^!!')
+   local resursive=find(path,'//$')
+   local pathname=lpegmatch(inhibitstripper,path)
+   local expression=makepathexpression(pathname)
+   local barename=gsub(pathname,"/+$","")
+   barename=resolveprefix(barename)
+   local scheme=url.hasscheme(barename)
+   local schemename=gsub(barename,"%.%*$",'')
+   entry[k]={
+    path=path,
+    pathname=pathname,
+    prescanned=prescanned,
+    recursive=recursive,
+    expression=expression,
+    barename=barename,
+    scheme=scheme,
+    schemename=schemename,
+   }
   end
-  return entry
+  entry.typespec=typespec
+  list[filetype]=entry
+ else
+  list[filetype]=false
+ end
+ return entry
 end
 local function find_intree(filename,filetype,wantedfiles,allresults)
-  local pathlists=instance.pathlists
-  if not pathlists then
-    pathlists=setmetatableindex({},makepathlist)
-    instance.pathlists=pathlists
+ local pathlists=instance.pathlists
+ if not pathlists then
+  pathlists=setmetatableindex({},makepathlist)
+  instance.pathlists=pathlists
+ end
+ local pathlist=pathlists[filetype]
+ if pathlist then
+  local method="intree"
+  local filelist=collect_files(wantedfiles) 
+  local dirlist={}
+  local result={}
+  if filelist then
+   for i=1,#filelist do
+    dirlist[i]=filedirname(filelist[i][3]).."/" 
+   end
   end
-  local pathlist=pathlists[filetype]
-  if pathlist then
-    local method="intree"
-    local filelist=collect_files(wantedfiles) 
-    local dirlist={}
-    local result={}
-    if filelist then
-      for i=1,#filelist do
-        dirlist[i]=filedirname(filelist[i][3]).."/" 
+  if trace_detail then
+   report_resolving("checking filename %a in tree",filename)
+  end
+  for k=1,#pathlist do
+   local entry=pathlist[k]
+   local path=entry.path
+   local pathname=entry.pathname
+   local done=false
+   if filelist then
+    local expression=entry.expression
+    if trace_detail then
+     report_resolving("using pattern %a for path %a",expression,pathname)
+    end
+    for k=1,#filelist do
+     local fl=filelist[k]
+     local f=fl[2]
+     local d=dirlist[k]
+     if find(d,expression) or find(resolveprefix(d),expression) then
+      result[#result+1]=resolveprefix(fl[3]) 
+      done=true
+      if allresults then
+       if trace_detail then
+        report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
+       end
+      else
+       if trace_detail then
+        report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
+       end
+       break
       end
+     elseif trace_detail then
+      report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+     end
     end
-    if trace_detail then
-      report_resolving("checking filename %a in tree",filename)
-    end
-    for k=1,#pathlist do
-      local entry=pathlist[k]
-      local path=entry.path
-      local pathname=entry.pathname
-      local done=false
-      if filelist then
-        local expression=entry.expression
+   end
+   if done then
+    method="database"
+   else
+    method="filesystem" 
+    local scheme=entry.scheme
+    if not scheme or scheme=="file" then
+     local pname=entry.schemename
+     if not find(pname,"*",1,true) then
+      if can_be_dir(pname) then
+       if not done and not entry.prescanned then
         if trace_detail then
-          report_resolving("using pattern %a for path %a",expression,pathname)
+         report_resolving("quick root scan for %a",pname)
         end
-        for k=1,#filelist do
-          local fl=filelist[k]
-          local f=fl[2]
-          local d=dirlist[k]
-          if find(d,expression) or find(resolveprefix(d),expression) then
-            result[#result+1]=resolveprefix(fl[3]) 
-            done=true
-            if allresults then
-              if trace_detail then
-                report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
-              end
-            else
-              if trace_detail then
-                report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
-              end
-              break
-            end
-          elseif trace_detail then
-            report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+        for k=1,#wantedfiles do
+         local w=wantedfiles[k]
+         local fname=check_subpath(filejoin(pname,w))
+         if fname then
+          result[#result+1]=fname
+          done=true
+          if not allresults then
+           break
           end
+         end
         end
-      end
-      if done then
-        method="database"
-      else
-        method="filesystem" 
-        local scheme=entry.scheme
-        if not scheme or scheme=="file" then
-          local pname=entry.schemename
-          if not find(pname,"*",1,true) then
-            if can_be_dir(pname) then
-              if not done and not entry.prescanned then
-                if trace_detail then
-                  report_resolving("quick root scan for %a",pname)
-                end
-                for k=1,#wantedfiles do
-                  local w=wantedfiles[k]
-                  local fname=check_subpath(filejoin(pname,w))
-                  if fname then
-                    result[#result+1]=fname
-                    done=true
-                    if not allresults then
-                      break
-                    end
-                  end
-                end
-                if not done and entry.recursive then
-                  if trace_detail then
-                    report_resolving("scanning filesystem for %a",pname)
-                  end
-                  local files=resolvers.simplescanfiles(pname,false,true)
-                  for k=1,#wantedfiles do
-                    local w=wantedfiles[k]
-                    local subpath=files[w]
-                    if not subpath or subpath=="" then
-                    elseif type(subpath)=="string" then
-                      local fname=check_subpath(filejoin(pname,subpath,w))
-                      if fname then
-                        result[#result+1]=fname
-                        done=true
-                        if not allresults then
-                          break
-                        end
-                      end
-                    else
-                      for i=1,#subpath do
-                        local sp=subpath[i]
-                        if sp=="" then
-                        else
-                          local fname=check_subpath(filejoin(pname,sp,w))
-                          if fname then
-                            result[#result+1]=fname
-                            done=true
-                            if not allresults then
-                              break
-                            end
-                          end
-                        end
-                      end
-                      if done and not allresults then
-                        break
-                      end
-                    end
-                  end
-                end
-              end
+        if not done and entry.recursive then
+         if trace_detail then
+          report_resolving("scanning filesystem for %a",pname)
+         end
+         local files=resolvers.simplescanfiles(pname,false,true)
+         for k=1,#wantedfiles do
+          local w=wantedfiles[k]
+          local subpath=files[w]
+          if not subpath or subpath=="" then
+          elseif type(subpath)=="string" then
+           local fname=check_subpath(filejoin(pname,subpath,w))
+           if fname then
+            result[#result+1]=fname
+            done=true
+            if not allresults then
+             break
             end
+           end
           else
-          end
-        else
-          for k=1,#wantedfiles do
-            local pname=entry.barename
-            local fname=methodhandler('finders',pname.."/"..wantedfiles[k])
-            if fname then
+           for i=1,#subpath do
+            local sp=subpath[i]
+            if sp=="" then
+            else
+             local fname=check_subpath(filejoin(pname,sp,w))
+             if fname then
               result[#result+1]=fname
               done=true
               if not allresults then
-                break
+               break
               end
+             end
             end
+           end
+           if done and not allresults then
+            break
+           end
           end
+         end
         end
+       end
       end
-      if done and not allresults then
+     else
+     end
+    else
+     for k=1,#wantedfiles do
+      local pname=entry.barename
+      local fname=methodhandler('finders',pname.."/"..wantedfiles[k])
+      if fname then
+       result[#result+1]=fname
+       done=true
+       if not allresults then
         break
+       end
       end
+     end
     end
-    if #result>0 then
-      return method,result
-    end
+   end
+   if done and not allresults then
+    break
+   end
   end
+  if #result>0 then
+   return method,result
+  end
+ end
 end
 local function find_onpath(filename,filetype,wantedfiles,allresults)
-  if trace_detail then
-    report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ if trace_detail then
+  report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ end
+ local result={}
+ for k=1,#wantedfiles do
+  local fname=wantedfiles[k]
+  if fname and isreadable(fname) then
+   filename=fname
+   result[#result+1]=filejoin('.',fname)
+   if not allresults then
+    break
+   end
   end
-  local result={}
-  for k=1,#wantedfiles do
-    local fname=wantedfiles[k]
-    if fname and isreadable(fname) then
-      filename=fname
-      result[#result+1]=filejoin('.',fname)
-      if not allresults then
-        break
-      end
-    end
-  end
-  if #result>0 then
-    return "onpath",result
-  end
+ end
+ if #result>0 then
+  return "onpath",result
+ end
 end
 local function find_otherwise(filename,filetype,wantedfiles,allresults) 
-  local filelist=collect_files(wantedfiles)
-  local fl=filelist and filelist[1]
-  if fl then
-    return "otherwise",{ resolveprefix(fl[3]) } 
-  end
+ local filelist=collect_files(wantedfiles)
+ local fl=filelist and filelist[1]
+ if fl then
+  return "otherwise",{ resolveprefix(fl[3]) } 
+ end
 end
 collect_instance_files=function(filename,askedformat,allresults) 
-  if not filename or filename=="" then
-    return {}
+ if not filename or filename=="" then
+  return {}
+ end
+ askedformat=askedformat or ""
+ filename=collapsepath(filename,".")
+ filename=gsub(filename,"^%./",getcurrentdir().."/") 
+ if allresults then
+  local filetype,wantedfiles=find_analyze(filename,askedformat)
+  local results={
+   { find_direct   (filename,true) },
+   { find_wildcard (filename,true) },
+   { find_qualified(filename,true,askedformat) },
+   { find_intree   (filename,filetype,wantedfiles,true) },
+   { find_onpath   (filename,filetype,wantedfiles,true) },
+   { find_otherwise(filename,filetype,wantedfiles,true) },
+  }
+  local result,status,done={},{},{}
+  for k,r in next,results do
+   local method,list=r[1],r[2]
+   if method and list then
+    for i=1,#list do
+     local c=collapsepath(list[i])
+     if not done[c] then
+      result[#result+1]=c
+      done[c]=true
+     end
+     status[#status+1]=formatters["%-10s: %s"](method,c)
+    end
+   end
   end
-  askedformat=askedformat or ""
-  filename=collapsepath(filename,".")
-  filename=gsub(filename,"^%./",getcurrentdir().."/") 
-  if allresults then
-    local filetype,wantedfiles=find_analyze(filename,askedformat)
-    local results={
-      { find_direct  (filename,true) },
-      { find_wildcard (filename,true) },
-      { find_qualified(filename,true,askedformat) },
-      { find_intree  (filename,filetype,wantedfiles,true) },
-      { find_onpath  (filename,filetype,wantedfiles,true) },
-      { find_otherwise(filename,filetype,wantedfiles,true) },
-    }
-    local result,status,done={},{},{}
-    for k,r in next,results do
-      local method,list=r[1],r[2]
-      if method and list then
-        for i=1,#list do
-          local c=collapsepath(list[i])
-          if not done[c] then
-            result[#result+1]=c
-            done[c]=true
-          end
-          status[#status+1]=formatters["%-10s: %s"](method,c)
-        end
-      end
+  if trace_detail then
+   report_resolving("lookup status: %s",table.serialize(status,filename))
+  end
+  return result,status
+ else
+  local method,result,stamp,filetype,wantedfiles
+  if instance.remember then
+   if askedformat=="" then
+    stamp=formatters["%s::%s"](suffixonly(filename),filename)
+   else
+    stamp=formatters["%s::%s"](askedformat,filename)
+   end
+   result=stamp and instance.found[stamp]
+   if result then
+    if trace_locating then
+     report_resolving("remembered file %a",filename)
     end
-    if trace_detail then
-      report_resolving("lookup status: %s",table.serialize(status,filename))
-    end
-    return result,status
-  else
-    local method,result,stamp,filetype,wantedfiles
-    if instance.remember then
-      if askedformat=="" then
-        stamp=formatters["%s::%s"](suffixonly(filename),filename)
-      else
-        stamp=formatters["%s::%s"](askedformat,filename)
-      end
-      result=stamp and instance.found[stamp]
-      if result then
-        if trace_locating then
-          report_resolving("remembered file %a",filename)
-        end
-        return result
-      end
-    end
-    method,result=find_direct(filename)
+    return result
+   end
+  end
+  method,result=find_direct(filename)
+  if not result then
+   method,result=find_wildcard(filename)
+   if not result then
+    method,result=find_qualified(filename,false,askedformat)
     if not result then
-      method,result=find_wildcard(filename)
-      if not result then
-        method,result=find_qualified(filename,false,askedformat)
-        if not result then
-          filetype,wantedfiles=find_analyze(filename,askedformat)
-          method,result=find_intree(filename,filetype,wantedfiles)
-          if not result then
-            method,result=find_onpath(filename,filetype,wantedfiles)
-            if resolve_otherwise and not result then
-              method,result=find_otherwise(filename,filetype,wantedfiles)
-            end
-          end
-        end
+     filetype,wantedfiles=find_analyze(filename,askedformat)
+     method,result=find_intree(filename,filetype,wantedfiles)
+     if not result then
+      method,result=find_onpath(filename,filetype,wantedfiles)
+      if resolve_otherwise and not result then
+       method,result=find_otherwise(filename,filetype,wantedfiles)
       end
+     end
     end
-    if result and #result>0 then
-      local foundname=collapsepath(result[1])
-      resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
-      result={ foundname }
-    else
-      result={} 
-    end
-    if stamp then
-      if trace_locating then
-        report_resolving("remembering file %a using hash %a",filename,stamp)
-      end
-      instance.found[stamp]=result
-    end
-    return result
+   end
   end
+  if result and #result>0 then
+   local foundname=collapsepath(result[1])
+   resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+   result={ foundname }
+  else
+   result={} 
+  end
+  if stamp then
+   if trace_locating then
+    report_resolving("remembering file %a using hash %a",filename,stamp)
+   end
+   instance.found[stamp]=result
+  end
+  return result
+ end
 end
 local function findfiles(filename,filetype,allresults)
-  if not filename or filename=="" then
-    return {}
+ if not filename or filename=="" then
+  return {}
+ end
+ local result,status=collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result==0 then
+  local lowered=lower(filename)
+  if filename~=lowered then
+   result,status=collect_instance_files(lowered,filetype or "",allresults)
   end
-  local result,status=collect_instance_files(filename,filetype or "",allresults)
-  if not result or #result==0 then
-    local lowered=lower(filename)
-    if filename~=lowered then
-      result,status=collect_instance_files(lowered,filetype or "",allresults)
-    end
-  end
-  return result or {},status
+ end
+ return result or {},status
 end
 function resolvers.findfiles(filename,filetype)
-  if not filename or filename=="" then
-    return ""
-  else
-    return findfiles(filename,filetype,true)
-  end
+ if not filename or filename=="" then
+  return ""
+ else
+  return findfiles(filename,filetype,true)
+ end
 end
 function resolvers.findfile(filename,filetype)
-  if not filename or filename=="" then
-    return ""
-  else
-    return findfiles(filename,filetype,false)[1] or ""
-  end
+ if not filename or filename=="" then
+  return ""
+ else
+  return findfiles(filename,filetype,false)[1] or ""
+ end
 end
 function resolvers.findpath(filename,filetype)
-  return filedirname(findfiles(filename,filetype,false)[1] or "")
+ return filedirname(findfiles(filename,filetype,false)[1] or "")
 end
 local function findgivenfiles(filename,allresults)
-  local base=filebasename(filename)
-  local result={}
-  local hashes=instance.hashes
-  local function okay(hash,path,name)
-    local found=methodhandler('concatinators',hash.type,hash.name,path,name)
-    if found and found~="" then
-      result[#result+1]=resolveprefix(found)
-      return not allresults
-    end
+ local base=filebasename(filename)
+ local result={}
+ local hashes=instance.hashes
+ local function okay(hash,path,name)
+  local found=methodhandler('concatinators',hash.type,hash.name,path,name)
+  if found and found~="" then
+   result[#result+1]=resolveprefix(found)
+   return not allresults
   end
-  for k=1,#hashes do
-    local hash=hashes[k]
-    local content=instance.files[hash.name]
-    if content then
-      local path,name=lookup(content,base)
-      if not path then
-      elseif type(path)=="string" then
-        if okay(hash,path,name) then
-          return result
-        end
-      else
-        for i=1,#path do
-          if okay(hash,path[i],name) then
-            return result
-          end
-        end
-      end
+ end
+ for k=1,#hashes do
+  local hash=hashes[k]
+  local content=instance.files[hash.name]
+  if content then
+   local path,name=lookup(content,base)
+   if not path then
+   elseif type(path)=="string" then
+    if okay(hash,path,name) then
+     return result
     end
+   else
+    for i=1,#path do
+     if okay(hash,path[i],name) then
+      return result
+     end
+    end
+   end
   end
-  return result
+ end
+ return result
 end
 function resolvers.findgivenfiles(filename)
-  return findgivenfiles(filename,true)
+ return findgivenfiles(filename,true)
 end
 function resolvers.findgivenfile(filename)
-  return findgivenfiles(filename,false)[1] or ""
+ return findgivenfiles(filename,false)[1] or ""
 end
 local makewildcard=Cs(
-  (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
+ (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
 )
 function resolvers.wildcardpattern(pattern)
-  return lpegmatch(makewildcard,pattern) or pattern
+ return lpegmatch(makewildcard,pattern) or pattern
 end
 local function findwildcardfiles(filename,allresults,result)
-  local result=result or {}
-  local base=filebasename(filename)
-  local dirn=filedirname(filename)
-  local path=lower(lpegmatch(makewildcard,dirn) or dirn)
-  local name=lower(lpegmatch(makewildcard,base) or base)
-  local files=instance.files
-  if find(name,"*",1,true) then
-    local hashes=instance.hashes
-    local function okay(found,path,base,hashname,hashtype)
-      if find(found,path) then
-        local full=methodhandler('concatinators',hashtype,hashname,found,base)
-        if full and full~="" then
-          result[#result+1]=resolveprefix(full)
-          return not allresults
-        end
-      end
+ local result=result or {}
+ local base=filebasename(filename)
+ local dirn=filedirname(filename)
+ local path=lower(lpegmatch(makewildcard,dirn) or dirn)
+ local name=lower(lpegmatch(makewildcard,base) or base)
+ local files=instance.files
+ if find(name,"*",1,true) then
+  local hashes=instance.hashes
+  local function okay(found,path,base,hashname,hashtype)
+   if find(found,path) then
+    local full=methodhandler('concatinators',hashtype,hashname,found,base)
+    if full and full~="" then
+     result[#result+1]=resolveprefix(full)
+     return not allresults
     end
-    for k=1,#hashes do
-      local hash=hashes[k]
-      local hashname=hash.name
-      local hashtype=hash.type
-      if hashname and hashtype then
-        for found,base in filtered(files[hashname],name) do
-          if type(found)=='string' then
-            if okay(found,path,base,hashname,hashtype) then
-              break
-            end
-          else
-            for i=1,#found do
-              if okay(found[i],path,base,hashname,hashtype) then
-                break
-              end
-            end
-          end
-        end
+   end
+  end
+  for k=1,#hashes do
+   local hash=hashes[k]
+   local hashname=hash.name
+   local hashtype=hash.type
+   if hashname and hashtype then
+    for found,base in filtered(files[hashname],name) do
+     if type(found)=='string' then
+      if okay(found,path,base,hashname,hashtype) then
+       break
       end
-    end
-  else
-    local function okayokay(found,path,base,hashname,hashtype)
-      if find(found,path) then
-        local full=methodhandler('concatinators',hashtype,hashname,found,base)
-        if full and full~="" then
-          result[#result+1]=resolveprefix(full)
-          return not allresults
-        end
+     else
+      for i=1,#found do
+       if okay(found[i],path,base,hashname,hashtype) then
+        break
+       end
       end
+     end
     end
-    local hashes=instance.hashes
-    for k=1,#hashes do
-      local hash=hashes[k]
-      local hashname=hash.name
-      local hashtype=hash.type
-      if hashname and hashtype then
-        local found,base=lookup(content,base)
-        if not found then
-        elseif type(found)=='string' then
-          if okay(found,path,base,hashname,hashtype) then
-            break
-          end
-        else
-          for i=1,#found do
-            if okay(found[i],path,base,hashname,hashtype) then
-              break
-            end
-          end
-        end
+   end
+  end
+ else
+  local function okayokay(found,path,base,hashname,hashtype)
+   if find(found,path) then
+    local full=methodhandler('concatinators',hashtype,hashname,found,base)
+    if full and full~="" then
+     result[#result+1]=resolveprefix(full)
+     return not allresults
+    end
+   end
+  end
+  local hashes=instance.hashes
+  for k=1,#hashes do
+   local hash=hashes[k]
+   local hashname=hash.name
+   local hashtype=hash.type
+   if hashname and hashtype then
+    local found,base=lookup(content,base)
+    if not found then
+    elseif type(found)=='string' then
+     if okay(found,path,base,hashname,hashtype) then
+      break
+     end
+    else
+     for i=1,#found do
+      if okay(found[i],path,base,hashname,hashtype) then
+       break
       end
+     end
     end
+   end
   end
-  return result
+ end
+ return result
 end
 function resolvers.findwildcardfiles(filename,result)
-  return findwildcardfiles(filename,true,result)
+ return findwildcardfiles(filename,true,result)
 end
 function resolvers.findwildcardfile(filename)
-  return findwildcardfiles(filename,false)[1] or ""
+ return findwildcardfiles(filename,false)[1] or ""
 end
 function resolvers.automount()
 end
 function resolvers.starttiming()
-  statistics.starttiming(instance)
+ statistics.starttiming(instance)
 end
 function resolvers.stoptiming()
-  statistics.stoptiming(instance)
+ statistics.stoptiming(instance)
 end
 function resolvers.load(option)
-  resolvers.starttiming()
-  identify_configuration_files()
-  load_configuration_files()
-  if option~="nofiles" then
-    load_databases()
-    resolvers.automount()
-  end
-  resolvers.stoptiming()
-  local files=instance.files
-  return files and next(files) and true
+ resolvers.starttiming()
+ identify_configuration_files()
+ load_configuration_files()
+ if option~="nofiles" then
+  load_databases()
+  resolvers.automount()
+ end
+ resolvers.stoptiming()
+ local files=instance.files
+ return files and next(files) and true
 end
 function resolvers.loadtime()
-  return statistics.elapsedtime(instance)
+ return statistics.elapsedtime(instance)
 end
 local function report(str)
+ if trace_locating then
+  report_resolving(str) 
+ else
+  print(str)
+ end
+end
+function resolvers.dowithfilesandreport(command,files,...) 
+ if files and #files>0 then
   if trace_locating then
-    report_resolving(str) 
-  else
-    print(str)
+   report('') 
   end
-end
-function resolvers.dowithfilesandreport(command,files,...) 
-  if files and #files>0 then
-    if trace_locating then
-      report('') 
+  if type(files)=="string" then
+   files={ files }
+  end
+  for f=1,#files do
+   local file=files[f]
+   local result=command(file,...)
+   if type(result)=='string' then
+    report(result)
+   else
+    for i=1,#result do
+     report(result[i]) 
     end
-    if type(files)=="string" then
-      files={ files }
-    end
-    for f=1,#files do
-      local file=files[f]
-      local result=command(file,...)
-      if type(result)=='string' then
-        report(result)
-      else
-        for i=1,#result do
-          report(result[i]) 
-        end
-      end
-    end
+   end
   end
+ end
 end
-function resolvers.showpath(str)   
-  return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
+function resolvers.showpath(str)  
+ return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
 end
 function resolvers.registerfile(files,name,path)
-  if files[name] then
-    if type(files[name])=='string' then
-      files[name]={ files[name],path }
-    else
-      files[name]=path
-    end
+ if files[name] then
+  if type(files[name])=='string' then
+   files[name]={ files[name],path }
   else
-    files[name]=path
+   files[name]=path
   end
+ else
+  files[name]=path
+ end
 end
 function resolvers.dowithpath(name,func)
-  local pathlist=resolvers.expandedpathlist(name)
-  for i=1,#pathlist do
-    func("^"..cleanpath(pathlist[i]))
-  end
+ local pathlist=resolvers.expandedpathlist(name)
+ for i=1,#pathlist do
+  func("^"..cleanpath(pathlist[i]))
+ end
 end
 function resolvers.dowithvariable(name,func)
-  func(expandedvariable(name))
+ func(expandedvariable(name))
 end
 function resolvers.locateformat(name)
-  local engine=environment.ownmain or "luatex"
-  local barename=removesuffix(name)
-  local fullname=addsuffix(barename,"fmt")
-  local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
-  if fmtname=="" then
-    fmtname=resolvers.findfile(fullname)
-    fmtname=cleanpath(fmtname)
+ local engine=environment.ownmain or "luatex"
+ local barename=removesuffix(name)
+ local fullname=addsuffix(barename,"fmt")
+ local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
+ if fmtname=="" then
+  fmtname=resolvers.findfile(fullname)
+  fmtname=cleanpath(fmtname)
+ end
+ if fmtname~="" then
+  local barename=removesuffix(fmtname)
+  local luaname=addsuffix(barename,luasuffixes.lua)
+  local lucname=addsuffix(barename,luasuffixes.luc)
+  local luiname=addsuffix(barename,luasuffixes.lui)
+  if isfile(luiname) then
+   return barename,luiname
+  elseif isfile(lucname) then
+   return barename,lucname
+  elseif isfile(luaname) then
+   return barename,luaname
   end
-  if fmtname~="" then
-    local barename=removesuffix(fmtname)
-    local luaname=addsuffix(barename,luasuffixes.lua)
-    local lucname=addsuffix(barename,luasuffixes.luc)
-    local luiname=addsuffix(barename,luasuffixes.lui)
-    if isfile(luiname) then
-      return barename,luiname
-    elseif isfile(lucname) then
-      return barename,lucname
-    elseif isfile(luaname) then
-      return barename,luaname
-    end
-  end
-  return nil,nil
+ end
+ return nil,nil
 end
 function resolvers.booleanvariable(str,default)
-  local b=resolvers.expansion(str)
-  if b=="" then
-    return default
-  else
-    b=toboolean(b)
-    return (b==nil and default) or b
-  end
+ local b=resolvers.expansion(str)
+ if b=="" then
+  return default
+ else
+  b=toboolean(b)
+  return (b==nil and default) or b
+ end
 end
 function resolvers.dowithfilesintree(pattern,handle,before,after) 
-  local hashes=instance.hashes
-  for i=1,#hashes do
-    local hash=hashes[i]
-    local blobtype=hash.type
-    local blobpath=hash.name
-    if blobtype and blobpath then
-      local total=0
-      local checked=0
-      local done=0
-      if before then
-        before(blobtype,blobpath,pattern)
+ local hashes=instance.hashes
+ for i=1,#hashes do
+  local hash=hashes[i]
+  local blobtype=hash.type
+  local blobpath=hash.name
+  if blobtype and blobpath then
+   local total=0
+   local checked=0
+   local done=0
+   if before then
+    before(blobtype,blobpath,pattern)
+   end
+   for path,name in filtered(instance.files[blobpath],pattern) do
+    if type(path)=="string" then
+     checked=checked+1
+     if handle(blobtype,blobpath,path,name) then
+      done=done+1
+     end
+    else
+     checked=checked+#path
+     for i=1,#path do
+      if handle(blobtype,blobpath,path[i],name) then
+       done=done+1
       end
-      for path,name in filtered(instance.files[blobpath],pattern) do
-        if type(path)=="string" then
-          checked=checked+1
-          if handle(blobtype,blobpath,path,name) then
-            done=done+1
-          end
-        else
-          checked=checked+#path
-          for i=1,#path do
-            if handle(blobtype,blobpath,path[i],name) then
-              done=done+1
-            end
-          end
-        end
-      end
-      if after then
-        after(blobtype,blobpath,pattern,total,checked,done)
-      end
+     end
     end
+   end
+   if after then
+    after(blobtype,blobpath,pattern,checked,done)
+   end
   end
+ end
 end
 local obsolete=resolvers.obsolete or {}
 resolvers.obsolete=obsolete
-resolvers.find_file=resolvers.findfile  obsolete.find_file=resolvers.findfile
-resolvers.find_files=resolvers.findfiles  obsolete.find_files=resolvers.findfiles
+resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
+resolvers.find_files=resolvers.findfiles   obsolete.find_files=resolvers.findfiles
 function resolvers.knownvariables(pattern)
-  if instance then
-    local environment=instance.environment
-    local variables=instance.variables
-    local expansions=instance.expansions
-    local order=instance.order
-    local pattern=upper(pattern or "")
-    local result={}
-    for i=1,#order do
-      for key in next,order[i] do
-        if result[key]==nil and key~="" and (pattern=="" or find(upper(key),pattern)) then
-          result[key]={
-            environment=rawget(environment,key),
-            variable=key,
-            expansion=expansions[key],
-            resolved=resolveprefix(expansions[key]),
-          }
-        end
-      end
+ if instance then
+  local environment=instance.environment
+  local variables=instance.variables
+  local expansions=instance.expansions
+  local order=instance.order
+  local pattern=upper(pattern or "")
+  local result={}
+  for i=1,#order do
+   for key in next,order[i] do
+    if result[key]==nil and key~="" and (pattern=="" or find(upper(key),pattern)) then
+     result[key]={
+      environment=rawget(environment,key),
+      variable=key,
+      expansion=expansions[key],
+      resolved=resolveprefix(expansions[key]),
+     }
     end
-    return result
-  else
-    return {}
+   end
   end
+  return result
+ else
+  return {}
+ end
 end
 
 
@@ -19311,14 +22885,14 @@
 
 package.loaded["data-pre"] = package.loaded["data-pre"] or true
 
--- original size: 4090, stripped down to: 3059
+-- original size: 4854, stripped down to: 2889
 
 if not modules then modules={} end modules ['data-pre']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 resolvers=resolvers
 local prefixes=resolvers.prefixes
@@ -19331,64 +22905,64 @@
 local joinpath=file.join
 local isfile=lfs.isfile
 prefixes.environment=function(str)
-  return cleanpath(expansion(str))
+ return cleanpath(expansion(str))
 end
 local function relative(str,n)
-  if not isfile(str) then
-    local pstr="./"..str
+ if not isfile(str) then
+  local pstr="./"..str
+  if isfile(pstr) then
+   str=pstr
+  else
+   local p="../"
+   for i=1,n or 2 do
+    local pstr=p..str
     if isfile(pstr) then
-      str=pstr
+     str=pstr
+     break
     else
-      local p="../"
-      for i=1,n or 2 do
-        local pstr=p..str
-        if isfile(pstr) then
-          str=pstr
-          break
-        else
-          p=p.."../"
-        end
-      end
+     p=p.."../"
     end
+   end
   end
-  return cleanpath(str)
+ end
+ return cleanpath(str)
 end
 local function locate(str)
-  local fullname=findgivenfile(str) or ""
-  return cleanpath(fullname~="" and fullname or str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(fullname~="" and fullname or str)
 end
 prefixes.relative=relative
 prefixes.locate=locate
 prefixes.auto=function(str)
-  local fullname=relative(str)
-  if not isfile(fullname) then
-    fullname=locate(str)
-  end
-  return fullname
+ local fullname=relative(str)
+ if not isfile(fullname) then
+  fullname=locate(str)
+ end
+ return fullname
 end
 prefixes.filename=function(str)
-  local fullname=findgivenfile(str) or ""
-  return cleanpath(basename((fullname~="" and fullname) or str)) 
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(basename((fullname~="" and fullname) or str)) 
 end
 prefixes.pathname=function(str)
-  local fullname=findgivenfile(str) or ""
-  return cleanpath(dirname((fullname~="" and fullname) or str))
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(dirname((fullname~="" and fullname) or str))
 end
 prefixes.selfautoloc=function(str)
-  local pth=getenv('SELFAUTOLOC')
-  return cleanpath(str and joinpath(pth,str) or pth)
+ local pth=getenv('SELFAUTOLOC')
+ return cleanpath(str and joinpath(pth,str) or pth)
 end
 prefixes.selfautoparent=function(str)
-  local pth=getenv('SELFAUTOPARENT')
-  return cleanpath(str and joinpath(pth,str) or pth)
+ local pth=getenv('SELFAUTOPARENT')
+ return cleanpath(str and joinpath(pth,str) or pth)
 end
 prefixes.selfautodir=function(str)
-  local pth=getenv('SELFAUTODIR')
-  return cleanpath(str and joinpath(pth,str) or pth)
+ local pth=getenv('SELFAUTODIR')
+ return cleanpath(str and joinpath(pth,str) or pth)
 end
 prefixes.home=function(str)
-  local pth=getenv('HOME')
-  return cleanpath(str and joinpath(pth,str) or pth)
+ local pth=getenv('HOME')
+ return cleanpath(str and joinpath(pth,str) or pth)
 end
 prefixes.env=prefixes.environment
 prefixes.rel=prefixes.relative
@@ -19398,24 +22972,24 @@
 prefixes.file=prefixes.filename
 prefixes.path=prefixes.pathname
 local function toppath()
-  local inputstack=resolvers.inputstack 
-  if not inputstack then         
-    return "."
-  end
-  local pathname=dirname(inputstack[#inputstack] or "")
-  if pathname=="" then
-    return "."
-  else
-    return pathname
-  end
+ local inputstack=resolvers.inputstack 
+ if not inputstack then      
+  return "."
+ end
+ local pathname=dirname(inputstack[#inputstack] or "")
+ if pathname=="" then
+  return "."
+ else
+  return pathname
+ end
 end
 local function jobpath()
-  local path=resolvers.stackpath()
-  if not path or path=="" then
-    return "."
-  else
-    return path
-  end
+ local path=resolvers.stackpath()
+ if not path or path=="" then
+  return "."
+ else
+  return path
+ end
 end
 resolvers.toppath=toppath
 resolvers.jobpath=jobpath
@@ -19423,8 +22997,6 @@
 prefixes.jobpath=function(str) return cleanpath(joinpath(jobpath(),str)) end 
 resolvers.setdynamic("toppath")
 resolvers.setdynamic("jobpath")
-prefixes.jobfile=prefixes.jobpath
-resolvers.setdynamic("jobfile")
 
 
 end -- of closure
@@ -19433,14 +23005,14 @@
 
 package.loaded["data-inp"] = package.loaded["data-inp"] or true
 
--- original size: 910, stripped down to: 823
+-- original size: 910, stripped down to: 818
 
 if not modules then modules={} end modules ['data-inp']={
-  version=1.001,
-  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"
+ version=1.001,
+ 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 allocate=utilities.storage.allocate
 local resolvers=resolvers
@@ -19463,14 +23035,14 @@
 
 package.loaded["data-out"] = package.loaded["data-out"] or true
 
--- original size: 530, stripped down to: 475
+-- original size: 530, stripped down to: 470
 
 if not modules then modules={} end modules ['data-out']={
-  version=1.001,
-  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"
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ aut