From bd95a21d2b31a5fab1b4cc7c2b0334823fb3a3e9 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Mon, 20 May 2013 02:00:00 +0200
Subject: beta 2013.05.20 02:00

---
 tex/generic/context/luatex/luatex-basics-gen.lua   |   654 +-
 tex/generic/context/luatex/luatex-basics-nod.lua   |   208 +-
 tex/generic/context/luatex/luatex-fonts-cbk.lua    |   136 +-
 tex/generic/context/luatex/luatex-fonts-def.lua    |   194 +-
 .../context/luatex/luatex-fonts-demo-vf-1.lua      |    76 +-
 tex/generic/context/luatex/luatex-fonts-enc.lua    |    56 +-
 tex/generic/context/luatex/luatex-fonts-ext.lua    |   544 +-
 tex/generic/context/luatex/luatex-fonts-lua.lua    |    66 +-
 tex/generic/context/luatex/luatex-fonts-merged.lua | 16296 +++++++++----------
 tex/generic/context/luatex/luatex-fonts-syn.lua    |   204 +-
 tex/generic/context/luatex/luatex-fonts-tfm.lua    |    76 +-
 tex/generic/context/luatex/luatex-languages.lua    |    90 +-
 tex/generic/context/luatex/luatex-math.lua         |   106 +-
 tex/generic/context/luatex/luatex-mplib.lua        |   982 +-
 tex/generic/context/luatex/luatex-preprocessor.lua |   326 +-
 tex/generic/context/luatex/luatex-swiglib-test.lua |    50 +-
 tex/generic/context/luatex/luatex-swiglib.lua      |   124 +-
 17 files changed, 10094 insertions(+), 10094 deletions(-)

(limited to 'tex/generic')

diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua
index 4c504a24e..0561778b4 100644
--- a/tex/generic/context/luatex/luatex-basics-gen.lua
+++ b/tex/generic/context/luatex/luatex-basics-gen.lua
@@ -1,327 +1,327 @@
-if not modules then modules = { } end modules ['luat-basics-gen'] = {
-    version   = 1.100,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local dummyfunction = function()
-end
-
-local dummyreporter = function(c)
-    return function(...)
-        (texio.reporter or texio.write_nl)(c .. " : " .. string.formatters(...))
-    end
-end
-
-statistics = {
-    register      = dummyfunction,
-    starttiming   = dummyfunction,
-    stoptiming    = dummyfunction,
-    elapsedtime   = nil,
-}
-
-directives = {
-    register      = dummyfunction,
-    enable        = dummyfunction,
-    disable       = dummyfunction,
-}
-
-trackers = {
-    register      = dummyfunction,
-    enable        = dummyfunction,
-    disable       = dummyfunction,
-}
-
-experiments = {
-    register      = dummyfunction,
-    enable        = dummyfunction,
-    disable       = dummyfunction,
-}
-
-storage = { -- probably no longer needed
-    register      = dummyfunction,
-    shared        = { },
-}
-
-logs = {
-    new           = dummyreporter,
-    reporter      = dummyreporter,
-    messenger     = dummyreporter,
-    report        = dummyfunction,
-}
-
-callbacks = {
-    register = function(n,f) return callback.register(n,f) end,
-
-}
-
-utilities = {
-    storage = {
-        allocate = function(t) return t or { } end,
-        mark     = function(t) return t or { } end,
-    },
-}
-
-characters = characters or {
-    data = { }
-}
-
--- we need to cheat a bit here
-
-texconfig.kpse_init = true
-
-resolvers = resolvers or { } -- no fancy file helpers used
-
-local remapper = {
-    otf    = "opentype fonts",
-    ttf    = "truetype fonts",
-    ttc    = "truetype fonts",
-    dfont  = "truetype fonts", -- "truetype dictionary",
-    cid    = "cid maps",
-    cidmap = "cid maps",
-    fea    = "font feature files",
-    pfa    = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
-    pfb    = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
-}
-
-function resolvers.findfile(name,fileformat)
-    name = string.gsub(name,"\\","/")
-    if not fileformat or fileformat == "" then
-        fileformat = file.suffix(name)
-        if fileformat == "" then
-            fileformat = "tex"
-        end
-    end
-    fileformat = string.lower(fileformat)
-    fileformat = remapper[fileformat] or fileformat
-    local found = kpse.find_file(name,fileformat)
-    if not found or found == "" then
-        found = kpse.find_file(name,"other text files")
-    end
-    return found
-end
-
--- function resolvers.findbinfile(name,fileformat)
---     if not fileformat or fileformat == "" then
---         fileformat = file.suffix(name)
---     end
---     return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat)
--- end
-
-resolvers.findbinfile = resolvers.findfile
-
-function resolvers.resolve(s)
-    return s
-end
-
-function resolvers.unresolve(s)
-    return s
-end
-
--- Caches ... I will make a real stupid version some day when I'm in the
--- mood. After all, the generic code does not need the more advanced
--- ConTeXt features. Cached data is not shared between ConTeXt and other
--- usage as I don't want any dependency at all. Also, ConTeXt might have
--- different needs and tricks added.
-
---~ containers.usecache = true
-
-caches = { }
-
-local writable  = nil
-local readables = { }
-local usingjit  = jit
-
-if not caches.namespace or caches.namespace == "" or caches.namespace == "context" then
-    caches.namespace = 'generic'
-end
-
-do
-
-    -- standard context tree setup
-
-    local cachepaths = kpse.expand_path('$TEXMFCACHE') or ""
-
-    -- quite like tex live or so
-
-    if cachepaths == "" then
-        cachepaths = kpse.expand_path('$TEXMFVAR')
-    end
-
-    -- this also happened to be used
-
-    if cachepaths == "" then
-        cachepaths = kpse.expand_path('$VARTEXMF')
-    end
-
-    -- and this is a last resort
-
-    if cachepaths == "" then
-        cachepaths = "."
-    end
-
-    cachepaths = string.split(cachepaths,os.type == "windows" and ";" or ":")
-
-    for i=1,#cachepaths do
-        local cachepath = cachepaths[i]
-        if not lfs.isdir(cachepath) then
-            lfs.mkdirs(cachepath) -- needed for texlive and latex
-            if lfs.isdir(cachepath) then
-                texio.write(string.format("(created cache path: %s)",cachepath))
-            end
-        end
-        if file.is_writable(cachepath) then
-            writable = file.join(cachepath,"luatex-cache")
-            lfs.mkdir(writable)
-            writable = file.join(writable,caches.namespace)
-            lfs.mkdir(writable)
-            break
-        end
-    end
-
-    for i=1,#cachepaths do
-        if file.is_readable(cachepaths[i]) then
-            readables[#readables+1] = file.join(cachepaths[i],"luatex-cache",caches.namespace)
-        end
-    end
-
-    if not writable then
-        texio.write_nl("quiting: fix your writable cache path")
-        os.exit()
-    elseif #readables == 0 then
-        texio.write_nl("quiting: fix your readable cache path")
-        os.exit()
-    elseif #readables == 1 and readables[1] == writable then
-        texio.write(string.format("(using cache: %s)",writable))
-    else
-        texio.write(string.format("(using write cache: %s)",writable))
-        texio.write(string.format("(using read cache: %s)",table.concat(readables, " ")))
-    end
-
-end
-
-function caches.getwritablepath(category,subcategory)
-    local path = file.join(writable,category)
-    lfs.mkdir(path)
-    path = file.join(path,subcategory)
-    lfs.mkdir(path)
-    return path
-end
-
-function caches.getreadablepaths(category,subcategory)
-    local t = { }
-    for i=1,#readables do
-        t[i] = file.join(readables[i],category,subcategory)
-    end
-    return t
-end
-
-local function makefullname(path,name)
-    if path and path ~= "" then
-        return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
-    end
-end
-
-function caches.is_writable(path,name)
-    local fullname = makefullname(path,name)
-    return fullname and file.is_writable(fullname)
-end
-
-function caches.loaddata(paths,name)
-    for i=1,#paths do
-        local data = false
-        local luaname, lucname = makefullname(paths[i],name)
-        if lucname and lfs.isfile(lucname) then -- maybe also check for size
-            texio.write(string.format("(load luc: %s)",lucname))
-            data = loadfile(lucname)
-            if data then
-                data = data()
-            end
-            if data then
-                return data
-            else
-                texio.write(string.format("(loading failed: %s)",lucname))
-            end
-        end
-        if luaname and lfs.isfile(luaname) then
-            texio.write(string.format("(load lua: %s)",luaname))
-            data = loadfile(luaname)
-            if data then
-                data = data()
-            end
-            if data then
-                return data
-            end
-        end
-    end
-end
-
-function caches.savedata(path,name,data)
-    local luaname, lucname = makefullname(path,name)
-    if luaname then
-        texio.write(string.format("(save: %s)",luaname))
-        table.tofile(luaname,data,true,{ reduce = true })
-        if lucname and type(caches.compile) == "function" then
-            os.remove(lucname) -- better be safe
-            texio.write(string.format("(save: %s)",lucname))
-            caches.compile(data,luaname,lucname)
-        end
-    end
-end
-
--- According to KH os.execute is not permitted in plain/latex so there is
--- no reason to use the normal context way. So the method here is slightly
--- different from the one we have in context. We also use different suffixes
--- as we don't want any clashes (sharing cache files is not that handy as
--- context moves on faster.)
---
--- Beware: serialization might fail on large files (so maybe we should pcall
--- this) in which case one should limit the method to luac and enable support
--- for execution.
-
--- function caches.compile(data,luaname,lucname)
---     local d = io.loaddata(luaname)
---     if not d or d == "" then
---         d = table.serialize(data,true) -- slow
---     end
---     if d and d ~= "" then
---         local f = io.open(lucname,'w')
---         if f then
---             local s = loadstring(d)
---             if s then
---                 f:write(string.dump(s,true))
---             end
---             f:close()
---         end
---     end
--- end
-
-function caches.compile(data,luaname,lucname)
-    local d = io.loaddata(luaname)
-    if not d or d == "" then
-        d = table.serialize(data,true) -- slow
-    end
-    if d and d ~= "" then
-        local f = io.open(lucname,'wb')
-        if f then
-            local s = loadstring(d)
-            if s then
-                f:write(string.dump(s,true))
-            end
-            f:close()
-        end
-    end
-end
-
---
-
-function table.setmetatableindex(t,f)
-    setmetatable(t,{ __index = f })
-end
+if not modules then modules = { } end modules ['luat-basics-gen'] = {
+    version   = 1.100,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local dummyfunction = function()
+end
+
+local dummyreporter = function(c)
+    return function(...)
+        (texio.reporter or texio.write_nl)(c .. " : " .. string.formatters(...))
+    end
+end
+
+statistics = {
+    register      = dummyfunction,
+    starttiming   = dummyfunction,
+    stoptiming    = dummyfunction,
+    elapsedtime   = nil,
+}
+
+directives = {
+    register      = dummyfunction,
+    enable        = dummyfunction,
+    disable       = dummyfunction,
+}
+
+trackers = {
+    register      = dummyfunction,
+    enable        = dummyfunction,
+    disable       = dummyfunction,
+}
+
+experiments = {
+    register      = dummyfunction,
+    enable        = dummyfunction,
+    disable       = dummyfunction,
+}
+
+storage = { -- probably no longer needed
+    register      = dummyfunction,
+    shared        = { },
+}
+
+logs = {
+    new           = dummyreporter,
+    reporter      = dummyreporter,
+    messenger     = dummyreporter,
+    report        = dummyfunction,
+}
+
+callbacks = {
+    register = function(n,f) return callback.register(n,f) end,
+
+}
+
+utilities = {
+    storage = {
+        allocate = function(t) return t or { } end,
+        mark     = function(t) return t or { } end,
+    },
+}
+
+characters = characters or {
+    data = { }
+}
+
+-- we need to cheat a bit here
+
+texconfig.kpse_init = true
+
+resolvers = resolvers or { } -- no fancy file helpers used
+
+local remapper = {
+    otf    = "opentype fonts",
+    ttf    = "truetype fonts",
+    ttc    = "truetype fonts",
+    dfont  = "truetype fonts", -- "truetype dictionary",
+    cid    = "cid maps",
+    cidmap = "cid maps",
+    fea    = "font feature files",
+    pfa    = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
+    pfb    = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
+}
+
+function resolvers.findfile(name,fileformat)
+    name = string.gsub(name,"\\","/")
+    if not fileformat or fileformat == "" then
+        fileformat = file.suffix(name)
+        if fileformat == "" then
+            fileformat = "tex"
+        end
+    end
+    fileformat = string.lower(fileformat)
+    fileformat = remapper[fileformat] or fileformat
+    local found = kpse.find_file(name,fileformat)
+    if not found or found == "" then
+        found = kpse.find_file(name,"other text files")
+    end
+    return found
+end
+
+-- function resolvers.findbinfile(name,fileformat)
+--     if not fileformat or fileformat == "" then
+--         fileformat = file.suffix(name)
+--     end
+--     return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat)
+-- end
+
+resolvers.findbinfile = resolvers.findfile
+
+function resolvers.resolve(s)
+    return s
+end
+
+function resolvers.unresolve(s)
+    return s
+end
+
+-- Caches ... I will make a real stupid version some day when I'm in the
+-- mood. After all, the generic code does not need the more advanced
+-- ConTeXt features. Cached data is not shared between ConTeXt and other
+-- usage as I don't want any dependency at all. Also, ConTeXt might have
+-- different needs and tricks added.
+
+--~ containers.usecache = true
+
+caches = { }
+
+local writable  = nil
+local readables = { }
+local usingjit  = jit
+
+if not caches.namespace or caches.namespace == "" or caches.namespace == "context" then
+    caches.namespace = 'generic'
+end
+
+do
+
+    -- standard context tree setup
+
+    local cachepaths = kpse.expand_path('$TEXMFCACHE') or ""
+
+    -- quite like tex live or so
+
+    if cachepaths == "" then
+        cachepaths = kpse.expand_path('$TEXMFVAR')
+    end
+
+    -- this also happened to be used
+
+    if cachepaths == "" then
+        cachepaths = kpse.expand_path('$VARTEXMF')
+    end
+
+    -- and this is a last resort
+
+    if cachepaths == "" then
+        cachepaths = "."
+    end
+
+    cachepaths = string.split(cachepaths,os.type == "windows" and ";" or ":")
+
+    for i=1,#cachepaths do
+        local cachepath = cachepaths[i]
+        if not lfs.isdir(cachepath) then
+            lfs.mkdirs(cachepath) -- needed for texlive and latex
+            if lfs.isdir(cachepath) then
+                texio.write(string.format("(created cache path: %s)",cachepath))
+            end
+        end
+        if file.is_writable(cachepath) then
+            writable = file.join(cachepath,"luatex-cache")
+            lfs.mkdir(writable)
+            writable = file.join(writable,caches.namespace)
+            lfs.mkdir(writable)
+            break
+        end
+    end
+
+    for i=1,#cachepaths do
+        if file.is_readable(cachepaths[i]) then
+            readables[#readables+1] = file.join(cachepaths[i],"luatex-cache",caches.namespace)
+        end
+    end
+
+    if not writable then
+        texio.write_nl("quiting: fix your writable cache path")
+        os.exit()
+    elseif #readables == 0 then
+        texio.write_nl("quiting: fix your readable cache path")
+        os.exit()
+    elseif #readables == 1 and readables[1] == writable then
+        texio.write(string.format("(using cache: %s)",writable))
+    else
+        texio.write(string.format("(using write cache: %s)",writable))
+        texio.write(string.format("(using read cache: %s)",table.concat(readables, " ")))
+    end
+
+end
+
+function caches.getwritablepath(category,subcategory)
+    local path = file.join(writable,category)
+    lfs.mkdir(path)
+    path = file.join(path,subcategory)
+    lfs.mkdir(path)
+    return path
+end
+
+function caches.getreadablepaths(category,subcategory)
+    local t = { }
+    for i=1,#readables do
+        t[i] = file.join(readables[i],category,subcategory)
+    end
+    return t
+end
+
+local function makefullname(path,name)
+    if path and path ~= "" then
+        return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
+    end
+end
+
+function caches.is_writable(path,name)
+    local fullname = makefullname(path,name)
+    return fullname and file.is_writable(fullname)
+end
+
+function caches.loaddata(paths,name)
+    for i=1,#paths do
+        local data = false
+        local luaname, lucname = makefullname(paths[i],name)
+        if lucname and lfs.isfile(lucname) then -- maybe also check for size
+            texio.write(string.format("(load luc: %s)",lucname))
+            data = loadfile(lucname)
+            if data then
+                data = data()
+            end
+            if data then
+                return data
+            else
+                texio.write(string.format("(loading failed: %s)",lucname))
+            end
+        end
+        if luaname and lfs.isfile(luaname) then
+            texio.write(string.format("(load lua: %s)",luaname))
+            data = loadfile(luaname)
+            if data then
+                data = data()
+            end
+            if data then
+                return data
+            end
+        end
+    end
+end
+
+function caches.savedata(path,name,data)
+    local luaname, lucname = makefullname(path,name)
+    if luaname then
+        texio.write(string.format("(save: %s)",luaname))
+        table.tofile(luaname,data,true,{ reduce = true })
+        if lucname and type(caches.compile) == "function" then
+            os.remove(lucname) -- better be safe
+            texio.write(string.format("(save: %s)",lucname))
+            caches.compile(data,luaname,lucname)
+        end
+    end
+end
+
+-- According to KH os.execute is not permitted in plain/latex so there is
+-- no reason to use the normal context way. So the method here is slightly
+-- different from the one we have in context. We also use different suffixes
+-- as we don't want any clashes (sharing cache files is not that handy as
+-- context moves on faster.)
+--
+-- Beware: serialization might fail on large files (so maybe we should pcall
+-- this) in which case one should limit the method to luac and enable support
+-- for execution.
+
+-- function caches.compile(data,luaname,lucname)
+--     local d = io.loaddata(luaname)
+--     if not d or d == "" then
+--         d = table.serialize(data,true) -- slow
+--     end
+--     if d and d ~= "" then
+--         local f = io.open(lucname,'w')
+--         if f then
+--             local s = loadstring(d)
+--             if s then
+--                 f:write(string.dump(s,true))
+--             end
+--             f:close()
+--         end
+--     end
+-- end
+
+function caches.compile(data,luaname,lucname)
+    local d = io.loaddata(luaname)
+    if not d or d == "" then
+        d = table.serialize(data,true) -- slow
+    end
+    if d and d ~= "" then
+        local f = io.open(lucname,'wb')
+        if f then
+            local s = loadstring(d)
+            if s then
+                f:write(string.dump(s,true))
+            end
+            f:close()
+        end
+    end
+end
+
+--
+
+function table.setmetatableindex(t,f)
+    setmetatable(t,{ __index = f })
+end
diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua
index 38ccd8fc7..5ab9df7f9 100644
--- a/tex/generic/context/luatex/luatex-basics-nod.lua
+++ b/tex/generic/context/luatex/luatex-basics-nod.lua
@@ -1,104 +1,104 @@
-if not modules then modules = { } end modules ['luatex-fonts-nod'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-fonts.lua",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
--- Don't depend on code here as it is only needed to complement the
--- font handler code.
-
--- Attributes:
-
-if tex.attribute[0] ~= 0 then
-
-    texio.write_nl("log","!")
-    texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
-    texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
-    texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
-    texio.write_nl("log","!")
-
-    tex.attribute[0] = 0 -- else no features
-
-end
-
-attributes            = attributes or { }
-attributes.unsetvalue = -0x7FFFFFFF
-
-local numbers, last = { }, 127
-
-attributes.private = attributes.private or function(name)
-    local number = numbers[name]
-    if not number then
-        if last < 255 then
-            last = last + 1
-        end
-        number = last
-        numbers[name] = number
-    end
-    return number
-end
-
--- Nodes:
-
-nodes              = { }
-nodes.pool         = { }
-nodes.handlers     = { }
-
-local nodecodes    = { } for k,v in next, node.types   () do nodecodes[string.gsub(v,"_","")] = k end
-local whatcodes    = { } for k,v in next, node.whatsits() do whatcodes[string.gsub(v,"_","")] = k end
-local glyphcodes   = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
-
-nodes.nodecodes    = nodecodes
-nodes.whatcodes    = whatcodes
-nodes.whatsitcodes = whatcodes
-nodes.glyphcodes   = glyphcodes
-
-local free_node    = node.free
-local remove_node  = node.remove
-local new_node     = node.new
-local traverse_id  = node.traverse_id
-
-local math_code    = nodecodes.math
-
-nodes.handlers.protectglyphs   = node.protect_glyphs
-nodes.handlers.unprotectglyphs = node.unprotect_glyphs
-
-function nodes.remove(head, current, free_too)
-   local t = current
-   head, current = remove_node(head,current)
-   if t then
-        if free_too then
-            free_node(t)
-            t = nil
-        else
-            t.next, t.prev = nil, nil
-        end
-   end
-   return head, current, t
-end
-
-function nodes.delete(head,current)
-    return nodes.remove(head,current,true)
-end
-
-nodes.before = node.insert_before
-nodes.after  = node.insert_after
-
-function nodes.pool.kern(k)
-    local n = new_node("kern",1)
-    n.kern = k
-    return n
-end
-
-function nodes.endofmath(n)
-    for n in traverse_id(math_code,n.next) do
-        return n
-    end
-end
+if not modules then modules = { } end modules ['luatex-fonts-nod'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-fonts.lua",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+-- Don't depend on code here as it is only needed to complement the
+-- font handler code.
+
+-- Attributes:
+
+if tex.attribute[0] ~= 0 then
+
+    texio.write_nl("log","!")
+    texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
+    texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
+    texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
+    texio.write_nl("log","!")
+
+    tex.attribute[0] = 0 -- else no features
+
+end
+
+attributes            = attributes or { }
+attributes.unsetvalue = -0x7FFFFFFF
+
+local numbers, last = { }, 127
+
+attributes.private = attributes.private or function(name)
+    local number = numbers[name]
+    if not number then
+        if last < 255 then
+            last = last + 1
+        end
+        number = last
+        numbers[name] = number
+    end
+    return number
+end
+
+-- Nodes:
+
+nodes              = { }
+nodes.pool         = { }
+nodes.handlers     = { }
+
+local nodecodes    = { } for k,v in next, node.types   () do nodecodes[string.gsub(v,"_","")] = k end
+local whatcodes    = { } for k,v in next, node.whatsits() do whatcodes[string.gsub(v,"_","")] = k end
+local glyphcodes   = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
+
+nodes.nodecodes    = nodecodes
+nodes.whatcodes    = whatcodes
+nodes.whatsitcodes = whatcodes
+nodes.glyphcodes   = glyphcodes
+
+local free_node    = node.free
+local remove_node  = node.remove
+local new_node     = node.new
+local traverse_id  = node.traverse_id
+
+local math_code    = nodecodes.math
+
+nodes.handlers.protectglyphs   = node.protect_glyphs
+nodes.handlers.unprotectglyphs = node.unprotect_glyphs
+
+function nodes.remove(head, current, free_too)
+   local t = current
+   head, current = remove_node(head,current)
+   if t then
+        if free_too then
+            free_node(t)
+            t = nil
+        else
+            t.next, t.prev = nil, nil
+        end
+   end
+   return head, current, t
+end
+
+function nodes.delete(head,current)
+    return nodes.remove(head,current,true)
+end
+
+nodes.before = node.insert_before
+nodes.after  = node.insert_after
+
+function nodes.pool.kern(k)
+    local n = new_node("kern",1)
+    n.kern = k
+    return n
+end
+
+function nodes.endofmath(n)
+    for n in traverse_id(math_code,n.next) do
+        return n
+    end
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-cbk.lua b/tex/generic/context/luatex/luatex-fonts-cbk.lua
index b4f4c8c91..9db94f65e 100644
--- a/tex/generic/context/luatex/luatex-fonts-cbk.lua
+++ b/tex/generic/context/luatex/luatex-fonts-cbk.lua
@@ -1,68 +1,68 @@
-if not modules then modules = { } end modules ['luatex-fonts-cbk'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts = fonts
-local nodes = nodes
-
--- Fonts: (might move to node-gef.lua)
-
-local traverse_id = node.traverse_id
-local glyph_code  = nodes.nodecodes.glyph
-
-function nodes.handlers.characters(head)
-    local fontdata = fonts.hashes.identifiers
-    if fontdata then
-        local usedfonts, done, prevfont = { }, false, nil
-        for n in traverse_id(glyph_code,head) do
-            local font = n.font
-            if font ~= prevfont then
-                prevfont = font
-                local used = usedfonts[font]
-                if not used then
-                    local tfmdata = fontdata[font] --
-                    if tfmdata then
-                        local shared = tfmdata.shared -- we need to check shared, only when same features
-                        if shared then
-                            local processors = shared.processes
-                            if processors and #processors > 0 then
-                                usedfonts[font] = processors
-                                done = true
-                            end
-                        end
-                    end
-                end
-            end
-        end
-        if done then
-            for font, processors in next, usedfonts do
-                for i=1,#processors do
-                    local h, d = processors[i](head,font,0)
-                    head, done = h or head, done or d
-                end
-            end
-        end
-        return head, true
-    else
-        return head, false
-    end
-end
-
-function nodes.simple_font_handler(head)
---  lang.hyphenate(head)
-    head = nodes.handlers.characters(head)
-    nodes.injections.handler(head)
-    nodes.handlers.protectglyphs(head)
-    head = node.ligaturing(head)
-    head = node.kerning(head)
-    return head
-end
+if not modules then modules = { } end modules ['luatex-fonts-cbk'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts = fonts
+local nodes = nodes
+
+-- Fonts: (might move to node-gef.lua)
+
+local traverse_id = node.traverse_id
+local glyph_code  = nodes.nodecodes.glyph
+
+function nodes.handlers.characters(head)
+    local fontdata = fonts.hashes.identifiers
+    if fontdata then
+        local usedfonts, done, prevfont = { }, false, nil
+        for n in traverse_id(glyph_code,head) do
+            local font = n.font
+            if font ~= prevfont then
+                prevfont = font
+                local used = usedfonts[font]
+                if not used then
+                    local tfmdata = fontdata[font] --
+                    if tfmdata then
+                        local shared = tfmdata.shared -- we need to check shared, only when same features
+                        if shared then
+                            local processors = shared.processes
+                            if processors and #processors > 0 then
+                                usedfonts[font] = processors
+                                done = true
+                            end
+                        end
+                    end
+                end
+            end
+        end
+        if done then
+            for font, processors in next, usedfonts do
+                for i=1,#processors do
+                    local h, d = processors[i](head,font,0)
+                    head, done = h or head, done or d
+                end
+            end
+        end
+        return head, true
+    else
+        return head, false
+    end
+end
+
+function nodes.simple_font_handler(head)
+--  lang.hyphenate(head)
+    head = nodes.handlers.characters(head)
+    nodes.injections.handler(head)
+    nodes.handlers.protectglyphs(head)
+    head = node.ligaturing(head)
+    head = node.kerning(head)
+    return head
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-def.lua b/tex/generic/context/luatex/luatex-fonts-def.lua
index affe763c2..0c2f0dbd5 100644
--- a/tex/generic/context/luatex/luatex-fonts-def.lua
+++ b/tex/generic/context/luatex/luatex-fonts-def.lua
@@ -1,97 +1,97 @@
-if not modules then modules = { } end modules ['luatex-font-def'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts = fonts
-
--- A bit of tuning for definitions.
-
-fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload
-
--- tricky: we sort of bypass the parser and directly feed all into
--- the sub parser
-
-function fonts.definers.getspecification(str)
-    return "", str, "", ":", str
-end
-
--- the generic name parser (different from context!)
-
-local list = { }
-
-local function issome ()    list.lookup = 'name'          end -- xetex mode prefers name (not in context!)
-local function isfile ()    list.lookup = 'file'          end
-local function isname ()    list.lookup = 'name'          end
-local function thename(s)   list.name   = s               end
-local function issub  (v)   list.sub    = v               end
-local function iscrap (s)   list.crap   = string.lower(s) end
-local function iskey  (k,v) list[k]     = v               end
-local function istrue (s)   list[s]     = true            end
-local function isfalse(s)   list[s]     = false           end
-
-local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C
-
-local spaces     = P(" ")^0
-local namespec   = (1-S("/:("))^0 -- was: (1-S("/: ("))^0
-local crapspec   = spaces * P("/") * (((1-P(":"))^0)/iscrap) * spaces
-local filename_1 = P("file:")/isfile * (namespec/thename)
-local filename_2 = P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]")
-local fontname_1 = P("name:")/isname * (namespec/thename)
-local fontname_2 = P(true)/issome * (namespec/thename)
-local sometext   = (R("az","AZ","09") + S("+-."))^1
-local truevalue  = P("+") * spaces * (sometext/istrue)
-local falsevalue = P("-") * spaces * (sometext/isfalse)
-local keyvalue   = (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey
-local somevalue  = sometext/istrue
-local subvalue   = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim
-local option     = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces
-local options    = P(":") * spaces * (P(";")^0  * option)^0
-
-local pattern    = (filename_1 + filename_2 + fontname_1 + fontname_2) * subvalue^0 * crapspec^0 * options^0
-
-local function colonized(specification) -- xetex mode
-    list = { }
-    lpeg.match(pattern,specification.specification)
-    list.crap = nil -- style not supported, maybe some day
-    if list.name then
-        specification.name = list.name
-        list.name = nil
-    end
-    if list.lookup then
-        specification.lookup = list.lookup
-        list.lookup = nil
-    end
-    if list.sub then
-        specification.sub = list.sub
-        list.sub = nil
-    end
-    specification.features.normal = fonts.handlers.otf.features.normalize(list)
-    return specification
-end
-
-fonts.definers.registersplit(":",colonized,"cryptic")
-fonts.definers.registersplit("", colonized,"more cryptic") -- catches \font\text=[names]
-
-function fonts.definers.applypostprocessors(tfmdata)
-    local postprocessors = tfmdata.postprocessors
-    if postprocessors then
-        for i=1,#postprocessors do
-            local extrahash = postprocessors[i](tfmdata) -- after scaling etc
-            if type(extrahash) == "string" and extrahash ~= "" then
-                -- e.g. a reencoding needs this
-                extrahash = string.gsub(lower(extrahash),"[^a-z]","-")
-                tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
-            end
-        end
-    end
-    return tfmdata
-end
+if not modules then modules = { } end modules ['luatex-font-def'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts = fonts
+
+-- A bit of tuning for definitions.
+
+fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload
+
+-- tricky: we sort of bypass the parser and directly feed all into
+-- the sub parser
+
+function fonts.definers.getspecification(str)
+    return "", str, "", ":", str
+end
+
+-- the generic name parser (different from context!)
+
+local list = { }
+
+local function issome ()    list.lookup = 'name'          end -- xetex mode prefers name (not in context!)
+local function isfile ()    list.lookup = 'file'          end
+local function isname ()    list.lookup = 'name'          end
+local function thename(s)   list.name   = s               end
+local function issub  (v)   list.sub    = v               end
+local function iscrap (s)   list.crap   = string.lower(s) end
+local function iskey  (k,v) list[k]     = v               end
+local function istrue (s)   list[s]     = true            end
+local function isfalse(s)   list[s]     = false           end
+
+local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C
+
+local spaces     = P(" ")^0
+local namespec   = (1-S("/:("))^0 -- was: (1-S("/: ("))^0
+local crapspec   = spaces * P("/") * (((1-P(":"))^0)/iscrap) * spaces
+local filename_1 = P("file:")/isfile * (namespec/thename)
+local filename_2 = P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]")
+local fontname_1 = P("name:")/isname * (namespec/thename)
+local fontname_2 = P(true)/issome * (namespec/thename)
+local sometext   = (R("az","AZ","09") + S("+-."))^1
+local truevalue  = P("+") * spaces * (sometext/istrue)
+local falsevalue = P("-") * spaces * (sometext/isfalse)
+local keyvalue   = (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey
+local somevalue  = sometext/istrue
+local subvalue   = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim
+local option     = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces
+local options    = P(":") * spaces * (P(";")^0  * option)^0
+
+local pattern    = (filename_1 + filename_2 + fontname_1 + fontname_2) * subvalue^0 * crapspec^0 * options^0
+
+local function colonized(specification) -- xetex mode
+    list = { }
+    lpeg.match(pattern,specification.specification)
+    list.crap = nil -- style not supported, maybe some day
+    if list.name then
+        specification.name = list.name
+        list.name = nil
+    end
+    if list.lookup then
+        specification.lookup = list.lookup
+        list.lookup = nil
+    end
+    if list.sub then
+        specification.sub = list.sub
+        list.sub = nil
+    end
+    specification.features.normal = fonts.handlers.otf.features.normalize(list)
+    return specification
+end
+
+fonts.definers.registersplit(":",colonized,"cryptic")
+fonts.definers.registersplit("", colonized,"more cryptic") -- catches \font\text=[names]
+
+function fonts.definers.applypostprocessors(tfmdata)
+    local postprocessors = tfmdata.postprocessors
+    if postprocessors then
+        for i=1,#postprocessors do
+            local extrahash = postprocessors[i](tfmdata) -- after scaling etc
+            if type(extrahash) == "string" and extrahash ~= "" then
+                -- e.g. a reencoding needs this
+                extrahash = string.gsub(lower(extrahash),"[^a-z]","-")
+                tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
+            end
+        end
+    end
+    return tfmdata
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua b/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
index 6b622aa05..3878ae648 100644
--- a/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
+++ b/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
@@ -1,38 +1,38 @@
-local identifiers = fonts.hashes.identifiers
-
-return function(specification)
-    local f1, id1 = fonts.constructors.readanddefine('lmroman10-regular',     specification.size)
-    local f2, id2 = fonts.constructors.readanddefine('lmsans10-regular',      specification.size)
-    local f3, id3 = fonts.constructors.readanddefine('lmtypewriter10-regular',specification.size)
-    if f1 and f2 and f3 then
-        f1.properties.name = specification.name
-        f1.properties.virtualized = true
-        f1.fonts = {
-            { id = id1 },
-            { id = id2 },
-            { id = id3 },
-        }
-        local color = { [0] =
-            { "special", "pdf:0 g" },
-            { "special", "pdf:1 0 0 rg" },
-            { "special", "pdf:0 1 0 rg" },
-            { "special", "pdf:0 0 1 rg" },
-        }
-        local chars = {
-            identifiers[id1].characters,
-            identifiers[id2].characters,
-            identifiers[id3].characters,
-        }
-        for u, v in next, f1.characters do
-            local n = math.floor(math.random(1,3)+0.5)
-            local c = chars[n][u] or v
-            v.commands = { color[n], { 'slot', n, u }, color[0] }
-            v.kerns    = nil
-            v.width    = c.width
-            v.height   = c.height
-            v.depth    = c.depth
-            v.italic   = nil
-        end
-    end
-    return f1
-end
+local identifiers = fonts.hashes.identifiers
+
+return function(specification)
+    local f1, id1 = fonts.constructors.readanddefine('lmroman10-regular',     specification.size)
+    local f2, id2 = fonts.constructors.readanddefine('lmsans10-regular',      specification.size)
+    local f3, id3 = fonts.constructors.readanddefine('lmtypewriter10-regular',specification.size)
+    if f1 and f2 and f3 then
+        f1.properties.name = specification.name
+        f1.properties.virtualized = true
+        f1.fonts = {
+            { id = id1 },
+            { id = id2 },
+            { id = id3 },
+        }
+        local color = { [0] =
+            { "special", "pdf:0 g" },
+            { "special", "pdf:1 0 0 rg" },
+            { "special", "pdf:0 1 0 rg" },
+            { "special", "pdf:0 0 1 rg" },
+        }
+        local chars = {
+            identifiers[id1].characters,
+            identifiers[id2].characters,
+            identifiers[id3].characters,
+        }
+        for u, v in next, f1.characters do
+            local n = math.floor(math.random(1,3)+0.5)
+            local c = chars[n][u] or v
+            v.commands = { color[n], { 'slot', n, u }, color[0] }
+            v.kerns    = nil
+            v.width    = c.width
+            v.height   = c.height
+            v.depth    = c.depth
+            v.italic   = nil
+        end
+    end
+    return f1
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-enc.lua b/tex/generic/context/luatex/luatex-fonts-enc.lua
index 03f68118b..e20c3a03b 100644
--- a/tex/generic/context/luatex/luatex-fonts-enc.lua
+++ b/tex/generic/context/luatex/luatex-fonts-enc.lua
@@ -1,28 +1,28 @@
-if not modules then modules = { } end modules ['luatex-font-enc'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts         = fonts
-fonts.encodings     = { }
-fonts.encodings.agl = { }
-
-setmetatable(fonts.encodings.agl, { __index = function(t,k)
-    if k == "unicodes" then
-        texio.write(" <loading (extended) adobe glyph list>")
-        local unicodes = dofile(resolvers.findfile("font-age.lua"))
-        fonts.encodings.agl = { unicodes = unicodes }
-        return unicodes
-    else
-        return nil
-    end
-end })
-
+if not modules then modules = { } end modules ['luatex-font-enc'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts         = fonts
+fonts.encodings     = { }
+fonts.encodings.agl = { }
+
+setmetatable(fonts.encodings.agl, { __index = function(t,k)
+    if k == "unicodes" then
+        texio.write(" <loading (extended) adobe glyph list>")
+        local unicodes = dofile(resolvers.findfile("font-age.lua"))
+        fonts.encodings.agl = { unicodes = unicodes }
+        return unicodes
+    else
+        return nil
+    end
+end })
+
diff --git a/tex/generic/context/luatex/luatex-fonts-ext.lua b/tex/generic/context/luatex/luatex-fonts-ext.lua
index 63927c035..b60d04512 100644
--- a/tex/generic/context/luatex/luatex-fonts-ext.lua
+++ b/tex/generic/context/luatex/luatex-fonts-ext.lua
@@ -1,272 +1,272 @@
-if not modules then modules = { } end modules ['luatex-fonts-ext'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts       = fonts
-local otffeatures = fonts.constructors.newfeatures("otf")
-
--- A few generic extensions.
-
-local function initializeitlc(tfmdata,value)
-    if value then
-        -- the magic 40 and it formula come from Dohyun Kim but we might need another guess
-        local parameters = tfmdata.parameters
-        local italicangle = parameters.italicangle
-        if italicangle and italicangle ~= 0 then
-            local properties = tfmdata.properties
-            local factor = tonumber(value) or 1
-            properties.hasitalics = true
-            properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
-        end
-    end
-end
-
-otffeatures.register {
-    name        = "itlc",
-    description = "italic correction",
-    initializers = {
-        base = initializeitlc,
-        node = initializeitlc,
-    }
-}
-
--- slant and extend
-
-local function initializeslant(tfmdata,value)
-    value = tonumber(value)
-    if not value then
-        value =  0
-    elseif value >  1 then
-        value =  1
-    elseif value < -1 then
-        value = -1
-    end
-    tfmdata.parameters.slantfactor = value
-end
-
-otffeatures.register {
-    name        = "slant",
-    description = "slant glyphs",
-    initializers = {
-        base = initializeslant,
-        node = initializeslant,
-    }
-}
-
-local function initializeextend(tfmdata,value)
-    value = tonumber(value)
-    if not value then
-        value =  0
-    elseif value >  10 then
-        value =  10
-    elseif value < -10 then
-        value = -10
-    end
-    tfmdata.parameters.extendfactor = value
-end
-
-otffeatures.register {
-    name        = "extend",
-    description = "scale glyphs horizontally",
-    initializers = {
-        base = initializeextend,
-        node = initializeextend,
-    }
-}
-
--- expansion and protrusion
-
-fonts.protrusions        = fonts.protrusions        or { }
-fonts.protrusions.setups = fonts.protrusions.setups or { }
-
-local setups = fonts.protrusions.setups
-
-local function initializeprotrusion(tfmdata,value)
-    if value then
-        local setup = setups[value]
-        if setup then
-            local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1
-            local emwidth = tfmdata.parameters.quad
-            tfmdata.parameters.protrusion = {
-                auto = true,
-            }
-            for i, chr in next, tfmdata.characters do
-                local v, pl, pr = setup[i], nil, nil
-                if v then
-                    pl, pr = v[1], v[2]
-                end
-                if pl and pl ~= 0 then chr.left_protruding  = left *pl*factor end
-                if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end
-            end
-        end
-    end
-end
-
-otffeatures.register {
-    name        = "protrusion",
-    description = "shift characters into the left and or right margin",
-    initializers = {
-        base = initializeprotrusion,
-        node = initializeprotrusion,
-    }
-}
-
-fonts.expansions         = fonts.expansions        or { }
-fonts.expansions.setups  = fonts.expansions.setups or { }
-
-local setups = fonts.expansions.setups
-
-local function initializeexpansion(tfmdata,value)
-    if value then
-        local setup = setups[value]
-        if setup then
-            local factor = setup.factor or 1
-            tfmdata.parameters.expansion = {
-                stretch = 10 * (setup.stretch or 0),
-                shrink  = 10 * (setup.shrink  or 0),
-                step    = 10 * (setup.step    or 0),
-                auto    = true,
-            }
-            for i, chr in next, tfmdata.characters do
-                local v = setup[i]
-                if v and v ~= 0 then
-                    chr.expansion_factor = v*factor
-                else -- can be option
-                    chr.expansion_factor = factor
-                end
-            end
-        end
-    end
-end
-
-otffeatures.register {
-    name        = "expansion",
-    description = "apply hz optimization",
-    initializers = {
-        base = initializeexpansion,
-        node = initializeexpansion,
-    }
-}
-
--- left over
-
-function fonts.loggers.onetimemessage() end
-
--- example vectors
-
-local byte = string.byte
-
-fonts.expansions.setups['default'] = {
-
-    stretch = 2, shrink = 2, step = .5, factor = 1,
-
-    [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
-    [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
-    [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
-    [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
-    [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
-    [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
-    [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
-    [byte('w')] = 0.7, [byte('z')] = 0.7,
-    [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
-}
-
-fonts.protrusions.setups['default'] = {
-
-    factor = 1, left = 1, right = 1,
-
-    [0x002C] = { 0, 1    }, -- comma
-    [0x002E] = { 0, 1    }, -- period
-    [0x003A] = { 0, 1    }, -- colon
-    [0x003B] = { 0, 1    }, -- semicolon
-    [0x002D] = { 0, 1    }, -- hyphen
-    [0x2013] = { 0, 0.50 }, -- endash
-    [0x2014] = { 0, 0.33 }, -- emdash
-    [0x3001] = { 0, 1    }, -- ideographic comma      、
-    [0x3002] = { 0, 1    }, -- ideographic full stop  。
-    [0x060C] = { 0, 1    }, -- arabic comma           ،
-    [0x061B] = { 0, 1    }, -- arabic semicolon       ؛
-    [0x06D4] = { 0, 1    }, -- arabic full stop       ۔
-
-}
-
--- normalizer
-
-fonts.handlers.otf.features.normalize = function(t)
-    if t.rand then
-        t.rand = "random"
-    end
-    return t
-end
-
--- bonus
-
-function fonts.helpers.nametoslot(name)
-    local t = type(name)
-    if t == "string" then
-        local tfmdata = fonts.hashes.identifiers[currentfont()]
-        local shared  = tfmdata and tfmdata.shared
-        local fntdata = shared and shared.rawdata
-        return fntdata and fntdata.resources.unicodes[name]
-    elseif t == "number" then
-        return n
-    end
-end
-
--- \font\test=file:somefont:reencode=mymessup
---
---  fonts.encodings.reencodings.mymessup = {
---      [109] = 110, -- m
---      [110] = 109, -- n
---  }
-
-fonts.encodings             = fonts.encodings or { }
-local reencodings           = { }
-fonts.encodings.reencodings = reencodings
-
-local function specialreencode(tfmdata,value)
-    -- we forget about kerns as we assume symbols and we
-    -- could issue a message if ther are kerns but it's
-    -- a hack anyway so we odn't care too much here
-    local encoding = value and reencodings[value]
-    if encoding then
-        local temp = { }
-        local char = tfmdata.characters
-        for k, v in next, encoding do
-            temp[k] = char[v]
-        end
-        for k, v in next, temp do
-            char[k] = temp[k]
-        end
-        -- if we use the font otherwise luatex gets confused so
-        -- we return an additional hash component for fullname
-        return string.format("reencoded:%s",value)
-    end
-end
-
-local function reencode(tfmdata,value)
-    tfmdata.postprocessors = tfmdata.postprocessors or { }
-    table.insert(tfmdata.postprocessors,
-        function(tfmdata)
-            return specialreencode(tfmdata,value)
-        end
-    )
-end
-
-otffeatures.register {
-    name         = "reencode",
-    description  = "reencode characters",
-    manipulators = {
-        base = reencode,
-        node = reencode,
-    }
-}
+if not modules then modules = { } end modules ['luatex-fonts-ext'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts       = fonts
+local otffeatures = fonts.constructors.newfeatures("otf")
+
+-- A few generic extensions.
+
+local function initializeitlc(tfmdata,value)
+    if value then
+        -- the magic 40 and it formula come from Dohyun Kim but we might need another guess
+        local parameters = tfmdata.parameters
+        local italicangle = parameters.italicangle
+        if italicangle and italicangle ~= 0 then
+            local properties = tfmdata.properties
+            local factor = tonumber(value) or 1
+            properties.hasitalics = true
+            properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
+        end
+    end
+end
+
+otffeatures.register {
+    name        = "itlc",
+    description = "italic correction",
+    initializers = {
+        base = initializeitlc,
+        node = initializeitlc,
+    }
+}
+
+-- slant and extend
+
+local function initializeslant(tfmdata,value)
+    value = tonumber(value)
+    if not value then
+        value =  0
+    elseif value >  1 then
+        value =  1
+    elseif value < -1 then
+        value = -1
+    end
+    tfmdata.parameters.slantfactor = value
+end
+
+otffeatures.register {
+    name        = "slant",
+    description = "slant glyphs",
+    initializers = {
+        base = initializeslant,
+        node = initializeslant,
+    }
+}
+
+local function initializeextend(tfmdata,value)
+    value = tonumber(value)
+    if not value then
+        value =  0
+    elseif value >  10 then
+        value =  10
+    elseif value < -10 then
+        value = -10
+    end
+    tfmdata.parameters.extendfactor = value
+end
+
+otffeatures.register {
+    name        = "extend",
+    description = "scale glyphs horizontally",
+    initializers = {
+        base = initializeextend,
+        node = initializeextend,
+    }
+}
+
+-- expansion and protrusion
+
+fonts.protrusions        = fonts.protrusions        or { }
+fonts.protrusions.setups = fonts.protrusions.setups or { }
+
+local setups = fonts.protrusions.setups
+
+local function initializeprotrusion(tfmdata,value)
+    if value then
+        local setup = setups[value]
+        if setup then
+            local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1
+            local emwidth = tfmdata.parameters.quad
+            tfmdata.parameters.protrusion = {
+                auto = true,
+            }
+            for i, chr in next, tfmdata.characters do
+                local v, pl, pr = setup[i], nil, nil
+                if v then
+                    pl, pr = v[1], v[2]
+                end
+                if pl and pl ~= 0 then chr.left_protruding  = left *pl*factor end
+                if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end
+            end
+        end
+    end
+end
+
+otffeatures.register {
+    name        = "protrusion",
+    description = "shift characters into the left and or right margin",
+    initializers = {
+        base = initializeprotrusion,
+        node = initializeprotrusion,
+    }
+}
+
+fonts.expansions         = fonts.expansions        or { }
+fonts.expansions.setups  = fonts.expansions.setups or { }
+
+local setups = fonts.expansions.setups
+
+local function initializeexpansion(tfmdata,value)
+    if value then
+        local setup = setups[value]
+        if setup then
+            local factor = setup.factor or 1
+            tfmdata.parameters.expansion = {
+                stretch = 10 * (setup.stretch or 0),
+                shrink  = 10 * (setup.shrink  or 0),
+                step    = 10 * (setup.step    or 0),
+                auto    = true,
+            }
+            for i, chr in next, tfmdata.characters do
+                local v = setup[i]
+                if v and v ~= 0 then
+                    chr.expansion_factor = v*factor
+                else -- can be option
+                    chr.expansion_factor = factor
+                end
+            end
+        end
+    end
+end
+
+otffeatures.register {
+    name        = "expansion",
+    description = "apply hz optimization",
+    initializers = {
+        base = initializeexpansion,
+        node = initializeexpansion,
+    }
+}
+
+-- left over
+
+function fonts.loggers.onetimemessage() end
+
+-- example vectors
+
+local byte = string.byte
+
+fonts.expansions.setups['default'] = {
+
+    stretch = 2, shrink = 2, step = .5, factor = 1,
+
+    [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
+    [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
+    [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
+    [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
+    [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
+    [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
+    [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
+    [byte('w')] = 0.7, [byte('z')] = 0.7,
+    [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
+}
+
+fonts.protrusions.setups['default'] = {
+
+    factor = 1, left = 1, right = 1,
+
+    [0x002C] = { 0, 1    }, -- comma
+    [0x002E] = { 0, 1    }, -- period
+    [0x003A] = { 0, 1    }, -- colon
+    [0x003B] = { 0, 1    }, -- semicolon
+    [0x002D] = { 0, 1    }, -- hyphen
+    [0x2013] = { 0, 0.50 }, -- endash
+    [0x2014] = { 0, 0.33 }, -- emdash
+    [0x3001] = { 0, 1    }, -- ideographic comma      、
+    [0x3002] = { 0, 1    }, -- ideographic full stop  。
+    [0x060C] = { 0, 1    }, -- arabic comma           ،
+    [0x061B] = { 0, 1    }, -- arabic semicolon       ؛
+    [0x06D4] = { 0, 1    }, -- arabic full stop       ۔
+
+}
+
+-- normalizer
+
+fonts.handlers.otf.features.normalize = function(t)
+    if t.rand then
+        t.rand = "random"
+    end
+    return t
+end
+
+-- bonus
+
+function fonts.helpers.nametoslot(name)
+    local t = type(name)
+    if t == "string" then
+        local tfmdata = fonts.hashes.identifiers[currentfont()]
+        local shared  = tfmdata and tfmdata.shared
+        local fntdata = shared and shared.rawdata
+        return fntdata and fntdata.resources.unicodes[name]
+    elseif t == "number" then
+        return n
+    end
+end
+
+-- \font\test=file:somefont:reencode=mymessup
+--
+--  fonts.encodings.reencodings.mymessup = {
+--      [109] = 110, -- m
+--      [110] = 109, -- n
+--  }
+
+fonts.encodings             = fonts.encodings or { }
+local reencodings           = { }
+fonts.encodings.reencodings = reencodings
+
+local function specialreencode(tfmdata,value)
+    -- we forget about kerns as we assume symbols and we
+    -- could issue a message if ther are kerns but it's
+    -- a hack anyway so we odn't care too much here
+    local encoding = value and reencodings[value]
+    if encoding then
+        local temp = { }
+        local char = tfmdata.characters
+        for k, v in next, encoding do
+            temp[k] = char[v]
+        end
+        for k, v in next, temp do
+            char[k] = temp[k]
+        end
+        -- if we use the font otherwise luatex gets confused so
+        -- we return an additional hash component for fullname
+        return string.format("reencoded:%s",value)
+    end
+end
+
+local function reencode(tfmdata,value)
+    tfmdata.postprocessors = tfmdata.postprocessors or { }
+    table.insert(tfmdata.postprocessors,
+        function(tfmdata)
+            return specialreencode(tfmdata,value)
+        end
+    )
+end
+
+otffeatures.register {
+    name         = "reencode",
+    description  = "reencode characters",
+    manipulators = {
+        base = reencode,
+        node = reencode,
+    }
+}
diff --git a/tex/generic/context/luatex/luatex-fonts-lua.lua b/tex/generic/context/luatex/luatex-fonts-lua.lua
index 9aa45fd22..ec3fe38be 100644
--- a/tex/generic/context/luatex/luatex-fonts-lua.lua
+++ b/tex/generic/context/luatex/luatex-fonts-lua.lua
@@ -1,33 +1,33 @@
-if not modules then modules = { } end modules ['luatex-fonts-lua'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts       = fonts
-fonts.formats.lua = "lua"
-
-function fonts.readers.lua(specification)
-    local fullname = specification.filename or ""
-    if fullname == "" then
-        local forced = specification.forced or ""
-        if forced ~= "" then
-            fullname = specification.name .. "." .. forced
-        else
-            fullname = specification.name
-        end
-    end
-    local fullname = resolvers.findfile(fullname) or ""
-    if fullname ~= "" then
-        local loader = loadfile(fullname)
-        loader = loader and loader()
-        return loader and loader(specification)
-    end
-end
+if not modules then modules = { } end modules ['luatex-fonts-lua'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts       = fonts
+fonts.formats.lua = "lua"
+
+function fonts.readers.lua(specification)
+    local fullname = specification.filename or ""
+    if fullname == "" then
+        local forced = specification.forced or ""
+        if forced ~= "" then
+            fullname = specification.name .. "." .. forced
+        else
+            fullname = specification.name
+        end
+    end
+    local fullname = resolvers.findfile(fullname) or ""
+    if fullname ~= "" then
+        local loader = loadfile(fullname)
+        loader = loader and loader()
+        return loader and loader(specification)
+    end
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index c8923a436..71f6e79a4 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,49 +1,49 @@
 -- merged file : luatex-fonts-merged.lua
 -- parent file : luatex-fonts.lua
--- merge date  : 05/19/13 19:27:29
+-- merge date  : 05/20/13 02:00:30
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
 local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
-_MAJORVERSION=tonumber(major) or 5
-_MINORVERSION=tonumber(minor) or 1
+_MAJORVERSION=tonumber(major) or 5
+_MINORVERSION=tonumber(minor) or 1
 _LUAVERSION=_MAJORVERSION+_MINORVERSION/10
-if not lpeg then
-  lpeg=require("lpeg")
+if not lpeg then
+  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
+  function load(first,...)
+    if type(first)=="string" then
+      return loadstring(first,...)
+    else
+      return loadnormal(first,...)
+    end
   end
 else
   loadstring=load
 end
 if not ipairs then
-  local function iterate(a,i)
-    i=i+1
-    local v=a[i]
-    if v~=nil then
+  local function iterate(a,i)
+    i=i+1
+    local v=a[i]
+    if v~=nil then
       return i,v 
-    end
+    end
   end
-  function ipairs(a)
-    return iterate,a,0
+  function ipairs(a)
+    return iterate,a,0
   end
 end
 if not pairs then
-  function pairs(t)
+  function pairs(t)
     return next,t 
   end
 end
@@ -58,602 +58,602 @@ end
 local print,select,tostring=print,select,tostring
 local inspectors={}
 function setinspector(inspector) 
-  inspectors[#inspectors+1]=inspector
+  inspectors[#inspectors+1]=inspector
 end
 function inspect(...) 
-  for s=1,select("#",...) do
-    local value=select(s,...)
-    local done=false
-    for i=1,#inspectors do
-      done=inspectors[i](value)
-      if done then
-        break
-      end
-    end
-    if not done then
-      print(tostring(value))
-    end
-  end
+  for s=1,select("#",...) do
+    local value=select(s,...)
+    local done=false
+    for i=1,#inspectors do
+      done=inspectors[i](value)
+      if done then
+        break
+      end
+    end
+    if not done then
+      print(tostring(value))
+    end
+  end
 end
 local dummy=function() end
-function optionalrequire(...)
-  local ok,result=xpcall(require,dummy,...)
-  if ok then
-    return result
-  end
-end
+function optionalrequire(...)
+  local ok,result=xpcall(require,dummy,...)
+  if ok then
+    return result
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
 lpeg=require("lpeg")
-local type,next,tostring=type,next,tostring
+local type,next,tostring=type,next,tostring
 local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
 local floor=math.floor
-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 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
 setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
 lpeg.patterns=lpeg.patterns or {} 
 local patterns=lpeg.patterns
-local anything=P(1)
-local endofstring=P(-1)
+local anything=P(1)
+local endofstring=P(-1)
 local alwaysmatched=P(true)
-patterns.anything=anything
-patterns.endofstring=endofstring
-patterns.beginofstring=alwaysmatched
+patterns.anything=anything
+patterns.endofstring=endofstring
+patterns.beginofstring=alwaysmatched
 patterns.alwaysmatched=alwaysmatched
-local digit,sign=R('09'),S('+-')
-local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
+local digit,sign=R('09'),S('+-')
+local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
 local newline=crlf+S("\r\n") 
-local escaped=P("\\")*anything
-local squote=P("'")
-local dquote=P('"')
+local escaped=P("\\")*anything
+local squote=P("'")
+local dquote=P('"')
 local space=P(" ")
-local utfbom_32_be=P('\000\000\254\255')
-local utfbom_32_le=P('\255\254\000\000')
-local utfbom_16_be=P('\255\254')
-local utfbom_16_le=P('\254\255')
-local utfbom_8=P('\239\187\191')
-local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
+local utfbom_32_be=P('\000\000\254\255')
+local utfbom_32_le=P('\255\254\000\000')
+local utfbom_16_be=P('\255\254')
+local utfbom_16_le=P('\254\255')
+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 utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0)
 local utf8next=R("\128\191")
-patterns.utf8one=R("\000\127")
-patterns.utf8two=R("\194\223")*utf8next
-patterns.utf8three=R("\224\239")*utf8next*utf8next
-patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
-patterns.utfbom=utfbom
-patterns.utftype=utftype
+patterns.utf8one=R("\000\127")
+patterns.utf8two=R("\194\223")*utf8next
+patterns.utf8three=R("\224\239")*utf8next*utf8next
+patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
+patterns.utfbom=utfbom
+patterns.utftype=utftype
 patterns.utfoffset=utfoffset
-local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
+local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
 local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false)
 local utf8character=P(1)*R("\128\191")^0 
-patterns.utf8=utf8char
-patterns.utf8char=utf8char
+patterns.utf8=utf8char
+patterns.utf8char=utf8char
 patterns.utf8character=utf8character 
-patterns.validutf8=validutf8char
+patterns.validutf8=validutf8char
 patterns.validutf8char=validutf8char
-local eol=S("\n\r")
+local eol=S("\n\r")
 local spacer=S(" \t\f\v") 
-local whitespace=eol+spacer
-local nonspacer=1-spacer
+local whitespace=eol+spacer
+local nonspacer=1-spacer
 local nonwhitespace=1-whitespace
-patterns.eol=eol
-patterns.spacer=spacer
-patterns.whitespace=whitespace
-patterns.nonspacer=nonspacer
+patterns.eol=eol
+patterns.spacer=spacer
+patterns.whitespace=whitespace
+patterns.nonspacer=nonspacer
 patterns.nonwhitespace=nonwhitespace
 local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
 local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
-patterns.stripper=stripper
+patterns.stripper=stripper
 patterns.collapser=collapser
-patterns.digit=digit
-patterns.sign=sign
-patterns.cardinal=sign^0*digit^1
-patterns.integer=sign^0*digit^1
-patterns.unsigned=digit^0*P('.')*digit^1
-patterns.float=sign^0*patterns.unsigned
-patterns.cunsigned=digit^0*P(',')*digit^1
-patterns.cfloat=sign^0*patterns.cunsigned
-patterns.number=patterns.float+patterns.integer
-patterns.cnumber=patterns.cfloat+patterns.integer
-patterns.oct=P("0")*R("07")^1
-patterns.octal=patterns.oct
-patterns.HEX=P("0x")*R("09","AF")^1
-patterns.hex=P("0x")*R("09","af")^1
-patterns.hexadecimal=P("0x")*R("09","AF","af")^1
-patterns.lowercase=R("az")
-patterns.uppercase=R("AZ")
-patterns.letter=patterns.lowercase+patterns.uppercase
-patterns.space=space
-patterns.tab=P("\t")
-patterns.spaceortab=patterns.space+patterns.tab
-patterns.newline=newline
-patterns.emptyline=newline^1
-patterns.equal=P("=")
-patterns.comma=P(",")
-patterns.commaspacer=P(",")*spacer^0
-patterns.period=P(".")
-patterns.colon=P(":")
-patterns.semicolon=P(";")
-patterns.underscore=P("_")
-patterns.escaped=escaped
-patterns.squote=squote
-patterns.dquote=dquote
-patterns.nosquote=(escaped+(1-squote))^0
-patterns.nodquote=(escaped+(1-dquote))^0
+patterns.digit=digit
+patterns.sign=sign
+patterns.cardinal=sign^0*digit^1
+patterns.integer=sign^0*digit^1
+patterns.unsigned=digit^0*P('.')*digit^1
+patterns.float=sign^0*patterns.unsigned
+patterns.cunsigned=digit^0*P(',')*digit^1
+patterns.cfloat=sign^0*patterns.cunsigned
+patterns.number=patterns.float+patterns.integer
+patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.oct=P("0")*R("07")^1
+patterns.octal=patterns.oct
+patterns.HEX=P("0x")*R("09","AF")^1
+patterns.hex=P("0x")*R("09","af")^1
+patterns.hexadecimal=P("0x")*R("09","AF","af")^1
+patterns.lowercase=R("az")
+patterns.uppercase=R("AZ")
+patterns.letter=patterns.lowercase+patterns.uppercase
+patterns.space=space
+patterns.tab=P("\t")
+patterns.spaceortab=patterns.space+patterns.tab
+patterns.newline=newline
+patterns.emptyline=newline^1
+patterns.equal=P("=")
+patterns.comma=P(",")
+patterns.commaspacer=P(",")*spacer^0
+patterns.period=P(".")
+patterns.colon=P(":")
+patterns.semicolon=P(";")
+patterns.underscore=P("_")
+patterns.escaped=escaped
+patterns.squote=squote
+patterns.dquote=dquote
+patterns.nosquote=(escaped+(1-squote))^0
+patterns.nodquote=(escaped+(1-dquote))^0
 patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"") 
 patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"") 
 patterns.unquoted=patterns.undouble+patterns.unsingle 
 patterns.unspacer=((patterns.spacer^1)/"")^0
-patterns.singlequoted=squote*patterns.nosquote*squote
-patterns.doublequoted=dquote*patterns.nodquote*dquote
+patterns.singlequoted=squote*patterns.nosquote*squote
+patterns.doublequoted=dquote*patterns.nodquote*dquote
 patterns.quoted=patterns.doublequoted+patterns.singlequoted
 patterns.propername=R("AZ","az","__")*R("09","AZ","az","__")^0*P(-1)
 patterns.somecontent=(anything-newline-space)^1 
 patterns.beginline=#(1-newline)
 patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
 local function anywhere(pattern) 
-  return P { P(pattern)+1*V(1) }
+  return P { P(pattern)+1*V(1) }
 end
 lpeg.anywhere=anywhere
-function lpeg.instringchecker(p)
-  p=anywhere(p)
-  return function(str)
-    return lpegmatch(p,str) and true or false
-  end
+function lpeg.instringchecker(p)
+  p=anywhere(p)
+  return function(str)
+    return lpegmatch(p,str) and true or false
+  end
 end
-function lpeg.splitter(pattern,action)
-  return (((1-P(pattern))^1)/action+1)^0
+function lpeg.splitter(pattern,action)
+  return (((1-P(pattern))^1)/action+1)^0
 end
-function lpeg.tsplitter(pattern,action)
-  return Ct((((1-P(pattern))^1)/action+1)^0)
+function lpeg.tsplitter(pattern,action)
+  return Ct((((1-P(pattern))^1)/action+1)^0)
 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
+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
-  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
-end
-lpeg.splitat=splitat
+      splitters_s[separator]=splitter
+    else
+      splitter=other*(separator*other)^0
+      splitters_m[separator]=splitter
+    end
+  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
+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)
+function string.splitup(str,separator)
+  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
-    end
-    return lpegmatch(c,str)
-  else
-    return { str }
-  end
+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
+    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
+local empty=spacing*Cc("")
+local nonempty=Cs((1-spacing)^1)*spacing^-1
 local content=(empty+nonempty)^1
 patterns.textline=content
 local linesplitter=tsplitat(newline)
 patterns.linesplitter=linesplitter
-function string.splitlines(str)
-  return lpegmatch(linesplitter,str)
+function string.splitlines(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)
-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)
-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
+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)
+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)
+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)
-  end
+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)
+  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)
-  end
+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)
+  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]
+  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
-  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)
-  local pattern
-  if type(lst)=="table" then
-    pattern=P(false)
-    if #lst==0 then
-      for k,v in next,lst do
+      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
+  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)
+  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
-  else
-    pattern=P(lst)
-  end
-  pattern=(1-pattern)^0*pattern
-  if makefunction then
-    return function(str)
-      return lpegmatch(pattern,str)
-    end
-  else
-    return pattern
-  end
+      end
+    else
+      for i=1,#lst do
+        pattern=pattern+P(lst[i])
+      end
+    end
+  else
+    pattern=P(lst)
+  end
+  pattern=(1-pattern)^0*pattern
+  if makefunction then
+    return function(str)
+      return lpegmatch(pattern,str)
+    end
+  else
+    return pattern
+  end
 end
 local splitters_f,splitters_s={},{}
 function lpeg.firstofsplit(separator) 
-  local splitter=splitters_f[separator]
-  if not splitter then
-    separator=P(separator)
-    splitter=C((1-separator)^0)
-    splitters_f[separator]=splitter
-  end
-  return splitter
+  local splitter=splitters_f[separator]
+  if not splitter then
+    separator=P(separator)
+    splitter=C((1-separator)^0)
+    splitters_f[separator]=splitter
+  end
+  return splitter
 end
 function lpeg.secondofsplit(separator) 
-  local splitter=splitters_s[separator]
-  if not splitter then
-    separator=P(separator)
-    splitter=(1-separator)^0*separator*C(anything^0)
-    splitters_s[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 }
+  local splitter=splitters_s[separator]
+  if not splitter then
+    separator=P(separator)
+    splitter=(1-separator)^0*separator*C(anything^0)
+    splitters_s[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 }
 end
 local nany=utf8char/""
-function lpeg.counter(pattern)
-  pattern=Cs((P(pattern)/" "+nany)^0)
-  return function(str)
-    return #lpegmatch(pattern,str)
-  end
+function lpeg.counter(pattern)
+  pattern=Cs((P(pattern)/" "+nany)^0)
+  return function(str)
+    return #lpegmatch(pattern,str)
+  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 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
+  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
+  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
+  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)
+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
+    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
+  else
+    local f=function(b)
+      return b>=first and b<=last
     end
     return utf8byte/f 
-  end
+  end
 end
-function lpeg.is_lpeg(p)
-  return p and lpegtype(p)=="pattern"
+function lpeg.is_lpeg(p)
+  return p and lpegtype(p)=="pattern"
 end
 function lpeg.oneof(list,...) 
-  if type(list)~="table" then
-    list={ 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
+  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
-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
-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
+local function copyindexed(old)
+  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
+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)
-    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
-          p=P(k)+p
-        else
-          p=P(k)
-        end
-      end
-      if p then
-        p=p/list
-      end
-    end
+    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
+          p=P(k)+p
+        else
+          p=P(k)
+        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
-        if k==v then
-          p=P(k)
-        else
-          p=P(k)/v
-        end
-      end
-    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
-    end
-  end
-  return p
-end
-local function make(t)
-  local p
-  local keys=sortedkeys(t)
-  for i=1,#keys do
-    local k=keys[i]
-    local v=t[k]
-    if not p then
-      if next(v) then
-        p=P(k)*make(v)
-      else
-        p=P(k)
-      end
-    else
-      if next(v) then
-        p=p+P(k)*make(v)
-      else
-        p=p+P(k)
-      end
-    end
-  end
-  return p
+    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
+  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 function make(t)
+  local p
+  local keys=sortedkeys(t)
+  for i=1,#keys do
+    local k=keys[i]
+    local v=t[k]
+    if not p then
+      if next(v) then
+        p=P(k)*make(v)
+      else
+        p=P(k)
+      end
+    else
+      if next(v) then
+        p=p+P(k)*make(v)
+      else
+        p=p+P(k)
+      end
+    end
+  end
+  return p
 end
 function lpeg.utfchartabletopattern(list) 
-  local tree={}
-  for i=1,#list do
-    local t=tree
-    for c in gmatch(list[i],".") do
-      if not t[c] then
-        t[c]={}
-      end
-      t=t[c]
-    end
-  end
-  return make(tree)
+  local tree={}
+  for i=1,#list do
+    local t=tree
+    for c in gmatch(list[i],".") do
+      if not t[c] then
+        t[c]={}
+      end
+      t=t[c]
+    end
+  end
+  return make(tree)
 end
 patterns.containseol=lpeg.finder(eol)
-local function nextstep(n,step,result)
+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
-  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 }))
-end
-local digit=R("09")
-local period=P(".")
-local zero=P("0")
+  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
+  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 }))
+end
+local digit=R("09")
+local period=P(".")
+local zero=P("0")
 local trailingzeros=zero^0*-digit 
-local case_1=period*trailingzeros/""
-local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
-local number=digit^1*(case_1+case_2)
+local case_1=period*trailingzeros/""
+local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
+local number=digit^1*(case_1+case_2)
 local stripper=Cs((number+1)^0)
 lpeg.patterns.stripzeros=stripper
 
@@ -661,1281 +661,1281 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
 functions=functions or {}
-function functions.dummy() end
+function functions.dummy() end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
-local string=string
-local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local string=string
+local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
 local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs
 local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote
-function string.unquoted(str)
-  return lpegmatch(unquoted,str) or str
+function string.unquoted(str)
+  return lpegmatch(unquoted,str) or str
 end
-function string.quoted(str)
+function string.quoted(str)
   return format("%q",str) 
 end
 function string.count(str,pattern) 
-  local n=0
+  local n=0
   for _ in gmatch(str,pattern) do 
-    n=n+1
-  end
-  return n
+    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
-end
-local stripper=patterns.stripper
-local collapser=patterns.collapser
+  if #str>n then
+    sentinel=sentinel or "..."
+    return sub(str,1,(n-#sentinel))..sentinel
+  else
+    return str
+  end
+end
+local stripper=patterns.stripper
+local collapser=patterns.collapser
 local longtostring=patterns.longtostring
-function string.strip(str)
-  return lpegmatch(stripper,str) or ""
+function string.strip(str)
+  return lpegmatch(stripper,str) or ""
 end
-function string.collapsespaces(str)
-  return lpegmatch(collapser,str) or ""
+function string.collapsespaces(str)
+  return lpegmatch(collapser,str) or ""
 end
-function string.longtostring(str)
-  return lpegmatch(longtostring,str) or ""
+function string.longtostring(str)
+  return lpegmatch(longtostring,str) or ""
 end
 local pattern=P(" ")^0*P(-1)
-function string.is_empty(str)
-  if str=="" then
-    return true
-  else
-    return lpegmatch(pattern,str) and true or false
-  end
-end
-local anything=patterns.anything
+function string.is_empty(str)
+  if 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 pattern_a=Cs ((allescapes+anything )^0 )
-local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
+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)
-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
-end
-function string.valid(str,default)
-  return (type(str)=="string" and str~="" and str) or default or nil
+function string.escapedpattern(str,simple)
+  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
+end
+function string.valid(str,default)
+  return (type(str)=="string" and str~="" and str) or default or nil
 end
 string.itself=function(s) return s end
 local pattern=Ct(C(1)^0) 
-function string.totable(str)
-  return lpegmatch(pattern,str)
+function string.totable(str)
+  return lpegmatch(pattern,str)
 end
 local replacer=lpeg.replacer("@","%%") 
-function string.tformat(fmt,...)
-  return format(lpegmatch(replacer,fmt),...)
+function string.tformat(fmt,...)
+  return format(lpegmatch(replacer,fmt),...)
 end
-string.quote=string.quoted
-string.unquote=string.unquoted
+string.quote=string.quoted
+string.unquote=string.unquoted
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
-local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
-local table,string=table,string
-local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
-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 type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
+local table,string=table,string
+local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+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.strip(tab)
-  local lst,l={},0
-  for i=1,#tab do
-    local s=lpegmatch(stripper,tab[i]) or ""
+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
-  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 {}
-  end
-end
-local function compare(a,b)
+    else
+      l=l+1
+      lst[l]=s
+    end
+  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 {}
+  end
+end
+local function compare(a,b)
   local ta,tb=type(a),type(b) 
-  if ta==tb then
-    return a<b
-  else
-    return tostring(a)<tostring(b)
-  end
-end
-local function sortedkeys(tab)
-  if tab then
+  if ta==tb then
+    return a<b
+  else
+    return tostring(a)<tostring(b)
+  end
+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
+    for key,_ in next,tab do
+      s=s+1
+      srt[s]=key
       if category==3 then
-      else
-        local tkey=type(key)
-        if tkey=="string" then
-          category=(category==2 and 3) or 1
-        elseif tkey=="number" then
-          category=(category==1 and 3) or 2
-        else
-          category=3
-        end
-      end
-    end
-    if category==0 or category==3 then
-      sort(srt,compare)
-    else
-      sort(srt)
-    end
-    return srt
-  else
-    return {}
-  end
+      else
+        local tkey=type(key)
+        if tkey=="string" then
+          category=(category==2 and 3) or 1
+        elseif tkey=="number" then
+          category=(category==1 and 3) or 2
+        else
+          category=3
+        end
+      end
+    end
+    if category==0 or category==3 then
+      sort(srt,compare)
+    else
+      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
-    sort(srt,cmp)
-    return srt
-  else
-    return {}
-  end
-end
-function table.allkeys(t)
-  local keys={}
-  for k,v in next,t do
-    for k,v in next,v do
-      keys[k]=true
-    end
-  end
-  return sortedkeys(keys)
-end
-table.sortedkeys=sortedkeys
+  if tab then
+    local srt,s={},0
+    for key,_ in next,tab do
+      if key then
+        s=s+1
+        srt[s]=key
+      end
+    end
+    sort(srt,cmp)
+    return srt
+  else
+    return {}
+  end
+end
+function table.allkeys(t)
+  local keys={}
+  for k,v in next,t do
+    for k,v in next,v do
+      keys[k]=true
+    end
+  end
+  return sortedkeys(keys)
+end
+table.sortedkeys=sortedkeys
 table.sortedhashkeys=sortedhashkeys
 local function nothing() end
-local function sortedhash(t,cmp)
-  if t then
-    local s
+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=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+    else
       s=sortedkeys(t) 
-    end
-    local n=0
-    local function kv(s)
-      n=n+1
-      local k=s[n]
-      return k,t[k]
-    end
-    return kv,s
-  else
-    return nothing
-  end
-end
-table.sortedhash=sortedhash
+    end
+    local n=0
+    local function kv(s)
+      n=n+1
+      local k=s[n]
+      return k,t[k]
+    end
+    return kv,s
+  else
+    return nothing
+  end
+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
-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
+function table.append(t,list)
+  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
 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
-  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
-  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
-  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
-  end
-  return tmp
+  t=t or {}
+  for i=1,select("#",...) do
+    for k,v in next,(select(i,...)) do
+      t[k]=v
+    end
+  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
+  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
+  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
+  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
+  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
+      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
+      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
-  end
+  tables=tables or {}
+  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
-    if type(v)~="table" then
-      tcopy[i]=v
-    elseif tables[v] then
-      tcopy[i]=tables[v]
-    else
-      tcopy[i]=copy(v,tables)
-    end
-  end
-  local mt=getmetatable(t)
-  if mt then
-    setmetatable(tcopy,mt)
-  end
-  return tcopy
-end
-table.fastcopy=fastcopy
+    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
+  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
-end
-function table.tohash(t,value)
-  local h={}
-  if t then
-    if value==nil then value=true end
+  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
-  end
-  return h
+      h[v]=value
+    end
+  end
+  return h
 end
-function table.fromhash(t)
-  local hsh,h={},0
+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
-  end
-  return hsh
+    if v then
+      h=h+1
+      hsh[h]=k
+    end
+  end
+  return hsh
 end
 local noquotes,hexify,handle,reduce,compact,inline,functions
 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',
+  'and','break','do','else','elseif','end','false','for','function','if',
+  'in','local','nil','not','or','repeat','return','then','true','until','while',
 }
-local function simple_table(t)
-  if #t>0 then
-    local n=0
-    for _,v in next,t do
-      n=n+1
-    end
-    if n==#t then
-      local tt,nt={},0
-      for i=1,#t do
-        local v=t[i]
-        local tv=type(v)
-        if tv=="number" then
-          nt=nt+1
-          if hexify then
-            tt[nt]=format("0x%04X",v)
-          else
+local function simple_table(t)
+  if #t>0 then
+    local n=0
+    for _,v in next,t do
+      n=n+1
+    end
+    if n==#t then
+      local tt,nt={},0
+      for i=1,#t do
+        local v=t[i]
+        local tv=type(v)
+        if tv=="number" then
+          nt=nt+1
+          if hexify then
+            tt[nt]=format("0x%04X",v)
+          else
             tt[nt]=tostring(v) 
-          end
-        elseif tv=="boolean" then
-          nt=nt+1
-          tt[nt]=tostring(v)
-        elseif tv=="string" then
-          nt=nt+1
-          tt[nt]=format("%q",v)
-        else
-          tt=nil
-          break
-        end
-      end
-      return tt
-    end
-  end
-  return nil
+          end
+        elseif tv=="boolean" then
+          nt=nt+1
+          tt[nt]=tostring(v)
+        elseif tv=="string" then
+          nt=nt+1
+          tt[nt]=format("%q",v)
+        else
+          tt=nil
+          break
+        end
+      end
+      return tt
+    end
+  end
+  return nil
 end
 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))
-    else
-      local tn=type(name)
-      if tn=="number" then
-        if hexify then
-          handle(format("%s[0x%04X]={",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,tostring(name)))
-      else
-        handle(format("%s{",depth))
-      end
-    end
+local function do_serialize(root,name,depth,level,indexed)
+  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%04X]={",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,tostring(name)))
+      else
+        handle(format("%s{",depth))
+      end
+    end
   end
   if root and next(root) then
-    local first,last=nil,0
-    if compact then
-      last=#root
-      for k=1,last do
-        if root[k]==nil then
-          last=k-1
-          break
-        end
-      end
-      if last>0 then
-        first=1
-      end
-    end
-    local sk=sortedkeys(root)
-    for i=1,#sk do
-      local k=sk[i]
+    local first,last=nil,0
+    if compact then
+      last=#root
+      for k=1,last do
+        if root[k]==nil then
+          last=k-1
+          break
+        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 t,tk=type(v),type(k)
-      if compact and first and tk=="number" and k>=first and k<=last then
-        if t=="number" then
-          if hexify then
-            handle(format("%s 0x%04X,",depth,v))
-          else
+      local t,tk=type(v),type(k)
+      if compact and first and tk=="number" and k>=first and k<=last then
+        if t=="number" then
+          if hexify then
+            handle(format("%s 0x%04X,",depth,v))
+          else
             handle(format("%s %s,",depth,v)) 
-          end
-        elseif t=="string" then
-          if reduce and tonumber(v) then
-            handle(format("%s %s,",depth,v))
-          else
-            handle(format("%s %q,",depth,v))
-          end
-        elseif t=="table" then
-          if not next(v) then
-            handle(format("%s {},",depth))
+          end
+        elseif t=="string" then
+          if reduce and tonumber(v) then
+            handle(format("%s %s,",depth,v))
+          else
+            handle(format("%s %q,",depth,v))
+          end
+        elseif t=="table" then
+          if not next(v) then
+            handle(format("%s {},",depth))
           elseif inline then 
-            local st=simple_table(v)
-            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 t=="boolean" then
-          handle(format("%s %s,",depth,tostring(v)))
-        elseif t=="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
+            local st=simple_table(v)
+            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 t=="boolean" then
+          handle(format("%s %s,",depth,tostring(v)))
+        elseif t=="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 t=="number" then
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
-          else
+        if false then
+          handle(format("%s __p__=nil,",depth))
+        end
+      elseif t=="number" then
+        if tk=="number" then
+          if hexify then
+            handle(format("%s [0x%04X]=0x%04X,",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%04X,",depth,tostring(k),v))
-          else
+          end
+        elseif tk=="boolean" then
+          if hexify then
+            handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
+          else
             handle(format("%s [%s]=%s,",depth,tostring(k),v)) 
-          end
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          if hexify then
-            handle(format("%s %s=0x%04X,",depth,k,v))
-          else
+          end
+        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+          if hexify then
+            handle(format("%s %s=0x%04X,",depth,k,v))
+          else
             handle(format("%s %s=%s,",depth,k,v)) 
-          end
-        else
-          if hexify then
-            handle(format("%s [%q]=0x%04X,",depth,k,v))
-          else
+          end
+        else
+          if hexify then
+            handle(format("%s [%q]=0x%04X,",depth,k,v))
+          else
             handle(format("%s [%q]=%s,",depth,k,v)) 
-          end
-        end
-      elseif t=="string" then
-        if reduce and tonumber(v) then
-          if tk=="number" then
-            if hexify then
-              handle(format("%s [0x%04X]=%s,",depth,k,v))
-            else
-              handle(format("%s [%s]=%s,",depth,k,v))
-            end
-          elseif tk=="boolean" then
-            handle(format("%s [%s]=%s,",depth,tostring(k),v))
-          elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-            handle(format("%s %s=%s,",depth,k,v))
-          else
-            handle(format("%s [%q]=%s,",depth,k,v))
-          end
-        else
-          if tk=="number" then
-            if hexify then
-              handle(format("%s [0x%04X]=%q,",depth,k,v))
-            else
-              handle(format("%s [%s]=%q,",depth,k,v))
-            end
-          elseif tk=="boolean" then
-            handle(format("%s [%s]=%q,",depth,tostring(k),v))
-          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
-        end
-      elseif t=="table" then
-        if not next(v) then
-          if tk=="number" then
-            if hexify then
-              handle(format("%s [0x%04X]={},",depth,k))
-            else
-              handle(format("%s [%s]={},",depth,k))
-            end
-          elseif tk=="boolean" then
-            handle(format("%s [%s]={},",depth,tostring(k)))
-          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=simple_table(v)
-          if st then
-            if tk=="number" then
-              if hexify then
-                handle(format("%s [0x%04X]={ %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,tostring(k),concat(st,", ")))
-            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 t=="boolean" then
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
-          else
-            handle(format("%s [%s]=%s,",depth,k,tostring(v)))
-          end
-        elseif tk=="boolean" then
-          handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
-        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
-          handle(format("%s %s=%s,",depth,k,tostring(v)))
-        else
-          handle(format("%s [%q]=%s,",depth,k,tostring(v)))
-        end
-      elseif t=="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%04X]=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,tostring(k),f))
-          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
-      else
-        if tk=="number" then
-          if hexify then
-            handle(format("%s [0x%04X]=%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,tostring(k),tostring(v)))
-        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
-      end
-    end
-  end
-  if level>0 then
-    handle(format("%s},",depth))
-  end
+          end
+        end
+      elseif t=="string" then
+        if reduce and tonumber(v) then
+          if tk=="number" then
+            if hexify then
+              handle(format("%s [0x%04X]=%s,",depth,k,v))
+            else
+              handle(format("%s [%s]=%s,",depth,k,v))
+            end
+          elseif tk=="boolean" then
+            handle(format("%s [%s]=%s,",depth,tostring(k),v))
+          elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+            handle(format("%s %s=%s,",depth,k,v))
+          else
+            handle(format("%s [%q]=%s,",depth,k,v))
+          end
+        else
+          if tk=="number" then
+            if hexify then
+              handle(format("%s [0x%04X]=%q,",depth,k,v))
+            else
+              handle(format("%s [%s]=%q,",depth,k,v))
+            end
+          elseif tk=="boolean" then
+            handle(format("%s [%s]=%q,",depth,tostring(k),v))
+          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
+        end
+      elseif t=="table" then
+        if not next(v) then
+          if tk=="number" then
+            if hexify then
+              handle(format("%s [0x%04X]={},",depth,k))
+            else
+              handle(format("%s [%s]={},",depth,k))
+            end
+          elseif tk=="boolean" then
+            handle(format("%s [%s]={},",depth,tostring(k)))
+          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=simple_table(v)
+          if st then
+            if tk=="number" then
+              if hexify then
+                handle(format("%s [0x%04X]={ %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,tostring(k),concat(st,", ")))
+            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 t=="boolean" then
+        if tk=="number" then
+          if hexify then
+            handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+          else
+            handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+          end
+        elseif tk=="boolean" then
+          handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
+        elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+          handle(format("%s %s=%s,",depth,k,tostring(v)))
+        else
+          handle(format("%s [%q]=%s,",depth,k,tostring(v)))
+        end
+      elseif t=="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%04X]=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,tostring(k),f))
+          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
+      else
+        if tk=="number" then
+          if hexify then
+            handle(format("%s [0x%04X]=%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,tostring(k),tostring(v)))
+        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
+      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
-    reduce=specification.reduce or false
-    functions=specification.functions
-    compact=specification.compact
-    inline=specification.inline and compact
-    if functions==nil then
-      functions=true
-    end
-    if compact==nil then
-      compact=true
-    end
-    if inline==nil then
-      inline=compact
-    end
-  else
-    noquotes=false
-    hexify=false
-    handle=_handle or print
-    reduce=false
-    compact=true
-    inline=true
-    functions=true
-  end
-  if tname=="string" then
-    if name=="return" then
-      handle("return {")
-    else
-      handle(name.."={")
-    end
-  elseif tname=="number" then
-    if hexify then
-      handle(format("[0x%04X]={",name))
-    else
-      handle("["..name.."]={")
-    end
-  elseif tname=="boolean" then
-    if name then
-      handle("return {")
-    else
-      handle("{")
-    end
-  else
-    handle("t={")
-  end
+  local tname=type(name)
+  if type(specification)=="table" then
+    noquotes=specification.noquotes
+    hexify=specification.hexify
+    handle=_handle or specification.handle or print
+    reduce=specification.reduce or false
+    functions=specification.functions
+    compact=specification.compact
+    inline=specification.inline and compact
+    if functions==nil then
+      functions=true
+    end
+    if compact==nil then
+      compact=true
+    end
+    if inline==nil then
+      inline=compact
+    end
+  else
+    noquotes=false
+    hexify=false
+    handle=_handle or print
+    reduce=false
+    compact=true
+    inline=true
+    functions=true
+  end
+  if tname=="string" then
+    if name=="return" then
+      handle("return {")
+    else
+      handle(name.."={")
+    end
+  elseif tname=="number" then
+    if hexify then
+      handle(format("[0x%04X]={",name))
+    else
+      handle("["..name.."]={")
+    end
+  elseif tname=="boolean" then
+    if name then
+      handle("return {")
+    else
+      handle("{")
+    end
+  else
+    handle("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) 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 dummy=root._w_h_a_t_e_v_e_r_
+      root._w_h_a_t_e_v_e_r_=nil
+    end
+    if next(root) 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")
 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
+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)
-    end
-    f:close()
-    io.flush()
-  end
+        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)
+    end
+    f:close()
+    io.flush()
+  end
 end
 local function flattened(t,f,depth) 
-  if f==nil then
-    f={}
-    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
-  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
+    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
+  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
 table.flattened=flattened
 local function unnest(t,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
-  end
-  return 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
+  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 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 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
-    end
-    return true
-  else
-    return false
-  end
+      elseif type(ai)=="table" and type(bi)=="table" then
+        if not are_equal(ai,bi) then
+          return false
+        end
+      else
+        return false
+      end
+    end
+    return true
+  else
+    return false
+  end
 end
 local function identical(a,b) 
-  for ka,va in next,a do
-    local vb=b[ka]
+  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
-table.identical=identical
+    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
+table.identical=identical
 table.are_equal=are_equal
 function table.compact(t) 
-  if t then
-    for k,v in next,t do
+  if t then
+    for k,v in next,t do
       if not next(v) then 
-        t[k]=nil
-      end
-    end
-  end
-end
-function table.contains(t,v)
-  if t then
-    for i=1,#t do
-      if t[i]==v then
-        return i
-      end
-    end
-  end
-  return false
-end
-function table.count(t)
-  local n=0
-  for k,v in next,t do
-    n=n+1
-  end
-  return n
+        t[k]=nil
+      end
+    end
+  end
+end
+function table.contains(t,v)
+  if t then
+    for i=1,#t do
+      if t[i]==v then
+        return i
+      end
+    end
+  end
+  return false
+end
+function table.count(t)
+  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
-  end
-  for k,v in next,t do
-    n[v]=k
-  end
-  return n
+  local n={}
+  if s then
+    for k,v in next,s do
+      n[k]=v
+    end
+  end
+  for k,v in next,t do
+    n[v]=k
+  end
+  return n
 end
 function table.mirrored(t) 
-  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
-  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
-  end
+  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
+  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
+  end
 end
 function table.sequenced(t,sep,simple) 
-  if not t then
-    return ""
-  end
-  local n=#t
-  local s={}
+  if not t then
+    return ""
+  end
+  local n=#t
+  local s={}
   if n>0 then
-    for i=1,n do
-      s[i]=tostring(t[i])
-    end
+    for i=1,n do
+      s[i]=tostring(t[i])
+    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
+    end
+  end
+  return concat(s,sep or " | ")
+end
+function table.print(t,...)
+  if type(t)~="table" then
+    print(tostring(t))
   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
-    end
-  end
-  return concat(s,sep or " | ")
-end
-function table.print(t,...)
-  if type(t)~="table" then
-    print(tostring(t))
-  else
-    serialize(print,t,...)
-  end
+    serialize(print,t,...)
+  end
 end
 setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
-function table.sub(t,i,j)
-  return { unpack(t,i,j) }
+function table.sub(t,i,j)
+  return { unpack(t,i,j) }
 end
-function table.is_empty(t)
-  return not t or not next(t)
+function table.is_empty(t)
+  return not t or not next(t)
 end
-function table.has_one_entry(t)
-  return t and not next(t,next(t))
+function table.has_one_entry(t)
+  return t and not next(t,next(t))
 end
 function table.loweredkeys(t) 
-  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
-  end
-  return new
-end
-function table.sorted(t,...)
-  sort(t,...)
+  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
+  end
+  return new
+end
+function table.sorted(t,...)
+  sort(t,...)
   return t 
-end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
-local io=io
-local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
-local concat=table.concat
-local floor=math.floor
+local io=io
+local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
+local concat=table.concat
+local floor=math.floor
 local type=type
-if string.find(os.getenv("PATH"),";") then
-  io.fileseparator,io.pathseparator="\\",";"
-else
-  io.fileseparator,io.pathseparator="/",":"
-end
-local function readall(f)
-  return f:read("*all")
-end
-local function readall(f)
-  local size=f:seek("end")
-  if size==0 then
-    return ""
-  elseif size<1024*1024 then
-    f:seek("set",0)
-    return f:read('*all')
-  else
-    local done=f:seek("set",0)
-    if size<1024*1024 then
-      step=1024*1024
-    elseif size>16*1024*1024 then
-      step=16*1024*1024
-    else
-      step=floor(size/(1024*1024))*1024*1024/8
-    end
-    local data={}
-    while true do
-      local r=f:read(step)
-      if not r then
-        return concat(data)
-      else
-        data[#data+1]=r
-      end
-    end
-  end
+if string.find(os.getenv("PATH"),";") then
+  io.fileseparator,io.pathseparator="\\",";"
+else
+  io.fileseparator,io.pathseparator="/",":"
+end
+local function readall(f)
+  return f:read("*all")
+end
+local function readall(f)
+  local size=f:seek("end")
+  if size==0 then
+    return ""
+  elseif size<1024*1024 then
+    f:seek("set",0)
+    return f:read('*all')
+  else
+    local done=f:seek("set",0)
+    if size<1024*1024 then
+      step=1024*1024
+    elseif size>16*1024*1024 then
+      step=16*1024*1024
+    else
+      step=floor(size/(1024*1024))*1024*1024/8
+    end
+    local data={}
+    while true do
+      local r=f:read(step)
+      if not r then
+        return concat(data)
+      else
+        data[#data+1]=r
+      end
+    end
+  end
 end
 io.readall=readall
 function io.loaddata(filename,textmode) 
-  local f=io.open(filename,(textmode and 'r') or 'rb')
+  local f=io.open(filename,(textmode and 'r') or 'rb')
+  if f then
+    local data=readall(f)
+    f:close()
+    if #data>0 then
+      return data
+    end
+  end
+end
+function io.savedata(filename,data,joiner)
+  local f=io.open(filename,"wb")
   if f then
-    local data=readall(f)
-    f:close()
-    if #data>0 then
-      return data
-    end
-  end
-end
-function io.savedata(filename,data,joiner)
-  local f=io.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()
-    io.flush()
-    return true
-  else
-    return false
-  end
+    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()
+    io.flush()
+    return true
+  else
+    return false
+  end
 end
 function io.loadlines(filename,n) 
-  local f=io.open(filename,'r')
+  local f=io.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[#lines+1]=line
-      else
-        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
-function io.loadchunk(filename,n)
-  local f=io.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=io.open(filename)
-  if f==nil then
-    return false
-  else
-    f:close()
-    return true
-  end
-end
-function io.size(filename)
-  local f=io.open(filename)
-  if f==nil then
-    return 0
-  else
-    local s=f:seek("end")
-    f:close()
-    return s
-  end
-end
-function io.noflines(f)
-  if type(f)=="string" then
-    local f=io.open(filename)
-    if f then
-      local n=f and io.noflines(f) or 0
-      f:close()
-      return n
-    else
-      return 0
-    end
-  else
-    local n=0
-    for _ in f:lines() do
-      n=n+1
-    end
-    f:seek('set',0)
-    return n
-  end
-end
-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
+  elseif n then
+    local lines={}
+    for i=1,n do
+      local line=f:read("*lines")
+      if line then
+        lines[#lines+1]=line
+      else
+        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
+function io.loadchunk(filename,n)
+  local f=io.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=io.open(filename)
+  if f==nil then
+    return false
+  else
+    f:close()
+    return true
+  end
+end
+function io.size(filename)
+  local f=io.open(filename)
+  if f==nil then
+    return 0
+  else
+    local s=f:seek("end")
+    f:close()
+    return s
+  end
+end
+function io.noflines(f)
+  if type(f)=="string" then
+    local f=io.open(filename)
+    if f then
+      local n=f and io.noflines(f) or 0
+      f:close()
+      return n
+    else
+      return 0
+    end
+  else
+    local n=0
+    for _ in f:lines() do
+      n=n+1
+    end
+    f:seek('set',0)
+    return n
+  end
+end
+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
 }
-function io.characters(f,n)
-  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
-  end
+function io.characters(f,n)
+  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
+  end
 }
-function io.bytes(f,n)
-  if f then
-    return nextbyte[n or 1],f
-  else
-    return nil,nil
-  end
-end
-function io.ask(question,default,options)
-  while true do
-    io.write(question)
-    if options then
-      io.write(format(" [%s]",concat(options,"|")))
-    end
-    if default then
-      io.write(format(" [%s]",default))
-    end
-    io.write(format(" "))
-    io.flush()
-    local answer=io.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
-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 256*a+b
-  elseif n==3 then
-    local a,b,c=byte(f:read(3),1,3)
-    return 256*256*a+256*b+c
-  elseif n==4 then
-    local a,b,c,d=byte(f:read(4),1,4)
-    return 256*256*256*a+256*256*b+256*c+d
-  elseif n==8 then
-    local a,b=readnumber(f,4),readnumber(f,4)
-    return 256*a+b
-  elseif n==12 then
-    local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
-    return 256*256*a+256*b+c
-  elseif n==-2 then
-    local b,a=byte(f:read(2),1,2)
-    return 256*a+b
-  elseif n==-3 then
-    local c,b,a=byte(f:read(3),1,3)
-    return 256*256*a+256*b+c
-  elseif n==-4 then
-    local d,c,b,a=byte(f:read(4),1,4)
-    return 256*256*256*a+256*256*b+256*c+d
-  elseif n==-8 then
-    local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
-    return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h
-  else
-    return 0
-  end
+function io.bytes(f,n)
+  if f then
+    return nextbyte[n or 1],f
+  else
+    return nil,nil
+  end
+end
+function io.ask(question,default,options)
+  while true do
+    io.write(question)
+    if options then
+      io.write(format(" [%s]",concat(options,"|")))
+    end
+    if default then
+      io.write(format(" [%s]",default))
+    end
+    io.write(format(" "))
+    io.flush()
+    local answer=io.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
+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 256*a+b
+  elseif n==3 then
+    local a,b,c=byte(f:read(3),1,3)
+    return 256*256*a+256*b+c
+  elseif n==4 then
+    local a,b,c,d=byte(f:read(4),1,4)
+    return 256*256*256*a+256*256*b+256*c+d
+  elseif n==8 then
+    local a,b=readnumber(f,4),readnumber(f,4)
+    return 256*a+b
+  elseif n==12 then
+    local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
+    return 256*256*a+256*b+c
+  elseif n==-2 then
+    local b,a=byte(f:read(2),1,2)
+    return 256*a+b
+  elseif n==-3 then
+    local c,b,a=byte(f:read(3),1,3)
+    return 256*256*a+256*b+c
+  elseif n==-4 then
+    local d,c,b,a=byte(f:read(4),1,4)
+    return 256*256*256*a+256*256*b+256*c+d
+  elseif n==-8 then
+    local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
+    return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*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
+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
 end
 if not io.i_limiter then function io.i_limiter() end end 
 if not io.o_limiter then function io.o_limiter() end end
@@ -1944,862 +1944,862 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
-file=file or {}
+file=file or {}
 local file=file
-if not lfs then
-  lfs=optionalrequire("lfs")
+if not lfs then
+  lfs=optionalrequire("lfs")
 end
 if not lfs then
-  lfs={
-    getcurrentdir=function()
-      return "."
-    end,
-    attributes=function()
-      return nil
-    end,
-    isfile=function(name)
-      local f=io.open(name,'rb')
-      if f then
-        f:close()
-        return true
-      end
-    end,
-    isdir=function(name)
-      print("you need to load lfs")
-      return false
-    end
+  lfs={
+    getcurrentdir=function()
+      return "."
+    end,
+    attributes=function()
+      return nil
+    end,
+    isfile=function(name)
+      local f=io.open(name,'rb')
+      if f then
+        f:close()
+        return true
+      end
+    end,
+    isdir=function(name)
+      print("you need to load lfs")
+      return false
+    end
   }
 elseif not lfs.isfile then
   local attributes=lfs.attributes
-  function lfs.isdir(name)
-    return attributes(name,"mode")=="directory"
+  function lfs.isdir(name)
+    return attributes(name,"mode")=="directory"
   end
-  function lfs.isfile(name)
-    return attributes(name,"mode")=="file"
+  function lfs.isfile(name)
+    return attributes(name,"mode")=="file"
   end
 end
-local insert,concat=table.insert,table.concat
-local match,find,gmatch=string.match,string.find,string.gmatch
-local lpegmatch=lpeg.match
-local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
+local insert,concat=table.insert,table.concat
+local match,find,gmatch=string.match,string.find,string.gmatch
+local lpegmatch=lpeg.match
+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 colon=P(":")
-local period=P(".")
-local periods=P("..")
-local fwslash=P("/")
-local bwslash=P("\\")
-local slashes=S("\\/")
-local noperiod=1-period
-local noslashes=1-slashes
-local name=noperiod^1
+local colon=P(":")
+local period=P(".")
+local periods=P("..")
+local fwslash=P("/")
+local bwslash=P("\\")
+local slashes=S("\\/")
+local noperiod=1-period
+local noslashes=1-slashes
+local name=noperiod^1
 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 ""
+local function pathpart(name,default)
+  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
+local function basename(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
+local function nameonly(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 ""
+local function suffixonly(name)
+  return name and lpegmatch(pattern,name) or ""
 end
-file.pathpart=pathpart
-file.basename=basename
-file.nameonly=nameonly
-file.suffixonly=suffixonly
+file.pathpart=pathpart
+file.basename=basename
+file.nameonly=nameonly
+file.suffixonly=suffixonly
 file.suffix=suffixonly
 file.dirname=pathpart  
 file.extname=suffixonly
-local drive=C(R("az","AZ"))*colon
-local path=C((noslashes^0*slashes)^0)
-local suffix=period*C(P(1-period)^0*P(-1))
-local base=C((1-suffix)^0)
+local drive=C(R("az","AZ"))*colon
+local path=C((noslashes^0*slashes)^0)
+local suffix=period*C(P(1-period)^0*P(-1))
+local base=C((1-suffix)^0)
 local rest=C(P(1)^0)
-drive=drive+Cc("")
-path=path+Cc("")
-base=base+Cc("")
+drive=drive+Cc("")
+path=path+Cc("")
+base=base+Cc("")
 suffix=suffix+Cc("")
-local pattern_a=drive*path*base*suffix
-local pattern_b=path*base*suffix
+local pattern_a=drive*path*base*suffix
+local pattern_b=path*base*suffix
 local pattern_c=C(drive*path)*C(base*suffix) 
 local pattern_d=path*rest
-function file.splitname(str,splitdrive)
+function file.splitname(str,splitdrive)
   if not str then
-  elseif splitdrive then
+  elseif splitdrive then
     return lpegmatch(pattern_a,str) 
-  else
+  else
     return lpegmatch(pattern_b,str) 
-  end
+  end
 end
-function file.splitbase(str)
-  if str then
+function file.splitbase(str)
+  if str then
     return lpegmatch(pattern_d,str) 
-  else
+  else
     return "",str 
-  end
+  end
 end
-function file.nametotable(str,splitdrive)
-  if str then
+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
-  end
+    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)
+function file.removesuffix(name)
+  return name and lpegmatch(pattern,name)
 end
-local suffix=period/""*(1-period-slashes)^1*-1
+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
-      return filename
-    end
-  else
-    local n,s=lpegmatch(pattern,filename)
-    if s and s~="" then
-      local t=type(criterium)
+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
+      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
+        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
-    end
-    return (n or filename).."."..suffix
-  end
-end
-local suffix=period*(1-period-slashes)^1*-1
+        if s==criterium then
+          return filename
+        end
+      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
+function file.replacesuffix(name,suffix)
+  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)
+function file.reslash(str)
+  return str and lpegmatch(reslasher,str)
 end
-function file.is_writable(name)
+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
-  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
+  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
+  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
 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
+function file.size(name)
+  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) 
 end
-local stripper=Cs(P(fwslash)^0/""*reslasher)
-local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
-local isroot=fwslash^1*-1
+local stripper=Cs(P(fwslash)^0/""*reslasher)
+local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
+local isroot=fwslash^1*-1
 local hasroot=fwslash^1
 local deslasher=lpeg.replacer(S("\\/")^1,"/")
-function file.join(...)
-  local lst={... }
-  local one=lst[1]
-  if lpegmatch(isnetwork,one) then
-    local two=lpegmatch(deslasher,concat(lst,"/",2))
-    return one.."/"..two
-  elseif lpegmatch(isroot,one) then
-    local two=lpegmatch(deslasher,concat(lst,"/",2))
-    if lpegmatch(hasroot,two) then
-      return two
-    else
-      return "/"..two
-    end
-  elseif one=="" then
-    return lpegmatch(stripper,concat(lst,"/",2))
-  else
-    return lpegmatch(deslasher,concat(lst,"/"))
-  end
-end
-local drivespec=R("az","AZ")^1*colon
-local anchors=fwslash+drivespec
-local untouched=periods+(1-period)^1*P(-1)
-local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
+function file.join(...)
+  local lst={... }
+  local one=lst[1]
+  if lpegmatch(isnetwork,one) then
+    local two=lpegmatch(deslasher,concat(lst,"/",2))
+    return one.."/"..two
+  elseif lpegmatch(isroot,one) then
+    local two=lpegmatch(deslasher,concat(lst,"/",2))
+    if lpegmatch(hasroot,two) then
+      return two
+    else
+      return "/"..two
+    end
+  elseif one=="" then
+    return lpegmatch(stripper,concat(lst,"/",2))
+  else
+    return lpegmatch(deslasher,concat(lst,"/"))
+  end
+end
+local drivespec=R("az","AZ")^1*colon
+local anchors=fwslash+drivespec
+local untouched=periods+(1-period)^1*P(-1)
+local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+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 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)
-    end
-    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
-      return newelements
-    end
-  end
-end
-local validchars=R("az","09","AZ","--","..")
-local pattern_a=lpeg.replacer(1-validchars)
-local pattern_a=Cs((validchars+P(1)/"-")^1)
-local whatever=P("-")^0/""
+    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)
+    end
+    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
+      return newelements
+    end
+  end
+end
+local validchars=R("az","09","AZ","--","..")
+local pattern_a=lpeg.replacer(1-validchars)
+local pattern_a=Cs((validchars+P(1)/"-")^1)
+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
+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
-  end
+    else
+      return str
+    end
+  end
 end
-file.readdata=io.loaddata
+file.readdata=io.loaddata
 file.savedata=io.savedata
-function file.copy(oldname,newname)
-  if oldname and newname then
-    local data=io.loaddata(oldname)
-    if data and data~="" then
-      file.savedata(newname,data)
-    end
-  end
-end
-local letter=R("az","AZ")+S("_-+")
+function file.copy(oldname,newname)
+  if oldname and newname then
+    local data=io.loaddata(oldname)
+    if data and data~="" then
+      file.savedata(newname,data)
+    end
+  end
+end
+local letter=R("az","AZ")+S("_-+")
 local separator=P("://")
-local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
+local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
 local rootbased=fwslash+letter*colon
-lpeg.patterns.qualified=qualified
+lpeg.patterns.qualified=qualified
 lpeg.patterns.rootbased=rootbased
-function file.is_qualified_path(filename)
-  return filename and lpegmatch(qualified,filename)~=nil
-end
-function file.is_rootbased_path(filename)
-  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
-end
-function lfs.mkdirs(path)
-  local full
-  for sub in gmatch(path,"([^\\/]+)") do
-    if full then
-      full=full.."/"..sub
-    else
-      full=sub
-    end
-    if not lfs.isdir(full) then
-      lfs.mkdir(full)
-    end
-  end
-end
+function file.is_qualified_path(filename)
+  return filename and lpegmatch(qualified,filename)~=nil
+end
+function file.is_rootbased_path(filename)
+  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
+end
+function lfs.mkdirs(path)
+  local full
+  for sub in gmatch(path,"([^\\/]+)") do
+    if full then
+      full=full.."/"..sub
+    else
+      full=sub
+    end
+    if not lfs.isdir(full) then
+      lfs.mkdir(full)
+    end
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
 local type,tonumber=type,tonumber
-boolean=boolean or {}
+boolean=boolean or {}
 local boolean=boolean
-function boolean.tonumber(b)
+function boolean.tonumber(b)
   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
-end
-function string.is_boolean(str,default)
-  if type(str)=="string" then
-    if str=="true" or str=="yes" or str=="on" or str=="t" then
-      return true
-    elseif str=="false" or str=="no" or str=="off" or str=="f" then
-      return false
-    end
-  end
-  return default
-end
+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
+end
+function string.is_boolean(str,default)
+  if type(str)=="string" then
+    if str=="true" or str=="yes" or str=="on" or str=="t" then
+      return true
+    elseif str=="false" or str=="no" or str=="off" or str=="f" then
+      return false
+    end
+  end
+  return default
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
 local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
-if not math.round then
-  function math.round(x) return floor(x+0.5) end
+if not math.round then
+  function math.round(x) return floor(x+0.5) end
 end
-if not math.div then
-  function math.div(n,m) return floor(n/m) end
+if not math.div then
+  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
+if not math.mod then
+  function math.mod(n,m) return n%m end
 end
 local pipi=2*math.pi/360
-if not math.sind then
-  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
-end
+if not math.sind then
+  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
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-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"
+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"
 }
-utilities=utilities or {}
-utilities.strings=utilities.strings or {}
+utilities=utilities or {}
+utilities.strings=utilities.strings or {}
 local strings=utilities.strings
-local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
-local load,dump=load,string.dump
-local tonumber,type,tostring=tonumber,type,tostring
-local unpack,concat=table.unpack,table.concat
-local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
-local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
+local load,dump=load,string.dump
+local tonumber,type,tostring=tonumber,type,tostring
+local unpack,concat=table.unpack,table.concat
+local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
+local patterns,lpegmatch=lpeg.patterns,lpeg.match
 local utfchar,utfbyte=utf.char,utf.byte
-local loadstripped=_LUAVERSION<5.2 and load or function(str)
+local loadstripped=_LUAVERSION<5.2 and load or function(str)
   return load(dump(load(str),true)) 
 end
 if not number then number={} end 
 local stripper=patterns.stripzeros
-local function points(n)
-  return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+local function points(n)
+  return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
 end
-local function basepoints(n)
-  return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
+local function basepoints(n)
+  return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
 end
-number.points=points
+number.points=points
 number.basepoints=basepoints
-local rubish=patterns.spaceortab^0*patterns.newline
-local anyrubish=patterns.spaceortab+patterns.newline
-local anything=patterns.anything
-local stripped=(patterns.spaceortab^1/"")*patterns.newline
-local leading=rubish^0/""
-local trailing=(anyrubish^1*patterns.endofstring)/""
+local rubish=patterns.spaceortab^0*patterns.newline
+local anyrubish=patterns.spaceortab+patterns.newline
+local anything=patterns.anything
+local stripped=(patterns.spaceortab^1/"")*patterns.newline
+local leading=rubish^0/""
+local trailing=(anyrubish^1*patterns.endofstring)/""
 local redundant=rubish^3/"\n"
 local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
-function strings.collapsecrlf(str)
-  return lpegmatch(pattern,str)
+function strings.collapsecrlf(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
-  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
+function strings.newrepeater(str,offset)
+  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 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((
-   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
+local pattern=Carg(1)/function(t)
+    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
-   end+patterns.newline*Cp()/function(position)
-     extra,start=0,position
-   end+patterns.anything
+     else
+       return ""
+     end
+   end+patterns.newline*Cp()/function(position)
+     extra,start=0,position
+   end+patterns.anything
  )^1)
-function strings.tabtospace(str,tab)
-  return lpegmatch(pattern,str,1,tab or 7)
+function strings.tabtospace(str,tab)
+  return lpegmatch(pattern,str,1,tab or 7)
 end
 function strings.striplong(str) 
-  str=gsub(str,"^%s*","")
-  str=gsub(str,"[\n\r]+ *","\n")
-  return str
+  str=gsub(str,"^%s*","")
+  str=gsub(str,"[\n\r]+ *","\n")
+  return str
 end
-function strings.nice(str)
+function strings.nice(str)
   str=gsub(str,"[:%-+_]+"," ") 
-  return 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
+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)..'"')
-end
-function string.autosingle(s,sep)
-  if s==nil then
-    return "''"
-  end
-  local t=type(s)
-  if t=="number" then
+  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).."'")
-end
-local tracedchars={}
-string.tracedchars=tracedchars
+  end
+  if t=="table" then
+    return ("'"..sequenced(s,sep or ",").."'")
+  end
+  return ("'"..tostring(s).."'")
+end
+local tracedchars={}
+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+"..format('%05X',c)..")")
-  end
-end
-function number.signed(i)
-  if i>0 then
-    return "+",i
-  else
-    return "-",-i
-  end
-end
-local preamble=[[
-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 tracedchar = string.tracedchar
-local autosingle = string.autosingle
-local autodouble = string.autodouble
-local sequenced = table.sequenced
+  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+"..format('%05X',c)..")")
+  end
+end
+function number.signed(i)
+  if i>0 then
+    return "+",i
+  else
+    return "-",-i
+  end
+end
+local preamble=[[
+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 tracedchar = string.tracedchar
+local autosingle = string.autosingle
+local autodouble = string.autodouble
+local sequenced = table.sequenced
 ]]
-local template=[[
-%s
-%s
-return function(%s) return %s end
+local template=[[
+%s
+%s
+return function(%s) return %s end
 ]]
 local arguments={ "a1" } 
-setmetatable(arguments,{ __index=function(t,k)
-    local v=t[k-1]..",a"..k
-    t[k]=v
-    return v
-  end
+setmetatable(arguments,{ __index=function(t,k)
+    local v=t[k-1]..",a"..k
+    t[k]=v
+    return v
+  end
 })
-local prefix_any=C((S("+- .")+R("09"))^0)
+local prefix_any=C((S("+- .")+R("09"))^0)
 local prefix_tab=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)
+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
+  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
-end
-local format_q=function()
-  n=n+1
+  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_q=function()
+  n=n+1
   return format("(a%s and format('%%q',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("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("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)
-end
-local format_f=function(f)
-  n=n+1
-  return format("format('%%%sf',a%s)",f,n)
-end
-local format_g=function(f)
-  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)
-end
-local format_e=function(f)
-  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)
-end
-local format_x=function(f)
-  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)
-end
-local format_o=function(f)
-  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)
-end
-local format_C=function()
-  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)
-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
-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
-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
-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
-end
-local format_p=function()
-  n=n+1
-  return format("points(a%s)",n)
-end
-local format_b=function()
-  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
-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
-end
-local format_l=function()
-  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)
+local format_I=function(f)
+  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)
+end
+local format_g=function(f)
+  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)
+end
+local format_e=function(f)
+  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)
+end
+local format_x=function(f)
+  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)
+end
+local format_o=function(f)
+  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)
+end
+local format_C=function()
+  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)
+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
+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
+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
+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
+end
+local format_p=function()
+  n=n+1
+  return format("points(a%s)",n)
+end
+local format_b=function()
+  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
+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
+end
+local format_l=function()
+  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)
 end
 local format_N=function() 
-  n=n+1
-  return format("tostring(tonumber(a%s) or a%s)",n,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
-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
+  return format("tostring(tonumber(a%s) or a%s)",n,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
+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
 end
 local format_w=function(f) 
-  n=n+1
-  f=tonumber(f)
+  n=n+1
+  f=tonumber(f)
   if f then 
     return format("nspaces[%s+a%s]",f,n) 
-  else
+  else
     return format("nspaces[a%s]",n) 
-  end
+  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_rest=function(s)
+local format_rest=function(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
-  if f==0 then
-    return extension
-  elseif f==1 then
-    n=n+1
-    local a="a"..n
+local format_extension=function(extensions,f,name)
+  local extension=extensions[name] or "tostring(%s)"
+  local f=tonumber(f) or 1
+  if f==0 then
+    return extension
+  elseif f==1 then
+    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)
-  else
-    local t={}
-    for i=1,f do
-      n=n+1
-      t[#t+1]="a"..n
-    end
-    return format(extension,unpack(t))
-  end
-end
-local builder=Cs { "start",
-  start=(
-    (
-      P("%")/""*(
+  elseif f<0 then
+    local a="a"..(n+f+1)
+    return format(extension,a,a)
+  else
+    local t={}
+    for i=1,f do
+      n=n+1
+      t[#t+1]="a"..n
+    end
+    return format(extension,unpack(t))
+  end
+end
+local builder=Cs { "start",
+  start=(
+    (
+      P("%")/""*(
         V("!") 
 +V("s")+V("q")+V("i")+V("d")+V("f")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o")
 +V("c")+V("C")+V("S") 
@@ -2811,8 +2811,8 @@ local builder=Cs { "start",
 +V("a") 
 +V("A")
 +V("*") 
-      )+V("*")
-    )*(P(-1)+Carg(1))
+      )+V("*")
+    )*(P(-1)+Carg(1))
   )^0,
   ["s"]=(prefix_any*P("s"))/format_s,
   ["q"]=(prefix_any*P("q"))/format_q,
@@ -2848,796 +2848,796 @@ local builder=Cs { "start",
   ["a"]=(prefix_any*P("a"))/format_a,
   ["A"]=(prefix_any*P("A"))/format_A,
   ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_rest,
-  ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
+  ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
 }
-local direct=Cs (
-    P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1)
+local direct=Cs (
+    P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1)
   )
-local function make(t,str)
-  local f
-  local p
-  local p=lpegmatch(direct,str)
-  if p then
-    f=loadstripped(p)()
-  else
-    n=0
+local function make(t,str)
+  local f
+  local p
+  local p=lpegmatch(direct,str)
+  if p then
+    f=loadstripped(p)()
+  else
+    n=0
     p=lpegmatch(builder,str,1,"..",t._extensions_) 
-    if n>0 then
+    if n>0 then
       p=format(template,preamble,t._preamble_,arguments[n],p)
-      f=loadstripped(p)()
-    else
-      f=function() return str end
-    end
-  end
-  t[str]=f
-  return f
+      f=loadstripped(p)()
+    else
+      f=function() return str end
+    end
+  end
+  t[str]=f
+  return f
 end
-local function use(t,fmt,...)
-  return t[fmt](...)
+local function use(t,fmt,...)
+  return t[fmt](...)
 end
 strings.formatters={}
-function strings.formatters.new()
-  local t={ _extensions_={},_preamble_="",_type_="formatter" }
-  setmetatable(t,{ __index=make,__call=use })
-  return t
+function strings.formatters.new()
+  local t={ _extensions_={},_preamble_="",_type_="formatter" }
+  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 preamble then
+local function add(t,name,template,preamble)
+  if type(t)=="table" and t._type_=="formatter" then
+    t._extensions_[name]=template or "%s"
+    if preamble then
       t._preamble_=preamble.."\n"..t._preamble_ 
-    end
-  end
+    end
+  end
 end
 strings.formatters.add=add
-lpeg.patterns.xmlescape=Cs((P("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+P(1))^0)
+lpeg.patterns.xmlescape=Cs((P("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+P(1))^0)
 lpeg.patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0)
-add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]])
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]])
 add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]])
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luat-basics-gen']={
-  version=1.100,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luat-basics-gen']={
+  version=1.100,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
-end
-local dummyfunction=function()
-end
-local dummyreporter=function(c)
-  return function(...)
-    (texio.reporter or texio.write_nl)(c.." : "..string.formatters(...))
-  end
-end
-statistics={
-  register=dummyfunction,
-  starttiming=dummyfunction,
-  stoptiming=dummyfunction,
-  elapsedtime=nil,
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
+end
+local dummyfunction=function()
+end
+local dummyreporter=function(c)
+  return function(...)
+    (texio.reporter or texio.write_nl)(c.." : "..string.formatters(...))
+  end
+end
+statistics={
+  register=dummyfunction,
+  starttiming=dummyfunction,
+  stoptiming=dummyfunction,
+  elapsedtime=nil,
 }
-directives={
-  register=dummyfunction,
-  enable=dummyfunction,
-  disable=dummyfunction,
+directives={
+  register=dummyfunction,
+  enable=dummyfunction,
+  disable=dummyfunction,
 }
-trackers={
-  register=dummyfunction,
-  enable=dummyfunction,
-  disable=dummyfunction,
+trackers={
+  register=dummyfunction,
+  enable=dummyfunction,
+  disable=dummyfunction,
 }
-experiments={
-  register=dummyfunction,
-  enable=dummyfunction,
-  disable=dummyfunction,
+experiments={
+  register=dummyfunction,
+  enable=dummyfunction,
+  disable=dummyfunction,
 }
 storage={ 
-  register=dummyfunction,
-  shared={},
+  register=dummyfunction,
+  shared={},
 }
-logs={
-  new=dummyreporter,
-  reporter=dummyreporter,
-  messenger=dummyreporter,
-  report=dummyfunction,
+logs={
+  new=dummyreporter,
+  reporter=dummyreporter,
+  messenger=dummyreporter,
+  report=dummyfunction,
 }
-callbacks={
+callbacks={
   register=function(n,f) return callback.register(n,f) end,
 }
-utilities={
-  storage={
-    allocate=function(t) return t or {} end,
-    mark=function(t) return t or {} end,
-  },
+utilities={
+  storage={
+    allocate=function(t) return t or {} end,
+    mark=function(t) return t or {} end,
+  },
 }
-characters=characters or {
-  data={}
+characters=characters or {
+  data={}
 }
 texconfig.kpse_init=true
 resolvers=resolvers or {} 
-local remapper={
-  otf="opentype fonts",
-  ttf="truetype fonts",
-  ttc="truetype fonts",
+local remapper={
+  otf="opentype fonts",
+  ttf="truetype fonts",
+  ttc="truetype fonts",
   dfont="truetype fonts",
-  cid="cid maps",
-  cidmap="cid maps",
-  fea="font feature files",
+  cid="cid maps",
+  cidmap="cid maps",
+  fea="font feature files",
   pfa="type1 fonts",
   pfb="type1 fonts",
 }
-function resolvers.findfile(name,fileformat)
-  name=string.gsub(name,"\\","/")
-  if not fileformat or fileformat=="" then
-    fileformat=file.suffix(name)
-    if fileformat=="" then
-      fileformat="tex"
-    end
-  end
-  fileformat=string.lower(fileformat)
-  fileformat=remapper[fileformat] or fileformat
-  local found=kpse.find_file(name,fileformat)
-  if not found or found=="" then
-    found=kpse.find_file(name,"other text files")
-  end
-  return found
+function resolvers.findfile(name,fileformat)
+  name=string.gsub(name,"\\","/")
+  if not fileformat or fileformat=="" then
+    fileformat=file.suffix(name)
+    if fileformat=="" then
+      fileformat="tex"
+    end
+  end
+  fileformat=string.lower(fileformat)
+  fileformat=remapper[fileformat] or fileformat
+  local found=kpse.find_file(name,fileformat)
+  if not found or found=="" then
+    found=kpse.find_file(name,"other text files")
+  end
+  return found
 end
 resolvers.findbinfile=resolvers.findfile
-function resolvers.resolve(s)
-  return s
+function resolvers.resolve(s)
+  return s
 end
-function resolvers.unresolve(s)
-  return s
+function resolvers.unresolve(s)
+  return s
 end
 caches={}
-local writable=nil
-local readables={}
+local writable=nil
+local readables={}
 local usingjit=jit
-if not caches.namespace or caches.namespace=="" or caches.namespace=="context" then
-  caches.namespace='generic'
+if not caches.namespace or caches.namespace=="" or caches.namespace=="context" then
+  caches.namespace='generic'
 end
 do
   local cachepaths=kpse.expand_path('$TEXMFCACHE') or ""
-  if cachepaths=="" then
-    cachepaths=kpse.expand_path('$TEXMFVAR')
+  if cachepaths=="" then
+    cachepaths=kpse.expand_path('$TEXMFVAR')
   end
-  if cachepaths=="" then
-    cachepaths=kpse.expand_path('$VARTEXMF')
+  if cachepaths=="" then
+    cachepaths=kpse.expand_path('$VARTEXMF')
   end
-  if cachepaths=="" then
-    cachepaths="."
+  if cachepaths=="" then
+    cachepaths="."
   end
   cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":")
-  for i=1,#cachepaths do
-    local cachepath=cachepaths[i]
-    if not lfs.isdir(cachepath) then
+  for i=1,#cachepaths do
+    local cachepath=cachepaths[i]
+    if not lfs.isdir(cachepath) then
       lfs.mkdirs(cachepath) 
-      if lfs.isdir(cachepath) then
-        texio.write(string.format("(created cache path: %s)",cachepath))
-      end
-    end
-    if file.is_writable(cachepath) then
-      writable=file.join(cachepath,"luatex-cache")
-      lfs.mkdir(writable)
-      writable=file.join(writable,caches.namespace)
-      lfs.mkdir(writable)
-      break
-    end
-  end
-  for i=1,#cachepaths do
-    if file.is_readable(cachepaths[i]) then
-      readables[#readables+1]=file.join(cachepaths[i],"luatex-cache",caches.namespace)
-    end
-  end
-  if not writable then
-    texio.write_nl("quiting: fix your writable cache path")
-    os.exit()
-  elseif #readables==0 then
-    texio.write_nl("quiting: fix your readable cache path")
-    os.exit()
-  elseif #readables==1 and readables[1]==writable then
-    texio.write(string.format("(using cache: %s)",writable))
-  else
-    texio.write(string.format("(using write cache: %s)",writable))
-    texio.write(string.format("(using read cache: %s)",table.concat(readables," ")))
-  end
-end
-function caches.getwritablepath(category,subcategory)
-  local path=file.join(writable,category)
-  lfs.mkdir(path)
-  path=file.join(path,subcategory)
-  lfs.mkdir(path)
-  return path
-end
-function caches.getreadablepaths(category,subcategory)
-  local t={}
-  for i=1,#readables do
-    t[i]=file.join(readables[i],category,subcategory)
-  end
-  return t
-end
-local function makefullname(path,name)
-  if path and path~="" then
-    return file.addsuffix(file.join(path,name),"lua"),file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
-  end
-end
-function caches.is_writable(path,name)
-  local fullname=makefullname(path,name)
-  return fullname and file.is_writable(fullname)
-end
-function caches.loaddata(paths,name)
-  for i=1,#paths do
-    local data=false
-    local luaname,lucname=makefullname(paths[i],name)
+      if lfs.isdir(cachepath) then
+        texio.write(string.format("(created cache path: %s)",cachepath))
+      end
+    end
+    if file.is_writable(cachepath) then
+      writable=file.join(cachepath,"luatex-cache")
+      lfs.mkdir(writable)
+      writable=file.join(writable,caches.namespace)
+      lfs.mkdir(writable)
+      break
+    end
+  end
+  for i=1,#cachepaths do
+    if file.is_readable(cachepaths[i]) then
+      readables[#readables+1]=file.join(cachepaths[i],"luatex-cache",caches.namespace)
+    end
+  end
+  if not writable then
+    texio.write_nl("quiting: fix your writable cache path")
+    os.exit()
+  elseif #readables==0 then
+    texio.write_nl("quiting: fix your readable cache path")
+    os.exit()
+  elseif #readables==1 and readables[1]==writable then
+    texio.write(string.format("(using cache: %s)",writable))
+  else
+    texio.write(string.format("(using write cache: %s)",writable))
+    texio.write(string.format("(using read cache: %s)",table.concat(readables," ")))
+  end
+end
+function caches.getwritablepath(category,subcategory)
+  local path=file.join(writable,category)
+  lfs.mkdir(path)
+  path=file.join(path,subcategory)
+  lfs.mkdir(path)
+  return path
+end
+function caches.getreadablepaths(category,subcategory)
+  local t={}
+  for i=1,#readables do
+    t[i]=file.join(readables[i],category,subcategory)
+  end
+  return t
+end
+local function makefullname(path,name)
+  if path and path~="" then
+    return file.addsuffix(file.join(path,name),"lua"),file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
+  end
+end
+function caches.is_writable(path,name)
+  local fullname=makefullname(path,name)
+  return fullname and file.is_writable(fullname)
+end
+function caches.loaddata(paths,name)
+  for i=1,#paths do
+    local data=false
+    local luaname,lucname=makefullname(paths[i],name)
     if lucname and lfs.isfile(lucname) then 
-      texio.write(string.format("(load luc: %s)",lucname))
-      data=loadfile(lucname)
-      if data then
-        data=data()
-      end
-      if data then
-        return data
-      else
-        texio.write(string.format("(loading failed: %s)",lucname))
-      end
-    end
-    if luaname and lfs.isfile(luaname) then
-      texio.write(string.format("(load lua: %s)",luaname))
-      data=loadfile(luaname)
-      if data then
-        data=data()
-      end
-      if data then
-        return data
-      end
-    end
-  end
-end
-function caches.savedata(path,name,data)
-  local luaname,lucname=makefullname(path,name)
-  if luaname then
-    texio.write(string.format("(save: %s)",luaname))
-    table.tofile(luaname,data,true,{ reduce=true })
-    if lucname and type(caches.compile)=="function" then
+      texio.write(string.format("(load luc: %s)",lucname))
+      data=loadfile(lucname)
+      if data then
+        data=data()
+      end
+      if data then
+        return data
+      else
+        texio.write(string.format("(loading failed: %s)",lucname))
+      end
+    end
+    if luaname and lfs.isfile(luaname) then
+      texio.write(string.format("(load lua: %s)",luaname))
+      data=loadfile(luaname)
+      if data then
+        data=data()
+      end
+      if data then
+        return data
+      end
+    end
+  end
+end
+function caches.savedata(path,name,data)
+  local luaname,lucname=makefullname(path,name)
+  if luaname then
+    texio.write(string.format("(save: %s)",luaname))
+    table.tofile(luaname,data,true,{ reduce=true })
+    if lucname and type(caches.compile)=="function" then
       os.remove(lucname) 
-      texio.write(string.format("(save: %s)",lucname))
-      caches.compile(data,luaname,lucname)
-    end
-  end
-end
-function caches.compile(data,luaname,lucname)
-  local d=io.loaddata(luaname)
-  if not d or d=="" then
+      texio.write(string.format("(save: %s)",lucname))
+      caches.compile(data,luaname,lucname)
+    end
+  end
+end
+function caches.compile(data,luaname,lucname)
+  local d=io.loaddata(luaname)
+  if not d or d=="" then
     d=table.serialize(data,true) 
-  end
-  if d and d~="" then
-    local f=io.open(lucname,'wb')
-    if f then
-      local s=loadstring(d)
-      if s then
-        f:write(string.dump(s,true))
-      end
-      f:close()
-    end
-  end
-end
-function table.setmetatableindex(t,f)
-  setmetatable(t,{ __index=f })
-end
+  end
+  if d and d~="" then
+    local f=io.open(lucname,'wb')
+    if f then
+      local s=loadstring(d)
+      if s then
+        f:write(string.dump(s,true))
+      end
+      f:close()
+    end
+  end
+end
+function table.setmetatableindex(t,f)
+  setmetatable(t,{ __index=f })
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['data-con']={
-  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"
+if not modules then modules={} end modules ['data-con']={
+  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=string.format,string.lower,string.gsub
-local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
-local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
 local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
-containers=containers or {}
-local containers=containers
+containers=containers or {}
+local containers=containers
 containers.usecache=true
 local report_containers=logs.reporter("resolvers","containers")
 local allocated={}
-local mt={
-  __index=function(t,k)
-    if k=="writable" then
-      local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
-      t.writable=writable
-      return writable
-    elseif k=="readables" then
-      local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
-      t.readables=readables
-      return readables
-    end
-  end,
-  __storage__=true
+local mt={
+  __index=function(t,k)
+    if k=="writable" then
+      local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
+      t.writable=writable
+      return writable
+    elseif k=="readables" then
+      local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
+      t.readables=readables
+      return readables
+    end
+  end,
+  __storage__=true
 }
-function containers.define(category,subcategory,version,enabled)
-  if category and subcategory then
-    local c=allocated[category]
-    if not c then
-      c={}
-      allocated[category]=c
-    end
-    local s=c[subcategory]
-    if not s then
-      s={
-        category=category,
-        subcategory=subcategory,
-        storage={},
-        enabled=enabled,
+function containers.define(category,subcategory,version,enabled)
+  if category and subcategory then
+    local c=allocated[category]
+    if not c then
+      c={}
+      allocated[category]=c
+    end
+    local s=c[subcategory]
+    if not s then
+      s={
+        category=category,
+        subcategory=subcategory,
+        storage={},
+        enabled=enabled,
         version=version or math.pi,
         trace=false,
-      }
-      setmetatable(s,mt)
-      c[subcategory]=s
-    end
-    return s
-  end
-end
-function containers.is_usable(container,name)
-  return container.enabled and caches and caches.is_writable(container.writable,name)
-end
-function containers.is_valid(container,name)
-  if name and name~="" then
-    local storage=container.storage[name]
-    return storage and storage.cache_version==container.version
-  else
-    return false
-  end
-end
-function containers.read(container,name)
-  local storage=container.storage
-  local stored=storage[name]
-  if not stored and container.enabled and caches and containers.usecache then
-    stored=caches.loaddata(container.readables,name)
-    if stored and stored.cache_version==container.version then
-      if trace_cache or trace_containers then
-        report_containers("action %a, category %a, name %a","load",container.subcategory,name)
-      end
-    else
-      stored=nil
-    end
-    storage[name]=stored
-  elseif stored then
-    if trace_cache or trace_containers then
-      report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
-    end
-  end
-  return stored
-end
-function containers.write(container,name,data)
-  if data then
-    data.cache_version=container.version
-    if container.enabled and caches then
-      local unique,shared=data.unique,data.shared
-      data.unique,data.shared=nil,nil
-      caches.savedata(container.writable,name,data)
-      if trace_cache or trace_containers then
-        report_containers("action %a, category %a, name %a","save",container.subcategory,name)
-      end
-      data.unique,data.shared=unique,shared
-    end
-    if trace_cache or trace_containers then
-      report_containers("action %a, category %a, name %a","store",container.subcategory,name)
-    end
-    container.storage[name]=data
-  end
-  return data
-end
-function containers.content(container,name)
-  return container.storage[name]
+      }
+      setmetatable(s,mt)
+      c[subcategory]=s
+    end
+    return s
+  end
+end
+function containers.is_usable(container,name)
+  return container.enabled and caches and caches.is_writable(container.writable,name)
+end
+function containers.is_valid(container,name)
+  if name and name~="" then
+    local storage=container.storage[name]
+    return storage and storage.cache_version==container.version
+  else
+    return false
+  end
+end
+function containers.read(container,name)
+  local storage=container.storage
+  local stored=storage[name]
+  if not stored and container.enabled and caches and containers.usecache then
+    stored=caches.loaddata(container.readables,name)
+    if stored and stored.cache_version==container.version then
+      if trace_cache or trace_containers then
+        report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+      end
+    else
+      stored=nil
+    end
+    storage[name]=stored
+  elseif stored then
+    if trace_cache or trace_containers then
+      report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+    end
+  end
+  return stored
+end
+function containers.write(container,name,data)
+  if data then
+    data.cache_version=container.version
+    if container.enabled and caches then
+      local unique,shared=data.unique,data.shared
+      data.unique,data.shared=nil,nil
+      caches.savedata(container.writable,name,data)
+      if trace_cache or trace_containers then
+        report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+      end
+      data.unique,data.shared=unique,shared
+    end
+    if trace_cache or trace_containers then
+      report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+    end
+    container.storage[name]=data
+  end
+  return data
+end
+function containers.content(container,name)
+  return container.storage[name]
 end
 function containers.cleanname(name)
   return (gsub(lower(name),"[^%w\128-\255]+","-")) 
-end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-fonts-nod']={
-  version=1.001,
-  comment="companion to luatex-fonts.lua",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-fonts-nod']={
+  version=1.001,
+  comment="companion to luatex-fonts.lua",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
 if tex.attribute[0]~=0 then
-  texio.write_nl("log","!")
-  texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
-  texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
-  texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
+  texio.write_nl("log","!")
+  texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
+  texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
+  texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
   texio.write_nl("log","!")
   tex.attribute[0]=0 
 end
-attributes=attributes or {}
+attributes=attributes or {}
 attributes.unsetvalue=-0x7FFFFFFF
 local numbers,last={},127
-attributes.private=attributes.private or function(name)
-  local number=numbers[name]
-  if not number then
-    if last<255 then
-      last=last+1
-    end
-    number=last
-    numbers[name]=number
-  end
-  return number
-end
-nodes={}
-nodes.pool={}
+attributes.private=attributes.private or function(name)
+  local number=numbers[name]
+  if not number then
+    if last<255 then
+      last=last+1
+    end
+    number=last
+    numbers[name]=number
+  end
+  return number
+end
+nodes={}
+nodes.pool={}
 nodes.handlers={}
-local nodecodes={} for k,v in next,node.types  () do nodecodes[string.gsub(v,"_","")]=k end
-local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
+local nodecodes={} for k,v in next,node.types  () do nodecodes[string.gsub(v,"_","")]=k end
+local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
 local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
-nodes.nodecodes=nodecodes
-nodes.whatcodes=whatcodes
-nodes.whatsitcodes=whatcodes
+nodes.nodecodes=nodecodes
+nodes.whatcodes=whatcodes
+nodes.whatsitcodes=whatcodes
 nodes.glyphcodes=glyphcodes
-local free_node=node.free
-local remove_node=node.remove
-local new_node=node.new
+local free_node=node.free
+local remove_node=node.remove
+local new_node=node.new
 local traverse_id=node.traverse_id
 local math_code=nodecodes.math
-nodes.handlers.protectglyphs=node.protect_glyphs
+nodes.handlers.protectglyphs=node.protect_glyphs
 nodes.handlers.unprotectglyphs=node.unprotect_glyphs
-function nodes.remove(head,current,free_too)
-  local t=current
-  head,current=remove_node(head,current)
-  if t then
-    if free_too then
-      free_node(t)
-      t=nil
-    else
-      t.next,t.prev=nil,nil
-    end
-  end
-  return head,current,t
-end
-function nodes.delete(head,current)
-  return nodes.remove(head,current,true)
-end
-nodes.before=node.insert_before
+function nodes.remove(head,current,free_too)
+  local t=current
+  head,current=remove_node(head,current)
+  if t then
+    if free_too then
+      free_node(t)
+      t=nil
+    else
+      t.next,t.prev=nil,nil
+    end
+  end
+  return head,current,t
+end
+function nodes.delete(head,current)
+  return nodes.remove(head,current,true)
+end
+nodes.before=node.insert_before
 nodes.after=node.insert_after
-function nodes.pool.kern(k)
-  local n=new_node("kern",1)
-  n.kern=k
-  return n
-end
-function nodes.endofmath(n)
-  for n in traverse_id(math_code,n.next) do
-    return n
-  end
-end
+function nodes.pool.kern(k)
+  local n=new_node("kern",1)
+  n.kern=k
+  return n
+end
+function nodes.endofmath(n)
+  for n in traverse_id(math_code,n.next) do
+    return n
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-ini']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-ini']={
+  version=1.001,
+  comment="companion to font-ini.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 report_defining=logs.reporter("fonts","defining")
-fonts=fonts or {}
+fonts=fonts or {}
 local fonts=fonts
 fonts.hashes={ identifiers=allocate() }
-fonts.tables=fonts.tables   or {}
-fonts.helpers=fonts.helpers  or {}
+fonts.tables=fonts.tables   or {}
+fonts.helpers=fonts.helpers  or {}
 fonts.tracers=fonts.tracers  or {} 
 fonts.specifiers=fonts.specifiers or {} 
 fonts.analyzers={} 
-fonts.readers={}
-fonts.definers={ methods={} }
+fonts.readers={}
+fonts.definers={ methods={} }
 fonts.loggers={ register=function() end }
-fontloader.totable=fontloader.to_table
+fontloader.totable=fontloader.to_table
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-con']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-con']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
-local utfbyte=utf.byte
-local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
+local next,tostring,rawget=next,tostring,rawget
+local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
+local utfbyte=utf.byte
+local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
 local derivetable=table.derive
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
 local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end)
 local report_defining=logs.reporter("fonts","defining")
-local fonts=fonts
-local constructors=fonts.constructors or {}
-fonts.constructors=constructors
+local fonts=fonts
+local constructors=fonts.constructors or {}
+fonts.constructors=constructors
 local handlers=fonts.handlers or {} 
 fonts.handlers=handlers
-local allocate=utilities.storage.allocate
+local allocate=utilities.storage.allocate
 local setmetatableindex=table.setmetatableindex
-constructors.dontembed=allocate()
-constructors.autocleanup=true
+constructors.dontembed=allocate()
+constructors.autocleanup=true
 constructors.namemode="fullpath" 
-constructors.version=1.01
+constructors.version=1.01
 constructors.cache=containers.define("fonts","constructors",constructors.version,false)
 constructors.privateoffset=0xF0000
-constructors.keys={
-  properties={
-    encodingbytes="number",
-    embedding="number",
-    cidinfo={},
-    format="string",
-    fontname="string",
-    fullname="string",
-    filename="filename",
-    psname="string",
-    name="string",
-    virtualized="boolean",
-    hasitalics="boolean",
-    autoitalicamount="basepoints",
-    nostackmath="boolean",
-    noglyphnames="boolean",
-    mode="string",
-    hasmath="boolean",
-    mathitalics="boolean",
-    textitalics="boolean",
-    finalized="boolean",
-  },
-  parameters={
-    mathsize="number",
-    scriptpercentage="float",
-    scriptscriptpercentage="float",
-    units="cardinal",
-    designsize="scaledpoints",
-    expansion={
+constructors.keys={
+  properties={
+    encodingbytes="number",
+    embedding="number",
+    cidinfo={},
+    format="string",
+    fontname="string",
+    fullname="string",
+    filename="filename",
+    psname="string",
+    name="string",
+    virtualized="boolean",
+    hasitalics="boolean",
+    autoitalicamount="basepoints",
+    nostackmath="boolean",
+    noglyphnames="boolean",
+    mode="string",
+    hasmath="boolean",
+    mathitalics="boolean",
+    textitalics="boolean",
+    finalized="boolean",
+  },
+  parameters={
+    mathsize="number",
+    scriptpercentage="float",
+    scriptscriptpercentage="float",
+    units="cardinal",
+    designsize="scaledpoints",
+    expansion={
                   stretch="integerscale",
                   shrink="integerscale",
                   step="integerscale",
-                  auto="boolean",
-                 },
-    protrusion={
-                  auto="boolean",
-                 },
-    slantfactor="float",
-    extendfactor="float",
-    factor="float",
-    hfactor="float",
-    vfactor="float",
-    size="scaledpoints",
-    units="scaledpoints",
-    scaledpoints="scaledpoints",
-    slantperpoint="scaledpoints",
-    spacing={
-                  width="scaledpoints",
-                  stretch="scaledpoints",
-                  shrink="scaledpoints",
-                  extra="scaledpoints",
-                 },
-    xheight="scaledpoints",
-    quad="scaledpoints",
-    ascender="scaledpoints",
-    descender="scaledpoints",
-    synonyms={
-                  space="spacing.width",
-                  spacestretch="spacing.stretch",
-                  spaceshrink="spacing.shrink",
-                  extraspace="spacing.extra",
-                  x_height="xheight",
-                  space_stretch="spacing.stretch",
-                  space_shrink="spacing.shrink",
-                  extra_space="spacing.extra",
-                  em="quad",
-                  ex="xheight",
-                  slant="slantperpoint",
-                 },
-  },
-  description={
-    width="basepoints",
-    height="basepoints",
-    depth="basepoints",
-    boundingbox={},
-  },
-  character={
-    width="scaledpoints",
-    height="scaledpoints",
-    depth="scaledpoints",
-    italic="scaledpoints",
-  },
+                  auto="boolean",
+                 },
+    protrusion={
+                  auto="boolean",
+                 },
+    slantfactor="float",
+    extendfactor="float",
+    factor="float",
+    hfactor="float",
+    vfactor="float",
+    size="scaledpoints",
+    units="scaledpoints",
+    scaledpoints="scaledpoints",
+    slantperpoint="scaledpoints",
+    spacing={
+                  width="scaledpoints",
+                  stretch="scaledpoints",
+                  shrink="scaledpoints",
+                  extra="scaledpoints",
+                 },
+    xheight="scaledpoints",
+    quad="scaledpoints",
+    ascender="scaledpoints",
+    descender="scaledpoints",
+    synonyms={
+                  space="spacing.width",
+                  spacestretch="spacing.stretch",
+                  spaceshrink="spacing.shrink",
+                  extraspace="spacing.extra",
+                  x_height="xheight",
+                  space_stretch="spacing.stretch",
+                  space_shrink="spacing.shrink",
+                  extra_space="spacing.extra",
+                  em="quad",
+                  ex="xheight",
+                  slant="slantperpoint",
+                 },
+  },
+  description={
+    width="basepoints",
+    height="basepoints",
+    depth="basepoints",
+    boundingbox={},
+  },
+  character={
+    width="scaledpoints",
+    height="scaledpoints",
+    depth="scaledpoints",
+    italic="scaledpoints",
+  },
 }
-local designsizes=allocate()
-constructors.designsizes=designsizes
-local loadedfonts=allocate()
+local designsizes=allocate()
+constructors.designsizes=designsizes
+local loadedfonts=allocate()
 constructors.loadedfonts=loadedfonts
-local factors={
-  pt=65536.0,
-  bp=65781.8,
+local factors={
+  pt=65536.0,
+  bp=65781.8,
 }
-function constructors.setfactor(f)
-  constructors.factor=factors[f or 'pt'] or factors.pt
+function constructors.setfactor(f)
+  constructors.factor=factors[f or 'pt'] or factors.pt
 end
 constructors.setfactor()
 function constructors.scaled(scaledpoints,designsize) 
-  if scaledpoints<0 then
-    if designsize then
-      local factor=constructors.factor
+  if scaledpoints<0 then
+    if designsize then
+      local factor=constructors.factor
       if designsize>factor then 
         return (- scaledpoints/1000)*designsize 
-      else
-        return (- scaledpoints/1000)*designsize*factor
-      end
-    else
-      return (- scaledpoints/1000)*10*factor
-    end
-  else
-    return scaledpoints
-  end
-end
-function constructors.cleanuptable(tfmdata)
-  if constructors.autocleanup and tfmdata.properties.virtualized then
-    for k,v in next,tfmdata.characters do
+      else
+        return (- scaledpoints/1000)*designsize*factor
+      end
+    else
+      return (- scaledpoints/1000)*10*factor
+    end
+  else
+    return scaledpoints
+  end
+end
+function constructors.cleanuptable(tfmdata)
+  if constructors.autocleanup and tfmdata.properties.virtualized then
+    for k,v in next,tfmdata.characters do
       if v.commands then v.commands=nil end
-    end
-  end
+    end
+  end
 end
-function constructors.calculatescale(tfmdata,scaledpoints)
-  local parameters=tfmdata.parameters
-  if scaledpoints<0 then
+function constructors.calculatescale(tfmdata,scaledpoints)
+  local parameters=tfmdata.parameters
+  if scaledpoints<0 then
     scaledpoints=(- scaledpoints/1000)*(tfmdata.designsize or parameters.designsize) 
-  end
+  end
   return scaledpoints,scaledpoints/(parameters.units or 1000) 
 end
-local unscaled={
-  ScriptPercentScaleDown=true,
-  ScriptScriptPercentScaleDown=true,
-  RadicalDegreeBottomRaisePercent=true
+local unscaled={
+  ScriptPercentScaleDown=true,
+  ScriptScriptPercentScaleDown=true,
+  RadicalDegreeBottomRaisePercent=true
 }
 function constructors.assignmathparameters(target,original)
-  local mathparameters=original.mathparameters
-  if mathparameters and next(mathparameters) then
-    local targetparameters=target.parameters
-    local targetproperties=target.properties
-    local targetmathparameters={}
-    local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor
-    for name,value in next,mathparameters do
-      if unscaled[name] then
-        targetmathparameters[name]=value
-      else
-        targetmathparameters[name]=value*factor
-      end
-    end
-    if not targetmathparameters.FractionDelimiterSize then
-      targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size
-    end
-    if not mathparameters.FractionDelimiterDisplayStyleSize then
-      targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size
-    end
-    target.mathparameters=targetmathparameters
-  end
+  local mathparameters=original.mathparameters
+  if mathparameters and next(mathparameters) then
+    local targetparameters=target.parameters
+    local targetproperties=target.properties
+    local targetmathparameters={}
+    local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor
+    for name,value in next,mathparameters do
+      if unscaled[name] then
+        targetmathparameters[name]=value
+      else
+        targetmathparameters[name]=value*factor
+      end
+    end
+    if not targetmathparameters.FractionDelimiterSize then
+      targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size
+    end
+    if not mathparameters.FractionDelimiterDisplayStyleSize then
+      targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size
+    end
+    target.mathparameters=targetmathparameters
+  end
 end
 function constructors.beforecopyingcharacters(target,original)
 end
 function constructors.aftercopyingcharacters(target,original)
 end
-function constructors.enhanceparameters(parameters)
-  local xheight=parameters.x_height
-  local quad=parameters.quad
-  local space=parameters.space
-  local stretch=parameters.space_stretch
-  local shrink=parameters.space_shrink
-  local extra=parameters.extra_space
-  local slant=parameters.slant
-  parameters.xheight=xheight
-  parameters.spacestretch=stretch
-  parameters.spaceshrink=shrink
-  parameters.extraspace=extra
-  parameters.em=quad
-  parameters.ex=xheight
-  parameters.slantperpoint=slant
-  parameters.spacing={
-    width=space,
-    stretch=stretch,
-    shrink=shrink,
-    extra=extra,
-  }
-end
-function constructors.scale(tfmdata,specification)
+function constructors.enhanceparameters(parameters)
+  local xheight=parameters.x_height
+  local quad=parameters.quad
+  local space=parameters.space
+  local stretch=parameters.space_stretch
+  local shrink=parameters.space_shrink
+  local extra=parameters.extra_space
+  local slant=parameters.slant
+  parameters.xheight=xheight
+  parameters.spacestretch=stretch
+  parameters.spaceshrink=shrink
+  parameters.extraspace=extra
+  parameters.em=quad
+  parameters.ex=xheight
+  parameters.slantperpoint=slant
+  parameters.spacing={
+    width=space,
+    stretch=stretch,
+    shrink=shrink,
+    extra=extra,
+  }
+end
+function constructors.scale(tfmdata,specification)
   local target={}
-  if tonumber(specification) then
-    specification={ size=specification }
+  if tonumber(specification) then
+    specification={ size=specification }
   end
-  local scaledpoints=specification.size
+  local scaledpoints=specification.size
   local relativeid=specification.relativeid
-  local properties=tfmdata.properties   or {}
-  local goodies=tfmdata.goodies    or {}
-  local resources=tfmdata.resources   or {}
+  local properties=tfmdata.properties   or {}
+  local goodies=tfmdata.goodies    or {}
+  local resources=tfmdata.resources   or {}
   local descriptions=tfmdata.descriptions  or {} 
   local characters=tfmdata.characters   or {} 
   local changed=tfmdata.changed    or {} 
-  local shared=tfmdata.shared     or {}
-  local parameters=tfmdata.parameters   or {}
+  local shared=tfmdata.shared     or {}
+  local parameters=tfmdata.parameters   or {}
   local mathparameters=tfmdata.mathparameters or {}
-  local targetcharacters={}
-  local targetdescriptions=derivetable(descriptions)
-  local targetparameters=derivetable(parameters)
-  local targetproperties=derivetable(properties)
+  local targetcharacters={}
+  local targetdescriptions=derivetable(descriptions)
+  local targetparameters=derivetable(parameters)
+  local targetproperties=derivetable(properties)
   local targetgoodies=goodies            
-  target.characters=targetcharacters
-  target.descriptions=targetdescriptions
+  target.characters=targetcharacters
+  target.descriptions=targetdescriptions
   target.parameters=targetparameters
-  target.properties=targetproperties
-  target.goodies=targetgoodies
-  target.shared=shared
-  target.resources=resources
+  target.properties=targetproperties
+  target.goodies=targetgoodies
+  target.shared=shared
+  target.resources=resources
   target.unscaled=tfmdata
-  local mathsize=tonumber(specification.mathsize) or 0
-  local textsize=tonumber(specification.textsize) or scaledpoints
-  local forcedsize=tonumber(parameters.mathsize  ) or 0
-  local extrafactor=tonumber(specification.factor ) or 1
-  if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then
-    scaledpoints=parameters.scriptpercentage*textsize/100
-  elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then
-    scaledpoints=parameters.scriptscriptpercentage*textsize/100
+  local mathsize=tonumber(specification.mathsize) or 0
+  local textsize=tonumber(specification.textsize) or scaledpoints
+  local forcedsize=tonumber(parameters.mathsize  ) or 0
+  local extrafactor=tonumber(specification.factor ) or 1
+  if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then
+    scaledpoints=parameters.scriptpercentage*textsize/100
+  elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then
+    scaledpoints=parameters.scriptscriptpercentage*textsize/100
   elseif forcedsize>1000 then 
-    scaledpoints=forcedsize
-  end
+    scaledpoints=forcedsize
+  end
   targetparameters.mathsize=mathsize  
   targetparameters.textsize=textsize  
   targetparameters.forcedsize=forcedsize 
   targetparameters.extrafactor=extrafactor
-  local tounicode=resources.tounicode
-  local defaultwidth=resources.defaultwidth or 0
-  local defaultheight=resources.defaultheight or 0
-  local defaultdepth=resources.defaultdepth or 0
+  local tounicode=resources.tounicode
+  local defaultwidth=resources.defaultwidth or 0
+  local defaultheight=resources.defaultheight or 0
+  local defaultdepth=resources.defaultdepth or 0
   local units=parameters.units or 1000
-  if target.fonts then
+  if target.fonts then
     target.fonts=fastcopy(target.fonts) 
   end
   targetproperties.language=properties.language or "dflt" 
   targetproperties.script=properties.script  or "dflt" 
   targetproperties.mode=properties.mode   or "base"
-  local askedscaledpoints=scaledpoints
+  local askedscaledpoints=scaledpoints
   local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints)
-  local hdelta=delta
+  local hdelta=delta
   local vdelta=delta
   target.designsize=parameters.designsize 
   target.units_per_em=units
   local direction=properties.direction or tfmdata.direction or 0 
-  target.direction=direction
+  target.direction=direction
   properties.direction=direction
   target.size=scaledpoints
-  target.encodingbytes=properties.encodingbytes or 1
-  target.embedding=properties.embedding or "subset"
-  target.tounicode=1
-  target.cidinfo=properties.cidinfo
+  target.encodingbytes=properties.encodingbytes or 1
+  target.embedding=properties.embedding or "subset"
+  target.tounicode=1
+  target.cidinfo=properties.cidinfo
   target.format=properties.format
   local fontname=properties.fontname or tfmdata.fontname 
   local fullname=properties.fullname or tfmdata.fullname 
@@ -3645,4275 +3645,4275 @@ function constructors.scale(tfmdata,specification)
   local psname=properties.psname  or tfmdata.psname  
   local name=properties.name   or tfmdata.name
   if not psname or psname=="" then
-    psname=fontname or (fullname and fonts.names.cleanname(fullname))
-  end
-  target.fontname=fontname
-  target.fullname=fullname
-  target.filename=filename
-  target.psname=psname
+    psname=fontname or (fullname and fonts.names.cleanname(fullname))
+  end
+  target.fontname=fontname
+  target.fullname=fullname
+  target.filename=filename
+  target.psname=psname
   target.name=name
-  properties.fontname=fontname
-  properties.fullname=fullname
-  properties.filename=filename
-  properties.psname=psname
+  properties.fontname=fontname
+  properties.fullname=fullname
+  properties.filename=filename
+  properties.psname=psname
   properties.name=name
-  local expansion=parameters.expansion
-  if expansion then
-    target.stretch=expansion.stretch
-    target.shrink=expansion.shrink
-    target.step=expansion.step
-    target.auto_expand=expansion.auto
-  end
-  local protrusion=parameters.protrusion
-  if protrusion then
-    target.auto_protrude=protrusion.auto
-  end
-  local extendfactor=parameters.extendfactor or 0
-  if extendfactor~=0 and extendfactor~=1 then
-    hdelta=hdelta*extendfactor
+  local expansion=parameters.expansion
+  if expansion then
+    target.stretch=expansion.stretch
+    target.shrink=expansion.shrink
+    target.step=expansion.step
+    target.auto_expand=expansion.auto
+  end
+  local protrusion=parameters.protrusion
+  if protrusion then
+    target.auto_protrude=protrusion.auto
+  end
+  local extendfactor=parameters.extendfactor or 0
+  if extendfactor~=0 and extendfactor~=1 then
+    hdelta=hdelta*extendfactor
     target.extend=extendfactor*1000 
-  else
+  else
     target.extend=1000 
   end
-  local slantfactor=parameters.slantfactor or 0
-  if slantfactor~=0 then
-    target.slant=slantfactor*1000
-  else
-    target.slant=0
-  end
-  targetparameters.factor=delta
-  targetparameters.hfactor=hdelta
-  targetparameters.vfactor=vdelta
-  targetparameters.size=scaledpoints
-  targetparameters.units=units
+  local slantfactor=parameters.slantfactor or 0
+  if slantfactor~=0 then
+    target.slant=slantfactor*1000
+  else
+    target.slant=0
+  end
+  targetparameters.factor=delta
+  targetparameters.hfactor=hdelta
+  targetparameters.vfactor=vdelta
+  targetparameters.size=scaledpoints
+  targetparameters.units=units
   targetparameters.scaledpoints=askedscaledpoints
-  local isvirtual=properties.virtualized or tfmdata.type=="virtual"
-  local hasquality=target.auto_expand or target.auto_protrude
-  local hasitalics=properties.hasitalics
-  local autoitalicamount=properties.autoitalicamount
-  local stackmath=not properties.nostackmath
-  local nonames=properties.noglyphnames
+  local isvirtual=properties.virtualized or tfmdata.type=="virtual"
+  local hasquality=target.auto_expand or target.auto_protrude
+  local hasitalics=properties.hasitalics
+  local autoitalicamount=properties.autoitalicamount
+  local stackmath=not properties.nostackmath
+  local nonames=properties.noglyphnames
   local nodemode=properties.mode=="node"
-  if changed and not next(changed) then
-    changed=false
+  if changed and not next(changed) then
+    changed=false
   end
   target.type=isvirtual and "virtual" or "real"
   target.postprocessors=tfmdata.postprocessors
-  local targetslant=(parameters.slant     or parameters[1] or 0)
-  local targetspace=(parameters.space     or parameters[2] or 0)*hdelta
-  local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta
-  local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta
-  local targetx_height=(parameters.x_height   or parameters[5] or 0)*vdelta
-  local targetquad=(parameters.quad     or parameters[6] or 0)*hdelta
+  local targetslant=(parameters.slant     or parameters[1] or 0)
+  local targetspace=(parameters.space     or parameters[2] or 0)*hdelta
+  local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta
+  local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta
+  local targetx_height=(parameters.x_height   or parameters[5] or 0)*vdelta
+  local targetquad=(parameters.quad     or parameters[6] or 0)*hdelta
   local targetextra_space=(parameters.extra_space  or parameters[7] or 0)*hdelta
   targetparameters.slant=targetslant 
-  targetparameters.space=targetspace
-  targetparameters.space_stretch=targetspace_stretch
-  targetparameters.space_shrink=targetspace_shrink
-  targetparameters.x_height=targetx_height
-  targetparameters.quad=targetquad
+  targetparameters.space=targetspace
+  targetparameters.space_stretch=targetspace_stretch
+  targetparameters.space_shrink=targetspace_shrink
+  targetparameters.x_height=targetx_height
+  targetparameters.quad=targetquad
   targetparameters.extra_space=targetextra_space
-  local ascender=parameters.ascender
-  if ascender then
-    targetparameters.ascender=delta*ascender
-  end
-  local descender=parameters.descender
-  if descender then
-    targetparameters.descender=delta*descender
+  local ascender=parameters.ascender
+  if ascender then
+    targetparameters.ascender=delta*ascender
+  end
+  local descender=parameters.descender
+  if descender then
+    targetparameters.descender=delta*descender
   end
   constructors.enhanceparameters(targetparameters)
-  local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0
-  local scaledwidth=defaultwidth*hdelta
-  local scaledheight=defaultheight*vdelta
+  local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0
+  local scaledwidth=defaultwidth*hdelta
+  local scaledheight=defaultheight*vdelta
   local scaleddepth=defaultdepth*vdelta
   local hasmath=(properties.hasmath or next(mathparameters)) and true
-  if hasmath then
+  if hasmath then
     constructors.assignmathparameters(target,tfmdata) 
-    properties.hasmath=true
-    target.nomath=false
-    target.MathConstants=target.mathparameters
-  else
-    properties.hasmath=false
-    target.nomath=true
+    properties.hasmath=true
+    target.nomath=false
+    target.MathConstants=target.mathparameters
+  else
+    properties.hasmath=false
+    target.nomath=true
     target.mathparameters=nil 
   end
-  local italickey="italic"
+  local italickey="italic"
   local useitalics=true
   if hasmath then
     autoitalicamount=false 
-  elseif properties.textitalics then
-    italickey="italic_correction"
-    useitalics=false
-    if properties.delaytextitalics then
-      autoitalicamount=false
-    end
-  end
-  if trace_defining then
-    report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
-      name,fullname,filename,hdelta,vdelta,
-      hasmath and "enabled" or "disabled",useitalics and "enabled" or "disabled")
+  elseif properties.textitalics then
+    italickey="italic_correction"
+    useitalics=false
+    if properties.delaytextitalics then
+      autoitalicamount=false
+    end
+  end
+  if trace_defining then
+    report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
+      name,fullname,filename,hdelta,vdelta,
+      hasmath and "enabled" or "disabled",useitalics and "enabled" or "disabled")
   end
   constructors.beforecopyingcharacters(target,tfmdata)
   local sharedkerns={}
-  for unicode,character in next,characters do
-    local chr,description,index,touni
+  for unicode,character in next,characters do
+    local chr,description,index,touni
     if changed then
-      local c=changed[unicode]
-      if c then
-        description=descriptions[c] or descriptions[unicode] or character
-        character=characters[c] or character
-        index=description.index or c
-        if tounicode then
+      local c=changed[unicode]
+      if c then
+        description=descriptions[c] or descriptions[unicode] or character
+        character=characters[c] or character
+        index=description.index or c
+        if tounicode then
           touni=tounicode[index] 
           if not touni then 
-            local d=descriptions[unicode] or characters[unicode]
-            local i=d.index or unicode
+            local d=descriptions[unicode] or characters[unicode]
+            local i=d.index or unicode
             touni=tounicode[i] 
-          end
-        end
-      else
-        description=descriptions[unicode] or character
-        index=description.index or unicode
-        if tounicode then
+          end
+        end
+      else
+        description=descriptions[unicode] or character
+        index=description.index or unicode
+        if tounicode then
           touni=tounicode[index] 
-        end
-      end
-    else
-      description=descriptions[unicode] or character
-      index=description.index or unicode
-      if tounicode then
+        end
+      end
+    else
+      description=descriptions[unicode] or character
+      index=description.index or unicode
+      if tounicode then
         touni=tounicode[index] 
-      end
-    end
-    local width=description.width
-    local height=description.height
-    local depth=description.depth
-    if width then width=hdelta*width else width=scaledwidth end
+      end
+    end
+    local width=description.width
+    local height=description.height
+    local depth=description.depth
+    if width then width=hdelta*width else width=scaledwidth end
     if height then height=vdelta*height else height=scaledheight end
-    if depth and depth~=0 then
-      depth=delta*depth
-      if nonames then
-        chr={
-          index=index,
-          height=height,
-          depth=depth,
-          width=width,
-        }
-      else
-        chr={
-          name=description.name,
-          index=index,
-          height=height,
-          depth=depth,
-          width=width,
-        }
-      end
+    if depth and depth~=0 then
+      depth=delta*depth
+      if nonames then
+        chr={
+          index=index,
+          height=height,
+          depth=depth,
+          width=width,
+        }
+      else
+        chr={
+          name=description.name,
+          index=index,
+          height=height,
+          depth=depth,
+          width=width,
+        }
+      end
     else
-      if nonames then
-        chr={
-          index=index,
-          height=height,
-          width=width,
-        }
-      else
-        chr={
-          name=description.name,
-          index=index,
-          height=height,
-          width=width,
-        }
-      end
-    end
-    if touni then
-      chr.tounicode=touni
-    end
+      if nonames then
+        chr={
+          index=index,
+          height=height,
+          width=width,
+        }
+      else
+        chr={
+          name=description.name,
+          index=index,
+          height=height,
+          width=width,
+        }
+      end
+    end
+    if touni then
+      chr.tounicode=touni
+    end
     if hasquality then
-      local ve=character.expansion_factor
-      if ve then
+      local ve=character.expansion_factor
+      if ve then
         chr.expansion_factor=ve*1000 
-      end
-      local vl=character.left_protruding
-      if vl then
-        chr.left_protruding=protrusionfactor*width*vl
-      end
-      local vr=character.right_protruding
-      if vr then
-        chr.right_protruding=protrusionfactor*width*vr
-      end
-    end
-    if autoitalicamount then
-      local vi=description.italic
-      if not vi then
-        local vi=description.boundingbox[3]-description.width+autoitalicamount
+      end
+      local vl=character.left_protruding
+      if vl then
+        chr.left_protruding=protrusionfactor*width*vl
+      end
+      local vr=character.right_protruding
+      if vr then
+        chr.right_protruding=protrusionfactor*width*vr
+      end
+    end
+    if autoitalicamount then
+      local vi=description.italic
+      if not vi then
+        local vi=description.boundingbox[3]-description.width+autoitalicamount
         if vi>0 then 
-          chr[italickey]=vi*hdelta
-        end
-      elseif vi~=0 then
-        chr[italickey]=vi*hdelta
-      end
-    elseif hasitalics then
-      local vi=description.italic
-      if vi and vi~=0 then
-        chr[italickey]=vi*hdelta
-      end
+          chr[italickey]=vi*hdelta
+        end
+      elseif vi~=0 then
+        chr[italickey]=vi*hdelta
+      end
+    elseif hasitalics then
+      local vi=description.italic
+      if vi and vi~=0 then
+        chr[italickey]=vi*hdelta
+      end
     end
     if hasmath then
-      local vn=character.next
-      if vn then
-        chr.next=vn
-      else
-        local vv=character.vert_variants
-        if vv then
-          local t={}
-          for i=1,#vv do
-            local vvi=vv[i]
-            t[i]={
-              ["start"]=(vvi["start"]  or 0)*vdelta,
-              ["end"]=(vvi["end"]   or 0)*vdelta,
-              ["advance"]=(vvi["advance"] or 0)*vdelta,
-              ["extender"]=vvi["extender"],
-              ["glyph"]=vvi["glyph"],
-            }
-          end
-          chr.vert_variants=t
-        else
-          local hv=character.horiz_variants
-          if hv then
-            local t={}
-            for i=1,#hv do
-              local hvi=hv[i]
-              t[i]={
-                ["start"]=(hvi["start"]  or 0)*hdelta,
-                ["end"]=(hvi["end"]   or 0)*hdelta,
-                ["advance"]=(hvi["advance"] or 0)*hdelta,
-                ["extender"]=hvi["extender"],
-                ["glyph"]=hvi["glyph"],
-              }
-            end
-            chr.horiz_variants=t
-          end
-        end
-      end
-      local va=character.top_accent
-      if va then
-        chr.top_accent=vdelta*va
-      end
-      if stackmath then
+      local vn=character.next
+      if vn then
+        chr.next=vn
+      else
+        local vv=character.vert_variants
+        if vv then
+          local t={}
+          for i=1,#vv do
+            local vvi=vv[i]
+            t[i]={
+              ["start"]=(vvi["start"]  or 0)*vdelta,
+              ["end"]=(vvi["end"]   or 0)*vdelta,
+              ["advance"]=(vvi["advance"] or 0)*vdelta,
+              ["extender"]=vvi["extender"],
+              ["glyph"]=vvi["glyph"],
+            }
+          end
+          chr.vert_variants=t
+        else
+          local hv=character.horiz_variants
+          if hv then
+            local t={}
+            for i=1,#hv do
+              local hvi=hv[i]
+              t[i]={
+                ["start"]=(hvi["start"]  or 0)*hdelta,
+                ["end"]=(hvi["end"]   or 0)*hdelta,
+                ["advance"]=(hvi["advance"] or 0)*hdelta,
+                ["extender"]=hvi["extender"],
+                ["glyph"]=hvi["glyph"],
+              }
+            end
+            chr.horiz_variants=t
+          end
+        end
+      end
+      local va=character.top_accent
+      if va then
+        chr.top_accent=vdelta*va
+      end
+      if stackmath then
         local mk=character.mathkerns 
-        if mk then
-          local kerns={}
-          local v=mk.top_right  if v then local k={} for i=1,#v do local vi=v[i]
-            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
-          end   kerns.top_right=k end
-          local v=mk.top_left   if v then local k={} for i=1,#v do local vi=v[i]
-            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
-          end   kerns.top_left=k end
-          local v=mk.bottom_left if v then local k={} for i=1,#v do local vi=v[i]
-            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
-          end   kerns.bottom_left=k end
-          local v=mk.bottom_right if v then local k={} for i=1,#v do local vi=v[i]
-            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
-          end   kerns.bottom_right=k end
+        if mk then
+          local kerns={}
+          local v=mk.top_right  if v then local k={} for i=1,#v do local vi=v[i]
+            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
+          end   kerns.top_right=k end
+          local v=mk.top_left   if v then local k={} for i=1,#v do local vi=v[i]
+            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
+          end   kerns.top_left=k end
+          local v=mk.bottom_left if v then local k={} for i=1,#v do local vi=v[i]
+            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
+          end   kerns.bottom_left=k end
+          local v=mk.bottom_right if v then local k={} for i=1,#v do local vi=v[i]
+            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern }
+          end   kerns.bottom_right=k end
           chr.mathkern=kerns 
-        end
-      end
-    end
-    if not nodemode then
-      local vk=character.kerns
-      if vk then
-        local s=sharedkerns[vk]
-        if not s then
-          s={}
-          for k,v in next,vk do s[k]=v*hdelta end
-          sharedkerns[vk]=s
-        end
-        chr.kerns=s
-      end
-      local vl=character.ligatures
-      if vl then
-        if true then
+        end
+      end
+    end
+    if not nodemode then
+      local vk=character.kerns
+      if vk then
+        local s=sharedkerns[vk]
+        if not s then
+          s={}
+          for k,v in next,vk do s[k]=v*hdelta end
+          sharedkerns[vk]=s
+        end
+        chr.kerns=s
+      end
+      local vl=character.ligatures
+      if vl then
+        if true then
           chr.ligatures=vl 
-        else
-          local tt={}
-          for i,l in next,vl do
-            tt[i]=l
-          end
-          chr.ligatures=tt
-        end
-      end
-    end
-    if isvirtual then
-      local vc=character.commands
+        else
+          local tt={}
+          for i,l in next,vl do
+            tt[i]=l
+          end
+          chr.ligatures=tt
+        end
+      end
+    end
+    if isvirtual then
+      local vc=character.commands
       if vc then
-        local ok=false
-        for i=1,#vc do
-          local key=vc[i][1]
-          if key=="right" or key=="down" then
-            ok=true
-            break
-          end
-        end
-        if ok then
-          local tt={}
-          for i=1,#vc do
-            local ivc=vc[i]
-            local key=ivc[1]
-            if key=="right" then
-              tt[i]={ key,ivc[2]*hdelta }
-            elseif key=="down" then
-              tt[i]={ key,ivc[2]*vdelta }
-            elseif key=="rule" then
-              tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta }
+        local ok=false
+        for i=1,#vc do
+          local key=vc[i][1]
+          if key=="right" or key=="down" then
+            ok=true
+            break
+          end
+        end
+        if ok then
+          local tt={}
+          for i=1,#vc do
+            local ivc=vc[i]
+            local key=ivc[1]
+            if key=="right" then
+              tt[i]={ key,ivc[2]*hdelta }
+            elseif key=="down" then
+              tt[i]={ key,ivc[2]*vdelta }
+            elseif key=="rule" then
+              tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta }
             else 
               tt[i]=ivc 
-            end
-          end
-          chr.commands=tt
-        else
-          chr.commands=vc
-        end
-        chr.index=nil
-      end
-    end
-    targetcharacters[unicode]=chr
+            end
+          end
+          chr.commands=tt
+        else
+          chr.commands=vc
+        end
+        chr.index=nil
+      end
+    end
+    targetcharacters[unicode]=chr
   end
   constructors.aftercopyingcharacters(target,tfmdata)
-  return target
+  return target
 end
-function constructors.finalize(tfmdata)
-  if tfmdata.properties and tfmdata.properties.finalized then
-    return
+function constructors.finalize(tfmdata)
+  if tfmdata.properties and tfmdata.properties.finalized then
+    return
   end
-  if not tfmdata.characters then
-    return nil
+  if not tfmdata.characters then
+    return nil
   end
-  if not tfmdata.goodies then
+  if not tfmdata.goodies then
     tfmdata.goodies={} 
   end
-  local parameters=tfmdata.parameters
-  if not parameters then
-    return nil
+  local parameters=tfmdata.parameters
+  if not parameters then
+    return nil
   end
-  if not parameters.expansion then
-    parameters.expansion={
-      stretch=tfmdata.stretch   or 0,
-      shrink=tfmdata.shrink   or 0,
-      step=tfmdata.step    or 0,
-      auto=tfmdata.auto_expand or false,
-    }
+  if not parameters.expansion then
+    parameters.expansion={
+      stretch=tfmdata.stretch   or 0,
+      shrink=tfmdata.shrink   or 0,
+      step=tfmdata.step    or 0,
+      auto=tfmdata.auto_expand or false,
+    }
   end
-  if not parameters.protrusion then
-    parameters.protrusion={
-      auto=auto_protrude
-    }
+  if not parameters.protrusion then
+    parameters.protrusion={
+      auto=auto_protrude
+    }
   end
-  if not parameters.size then
-    parameters.size=tfmdata.size
+  if not parameters.size then
+    parameters.size=tfmdata.size
   end
-  if not parameters.extendfactor then
-    parameters.extendfactor=tfmdata.extend or 0
+  if not parameters.extendfactor then
+    parameters.extendfactor=tfmdata.extend or 0
   end
-  if not parameters.slantfactor then
-    parameters.slantfactor=tfmdata.slant or 0
+  if not parameters.slantfactor then
+    parameters.slantfactor=tfmdata.slant or 0
   end
-  if not parameters.designsize then
-    parameters.designsize=tfmdata.designsize or 655360
+  if not parameters.designsize then
+    parameters.designsize=tfmdata.designsize or 655360
   end
-  if not parameters.units then
-    parameters.units=tfmdata.units_per_em or 1000
+  if not parameters.units then
+    parameters.units=tfmdata.units_per_em or 1000
   end
-  if not tfmdata.descriptions then
+  if not tfmdata.descriptions then
     local descriptions={} 
-    setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end)
-    tfmdata.descriptions=descriptions
-  end
-  local properties=tfmdata.properties
-  if not properties then
-    properties={}
-    tfmdata.properties=properties
-  end
-  if not properties.virtualized then
-    properties.virtualized=tfmdata.type=="virtual"
-  end
-  if not tfmdata.properties then
-    tfmdata.properties={
-      fontname=tfmdata.fontname,
-      filename=tfmdata.filename,
-      fullname=tfmdata.fullname,
-      name=tfmdata.name,
+    setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end)
+    tfmdata.descriptions=descriptions
+  end
+  local properties=tfmdata.properties
+  if not properties then
+    properties={}
+    tfmdata.properties=properties
+  end
+  if not properties.virtualized then
+    properties.virtualized=tfmdata.type=="virtual"
+  end
+  if not tfmdata.properties then
+    tfmdata.properties={
+      fontname=tfmdata.fontname,
+      filename=tfmdata.filename,
+      fullname=tfmdata.fullname,
+      name=tfmdata.name,
       psname=tfmdata.psname,
-      encodingbytes=tfmdata.encodingbytes or 1,
-      embedding=tfmdata.embedding   or "subset",
-      tounicode=tfmdata.tounicode   or 1,
-      cidinfo=tfmdata.cidinfo    or nil,
-      format=tfmdata.format    or "type1",
-      direction=tfmdata.direction   or 0,
-    }
-  end
-  if not tfmdata.resources then
-    tfmdata.resources={}
-  end
-  if not tfmdata.shared then
-    tfmdata.shared={}
-  end
-  if not properties.hasmath then
-    properties.hasmath=not tfmdata.nomath
-  end
-  tfmdata.MathConstants=nil
+      encodingbytes=tfmdata.encodingbytes or 1,
+      embedding=tfmdata.embedding   or "subset",
+      tounicode=tfmdata.tounicode   or 1,
+      cidinfo=tfmdata.cidinfo    or nil,
+      format=tfmdata.format    or "type1",
+      direction=tfmdata.direction   or 0,
+    }
+  end
+  if not tfmdata.resources then
+    tfmdata.resources={}
+  end
+  if not tfmdata.shared then
+    tfmdata.shared={}
+  end
+  if not properties.hasmath then
+    properties.hasmath=not tfmdata.nomath
+  end
+  tfmdata.MathConstants=nil
   tfmdata.postprocessors=nil
-  tfmdata.fontname=nil
-  tfmdata.filename=nil
-  tfmdata.fullname=nil
+  tfmdata.fontname=nil
+  tfmdata.filename=nil
+  tfmdata.fullname=nil
   tfmdata.name=nil 
   tfmdata.psname=nil
-  tfmdata.encodingbytes=nil
-  tfmdata.embedding=nil
-  tfmdata.tounicode=nil
-  tfmdata.cidinfo=nil
-  tfmdata.format=nil
-  tfmdata.direction=nil
-  tfmdata.type=nil
-  tfmdata.nomath=nil
+  tfmdata.encodingbytes=nil
+  tfmdata.embedding=nil
+  tfmdata.tounicode=nil
+  tfmdata.cidinfo=nil
+  tfmdata.format=nil
+  tfmdata.direction=nil
+  tfmdata.type=nil
+  tfmdata.nomath=nil
   tfmdata.designsize=nil
-  tfmdata.size=nil
-  tfmdata.stretch=nil
-  tfmdata.shrink=nil
-  tfmdata.step=nil
-  tfmdata.auto_expand=nil
-  tfmdata.auto_protrude=nil
-  tfmdata.extend=nil
-  tfmdata.slant=nil
+  tfmdata.size=nil
+  tfmdata.stretch=nil
+  tfmdata.shrink=nil
+  tfmdata.step=nil
+  tfmdata.auto_expand=nil
+  tfmdata.auto_protrude=nil
+  tfmdata.extend=nil
+  tfmdata.slant=nil
   tfmdata.units_per_em=nil
   properties.finalized=true
-  return tfmdata
+  return tfmdata
 end
-local hashmethods={}
+local hashmethods={}
 constructors.hashmethods=hashmethods
 function constructors.hashfeatures(specification) 
-  local features=specification.features
-  if features then
-    local t,tn={},0
-    for category,list in next,features do
-      if next(list) then
-        local hasher=hashmethods[category]
-        if hasher then
-          local hash=hasher(list)
-          if hash then
-            tn=tn+1
-            t[tn]=category..":"..hash
-          end
-        end
-      end
-    end
-    if tn>0 then
-      return concat(t," & ")
-    end
-  end
-  return "unknown"
-end
-hashmethods.normal=function(list)
-  local s={}
-  local n=0
-  for k,v in next,list do
+  local features=specification.features
+  if features then
+    local t,tn={},0
+    for category,list in next,features do
+      if next(list) then
+        local hasher=hashmethods[category]
+        if hasher then
+          local hash=hasher(list)
+          if hash then
+            tn=tn+1
+            t[tn]=category..":"..hash
+          end
+        end
+      end
+    end
+    if tn>0 then
+      return concat(t," & ")
+    end
+  end
+  return "unknown"
+end
+hashmethods.normal=function(list)
+  local s={}
+  local n=0
+  for k,v in next,list do
     if not k then
     elseif k=="number" or k=="features" then
-    else
-      n=n+1
-      s[n]=k
-    end
-  end
-  if n>0 then
-    sort(s)
-    for i=1,n do
-      local k=s[i]
-      s[i]=k..'='..tostring(list[k])
-    end
-    return concat(s,"+")
-  end
-end
-function constructors.hashinstance(specification,force)
-  local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks
-  if force or not hash then
-    hash=constructors.hashfeatures(specification)
-    specification.hash=hash
-  end
-  if size<1000 and designsizes[hash] then
-    size=math.round(constructors.scaled(size,designsizes[hash]))
-    specification.size=size
-  end
-    if fallbacks then
-      return hash..' @ '..tostring(size)..' @ '..fallbacks
-    else
-      return hash..' @ '..tostring(size)
+    else
+      n=n+1
+      s[n]=k
+    end
+  end
+  if n>0 then
+    sort(s)
+    for i=1,n do
+      local k=s[i]
+      s[i]=k..'='..tostring(list[k])
+    end
+    return concat(s,"+")
+  end
+end
+function constructors.hashinstance(specification,force)
+  local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks
+  if force or not hash then
+    hash=constructors.hashfeatures(specification)
+    specification.hash=hash
+  end
+  if size<1000 and designsizes[hash] then
+    size=math.round(constructors.scaled(size,designsizes[hash]))
+    specification.size=size
+  end
+    if fallbacks then
+      return hash..' @ '..tostring(size)..' @ '..fallbacks
+    else
+      return hash..' @ '..tostring(size)
     end
 end
 function constructors.setname(tfmdata,specification) 
   if constructors.namemode=="specification" then
-    local specname=specification.specification
-    if specname then
-      tfmdata.properties.name=specname
-      if trace_defining then
-        report_otf("overloaded fontname %a",specname)
-      end
-    end
-  end
-end
-function constructors.checkedfilename(data)
-  local foundfilename=data.foundfilename
-  if not foundfilename then
-    local askedfilename=data.filename or ""
-    if askedfilename~="" then
+    local specname=specification.specification
+    if specname then
+      tfmdata.properties.name=specname
+      if trace_defining then
+        report_otf("overloaded fontname %a",specname)
+      end
+    end
+  end
+end
+function constructors.checkedfilename(data)
+  local foundfilename=data.foundfilename
+  if not foundfilename then
+    local askedfilename=data.filename or ""
+    if askedfilename~="" then
       askedfilename=resolvers.resolve(askedfilename) 
-      foundfilename=resolvers.findbinfile(askedfilename,"") or ""
-      if foundfilename=="" then
-        report_defining("source file %a is not found",askedfilename)
-        foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or ""
-        if foundfilename~="" then
-          report_defining("using source file %a due to cache mismatch",foundfilename)
-        end
-      end
-    end
-    data.foundfilename=foundfilename
-  end
-  return foundfilename
-end
-local formats=allocate()
+      foundfilename=resolvers.findbinfile(askedfilename,"") or ""
+      if foundfilename=="" then
+        report_defining("source file %a is not found",askedfilename)
+        foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or ""
+        if foundfilename~="" then
+          report_defining("using source file %a due to cache mismatch",foundfilename)
+        end
+      end
+    end
+    data.foundfilename=foundfilename
+  end
+  return foundfilename
+end
+local formats=allocate()
 fonts.formats=formats
-setmetatableindex(formats,function(t,k)
-  local l=lower(k)
-  if rawget(t,k) then
-    t[k]=l
-    return l
-  end
-  return rawget(t,file.suffix(l))
+setmetatableindex(formats,function(t,k)
+  local l=lower(k)
+  if rawget(t,k) then
+    t[k]=l
+    return l
+  end
+  return rawget(t,file.suffix(l))
 end)
 local locations={}
-local function setindeed(mode,target,group,name,action,position)
-  local t=target[mode]
-  if not t then
-    report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
-    os.exit()
+local function setindeed(mode,target,group,name,action,position)
+  local t=target[mode]
+  if not t then
+    report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+    os.exit()
   elseif position then
-    insert(t,position,{ name=name,action=action })
-  else
-    for i=1,#t do
-      local ti=t[i]
-      if ti.name==name then
-        ti.action=action
-        return
-      end
-    end
-    insert(t,{ name=name,action=action })
-  end
-end
-local function set(group,name,target,source)
-  target=target[group]
-  if not target then
-    report_defining("fatal target error in setting feature %a, group %a",name,group)
-    os.exit()
-  end
-  local source=source[group]
-  if not source then
-    report_defining("fatal source error in setting feature %a, group %a",name,group)
-    os.exit()
-  end
-  local node=source.node
-  local base=source.base
-  local position=source.position
-  if node then
-    setindeed("node",target,group,name,node,position)
-  end
-  if base then
-    setindeed("base",target,group,name,base,position)
-  end
-end
-local function register(where,specification)
-  local name=specification.name
-  if name and name~="" then
-    local default=specification.default
-    local description=specification.description
-    local initializers=specification.initializers
-    local processors=specification.processors
-    local manipulators=specification.manipulators
-    local modechecker=specification.modechecker
-    if default then
-      where.defaults[name]=default
-    end
-    if description and description~="" then
-      where.descriptions[name]=description
-    end
-    if initializers then
-      set('initializers',name,where,specification)
-    end
-    if processors then
-      set('processors',name,where,specification)
-    end
-    if manipulators then
-      set('manipulators',name,where,specification)
-    end
-    if modechecker then
-      where.modechecker=modechecker
-    end
-  end
+    insert(t,position,{ name=name,action=action })
+  else
+    for i=1,#t do
+      local ti=t[i]
+      if ti.name==name then
+        ti.action=action
+        return
+      end
+    end
+    insert(t,{ name=name,action=action })
+  end
+end
+local function set(group,name,target,source)
+  target=target[group]
+  if not target then
+    report_defining("fatal target error in setting feature %a, group %a",name,group)
+    os.exit()
+  end
+  local source=source[group]
+  if not source then
+    report_defining("fatal source error in setting feature %a, group %a",name,group)
+    os.exit()
+  end
+  local node=source.node
+  local base=source.base
+  local position=source.position
+  if node then
+    setindeed("node",target,group,name,node,position)
+  end
+  if base then
+    setindeed("base",target,group,name,base,position)
+  end
+end
+local function register(where,specification)
+  local name=specification.name
+  if name and name~="" then
+    local default=specification.default
+    local description=specification.description
+    local initializers=specification.initializers
+    local processors=specification.processors
+    local manipulators=specification.manipulators
+    local modechecker=specification.modechecker
+    if default then
+      where.defaults[name]=default
+    end
+    if description and description~="" then
+      where.descriptions[name]=description
+    end
+    if initializers then
+      set('initializers',name,where,specification)
+    end
+    if processors then
+      set('processors',name,where,specification)
+    end
+    if manipulators then
+      set('manipulators',name,where,specification)
+    end
+    if modechecker then
+      where.modechecker=modechecker
+    end
+  end
 end
 constructors.registerfeature=register
-function constructors.getfeatureaction(what,where,mode,name)
-  what=handlers[what].features
-  if what then
-    where=what[where]
-    if where then
-      mode=where[mode]
-      if mode then
-        for i=1,#mode do
-          local m=mode[i]
-          if m.name==name then
-            return m.action
-          end
-        end
-      end
-    end
-  end
+function constructors.getfeatureaction(what,where,mode,name)
+  what=handlers[what].features
+  if what then
+    where=what[where]
+    if where then
+      mode=where[mode]
+      if mode then
+        for i=1,#mode do
+          local m=mode[i]
+          if m.name==name then
+            return m.action
+          end
+        end
+      end
+    end
+  end
 end
 function constructors.newhandler(what) 
-  local handler=handlers[what]
-  if not handler then
-    handler={}
-    handlers[what]=handler
-  end
-  return handler
+  local handler=handlers[what]
+  if not handler then
+    handler={}
+    handlers[what]=handler
+  end
+  return handler
 end
 function constructors.newfeatures(what) 
-  local handler=handlers[what]
-  local features=handler.features
-  if not features then
+  local handler=handlers[what]
+  local features=handler.features
+  if not features then
     local tables=handler.tables   
     local statistics=handler.statistics 
-    features=allocate {
-      defaults={},
-      descriptions=tables and tables.features or {},
-      used=statistics and statistics.usedfeatures or {},
-      initializers={ base={},node={} },
-      processors={ base={},node={} },
-      manipulators={ base={},node={} },
-    }
-    features.register=function(specification) return register(features,specification) end
+    features=allocate {
+      defaults={},
+      descriptions=tables and tables.features or {},
+      used=statistics and statistics.usedfeatures or {},
+      initializers={ base={},node={} },
+      processors={ base={},node={} },
+      manipulators={ base={},node={} },
+    }
+    features.register=function(specification) return register(features,specification) end
     handler.features=features 
-  end
-  return features
+  end
+  return features
 end
-function constructors.checkedfeatures(what,features)
-  local defaults=handlers[what].features.defaults
-  if features and next(features) then
+function constructors.checkedfeatures(what,features)
+  local defaults=handlers[what].features.defaults
+  if features and next(features) then
     features=fastcopy(features) 
-    for key,value in next,defaults do
-      if features[key]==nil then
-        features[key]=value
-      end
-    end
-    return features
-  else
+    for key,value in next,defaults do
+      if features[key]==nil then
+        features[key]=value
+      end
+    end
+    return features
+  else
     return fastcopy(defaults) 
-  end
+  end
 end
-function constructors.initializefeatures(what,tfmdata,features,trace,report)
-  if features and next(features) then
+function constructors.initializefeatures(what,tfmdata,features,trace,report)
+  if features and next(features) then
     local properties=tfmdata.properties or {} 
-    local whathandler=handlers[what]
-    local whatfeatures=whathandler.features
-    local whatinitializers=whatfeatures.initializers
+    local whathandler=handlers[what]
+    local whatfeatures=whathandler.features
+    local whatinitializers=whatfeatures.initializers
     local whatmodechecker=whatfeatures.modechecker
-    local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
+    local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
     properties.mode=mode 
     features.mode=mode
-    local done={}
-    while true do
-      local redo=false
-      local initializers=whatfeatures.initializers[mode]
-      if initializers then
-        for i=1,#initializers do
-          local step=initializers[i]
+    local done={}
+    while true do
+      local redo=false
+      local initializers=whatfeatures.initializers[mode]
+      if initializers then
+        for i=1,#initializers do
+          local step=initializers[i]
           local feature=step.name
-          local value=features[feature]
+          local value=features[feature]
           if not value then
           elseif done[feature] then
-          else
-            local action=step.action
-            if trace then
-              report("initializing feature %a to %a for mode %a for font %a",feature,
-                value,mode,tfmdata.properties.fullname)
-            end
+          else
+            local action=step.action
+            if trace then
+              report("initializing feature %a to %a for mode %a for font %a",feature,
+                value,mode,tfmdata.properties.fullname)
+            end
             action(tfmdata,value,features) 
-            if mode~=properties.mode or mode~=features.mode then
-              if whatmodechecker then
+            if mode~=properties.mode or mode~=features.mode then
+              if whatmodechecker then
                 properties.mode=whatmodechecker(tfmdata,features,properties.mode) 
-                features.mode=properties.mode
-              end
-              if mode~=properties.mode then
-                mode=properties.mode
-                redo=true
-              end
-            end
-            done[feature]=true
-          end
-          if redo then
-            break
-          end
-        end
-        if not redo then
-          break
-        end
-      else
-        break
-      end
-    end
+                features.mode=properties.mode
+              end
+              if mode~=properties.mode then
+                mode=properties.mode
+                redo=true
+              end
+            end
+            done[feature]=true
+          end
+          if redo then
+            break
+          end
+        end
+        if not redo then
+          break
+        end
+      else
+        break
+      end
+    end
     properties.mode=mode 
-    return true
-  else
-    return false
-  end
-end
-function constructors.collectprocessors(what,tfmdata,features,trace,report)
-  local processes,nofprocesses={},0
-  if features and next(features) then
-    local properties=tfmdata.properties
-    local whathandler=handlers[what]
-    local whatfeatures=whathandler.features
-    local whatprocessors=whatfeatures.processors
-    local processors=whatprocessors[properties.mode]
-    if processors then
-      for i=1,#processors do
-        local step=processors[i]
-        local feature=step.name
-        if features[feature] then
-          local action=step.action
-          if trace then
-            report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
-          end
-          if action then
-            nofprocesses=nofprocesses+1
-            processes[nofprocesses]=action
-          end
-        end
-      end
-    elseif trace then
-      report("no feature processors for mode %a for font %a",mode,tfmdata.properties.fullname)
-    end
-  end
-  return processes
-end
-function constructors.applymanipulators(what,tfmdata,features,trace,report)
-  if features and next(features) then
-    local properties=tfmdata.properties
-    local whathandler=handlers[what]
-    local whatfeatures=whathandler.features
-    local whatmanipulators=whatfeatures.manipulators
-    local manipulators=whatmanipulators[properties.mode]
-    if manipulators then
-      for i=1,#manipulators do
-        local step=manipulators[i]
-        local feature=step.name
-        local value=features[feature]
-        if value then
-          local action=step.action
-          if trace then
-            report("applying feature manipulator %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
-          end
-          if action then
-            action(tfmdata,feature,value)
-          end
-        end
-      end
-    end
-  end
-end
+    return true
+  else
+    return false
+  end
+end
+function constructors.collectprocessors(what,tfmdata,features,trace,report)
+  local processes,nofprocesses={},0
+  if features and next(features) then
+    local properties=tfmdata.properties
+    local whathandler=handlers[what]
+    local whatfeatures=whathandler.features
+    local whatprocessors=whatfeatures.processors
+    local processors=whatprocessors[properties.mode]
+    if processors then
+      for i=1,#processors do
+        local step=processors[i]
+        local feature=step.name
+        if features[feature] then
+          local action=step.action
+          if trace then
+            report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+          end
+          if action then
+            nofprocesses=nofprocesses+1
+            processes[nofprocesses]=action
+          end
+        end
+      end
+    elseif trace then
+      report("no feature processors for mode %a for font %a",mode,tfmdata.properties.fullname)
+    end
+  end
+  return processes
+end
+function constructors.applymanipulators(what,tfmdata,features,trace,report)
+  if features and next(features) then
+    local properties=tfmdata.properties
+    local whathandler=handlers[what]
+    local whatfeatures=whathandler.features
+    local whatmanipulators=whatfeatures.manipulators
+    local manipulators=whatmanipulators[properties.mode]
+    if manipulators then
+      for i=1,#manipulators do
+        local step=manipulators[i]
+        local feature=step.name
+        local value=features[feature]
+        if value then
+          local action=step.action
+          if trace then
+            report("applying feature manipulator %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+          end
+          if action then
+            action(tfmdata,feature,value)
+          end
+        end
+      end
+    end
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-font-enc']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-font-enc']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
-local fonts=fonts
-fonts.encodings={}
+local fonts=fonts
+fonts.encodings={}
 fonts.encodings.agl={}
-setmetatable(fonts.encodings.agl,{ __index=function(t,k)
-  if k=="unicodes" then
-    texio.write(" <loading (extended) adobe glyph list>")
-    local unicodes=dofile(resolvers.findfile("font-age.lua"))
-    fonts.encodings.agl={ unicodes=unicodes }
-    return unicodes
-  else
-    return nil
-  end
+setmetatable(fonts.encodings.agl,{ __index=function(t,k)
+  if k=="unicodes" then
+    texio.write(" <loading (extended) adobe glyph list>")
+    local unicodes=dofile(resolvers.findfile("font-age.lua"))
+    fonts.encodings.agl={ unicodes=unicodes }
+    return unicodes
+  else
+    return nil
+  end
 end })
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-cid']={
-  version=1.001,
-  comment="companion to font-otf.lua (cidmaps)",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-cid']={
+  version=1.001,
+  comment="companion to font-otf.lua (cidmaps)",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-local format,match,lower=string.format,string.match,string.lower
-local tonumber=tonumber
+local format,match,lower=string.format,string.match,string.lower
+local tonumber=tonumber
 local P,S,R,C,V,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.match
 local fonts,logs,trackers=fonts,logs,trackers
 local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
 local report_otf=logs.reporter("fonts","otf loading")
-local cid={}
+local cid={}
 fonts.cid=cid
-local cidmap={}
+local cidmap={}
 local cidmax=10
-local number=C(R("09","af","AF")^1)
-local space=S(" \n\r\t")
-local spaces=space^0
-local period=P(".")
-local periods=period*period
+local number=C(R("09","af","AF")^1)
+local space=S(" \n\r\t")
+local spaces=space^0
+local period=P(".")
+local periods=period*period
 local name=P("/")*C((1-space)^1)
 local unicodes,names={},{} 
-local function do_one(a,b)
-  unicodes[tonumber(a)]=tonumber(b,16)
-end
-local function do_range(a,b,c)
-  c=tonumber(c,16)
-  for i=tonumber(a),tonumber(b) do
-    unicodes[i]=c
-    c=c+1
-  end
-end
-local function do_name(a,b)
-  names[tonumber(a)]=b
-end
-local grammar=P { "start",
-  start=number*spaces*number*V("series"),
-  series=(spaces*(V("one")+V("range")+V("named")))^1,
-  one=(number*spaces*number)/do_one,
-  range=(number*periods*number*spaces*number)/do_range,
-  named=(number*spaces*name)/do_name
+local function do_one(a,b)
+  unicodes[tonumber(a)]=tonumber(b,16)
+end
+local function do_range(a,b,c)
+  c=tonumber(c,16)
+  for i=tonumber(a),tonumber(b) do
+    unicodes[i]=c
+    c=c+1
+  end
+end
+local function do_name(a,b)
+  names[tonumber(a)]=b
+end
+local grammar=P { "start",
+  start=number*spaces*number*V("series"),
+  series=(spaces*(V("one")+V("range")+V("named")))^1,
+  one=(number*spaces*number)/do_one,
+  range=(number*periods*number*spaces*number)/do_range,
+  named=(number*spaces*name)/do_name
 }
-local function loadcidfile(filename)
-  local data=io.loaddata(filename)
-  if data then
-    unicodes,names={},{}
-    lpegmatch(grammar,data)
-    local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$")
-    return {
-      supplement=supplement,
-      registry=registry,
-      ordering=ordering,
-      filename=filename,
-      unicodes=unicodes,
-      names=names
-    }
-  end
+local function loadcidfile(filename)
+  local data=io.loaddata(filename)
+  if data then
+    unicodes,names={},{}
+    lpegmatch(grammar,data)
+    local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$")
+    return {
+      supplement=supplement,
+      registry=registry,
+      ordering=ordering,
+      filename=filename,
+      unicodes=unicodes,
+      names=names
+    }
+  end
 end
 cid.loadfile=loadcidfile 
 local template="%s-%s-%s.cidmap"
-local function locate(registry,ordering,supplement)
-  local filename=format(template,registry,ordering,supplement)
-  local hashname=lower(filename)
-  local found=cidmap[hashname]
-  if not found then
-    if trace_loading then
-      report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
-    end
-    local fullname=resolvers.findfile(filename,'cid') or ""
-    if fullname~="" then
-      found=loadcidfile(fullname)
-      if found then
-        if trace_loading then
-          report_otf("using cidmap file %a",filename)
-        end
-        cidmap[hashname]=found
-        found.usedname=file.basename(filename)
-      end
-    end
-  end
-  return found
-end
-function cid.getmap(specification)
-  if not specification then
-    report_otf("invalid cidinfo specification, table expected")
-    return
-  end
-  local registry=specification.registry
-  local ordering=specification.ordering
+local function locate(registry,ordering,supplement)
+  local filename=format(template,registry,ordering,supplement)
+  local hashname=lower(filename)
+  local found=cidmap[hashname]
+  if not found then
+    if trace_loading then
+      report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
+    end
+    local fullname=resolvers.findfile(filename,'cid') or ""
+    if fullname~="" then
+      found=loadcidfile(fullname)
+      if found then
+        if trace_loading then
+          report_otf("using cidmap file %a",filename)
+        end
+        cidmap[hashname]=found
+        found.usedname=file.basename(filename)
+      end
+    end
+  end
+  return found
+end
+function cid.getmap(specification)
+  if not specification then
+    report_otf("invalid cidinfo specification, table expected")
+    return
+  end
+  local registry=specification.registry
+  local ordering=specification.ordering
   local supplement=specification.supplement
-  local filename=format(registry,ordering,supplement)
-  local found=cidmap[lower(filename)]
-  if found then
-    return found
-  end
-  if trace_loading then
-    report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
-  end
-  found=locate(registry,ordering,supplement)
-  if not found then
-    local supnum=tonumber(supplement)
+  local filename=format(registry,ordering,supplement)
+  local found=cidmap[lower(filename)]
+  if found then
+    return found
+  end
+  if trace_loading then
+    report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
+  end
+  found=locate(registry,ordering,supplement)
+  if not found then
+    local supnum=tonumber(supplement)
     local cidnum=nil
-    if supnum<cidmax then
-      for s=supnum+1,cidmax do
-        local c=locate(registry,ordering,s)
-        if c then
-          found,cidnum=c,s
-          break
-        end
-      end
-    end
-    if not found and supnum>0 then
-      for s=supnum-1,0,-1 do
-        local c=locate(registry,ordering,s)
-        if c then
-          found,cidnum=c,s
-          break
-        end
-      end
-    end
-    registry=lower(registry)
-    ordering=lower(ordering)
-    if found and cidnum>0 then
-      for s=0,cidnum-1 do
-        local filename=format(template,registry,ordering,s)
-        if not cidmap[filename] then
-          cidmap[filename]=found
-        end
-      end
-    end
-  end
-  return found
-end
+    if supnum<cidmax then
+      for s=supnum+1,cidmax do
+        local c=locate(registry,ordering,s)
+        if c then
+          found,cidnum=c,s
+          break
+        end
+      end
+    end
+    if not found and supnum>0 then
+      for s=supnum-1,0,-1 do
+        local c=locate(registry,ordering,s)
+        if c then
+          found,cidnum=c,s
+          break
+        end
+      end
+    end
+    registry=lower(registry)
+    ordering=lower(ordering)
+    if found and cidnum>0 then
+      for s=0,cidnum-1 do
+        local filename=format(template,registry,ordering,s)
+        if not cidmap[filename] then
+          cidmap[filename]=found
+        end
+      end
+    end
+  end
+  return found
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-map']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-map']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
 local tonumber=tonumber
-local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
-local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
-local utfbyte=utf.byte
+local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
+local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
+local utfbyte=utf.byte
 local floor=math.floor
-local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
+local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
 local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
 local report_fonts=logs.reporter("fonts","loading") 
-local fonts=fonts or {}
-local mappings=fonts.mappings or {}
+local fonts=fonts or {}
+local mappings=fonts.mappings or {}
 fonts.mappings=mappings
 local function loadlumtable(filename) 
-  local lumname=file.replacesuffix(file.basename(filename),"lum")
-  local lumfile=resolvers.findfile(lumname,"map") or ""
-  if lumfile~="" and lfs.isfile(lumfile) then
-    if trace_loading or trace_mapping then
-      report_fonts("loading map table %a",lumfile)
-    end
-    lumunic=dofile(lumfile)
-    return lumunic,lumfile
-  end
-end
-local hex=R("AF","09")
-local hexfour=(hex*hex*hex*hex)/function(s) return tonumber(s,16) end
-local hexsix=(hex*hex*hex*hex*hex*hex)/function(s) return tonumber(s,16) end
-local dec=(R("09")^1)/tonumber
-local period=P(".")
-local unicode=P("uni")*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
-local ucode=P("u")*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
+  local lumname=file.replacesuffix(file.basename(filename),"lum")
+  local lumfile=resolvers.findfile(lumname,"map") or ""
+  if lumfile~="" and lfs.isfile(lumfile) then
+    if trace_loading or trace_mapping then
+      report_fonts("loading map table %a",lumfile)
+    end
+    lumunic=dofile(lumfile)
+    return lumunic,lumfile
+  end
+end
+local hex=R("AF","09")
+local hexfour=(hex*hex*hex*hex)/function(s) return tonumber(s,16) end
+local hexsix=(hex*hex*hex*hex*hex*hex)/function(s) return tonumber(s,16) end
+local dec=(R("09")^1)/tonumber
+local period=P(".")
+local unicode=P("uni")*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
+local ucode=P("u")*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
 local index=P("index")*dec*Cc(false)
 local parser=unicode+ucode+index
 local parsers={}
-local function makenameparser(str)
-  if not str or str=="" then
-    return parser
-  else
-    local p=parsers[str]
-    if not p then
-      p=P(str)*period*dec*Cc(false)
-      parsers[str]=p
-    end
-    return p
-  end
-end
-local function tounicode16(unicode,name)
-  if unicode<0x10000 then
-    return format("%04X",unicode)
-  elseif unicode<0x1FFFFFFFFF then
-    return format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
-  else
-    report_fonts("can't convert %a in %a into tounicode",unicode,name)
-  end
-end
-local function tounicode16sequence(unicodes,name)
-  local t={}
-  for l=1,#unicodes do
-    local unicode=unicodes[l]
-    if unicode<0x10000 then
-      t[l]=format("%04X",unicode)
-    elseif unicode<0x1FFFFFFFFF then
-      t[l]=format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
-    else
-      report_fonts ("can't convert %a in %a into tounicode",unicode,name)
-    end
-  end
-  return concat(t)
-end
-local function fromunicode16(str)
-  if #str==4 then
-    return tonumber(str,16)
-  else
-    local l,r=match(str,"(....)(....)")
-    return (tonumber(l,16))*0x400+tonumber(r,16)-0xDC00
-  end
-end
-mappings.loadlumtable=loadlumtable
-mappings.makenameparser=makenameparser
-mappings.tounicode16=tounicode16
-mappings.tounicode16sequence=tounicode16sequence
+local function makenameparser(str)
+  if not str or str=="" then
+    return parser
+  else
+    local p=parsers[str]
+    if not p then
+      p=P(str)*period*dec*Cc(false)
+      parsers[str]=p
+    end
+    return p
+  end
+end
+local function tounicode16(unicode,name)
+  if unicode<0x10000 then
+    return format("%04X",unicode)
+  elseif unicode<0x1FFFFFFFFF then
+    return format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
+  else
+    report_fonts("can't convert %a in %a into tounicode",unicode,name)
+  end
+end
+local function tounicode16sequence(unicodes,name)
+  local t={}
+  for l=1,#unicodes do
+    local unicode=unicodes[l]
+    if unicode<0x10000 then
+      t[l]=format("%04X",unicode)
+    elseif unicode<0x1FFFFFFFFF then
+      t[l]=format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
+    else
+      report_fonts ("can't convert %a in %a into tounicode",unicode,name)
+    end
+  end
+  return concat(t)
+end
+local function fromunicode16(str)
+  if #str==4 then
+    return tonumber(str,16)
+  else
+    local l,r=match(str,"(....)(....)")
+    return (tonumber(l,16))*0x400+tonumber(r,16)-0xDC00
+  end
+end
+mappings.loadlumtable=loadlumtable
+mappings.makenameparser=makenameparser
+mappings.tounicode16=tounicode16
+mappings.tounicode16sequence=tounicode16sequence
 mappings.fromunicode16=fromunicode16
-local separator=S("_.")
-local other=C((1-separator)^1)
+local separator=S("_.")
+local other=C((1-separator)^1)
 local ligsplitter=Ct(other*(separator*other)^0)
-function mappings.addtounicode(data,filename)
-  local resources=data.resources
-  local properties=data.properties
-  local descriptions=data.descriptions
-  local unicodes=resources.unicodes
-  if not unicodes then
-    return
-  end
-  unicodes['space']=unicodes['space'] or 32
-  unicodes['hyphen']=unicodes['hyphen'] or 45
-  unicodes['zwj']=unicodes['zwj']  or 0x200D
+function mappings.addtounicode(data,filename)
+  local resources=data.resources
+  local properties=data.properties
+  local descriptions=data.descriptions
+  local unicodes=resources.unicodes
+  if not unicodes then
+    return
+  end
+  unicodes['space']=unicodes['space'] or 32
+  unicodes['hyphen']=unicodes['hyphen'] or 45
+  unicodes['zwj']=unicodes['zwj']  or 0x200D
   unicodes['zwnj']=unicodes['zwnj']  or 0x200C
-  local private=fonts.constructors.privateoffset
-  local unknown=format("%04X",utfbyte("?"))
+  local private=fonts.constructors.privateoffset
+  local unknown=format("%04X",utfbyte("?"))
   local unicodevector=fonts.encodings.agl.unicodes 
-  local tounicode={}
-  local originals={}
-  resources.tounicode=tounicode
-  resources.originals=originals
-  local lumunic,uparser,oparser
-  local cidinfo,cidnames,cidcodes,usedmap
+  local tounicode={}
+  local originals={}
+  resources.tounicode=tounicode
+  resources.originals=originals
+  local lumunic,uparser,oparser
+  local cidinfo,cidnames,cidcodes,usedmap
   if false then 
-    lumunic=loadlumtable(filename)
-    lumunic=lumunic and lumunic.tounicode
+    lumunic=loadlumtable(filename)
+    lumunic=lumunic and lumunic.tounicode
   end
-  cidinfo=properties.cidinfo
+  cidinfo=properties.cidinfo
   usedmap=cidinfo and fonts.cid.getmap(cidinfo)
-  if usedmap then
-    oparser=usedmap and makenameparser(cidinfo.ordering)
-    cidnames=usedmap.names
-    cidcodes=usedmap.unicodes
-  end
-  uparser=makenameparser()
-  local ns,nl=0,0
-  for unic,glyph in next,descriptions do
-    local index=glyph.index
-    local name=glyph.name
-    if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
-      local unicode=lumunic and lumunic[name] or unicodevector[name]
-      if unicode then
-        originals[index]=unicode
-        tounicode[index]=tounicode16(unicode,name)
-        ns=ns+1
-      end
-      if (not unicode) and usedmap then
-        local foundindex=lpegmatch(oparser,name)
-        if foundindex then
+  if usedmap then
+    oparser=usedmap and makenameparser(cidinfo.ordering)
+    cidnames=usedmap.names
+    cidcodes=usedmap.unicodes
+  end
+  uparser=makenameparser()
+  local ns,nl=0,0
+  for unic,glyph in next,descriptions do
+    local index=glyph.index
+    local name=glyph.name
+    if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
+      local unicode=lumunic and lumunic[name] or unicodevector[name]
+      if unicode then
+        originals[index]=unicode
+        tounicode[index]=tounicode16(unicode,name)
+        ns=ns+1
+      end
+      if (not unicode) and usedmap then
+        local foundindex=lpegmatch(oparser,name)
+        if foundindex then
           unicode=cidcodes[foundindex] 
-          if unicode then
-            originals[index]=unicode
-            tounicode[index]=tounicode16(unicode,name)
-            ns=ns+1
-          else
+          if unicode then
+            originals[index]=unicode
+            tounicode[index]=tounicode16(unicode,name)
+            ns=ns+1
+          else
             local reference=cidnames[foundindex] 
-            if reference then
-              local foundindex=lpegmatch(oparser,reference)
-              if foundindex then
-                unicode=cidcodes[foundindex]
-                if unicode then
-                  originals[index]=unicode
-                  tounicode[index]=tounicode16(unicode,name)
-                  ns=ns+1
-                end
-              end
-              if not unicode or unicode=="" then
-                local foundcodes,multiple=lpegmatch(uparser,reference)
-                if foundcodes then
-                  originals[index]=foundcodes
-                  if multiple then
-                    tounicode[index]=tounicode16sequence(foundcodes)
-                    nl=nl+1
-                    unicode=true
-                  else
-                    tounicode[index]=tounicode16(foundcodes,name)
-                    ns=ns+1
-                    unicode=foundcodes
-                  end
-                end
-              end
-            end
-          end
-        end
-      end
-      if not unicode or unicode=="" then
-        local split=lpegmatch(ligsplitter,name)
-        local nplit=split and #split or 0
-        if nplit>=2 then
-          local t,n={},0
-          for l=1,nplit do
-            local base=split[l]
-            local u=unicodes[base] or unicodevector[base]
-            if not u then
-              break
-            elseif type(u)=="table" then
-              n=n+1
-              t[n]=u[1]
-            else
-              n=n+1
-              t[n]=u
-            end
-          end
+            if reference then
+              local foundindex=lpegmatch(oparser,reference)
+              if foundindex then
+                unicode=cidcodes[foundindex]
+                if unicode then
+                  originals[index]=unicode
+                  tounicode[index]=tounicode16(unicode,name)
+                  ns=ns+1
+                end
+              end
+              if not unicode or unicode=="" then
+                local foundcodes,multiple=lpegmatch(uparser,reference)
+                if foundcodes then
+                  originals[index]=foundcodes
+                  if multiple then
+                    tounicode[index]=tounicode16sequence(foundcodes)
+                    nl=nl+1
+                    unicode=true
+                  else
+                    tounicode[index]=tounicode16(foundcodes,name)
+                    ns=ns+1
+                    unicode=foundcodes
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+      if not unicode or unicode=="" then
+        local split=lpegmatch(ligsplitter,name)
+        local nplit=split and #split or 0
+        if nplit>=2 then
+          local t,n={},0
+          for l=1,nplit do
+            local base=split[l]
+            local u=unicodes[base] or unicodevector[base]
+            if not u then
+              break
+            elseif type(u)=="table" then
+              n=n+1
+              t[n]=u[1]
+            else
+              n=n+1
+              t[n]=u
+            end
+          end
           if n==0 then
-          elseif n==1 then
-            originals[index]=t[1]
-            tounicode[index]=tounicode16(t[1],name)
-          else
-            originals[index]=t
-            tounicode[index]=tounicode16sequence(t)
-          end
-          nl=nl+1
-          unicode=true
+          elseif n==1 then
+            originals[index]=t[1]
+            tounicode[index]=tounicode16(t[1],name)
+          else
+            originals[index]=t
+            tounicode[index]=tounicode16sequence(t)
+          end
+          nl=nl+1
+          unicode=true
         else
-        end
-      end
-      if not unicode or unicode=="" then
-        local foundcodes,multiple=lpegmatch(uparser,name)
-        if foundcodes then
-          if multiple then
-            originals[index]=foundcodes
-            tounicode[index]=tounicode16sequence(foundcodes,name)
-            nl=nl+1
-            unicode=true
-          else
-            originals[index]=foundcodes
-            tounicode[index]=tounicode16(foundcodes,name)
-            ns=ns+1
-            unicode=foundcodes
-          end
-        end
-      end
-    end
-  end
-  if trace_mapping then
-    for unic,glyph in table.sortedhash(descriptions) do
-      local name=glyph.name
-      local index=glyph.index
-      local toun=tounicode[index]
-      if toun then
-        report_fonts("internal slot %U, name %a, unicode %U, tounicode %a",index,name,unic,toun)
-      else
-        report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
-      end
-    end
-  end
-  if trace_loading and (ns>0 or nl>0) then
-    report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns)
-  end
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['luatex-fonts-syn']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
-}
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
-end
-local fonts=fonts
-fonts.names=fonts.names or {}
-fonts.names.version=1.001 
-fonts.names.basename="luatex-fonts-names"
-fonts.names.new_to_old={}
-fonts.names.old_to_new={}
+        end
+      end
+      if not unicode or unicode=="" then
+        local foundcodes,multiple=lpegmatch(uparser,name)
+        if foundcodes then
+          if multiple then
+            originals[index]=foundcodes
+            tounicode[index]=tounicode16sequence(foundcodes,name)
+            nl=nl+1
+            unicode=true
+          else
+            originals[index]=foundcodes
+            tounicode[index]=tounicode16(foundcodes,name)
+            ns=ns+1
+            unicode=foundcodes
+          end
+        end
+      end
+    end
+  end
+  if trace_mapping then
+    for unic,glyph in table.sortedhash(descriptions) do
+      local name=glyph.name
+      local index=glyph.index
+      local toun=tounicode[index]
+      if toun then
+        report_fonts("internal slot %U, name %a, unicode %U, tounicode %a",index,name,unic,toun)
+      else
+        report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
+      end
+    end
+  end
+  if trace_loading and (ns>0 or nl>0) then
+    report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns)
+  end
+end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['luatex-fonts-syn']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
+}
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
+end
+local fonts=fonts
+fonts.names=fonts.names or {}
+fonts.names.version=1.001 
+fonts.names.basename="luatex-fonts-names"
+fonts.names.new_to_old={}
+fonts.names.old_to_new={}
 fonts.names.cache=containers.define("fonts","data",fonts.names.version,true)
 local data,loaded=nil,false
 local fileformats={ "lua","tex","other text files" }
-function fonts.names.reportmissingbase()
-  texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>")
-  fonts.names.reportmissingbase=nil
-end
-function fonts.names.reportmissingname()
-  texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>")
-  fonts.names.reportmissingname=nil
-end
-function fonts.names.resolve(name,sub)
-  if not loaded then
-    local basename=fonts.names.basename
-    if basename and basename~="" then
-      data=containers.read(fonts.names.cache,basename)
-      if not data then
-        basename=file.addsuffix(basename,"lua")
-        for i=1,#fileformats do
-          local format=fileformats[i]
-          local foundname=resolvers.findfile(basename,format) or ""
-          if foundname~="" then
-            data=dofile(foundname)
-            texio.write("<font database loaded: ",foundname,">")
-            break
-          end
-        end
-      end
-    end
-    loaded=true
-  end
-  if type(data)=="table" and data.version==fonts.names.version then
-    local condensed=string.gsub(string.lower(name),"[^%a%d]","")
-    local found=data.mappings and data.mappings[condensed]
-    if found then
-      local fontname,filename,subfont=found[1],found[2],found[3]
-      if subfont then
-        return filename,fontname
-      else
-        return filename,false
-      end
-    elseif fonts.names.reportmissingname then
-      fonts.names.reportmissingname()
+function fonts.names.reportmissingbase()
+  texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>")
+  fonts.names.reportmissingbase=nil
+end
+function fonts.names.reportmissingname()
+  texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>")
+  fonts.names.reportmissingname=nil
+end
+function fonts.names.resolve(name,sub)
+  if not loaded then
+    local basename=fonts.names.basename
+    if basename and basename~="" then
+      data=containers.read(fonts.names.cache,basename)
+      if not data then
+        basename=file.addsuffix(basename,"lua")
+        for i=1,#fileformats do
+          local format=fileformats[i]
+          local foundname=resolvers.findfile(basename,format) or ""
+          if foundname~="" then
+            data=dofile(foundname)
+            texio.write("<font database loaded: ",foundname,">")
+            break
+          end
+        end
+      end
+    end
+    loaded=true
+  end
+  if type(data)=="table" and data.version==fonts.names.version then
+    local condensed=string.gsub(string.lower(name),"[^%a%d]","")
+    local found=data.mappings and data.mappings[condensed]
+    if found then
+      local fontname,filename,subfont=found[1],found[2],found[3]
+      if subfont then
+        return filename,fontname
+      else
+        return filename,false
+      end
+    elseif fonts.names.reportmissingname then
+      fonts.names.reportmissingname()
       return name,false 
-    end
-  elseif fonts.names.reportmissingbase then
-    fonts.names.reportmissingbase()
-  end
+    end
+  elseif fonts.names.reportmissingbase then
+    fonts.names.reportmissingbase()
+  end
 end
 fonts.names.resolvespec=fonts.names.resolve 
 function fonts.names.getfilename(askedname,suffix) 
-  return ""
-end
+  return ""
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-fonts-tfm']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-fonts-tfm']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
-local fonts=fonts
-local tfm={}
-fonts.handlers.tfm=tfm
+local fonts=fonts
+local tfm={}
+fonts.handlers.tfm=tfm
 fonts.formats.tfm="type1" 
-function fonts.readers.tfm(specification)
-  local fullname=specification.filename or ""
-  if fullname=="" then
-    local forced=specification.forced or ""
-    if forced~="" then
-      fullname=specification.name.."."..forced
-    else
-      fullname=specification.name
-    end
-  end
-  local foundname=resolvers.findbinfile(fullname,'tfm') or ""
-  if foundname=="" then
-    foundname=resolvers.findbinfile(fullname,'ofm') or ""
-  end
-  if foundname~="" then
-    specification.filename=foundname
-    specification.format="ofm"
-    return font.read_tfm(specification.filename,specification.size)
-  end
-end
+function fonts.readers.tfm(specification)
+  local fullname=specification.filename or ""
+  if fullname=="" then
+    local forced=specification.forced or ""
+    if forced~="" then
+      fullname=specification.name.."."..forced
+    else
+      fullname=specification.name
+    end
+  end
+  local foundname=resolvers.findbinfile(fullname,'tfm') or ""
+  if foundname=="" then
+    foundname=resolvers.findbinfile(fullname,'ofm') or ""
+  end
+  if foundname~="" then
+    specification.filename=foundname
+    specification.format="ofm"
+    return font.read_tfm(specification.filename,specification.size)
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-oti']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-oti']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
 local lower=string.lower
-local fonts=fonts
+local fonts=fonts
 local constructors=fonts.constructors
-local otf=constructors.newhandler("otf")
-local otffeatures=constructors.newfeatures("otf")
-local otftables=otf.tables
+local otf=constructors.newhandler("otf")
+local otffeatures=constructors.newfeatures("otf")
+local otftables=otf.tables
 local registerotffeature=otffeatures.register
 local allocate=utilities.storage.allocate
-registerotffeature {
-  name="features",
-  description="initialization of feature handler",
-  default=true,
+registerotffeature {
+  name="features",
+  description="initialization of feature handler",
+  default=true,
 }
-local function setmode(tfmdata,value)
-  if value then
-    tfmdata.properties.mode=lower(value)
-  end
-end
-local function setlanguage(tfmdata,value)
-  if value then
-    local cleanvalue=lower(value)
-    local languages=otftables and otftables.languages
-    local properties=tfmdata.properties
-    if not languages then
-      properties.language=cleanvalue
-    elseif languages[value] then
-      properties.language=cleanvalue
-    else
-      properties.language="dflt"
-    end
-  end
-end
-local function setscript(tfmdata,value)
-  if value then
-    local cleanvalue=lower(value)
-    local scripts=otftables and otftables.scripts
-    local properties=tfmdata.properties
-    if not scripts then
-      properties.script=cleanvalue
-    elseif scripts[value] then
-      properties.script=cleanvalue
-    else
-      properties.script="dflt"
-    end
-  end
-end
-registerotffeature {
-  name="mode",
-  description="mode",
-  initializers={
-    base=setmode,
-    node=setmode,
-  }
+local function setmode(tfmdata,value)
+  if value then
+    tfmdata.properties.mode=lower(value)
+  end
+end
+local function setlanguage(tfmdata,value)
+  if value then
+    local cleanvalue=lower(value)
+    local languages=otftables and otftables.languages
+    local properties=tfmdata.properties
+    if not languages then
+      properties.language=cleanvalue
+    elseif languages[value] then
+      properties.language=cleanvalue
+    else
+      properties.language="dflt"
+    end
+  end
+end
+local function setscript(tfmdata,value)
+  if value then
+    local cleanvalue=lower(value)
+    local scripts=otftables and otftables.scripts
+    local properties=tfmdata.properties
+    if not scripts then
+      properties.script=cleanvalue
+    elseif scripts[value] then
+      properties.script=cleanvalue
+    else
+      properties.script="dflt"
+    end
+  end
+end
+registerotffeature {
+  name="mode",
+  description="mode",
+  initializers={
+    base=setmode,
+    node=setmode,
+  }
 }
-registerotffeature {
-  name="language",
-  description="language",
-  initializers={
-    base=setlanguage,
-    node=setlanguage,
-  }
+registerotffeature {
+  name="language",
+  description="language",
+  initializers={
+    base=setlanguage,
+    node=setlanguage,
+  }
 }
-registerotffeature {
-  name="script",
-  description="script",
-  initializers={
-    base=setscript,
-    node=setscript,
-  }
+registerotffeature {
+  name="script",
+  description="script",
+  initializers={
+    base=setscript,
+    node=setscript,
+  }
 }
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-otf']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-otf']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-local utfbyte=utf.byte
-local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring=type,next,tonumber,tostring
-local abs=math.abs
-local getn=table.getn
-local lpegmatch=lpeg.match
-local reversed,concat,remove=table.reversed,table.concat,table.remove
-local ioflush=io.flush
-local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive
+local utfbyte=utf.byte
+local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
+local type,next,tonumber,tostring=type,next,tonumber,tostring
+local abs=math.abs
+local getn=table.getn
+local lpegmatch=lpeg.match
+local reversed,concat,remove=table.reversed,table.concat,table.remove
+local ioflush=io.flush
+local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive
 local formatters=string.formatters
-local allocate=utilities.storage.allocate
-local registertracker=trackers.register
-local registerdirective=directives.register
-local starttiming=statistics.starttiming
-local stoptiming=statistics.stoptiming
-local elapsedtime=statistics.elapsedtime
+local allocate=utilities.storage.allocate
+local registertracker=trackers.register
+local registerdirective=directives.register
+local starttiming=statistics.starttiming
+local stoptiming=statistics.stoptiming
+local elapsedtime=statistics.elapsedtime
 local findbinfile=resolvers.findbinfile
-local trace_private=false registertracker("otf.private",function(v) trace_private=v end)
-local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
-local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
-local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dynamics=v end)
-local trace_sequences=false registertracker("otf.sequences",function(v) trace_sequences=v end)
-local trace_markwidth=false registertracker("otf.markwidth",function(v) trace_markwidth=v end)
+local trace_private=false registertracker("otf.private",function(v) trace_private=v end)
+local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
+local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
+local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dynamics=v end)
+local trace_sequences=false registertracker("otf.sequences",function(v) trace_sequences=v end)
+local trace_markwidth=false registertracker("otf.markwidth",function(v) trace_markwidth=v end)
 local trace_defining=false registertracker("fonts.defining",function(v) trace_defining=v end)
 local report_otf=logs.reporter("fonts","otf loading")
-local fonts=fonts
+local fonts=fonts
 local otf=fonts.handlers.otf
 otf.glists={ "gsub","gpos" }
 otf.version=2.743 
 otf.cache=containers.define("fonts","otf",otf.version,true)
-local fontdata=fonts.hashes.identifiers
+local fontdata=fonts.hashes.identifiers
 local chardata=characters and characters.data 
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.newfeatures("otf")
 local registerotffeature=otffeatures.register
-local enhancers=allocate()
-otf.enhancers=enhancers
-local patches={}
+local enhancers=allocate()
+otf.enhancers=enhancers
+local patches={}
 enhancers.patches=patches
-local definers=fonts.definers
-local readers=fonts.readers
+local definers=fonts.definers
+local readers=fonts.readers
 local constructors=fonts.constructors
-local forceload=false
+local forceload=false
 local cleanup=0   
 local usemetatables=false 
-local packdata=true
-local syncspace=true
-local forcenotdef=false
+local packdata=true
+local syncspace=true
+local forcenotdef=false
 local includesubfonts=false
-local wildcard="*"
+local wildcard="*"
 local default="dflt"
-local fontloaderfields=fontloader.fields
-local mainfields=nil
+local fontloaderfields=fontloader.fields
+local mainfields=nil
 local glyphfields=nil 
-registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end)
-registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
-registerdirective("fonts.otf.loader.usemetatables",function(v) usemetatables=v end)
-registerdirective("fonts.otf.loader.pack",function(v) packdata=v end)
-registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
+registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end)
+registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
+registerdirective("fonts.otf.loader.usemetatables",function(v) usemetatables=v end)
+registerdirective("fonts.otf.loader.pack",function(v) packdata=v end)
+registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
 registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end)
-local function load_featurefile(raw,featurefile)
-  if featurefile and featurefile~="" then
-    if trace_loading then
-      report_otf("using featurefile %a",featurefile)
-    end
-    fontloader.apply_featurefile(raw,featurefile)
-  end
-end
-local function showfeatureorder(rawdata,filename)
-  local sequences=rawdata.resources.sequences
-  if sequences and #sequences>0 then
-    if trace_loading then
-      report_otf("font %a has %s sequences",filename,#sequences)
-      report_otf(" ")
-    end
-    for nos=1,#sequences do
-      local sequence=sequences[nos]
-      local typ=sequence.type   or "no-type"
-      local name=sequence.name   or "no-name"
-      local subtables=sequence.subtables or { "no-subtables" }
-      local features=sequence.features
-      if trace_loading then
-        report_otf("%3i  %-15s  %-20s  [% t]",nos,name,typ,subtables)
-      end
-      if features then
-        for feature,scripts in next,features do
-          local tt={}
-          if type(scripts)=="table" then
-            for script,languages in next,scripts do
-              local ttt={}
-              for language,_ in next,languages do
-                ttt[#ttt+1]=language
-              end
-              tt[#tt+1]=formatters["[%s: % t]"](script,ttt)
-            end
-            if trace_loading then
-              report_otf("       %s: % t",feature,tt)
-            end
-          else
-            if trace_loading then
-              report_otf("       %s: %S",feature,scripts)
-            end
-          end
-        end
-      end
-    end
-    if trace_loading then
-      report_otf("\n")
-    end
-  elseif trace_loading then
-    report_otf("font %a has no sequences",filename)
-  end
+local function load_featurefile(raw,featurefile)
+  if featurefile and featurefile~="" then
+    if trace_loading then
+      report_otf("using featurefile %a",featurefile)
+    end
+    fontloader.apply_featurefile(raw,featurefile)
+  end
+end
+local function showfeatureorder(rawdata,filename)
+  local sequences=rawdata.resources.sequences
+  if sequences and #sequences>0 then
+    if trace_loading then
+      report_otf("font %a has %s sequences",filename,#sequences)
+      report_otf(" ")
+    end
+    for nos=1,#sequences do
+      local sequence=sequences[nos]
+      local typ=sequence.type   or "no-type"
+      local name=sequence.name   or "no-name"
+      local subtables=sequence.subtables or { "no-subtables" }
+      local features=sequence.features
+      if trace_loading then
+        report_otf("%3i  %-15s  %-20s  [% t]",nos,name,typ,subtables)
+      end
+      if features then
+        for feature,scripts in next,features do
+          local tt={}
+          if type(scripts)=="table" then
+            for script,languages in next,scripts do
+              local ttt={}
+              for language,_ in next,languages do
+                ttt[#ttt+1]=language
+              end
+              tt[#tt+1]=formatters["[%s: % t]"](script,ttt)
+            end
+            if trace_loading then
+              report_otf("       %s: % t",feature,tt)
+            end
+          else
+            if trace_loading then
+              report_otf("       %s: %S",feature,scripts)
+            end
+          end
+        end
+      end
+    end
+    if trace_loading then
+      report_otf("\n")
+    end
+  elseif trace_loading then
+    report_otf("font %a has no sequences",filename)
+  end
 end
 local valid_fields=table.tohash {
   "ascent",
-  "cidinfo",
+  "cidinfo",
   "copyright",
-  "descent",
-  "design_range_bottom",
-  "design_range_top",
-  "design_size",
-  "encodingchanged",
-  "extrema_bound",
-  "familyname",
-  "fontname",
-  "fontname",
-  "fontstyle_id",
-  "fontstyle_name",
+  "descent",
+  "design_range_bottom",
+  "design_range_top",
+  "design_size",
+  "encodingchanged",
+  "extrema_bound",
+  "familyname",
+  "fontname",
+  "fontname",
+  "fontstyle_id",
+  "fontstyle_name",
   "fullname",
   "hasvmetrics",
-  "horiz_base",
-  "issans",
-  "isserif",
+  "horiz_base",
+  "issans",
+  "isserif",
   "italicangle",
   "macstyle",
-  "onlybitmaps",
-  "origname",
-  "os2_version",
+  "onlybitmaps",
+  "origname",
+  "os2_version",
   "pfminfo",
-  "serifcheck",
+  "serifcheck",
   "sfd_version",
-  "strokedfont",
+  "strokedfont",
   "strokewidth",
   "table_version",
-  "ttf_tables",
-  "uni_interp",
-  "uniqueid",
-  "units_per_em",
-  "upos",
-  "use_typo_metrics",
+  "ttf_tables",
+  "uni_interp",
+  "uniqueid",
+  "units_per_em",
+  "upos",
+  "use_typo_metrics",
   "uwidth",
-  "version",
-  "vert_base",
-  "weight",
+  "version",
+  "vert_base",
+  "weight",
   "weight_width_slope_only",
 }
-local ordered_enhancers={
+local ordered_enhancers={
   "prepare tables",
-  "prepare glyphs",
+  "prepare glyphs",
   "prepare lookups",
-  "analyze glyphs",
+  "analyze glyphs",
   "analyze math",
   "prepare tounicode",
-  "reorganize lookups",
-  "reorganize mark classes",
+  "reorganize lookups",
+  "reorganize mark classes",
   "reorganize anchor classes",
-  "reorganize glyph kerns",
-  "reorganize glyph lookups",
+  "reorganize glyph kerns",
+  "reorganize glyph lookups",
   "reorganize glyph anchors",
   "merge kern classes",
-  "reorganize features",
+  "reorganize features",
   "reorganize subtables",
-  "check glyphs",
-  "check metadata",
+  "check glyphs",
+  "check metadata",
   "check extra features",
   "check encoding",
   "add duplicates",
-  "cleanup tables",
+  "cleanup tables",
 }
-local actions=allocate()
-local before=allocate()
+local actions=allocate()
+local before=allocate()
 local after=allocate()
-patches.before=before
+patches.before=before
 patches.after=after
-local function enhance(name,data,filename,raw)
-  local enhancer=actions[name]
-  if enhancer then
-    if trace_loading then
-      report_otf("apply enhancement %a to file %a",name,filename)
-      ioflush()
-    end
-    enhancer(data,filename,raw)
+local function enhance(name,data,filename,raw)
+  local enhancer=actions[name]
+  if enhancer then
+    if trace_loading then
+      report_otf("apply enhancement %a to file %a",name,filename)
+      ioflush()
+    end
+    enhancer(data,filename,raw)
   else
-  end
+  end
 end
-function enhancers.apply(data,filename,raw)
-  local basename=file.basename(lower(filename))
-  if trace_loading then
-    report_otf("%s enhancing file %a","start",filename)
-  end
+function enhancers.apply(data,filename,raw)
+  local basename=file.basename(lower(filename))
+  if trace_loading then
+    report_otf("%s enhancing file %a","start",filename)
+  end
   ioflush() 
-  for e=1,#ordered_enhancers do
-    local enhancer=ordered_enhancers[e]
-    local b=before[enhancer]
-    if b then
-      for pattern,action in next,b do
-        if find(basename,pattern) then
-          action(data,filename,raw)
-        end
-      end
-    end
-    enhance(enhancer,data,filename,raw)
-    local a=after[enhancer]
-    if a then
-      for pattern,action in next,a do
-        if find(basename,pattern) then
-          action(data,filename,raw)
-        end
-      end
-    end
+  for e=1,#ordered_enhancers do
+    local enhancer=ordered_enhancers[e]
+    local b=before[enhancer]
+    if b then
+      for pattern,action in next,b do
+        if find(basename,pattern) then
+          action(data,filename,raw)
+        end
+      end
+    end
+    enhance(enhancer,data,filename,raw)
+    local a=after[enhancer]
+    if a then
+      for pattern,action in next,a do
+        if find(basename,pattern) then
+          action(data,filename,raw)
+        end
+      end
+    end
     ioflush() 
-  end
-  if trace_loading then
-    report_otf("%s enhancing file %a","stop",filename)
-  end
+  end
+  if trace_loading then
+    report_otf("%s enhancing file %a","stop",filename)
+  end
   ioflush() 
 end
-function patches.register(what,where,pattern,action)
-  local pw=patches[what]
-  if pw then
-    local ww=pw[where]
-    if ww then
-      ww[pattern]=action
-    else
-      pw[where]={ [pattern]=action}
-    end
-  end
-end
-function patches.report(fmt,...)
-  if trace_loading then
-    report_otf("patching: %s",formatters[fmt](...))
-  end
+function patches.register(what,where,pattern,action)
+  local pw=patches[what]
+  if pw then
+    local ww=pw[where]
+    if ww then
+      ww[pattern]=action
+    else
+      pw[where]={ [pattern]=action}
+    end
+  end
+end
+function patches.report(fmt,...)
+  if trace_loading then
+    report_otf("patching: %s",formatters[fmt](...))
+  end
 end
 function enhancers.register(what,action) 
-  actions[what]=action
-end
-function otf.load(filename,format,sub,featurefile)
-  local base=file.basename(file.removesuffix(filename))
-  local name=file.removesuffix(base)
-  local attr=lfs.attributes(filename)
-  local size=attr and attr.size or 0
-  local time=attr and attr.modification or 0
-  if featurefile then
-    name=name.."@"..file.removesuffix(file.basename(featurefile))
-  end
-  if sub=="" then
-    sub=false
-  end
-  local hash=name
-  if sub then
-    hash=hash.."-"..sub
-  end
-  hash=containers.cleanname(hash)
-  local featurefiles
-  if featurefile then
-    featurefiles={}
-    for s in gmatch(featurefile,"[^,]+") do
-      local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
-      if name=="" then
-        report_otf("loading error, no featurefile %a",s)
-      else
-        local attr=lfs.attributes(name)
-        featurefiles[#featurefiles+1]={
-          name=name,
-          size=attr and attr.size or 0,
-          time=attr and attr.modification or 0,
-        }
-      end
-    end
-    if #featurefiles==0 then
-      featurefiles=nil
-    end
-  end
-  local data=containers.read(otf.cache,hash)
-  local reload=not data or data.size~=size or data.time~=time
-  if forceload then
-    report_otf("forced reload of %a due to hard coded flag",filename)
-    reload=true
-  end
-  if not reload then
-    local featuredata=data.featuredata
-    if featurefiles then
-      if not featuredata or #featuredata~=#featurefiles then
-        reload=true
-      else
-        for i=1,#featurefiles do
-          local fi,fd=featurefiles[i],featuredata[i]
-          if fi.name~=fd.name or fi.size~=fd.size or fi.time~=fd.time then
-            reload=true
-            break
-          end
-        end
-      end
-    elseif featuredata then
-      reload=true
-    end
-    if reload then
-      report_otf("loading: forced reload due to changed featurefile specification %a",featurefile)
-    end
-   end
-   if reload then
-    report_otf("loading %a, hash %a",filename,hash)
-    local fontdata,messages
-    if sub then
-      fontdata,messages=fontloader.open(filename,sub)
-    else
-      fontdata,messages=fontloader.open(filename)
-    end
-    if fontdata then
-      mainfields=mainfields or (fontloaderfields and fontloaderfields(fontdata))
-    end
-    if trace_loading and messages and #messages>0 then
-      if type(messages)=="string" then
-        report_otf("warning: %s",messages)
-      else
-        for m=1,#messages do
-          report_otf("warning: %S",messages[m])
-        end
-      end
-    else
-      report_otf("loading done")
-    end
-    if fontdata then
-      if featurefiles then
-        for i=1,#featurefiles do
-          load_featurefile(fontdata,featurefiles[i].name)
-        end
-      end
+  actions[what]=action
+end
+function otf.load(filename,format,sub,featurefile)
+  local base=file.basename(file.removesuffix(filename))
+  local name=file.removesuffix(base)
+  local attr=lfs.attributes(filename)
+  local size=attr and attr.size or 0
+  local time=attr and attr.modification or 0
+  if featurefile then
+    name=name.."@"..file.removesuffix(file.basename(featurefile))
+  end
+  if sub=="" then
+    sub=false
+  end
+  local hash=name
+  if sub then
+    hash=hash.."-"..sub
+  end
+  hash=containers.cleanname(hash)
+  local featurefiles
+  if featurefile then
+    featurefiles={}
+    for s in gmatch(featurefile,"[^,]+") do
+      local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
+      if name=="" then
+        report_otf("loading error, no featurefile %a",s)
+      else
+        local attr=lfs.attributes(name)
+        featurefiles[#featurefiles+1]={
+          name=name,
+          size=attr and attr.size or 0,
+          time=attr and attr.modification or 0,
+        }
+      end
+    end
+    if #featurefiles==0 then
+      featurefiles=nil
+    end
+  end
+  local data=containers.read(otf.cache,hash)
+  local reload=not data or data.size~=size or data.time~=time
+  if forceload then
+    report_otf("forced reload of %a due to hard coded flag",filename)
+    reload=true
+  end
+  if not reload then
+    local featuredata=data.featuredata
+    if featurefiles then
+      if not featuredata or #featuredata~=#featurefiles then
+        reload=true
+      else
+        for i=1,#featurefiles do
+          local fi,fd=featurefiles[i],featuredata[i]
+          if fi.name~=fd.name or fi.size~=fd.size or fi.time~=fd.time then
+            reload=true
+            break
+          end
+        end
+      end
+    elseif featuredata then
+      reload=true
+    end
+    if reload then
+      report_otf("loading: forced reload due to changed featurefile specification %a",featurefile)
+    end
+   end
+   if reload then
+    report_otf("loading %a, hash %a",filename,hash)
+    local fontdata,messages
+    if sub then
+      fontdata,messages=fontloader.open(filename,sub)
+    else
+      fontdata,messages=fontloader.open(filename)
+    end
+    if fontdata then
+      mainfields=mainfields or (fontloaderfields and fontloaderfields(fontdata))
+    end
+    if trace_loading and messages and #messages>0 then
+      if type(messages)=="string" then
+        report_otf("warning: %s",messages)
+      else
+        for m=1,#messages do
+          report_otf("warning: %S",messages[m])
+        end
+      end
+    else
+      report_otf("loading done")
+    end
+    if fontdata then
+      if featurefiles then
+        for i=1,#featurefiles do
+          load_featurefile(fontdata,featurefiles[i].name)
+        end
+      end
       local unicodes={
-      }
-      local splitter=lpeg.splitter(" ",unicodes)
-      data={
-        size=size,
-        time=time,
-        format=format,
-        featuredata=featurefiles,
-        resources={
+      }
+      local splitter=lpeg.splitter(" ",unicodes)
+      data={
+        size=size,
+        time=time,
+        format=format,
+        featuredata=featurefiles,
+        resources={
           filename=resolvers.unresolve(filename),
-          version=otf.version,
-          creator="context mkiv",
-          unicodes=unicodes,
+          version=otf.version,
+          creator="context mkiv",
+          unicodes=unicodes,
           indices={
-          },
+          },
           duplicates={
-          },
+          },
           variants={
-          },
-          lookuptypes={},
-        },
+          },
+          lookuptypes={},
+        },
         metadata={
-        },
+        },
         properties={
-        },
-        descriptions={},
-        goodies={},
-        helpers={
-          tounicodelist=splitter,
-          tounicodetable=lpeg.Ct(splitter),
-        },
-      }
-      starttiming(data)
-      report_otf("file size: %s",size)
-      enhancers.apply(data,filename,fontdata)
-      local packtime={}
-      if packdata then
-        if cleanup>0 then
-          collectgarbage("collect")
-        end
-        starttiming(packtime)
-        enhance("pack",data,filename,nil)
-        stoptiming(packtime)
-      end
-      report_otf("saving %a in cache",filename)
-      data=containers.write(otf.cache,hash,data)
-      if cleanup>1 then
-        collectgarbage("collect")
-      end
-      stoptiming(data)
+        },
+        descriptions={},
+        goodies={},
+        helpers={
+          tounicodelist=splitter,
+          tounicodetable=lpeg.Ct(splitter),
+        },
+      }
+      starttiming(data)
+      report_otf("file size: %s",size)
+      enhancers.apply(data,filename,fontdata)
+      local packtime={}
+      if packdata then
+        if cleanup>0 then
+          collectgarbage("collect")
+        end
+        starttiming(packtime)
+        enhance("pack",data,filename,nil)
+        stoptiming(packtime)
+      end
+      report_otf("saving %a in cache",filename)
+      data=containers.write(otf.cache,hash,data)
+      if cleanup>1 then
+        collectgarbage("collect")
+      end
+      stoptiming(data)
       if elapsedtime then 
-        report_otf("preprocessing and caching time %s, packtime %s",
-          elapsedtime(data),packdata and elapsedtime(packtime) or 0)
-      end
+        report_otf("preprocessing and caching time %s, packtime %s",
+          elapsedtime(data),packdata and elapsedtime(packtime) or 0)
+      end
       fontloader.close(fontdata) 
-      if cleanup>3 then
-        collectgarbage("collect")
-      end
+      if cleanup>3 then
+        collectgarbage("collect")
+      end
       data=containers.read(otf.cache,hash) 
-      if cleanup>2 then
-        collectgarbage("collect")
-      end
-    else
-      data=nil
-      report_otf("loading failed due to read error")
-    end
-  end
-  if data then
-    if trace_defining then
-      report_otf("loading from cache using hash %a",hash)
-    end
-    enhance("unpack",data,filename,nil,false)
-    enhance("add dimensions",data,filename,nil,false)
-    if trace_sequences then
-      showfeatureorder(data,filename)
-    end
-  end
-  return data
-end
-local mt={
+      if cleanup>2 then
+        collectgarbage("collect")
+      end
+    else
+      data=nil
+      report_otf("loading failed due to read error")
+    end
+  end
+  if data then
+    if trace_defining then
+      report_otf("loading from cache using hash %a",hash)
+    end
+    enhance("unpack",data,filename,nil,false)
+    enhance("add dimensions",data,filename,nil,false)
+    if trace_sequences then
+      showfeatureorder(data,filename)
+    end
+  end
+  return data
+end
+local mt={
   __index=function(t,k) 
-    if k=="height" then
-      local ht=t.boundingbox[4]
-      return ht<0 and 0 or ht
-    elseif k=="depth" then
-      local dp=-t.boundingbox[2]
-      return dp<0 and 0 or dp
-    elseif k=="width" then
-      return 0
+    if k=="height" then
+      local ht=t.boundingbox[4]
+      return ht<0 and 0 or ht
+    elseif k=="depth" then
+      local dp=-t.boundingbox[2]
+      return dp<0 and 0 or dp
+    elseif k=="width" then
+      return 0
     elseif k=="name" then 
-      return forcenotdef and ".notdef"
-    end
-  end
+      return forcenotdef and ".notdef"
+    end
+  end
 }
-actions["prepare tables"]=function(data,filename,raw)
-  data.properties.hasitalics=false
+actions["prepare tables"]=function(data,filename,raw)
+  data.properties.hasitalics=false
 end
 actions["add dimensions"]=function(data,filename)
-  if data then
-    local descriptions=data.descriptions
-    local resources=data.resources
-    local defaultwidth=resources.defaultwidth or 0
-    local defaultheight=resources.defaultheight or 0
-    local defaultdepth=resources.defaultdepth or 0
-    local basename=trace_markwidth and file.basename(filename)
-    if usemetatables then
-      for _,d in next,descriptions do
-        local wd=d.width
-        if not wd then
-          d.width=defaultwidth
-        elseif trace_markwidth and wd~=0 and d.class=="mark" then
+  if data then
+    local descriptions=data.descriptions
+    local resources=data.resources
+    local defaultwidth=resources.defaultwidth or 0
+    local defaultheight=resources.defaultheight or 0
+    local defaultdepth=resources.defaultdepth or 0
+    local basename=trace_markwidth and file.basename(filename)
+    if usemetatables then
+      for _,d in next,descriptions do
+        local wd=d.width
+        if not wd then
+          d.width=defaultwidth
+        elseif trace_markwidth and wd~=0 and d.class=="mark" then
           report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
-        end
-        setmetatable(d,mt)
-      end
-    else
-      for _,d in next,descriptions do
-        local bb,wd=d.boundingbox,d.width
-        if not wd then
-          d.width=defaultwidth
-        elseif trace_markwidth and wd~=0 and d.class=="mark" then
+        end
+        setmetatable(d,mt)
+      end
+    else
+      for _,d in next,descriptions do
+        local bb,wd=d.boundingbox,d.width
+        if not wd then
+          d.width=defaultwidth
+        elseif trace_markwidth and wd~=0 and d.class=="mark" then
           report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
         end
-        if bb then
-          local ht,dp=bb[4],-bb[2]
+        if bb then
+          local ht,dp=bb[4],-bb[2]
           if ht==0 or ht<0 then
-          else
-            d.height=ht
-          end
+          else
+            d.height=ht
+          end
           if dp==0 or dp<0 then
-          else
-            d.depth=dp
-          end
-        end
-      end
-    end
-  end
+          else
+            d.depth=dp
+          end
+        end
+      end
+    end
+  end
 end
 local function somecopy(old) 
-  if old then
-    local new={}
-    if type(old)=="table" then
-      for k,v in next,old do
+  if old then
+    local new={}
+    if type(old)=="table" then
+      for k,v in next,old do
         if k=="glyphs" then
-        elseif type(v)=="table" then
-          new[k]=somecopy(v)
-        else
-          new[k]=v
-        end
-      end
-    else
-      for i=1,#mainfields do
-        local k=mainfields[i]
-        local v=old[k]
+        elseif type(v)=="table" then
+          new[k]=somecopy(v)
+        else
+          new[k]=v
+        end
+      end
+    else
+      for i=1,#mainfields do
+        local k=mainfields[i]
+        local v=old[k]
         if k=="glyphs" then
-        elseif type(v)=="table" then
-          new[k]=somecopy(v)
-        else
-          new[k]=v
-        end
-      end
-    end
-    return new
-  else
-    return {}
-  end
-end
-actions["prepare glyphs"]=function(data,filename,raw)
-  local rawglyphs=raw.glyphs
-  local rawsubfonts=raw.subfonts
-  local rawcidinfo=raw.cidinfo
-  local criterium=constructors.privateoffset
-  local private=criterium
-  local resources=data.resources
-  local metadata=data.metadata
-  local properties=data.properties
-  local descriptions=data.descriptions
+        elseif type(v)=="table" then
+          new[k]=somecopy(v)
+        else
+          new[k]=v
+        end
+      end
+    end
+    return new
+  else
+    return {}
+  end
+end
+actions["prepare glyphs"]=function(data,filename,raw)
+  local rawglyphs=raw.glyphs
+  local rawsubfonts=raw.subfonts
+  local rawcidinfo=raw.cidinfo
+  local criterium=constructors.privateoffset
+  local private=criterium
+  local resources=data.resources
+  local metadata=data.metadata
+  local properties=data.properties
+  local descriptions=data.descriptions
   local unicodes=resources.unicodes 
   local indices=resources.indices 
-  local duplicates=resources.duplicates
+  local duplicates=resources.duplicates
   local variants=resources.variants
   if rawsubfonts then
-    metadata.subfonts=includesubfonts and {}
+    metadata.subfonts=includesubfonts and {}
     properties.cidinfo=rawcidinfo
-    if rawcidinfo.registry then
-      local cidmap=fonts.cid.getmap(rawcidinfo)
-      if cidmap then
-        rawcidinfo.usedname=cidmap.usedname
-        local nofnames,nofunicodes=0,0
-        local cidunicodes,cidnames=cidmap.unicodes,cidmap.names
-        for cidindex=1,#rawsubfonts do
-          local subfont=rawsubfonts[cidindex]
-          local cidglyphs=subfont.glyphs
-          if includesubfonts then
-            metadata.subfonts[cidindex]=somecopy(subfont)
-          end
+    if rawcidinfo.registry then
+      local cidmap=fonts.cid.getmap(rawcidinfo)
+      if cidmap then
+        rawcidinfo.usedname=cidmap.usedname
+        local nofnames,nofunicodes=0,0
+        local cidunicodes,cidnames=cidmap.unicodes,cidmap.names
+        for cidindex=1,#rawsubfonts do
+          local subfont=rawsubfonts[cidindex]
+          local cidglyphs=subfont.glyphs
+          if includesubfonts then
+            metadata.subfonts[cidindex]=somecopy(subfont)
+          end
           for index=0,subfont.glyphcnt-1 do 
-            local glyph=cidglyphs[index]
-            if glyph then
-              local unicode=glyph.unicode
-              local name=glyph.name or cidnames[index]
-              if not unicode or unicode==-1 or unicode>=criterium then
-                unicode=cidunicodes[index]
-              end
-              if unicode and descriptions[unicode] then
-                report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
-                unicode=-1
-              end
-              if not unicode or unicode==-1 or unicode>=criterium then
-                if not name then
-                  name=format("u%06X",private)
-                end
-                unicode=private
-                unicodes[name]=private
-                if trace_private then
-                  report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
-                end
-                private=private+1
-                nofnames=nofnames+1
-              else
-                if not name then
-                  name=format("u%06X",unicode)
-                end
-                unicodes[name]=unicode
-                nofunicodes=nofunicodes+1
-              end
+            local glyph=cidglyphs[index]
+            if glyph then
+              local unicode=glyph.unicode
+              local name=glyph.name or cidnames[index]
+              if not unicode or unicode==-1 or unicode>=criterium then
+                unicode=cidunicodes[index]
+              end
+              if unicode and descriptions[unicode] then
+                report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+                unicode=-1
+              end
+              if not unicode or unicode==-1 or unicode>=criterium then
+                if not name then
+                  name=format("u%06X",private)
+                end
+                unicode=private
+                unicodes[name]=private
+                if trace_private then
+                  report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                end
+                private=private+1
+                nofnames=nofnames+1
+              else
+                if not name then
+                  name=format("u%06X",unicode)
+                end
+                unicodes[name]=unicode
+                nofunicodes=nofunicodes+1
+              end
               indices[index]=unicode 
               local description={
-                boundingbox=glyph.boundingbox,
+                boundingbox=glyph.boundingbox,
                 name=glyph.name or name or "unknown",
-                cidindex=cidindex,
-                index=index,
-                glyph=glyph,
+                cidindex=cidindex,
+                index=index,
+                glyph=glyph,
               }
-              descriptions[unicode]=description
+              descriptions[unicode]=description
             else
-            end
-          end
-        end
-        if trace_loading then
-          report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames)
-        end
-      elseif trace_loading then
-        report_otf("unable to remap cid font, missing cid file for %a",filename)
-      end
-    elseif trace_loading then
-      report_otf("font %a has no glyphs",filename)
+            end
+          end
+        end
+        if trace_loading then
+          report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames)
+        end
+      elseif trace_loading then
+        report_otf("unable to remap cid font, missing cid file for %a",filename)
+      end
+    elseif trace_loading then
+      report_otf("font %a has no glyphs",filename)
     end
   else
     for index=0,raw.glyphcnt-1 do 
-      local glyph=rawglyphs[index]
-      if glyph then
-        local unicode=glyph.unicode
-        local name=glyph.name
-        if not unicode or unicode==-1 or unicode>=criterium then
-          unicode=private
-          unicodes[name]=private
-          if trace_private then
-            report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
-          end
-          private=private+1
-        else
-          unicodes[name]=unicode
-        end
-        indices[index]=unicode
-        if not name then
-          name=format("u%06X",unicode)
-        end
+      local glyph=rawglyphs[index]
+      if glyph then
+        local unicode=glyph.unicode
+        local name=glyph.name
+        if not unicode or unicode==-1 or unicode>=criterium then
+          unicode=private
+          unicodes[name]=private
+          if trace_private then
+            report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+          end
+          private=private+1
+        else
+          unicodes[name]=unicode
+        end
+        indices[index]=unicode
+        if not name then
+          name=format("u%06X",unicode)
+        end
         descriptions[unicode]={
-          boundingbox=glyph.boundingbox,
-          name=name,
-          index=index,
-          glyph=glyph,
-        }
-        local altuni=glyph.altuni
-        if altuni then
-          local d
-          for i=1,#altuni do
-            local a=altuni[i]
-            local u=a.unicode
-            local v=a.variant
+          boundingbox=glyph.boundingbox,
+          name=name,
+          index=index,
+          glyph=glyph,
+        }
+        local altuni=glyph.altuni
+        if altuni then
+          local d
+          for i=1,#altuni do
+            local a=altuni[i]
+            local u=a.unicode
+            local v=a.variant
             if v then
-              local vv=variants[v]
-              if vv then
-                vv[u]=unicode
+              local vv=variants[v]
+              if vv then
+                vv[u]=unicode
               else 
-                vv={ [u]=unicode }
-                variants[v]=vv
-              end
-            elseif d then
-              d[#d+1]=u
-            else
-              d={ u }
-            end
-          end
-          if d then
-            duplicates[unicode]=d
-          end
-        end
-      else
-        report_otf("potential problem: glyph %U is used but empty",index)
-      end
+                vv={ [u]=unicode }
+                variants[v]=vv
+              end
+            elseif d then
+              d[#d+1]=u
+            else
+              d={ u }
+            end
+          end
+          if d then
+            duplicates[unicode]=d
+          end
+        end
+      else
+        report_otf("potential problem: glyph %U is used but empty",index)
+      end
     end
   end
   resources.private=private
 end
-actions["check encoding"]=function(data,filename,raw)
-  local descriptions=data.descriptions
-  local resources=data.resources
-  local properties=data.properties
+actions["check encoding"]=function(data,filename,raw)
+  local descriptions=data.descriptions
+  local resources=data.resources
+  local properties=data.properties
   local unicodes=resources.unicodes 
   local indices=resources.indices 
   local duplicates=resources.duplicates
-  local mapdata=raw.map or {}
+  local mapdata=raw.map or {}
   local unicodetoindex=mapdata and mapdata.map or {}
-  local encname=lower(data.enc_name or mapdata.enc_name or "")
+  local encname=lower(data.enc_name or mapdata.enc_name or "")
   local criterium=0xFFFF
   if find(encname,"unicode") then 
-    if trace_loading then
-      report_otf("checking embedded unicode map %a",encname)
-    end
+    if trace_loading then
+      report_otf("checking embedded unicode map %a",encname)
+    end
     for unicode,index in next,unicodetoindex do 
-      if unicode<=criterium and not descriptions[unicode] then
+      if unicode<=criterium and not descriptions[unicode] then
         local parent=indices[index] 
-        if not parent then
-          report_otf("weird, unicode %U points to nowhere with index %H",unicode,index)
-        else
-          local parentdescription=descriptions[parent]
-          if parentdescription then
-            local altuni=parentdescription.altuni
-            if not altuni then
-              altuni={ { unicode=parent } }
-              parentdescription.altuni=altuni
-              duplicates[parent]={ unicode }
-            else
-              local done=false
-              for i=1,#altuni do
-                if altuni[i].unicode==parent then
-                  done=true
-                  break
-                end
-              end
+        if not parent then
+          report_otf("weird, unicode %U points to nowhere with index %H",unicode,index)
+        else
+          local parentdescription=descriptions[parent]
+          if parentdescription then
+            local altuni=parentdescription.altuni
+            if not altuni then
+              altuni={ { unicode=parent } }
+              parentdescription.altuni=altuni
+              duplicates[parent]={ unicode }
+            else
+              local done=false
+              for i=1,#altuni do
+                if altuni[i].unicode==parent then
+                  done=true
+                  break
+                end
+              end
               if not done then
-                altuni[#altuni+1]={ unicode=parent }
-                table.insert(duplicates[parent],unicode)
-              end
-            end
-            if trace_loading then
-              report_otf("weird, unicode %U points to nowhere with index %H",unicode,index)
-            end
-          else
-            report_otf("weird, unicode %U points to %U with index %H",unicode,index)
-          end
-        end
-      end
-    end
-  elseif properties.cidinfo then
-    report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname)
-  else
-    report_otf("warning: non unicode map %a, only using glyph unicode data",encname or "whatever")
-  end
-  if mapdata then
+                altuni[#altuni+1]={ unicode=parent }
+                table.insert(duplicates[parent],unicode)
+              end
+            end
+            if trace_loading then
+              report_otf("weird, unicode %U points to nowhere with index %H",unicode,index)
+            end
+          else
+            report_otf("weird, unicode %U points to %U with index %H",unicode,index)
+          end
+        end
+      end
+    end
+  elseif properties.cidinfo then
+    report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname)
+  else
+    report_otf("warning: non unicode map %a, only using glyph unicode data",encname or "whatever")
+  end
+  if mapdata then
     mapdata.map={} 
-  end
+  end
 end
-actions["add duplicates"]=function(data,filename,raw)
-  local descriptions=data.descriptions
-  local resources=data.resources
-  local properties=data.properties
+actions["add duplicates"]=function(data,filename,raw)
+  local descriptions=data.descriptions
+  local resources=data.resources
+  local properties=data.properties
   local unicodes=resources.unicodes 
   local indices=resources.indices 
   local duplicates=resources.duplicates
-  for unicode,d in next,duplicates do
-    for i=1,#d do
-      local u=d[i]
-      if not descriptions[u] then
-        local description=descriptions[unicode]
+  for unicode,d in next,duplicates do
+    for i=1,#d do
+      local u=d[i]
+      if not descriptions[u] then
+        local description=descriptions[unicode]
         local duplicate=table.copy(description) 
-        duplicate.comment=format("copy of U+%05X",unicode)
-        descriptions[u]=duplicate
-        local n=0
-        for _,description in next,descriptions do
-          if kerns then
-            local kerns=description.kerns
-            for _,k in next,kerns do
-              local ku=k[unicode]
-              if ku then
-                k[u]=ku
-                n=n+1
-              end
-            end
-          end
-        end
-        if trace_loading then
-          report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n)
-        end
-      end
-    end
-  end
+        duplicate.comment=format("copy of U+%05X",unicode)
+        descriptions[u]=duplicate
+        local n=0
+        for _,description in next,descriptions do
+          if kerns then
+            local kerns=description.kerns
+            for _,k in next,kerns do
+              local ku=k[unicode]
+              if ku then
+                k[u]=ku
+                n=n+1
+              end
+            end
+          end
+        end
+        if trace_loading then
+          report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n)
+        end
+      end
+    end
+  end
 end
 actions["analyze glyphs"]=function(data,filename,raw) 
-  local descriptions=data.descriptions
-  local resources=data.resources
-  local metadata=data.metadata
-  local properties=data.properties
-  local hasitalics=false
-  local widths={}
+  local descriptions=data.descriptions
+  local resources=data.resources
+  local metadata=data.metadata
+  local properties=data.properties
+  local hasitalics=false
+  local widths={}
   local marks={} 
-  for unicode,description in next,descriptions do
-    local glyph=description.glyph
-    local italic=glyph.italic_correction
+  for unicode,description in next,descriptions do
+    local glyph=description.glyph
+    local italic=glyph.italic_correction
     if not italic then
     elseif italic==0 then
-    else
-      description.italic=italic
-      hasitalics=true
-    end
-    local width=glyph.width
-    widths[width]=(widths[width] or 0)+1
-    local class=glyph.class
-    if class then
-      if class=="mark" then
-        marks[unicode]=true
-      end
-      description.class=class
-    end
+    else
+      description.italic=italic
+      hasitalics=true
+    end
+    local width=glyph.width
+    widths[width]=(widths[width] or 0)+1
+    local class=glyph.class
+    if class then
+      if class=="mark" then
+        marks[unicode]=true
+      end
+      description.class=class
+    end
   end
   properties.hasitalics=hasitalics
   resources.marks=marks
-  local wd,most=0,1
-  for k,v in next,widths do
-    if v>most then
-      wd,most=k,v
-    end
-  end
+  local wd,most=0,1
+  for k,v in next,widths do
+    if v>most then
+      wd,most=k,v
+    end
+  end
   if most>1000 then 
-    if trace_loading then
-      report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
-    end
-    for unicode,description in next,descriptions do
+    if trace_loading then
+      report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
+    end
+    for unicode,description in next,descriptions do
       if description.width==wd then
-      else
-        description.width=description.glyph.width
-      end
-    end
-    resources.defaultwidth=wd
-  else
-    for unicode,description in next,descriptions do
-      description.width=description.glyph.width
-    end
-  end
-end
-actions["reorganize mark classes"]=function(data,filename,raw)
-  local mark_classes=raw.mark_classes
-  if mark_classes then
-    local resources=data.resources
-    local unicodes=resources.unicodes
-    local markclasses={}
-    resources.markclasses=markclasses 
-    for name,class in next,mark_classes do
-      local t={}
-      for s in gmatch(class,"[^ ]+") do
-        t[unicodes[s]]=true
-      end
-      markclasses[name]=t
-    end
-  end
-end
-actions["reorganize features"]=function(data,filename,raw) 
-  local features={}
-  data.resources.features=features
-  for k,what in next,otf.glists do
-    local dw=raw[what]
-    if dw then
-      local f={}
-      features[what]=f
-      for i=1,#dw do
-        local d=dw[i]
-        local dfeatures=d.features
-        if dfeatures then
-          for i=1,#dfeatures do
-            local df=dfeatures[i]
-            local tag=strip(lower(df.tag))
-            local ft=f[tag]
-            if not ft then
-              ft={}
-              f[tag]=ft
-            end
-            local dscripts=df.scripts
-            for i=1,#dscripts do
-              local d=dscripts[i]
-              local languages=d.langs
-              local script=strip(lower(d.script))
-              local fts=ft[script] if not fts then fts={} ft[script]=fts end
-              for i=1,#languages do
-                fts[strip(lower(languages[i]))]=true
-              end
-            end
-          end
-        end
-      end
-    end
-  end
-end
-actions["reorganize anchor classes"]=function(data,filename,raw)
-  local resources=data.resources
-  local anchor_to_lookup={}
-  local lookup_to_anchor={}
-  resources.anchor_to_lookup=anchor_to_lookup
-  resources.lookup_to_anchor=lookup_to_anchor
-  local classes=raw.anchor_classes 
-  if classes then
-    for c=1,#classes do
-      local class=classes[c]
-      local anchor=class.name
-      local lookups=class.lookup
-      if type(lookups)~="table" then
-        lookups={ lookups }
-      end
-      local a=anchor_to_lookup[anchor]
-      if not a then
-        a={}
-        anchor_to_lookup[anchor]=a
-      end
-      for l=1,#lookups do
-        local lookup=lookups[l]
-        local l=lookup_to_anchor[lookup]
-        if l then
-          l[anchor]=true
-        else
-          l={ [anchor]=true }
-          lookup_to_anchor[lookup]=l
-        end
-        a[lookup]=true
-      end
-    end
-  end
-end
-actions["prepare tounicode"]=function(data,filename,raw)
-  fonts.mappings.addtounicode(data,filename)
-end
-local g_directions={
-  gsub_contextchain=1,
-  gpos_contextchain=1,
-  gsub_reversecontextchain=-1,
-  gpos_reversecontextchain=-1,
+      else
+        description.width=description.glyph.width
+      end
+    end
+    resources.defaultwidth=wd
+  else
+    for unicode,description in next,descriptions do
+      description.width=description.glyph.width
+    end
+  end
+end
+actions["reorganize mark classes"]=function(data,filename,raw)
+  local mark_classes=raw.mark_classes
+  if mark_classes then
+    local resources=data.resources
+    local unicodes=resources.unicodes
+    local markclasses={}
+    resources.markclasses=markclasses 
+    for name,class in next,mark_classes do
+      local t={}
+      for s in gmatch(class,"[^ ]+") do
+        t[unicodes[s]]=true
+      end
+      markclasses[name]=t
+    end
+  end
+end
+actions["reorganize features"]=function(data,filename,raw) 
+  local features={}
+  data.resources.features=features
+  for k,what in next,otf.glists do
+    local dw=raw[what]
+    if dw then
+      local f={}
+      features[what]=f
+      for i=1,#dw do
+        local d=dw[i]
+        local dfeatures=d.features
+        if dfeatures then
+          for i=1,#dfeatures do
+            local df=dfeatures[i]
+            local tag=strip(lower(df.tag))
+            local ft=f[tag]
+            if not ft then
+              ft={}
+              f[tag]=ft
+            end
+            local dscripts=df.scripts
+            for i=1,#dscripts do
+              local d=dscripts[i]
+              local languages=d.langs
+              local script=strip(lower(d.script))
+              local fts=ft[script] if not fts then fts={} ft[script]=fts end
+              for i=1,#languages do
+                fts[strip(lower(languages[i]))]=true
+              end
+            end
+          end
+        end
+      end
+    end
+  end
+end
+actions["reorganize anchor classes"]=function(data,filename,raw)
+  local resources=data.resources
+  local anchor_to_lookup={}
+  local lookup_to_anchor={}
+  resources.anchor_to_lookup=anchor_to_lookup
+  resources.lookup_to_anchor=lookup_to_anchor
+  local classes=raw.anchor_classes 
+  if classes then
+    for c=1,#classes do
+      local class=classes[c]
+      local anchor=class.name
+      local lookups=class.lookup
+      if type(lookups)~="table" then
+        lookups={ lookups }
+      end
+      local a=anchor_to_lookup[anchor]
+      if not a then
+        a={}
+        anchor_to_lookup[anchor]=a
+      end
+      for l=1,#lookups do
+        local lookup=lookups[l]
+        local l=lookup_to_anchor[lookup]
+        if l then
+          l[anchor]=true
+        else
+          l={ [anchor]=true }
+          lookup_to_anchor[lookup]=l
+        end
+        a[lookup]=true
+      end
+    end
+  end
+end
+actions["prepare tounicode"]=function(data,filename,raw)
+  fonts.mappings.addtounicode(data,filename)
+end
+local g_directions={
+  gsub_contextchain=1,
+  gpos_contextchain=1,
+  gsub_reversecontextchain=-1,
+  gpos_reversecontextchain=-1,
 }
-local function supported(features)
-  for i=1,#features do
-    if features[i].ismac then
-      return false
-    end
-  end
-  return true
-end
-actions["reorganize subtables"]=function(data,filename,raw)
-  local resources=data.resources
-  local sequences={}
-  local lookups={}
-  local chainedfeatures={}
-  resources.sequences=sequences
-  resources.lookups=lookups
-  for _,what in next,otf.glists do
-    local dw=raw[what]
-    if dw then
-      for k=1,#dw do
-        local gk=dw[k]
+local function supported(features)
+  for i=1,#features do
+    if features[i].ismac then
+      return false
+    end
+  end
+  return true
+end
+actions["reorganize subtables"]=function(data,filename,raw)
+  local resources=data.resources
+  local sequences={}
+  local lookups={}
+  local chainedfeatures={}
+  resources.sequences=sequences
+  resources.lookups=lookups
+  for _,what in next,otf.glists do
+    local dw=raw[what]
+    if dw then
+      for k=1,#dw do
+        local gk=dw[k]
         local features=gk.features
         if not features or supported(features) then 
-          local typ=gk.type
-          local chain=g_directions[typ] or 0
-          local subtables=gk.subtables
-          if subtables then
-            local t={}
-            for s=1,#subtables do
-              t[s]=subtables[s].name
-            end
-            subtables=t
-          end
-          local flags,markclass=gk.flags,nil
-          if flags then
+          local typ=gk.type
+          local chain=g_directions[typ] or 0
+          local subtables=gk.subtables
+          if subtables then
+            local t={}
+            for s=1,#subtables do
+              t[s]=subtables[s].name
+            end
+            subtables=t
+          end
+          local flags,markclass=gk.flags,nil
+          if flags then
             local t={ 
-              (flags.ignorecombiningmarks and "mark")   or false,
-              (flags.ignoreligatures   and "ligature") or false,
-              (flags.ignorebaseglyphs   and "base")   or false,
-               flags.r2l                 or false,
-            }
-            markclass=flags.mark_class
-            if markclass then
-              markclass=resources.markclasses[markclass]
-            end
-            flags=t
+              (flags.ignorecombiningmarks and "mark")   or false,
+              (flags.ignoreligatures   and "ligature") or false,
+              (flags.ignorebaseglyphs   and "base")   or false,
+               flags.r2l                 or false,
+            }
+            markclass=flags.mark_class
+            if markclass then
+              markclass=resources.markclasses[markclass]
+            end
+            flags=t
           end
           local name=gk.name
           if not name then
-            report_otf("skipping weird lookup number %s",k)
+            report_otf("skipping weird lookup number %s",k)
           elseif features then
-            local f={}
-            for i=1,#features do
-              local df=features[i]
-              local tag=strip(lower(df.tag))
-              local ft=f[tag] if not ft then ft={} f[tag]=ft end
-              local dscripts=df.scripts
-              for i=1,#dscripts do
-                local d=dscripts[i]
-                local languages=d.langs
-                local script=strip(lower(d.script))
-                local fts=ft[script] if not fts then fts={} ft[script]=fts end
-                for i=1,#languages do
-                  fts[strip(lower(languages[i]))]=true
-                end
-              end
-            end
-            sequences[#sequences+1]={
-              type=typ,
-              chain=chain,
-              flags=flags,
-              name=name,
-              subtables=subtables,
-              markclass=markclass,
-              features=f,
-            }
-          else
-            lookups[name]={
-              type=typ,
-              chain=chain,
-              flags=flags,
-              subtables=subtables,
-              markclass=markclass,
-            }
-          end
-        end
-      end
-    end
-  end
-end
-actions["prepare lookups"]=function(data,filename,raw)
-  local lookups=raw.lookups
-  if lookups then
-    data.lookups=lookups
-  end
-end
-local function t_uncover(splitter,cache,covers)
-  local result={}
-  for n=1,#covers do
-    local cover=covers[n]
-    local uncovered=cache[cover]
-    if not uncovered then
-      uncovered=lpegmatch(splitter,cover)
-      cache[cover]=uncovered
-    end
-    result[n]=uncovered
-  end
-  return result
-end
-local function s_uncover(splitter,cache,cover)
-  if cover=="" then
-    return nil
-  else
-    local uncovered=cache[cover]
-    if not uncovered then
+            local f={}
+            for i=1,#features do
+              local df=features[i]
+              local tag=strip(lower(df.tag))
+              local ft=f[tag] if not ft then ft={} f[tag]=ft end
+              local dscripts=df.scripts
+              for i=1,#dscripts do
+                local d=dscripts[i]
+                local languages=d.langs
+                local script=strip(lower(d.script))
+                local fts=ft[script] if not fts then fts={} ft[script]=fts end
+                for i=1,#languages do
+                  fts[strip(lower(languages[i]))]=true
+                end
+              end
+            end
+            sequences[#sequences+1]={
+              type=typ,
+              chain=chain,
+              flags=flags,
+              name=name,
+              subtables=subtables,
+              markclass=markclass,
+              features=f,
+            }
+          else
+            lookups[name]={
+              type=typ,
+              chain=chain,
+              flags=flags,
+              subtables=subtables,
+              markclass=markclass,
+            }
+          end
+        end
+      end
+    end
+  end
+end
+actions["prepare lookups"]=function(data,filename,raw)
+  local lookups=raw.lookups
+  if lookups then
+    data.lookups=lookups
+  end
+end
+local function t_uncover(splitter,cache,covers)
+  local result={}
+  for n=1,#covers do
+    local cover=covers[n]
+    local uncovered=cache[cover]
+    if not uncovered then
+      uncovered=lpegmatch(splitter,cover)
+      cache[cover]=uncovered
+    end
+    result[n]=uncovered
+  end
+  return result
+end
+local function s_uncover(splitter,cache,cover)
+  if cover=="" then
+    return nil
+  else
+    local uncovered=cache[cover]
+    if not uncovered then
       uncovered=lpegmatch(splitter,cover)
-      cache[cover]=uncovered
-    end
-    return { uncovered }
-  end
-end
-local function t_hashed(t,cache)
-  if t then
-    local ht={}
-    for i=1,#t do
-      local ti=t[i]
-      local tih=cache[ti]
-      if not tih then
-        tih={}
-        for i=1,#ti do
-          tih[ti[i]]=true
-        end
-        cache[ti]=tih
-      end
-      ht[i]=tih
-    end
-    return ht
-  else
-    return nil
-  end
-end
-local function s_hashed(t,cache)
-  if t then
-    local ht={}
-    local tf=t[1]
-    for i=1,#tf do
-      ht[i]={ [tf[i]]=true }
-    end
-    return ht
-  else
-    return nil
-  end
-end
-local function r_uncover(splitter,cache,cover,replacements)
-  if cover=="" then
-    return nil
+      cache[cover]=uncovered
+    end
+    return { uncovered }
+  end
+end
+local function t_hashed(t,cache)
+  if t then
+    local ht={}
+    for i=1,#t do
+      local ti=t[i]
+      local tih=cache[ti]
+      if not tih then
+        tih={}
+        for i=1,#ti do
+          tih[ti[i]]=true
+        end
+        cache[ti]=tih
+      end
+      ht[i]=tih
+    end
+    return ht
+  else
+    return nil
+  end
+end
+local function s_hashed(t,cache)
+  if t then
+    local ht={}
+    local tf=t[1]
+    for i=1,#tf do
+      ht[i]={ [tf[i]]=true }
+    end
+    return ht
+  else
+    return nil
+  end
+end
+local function r_uncover(splitter,cache,cover,replacements)
+  if cover=="" then
+    return nil
   else
-    local uncovered=cover[1]
-    local replaced=cache[replacements]
-    if not replaced then
-      replaced=lpegmatch(splitter,replacements)
-      cache[replacements]=replaced
-    end
-    local nu,nr=#uncovered,#replaced
-    local r={}
-    if nu==nr then
-      for i=1,nu do
-        r[uncovered[i]]=replaced[i]
-      end
-    end
-    return r
-  end
+    local uncovered=cover[1]
+    local replaced=cache[replacements]
+    if not replaced then
+      replaced=lpegmatch(splitter,replacements)
+      cache[replacements]=replaced
+    end
+    local nu,nr=#uncovered,#replaced
+    local r={}
+    if nu==nr then
+      for i=1,nu do
+        r[uncovered[i]]=replaced[i]
+      end
+    end
+    return r
+  end
 end
 actions["reorganize lookups"]=function(data,filename,raw)
-  if data.lookups then
-    local splitter=data.helpers.tounicodetable
-    local t_u_cache={}
+  if data.lookups then
+    local splitter=data.helpers.tounicodetable
+    local t_u_cache={}
     local s_u_cache=t_u_cache 
-    local t_h_cache={}
+    local t_h_cache={}
     local s_h_cache=t_h_cache 
     local r_u_cache={} 
-    for _,lookup in next,data.lookups do
-      local rules=lookup.rules
-      if rules then
-        local format=lookup.format
-        if format=="class" then
-          local before_class=lookup.before_class
-          if before_class then
-            before_class=t_uncover(splitter,t_u_cache,reversed(before_class))
-          end
-          local current_class=lookup.current_class
-          if current_class then
-            current_class=t_uncover(splitter,t_u_cache,current_class)
-          end
-          local after_class=lookup.after_class
-          if after_class then
-            after_class=t_uncover(splitter,t_u_cache,after_class)
-          end
-          for i=1,#rules do
-            local rule=rules[i]
-            local class=rule.class
-            local before=class.before
-            if before then
-              for i=1,#before do
-                before[i]=before_class[before[i]] or {}
-              end
-              rule.before=t_hashed(before,t_h_cache)
-            end
-            local current=class.current
-            local lookups=rule.lookups
-            if current then
-              for i=1,#current do
+    for _,lookup in next,data.lookups do
+      local rules=lookup.rules
+      if rules then
+        local format=lookup.format
+        if format=="class" then
+          local before_class=lookup.before_class
+          if before_class then
+            before_class=t_uncover(splitter,t_u_cache,reversed(before_class))
+          end
+          local current_class=lookup.current_class
+          if current_class then
+            current_class=t_uncover(splitter,t_u_cache,current_class)
+          end
+          local after_class=lookup.after_class
+          if after_class then
+            after_class=t_uncover(splitter,t_u_cache,after_class)
+          end
+          for i=1,#rules do
+            local rule=rules[i]
+            local class=rule.class
+            local before=class.before
+            if before then
+              for i=1,#before do
+                before[i]=before_class[before[i]] or {}
+              end
+              rule.before=t_hashed(before,t_h_cache)
+            end
+            local current=class.current
+            local lookups=rule.lookups
+            if current then
+              for i=1,#current do
                 current[i]=current_class[current[i]] or {}
-                if lookups and not lookups[i] then
+                if lookups and not lookups[i] then
                   lookups[i]="" 
                 end
-              end
-              rule.current=t_hashed(current,t_h_cache)
-            end
-            local after=class.after
-            if after then
-              for i=1,#after do
-                after[i]=after_class[after[i]] or {}
-              end
-              rule.after=t_hashed(after,t_h_cache)
-            end
-            rule.class=nil
-          end
-          lookup.before_class=nil
-          lookup.current_class=nil
-          lookup.after_class=nil
-          lookup.format="coverage"
-        elseif format=="coverage" then
-          for i=1,#rules do
-            local rule=rules[i]
-            local coverage=rule.coverage
-            if coverage then
-              local before=coverage.before
-              if before then
-                before=t_uncover(splitter,t_u_cache,reversed(before))
-                rule.before=t_hashed(before,t_h_cache)
-              end
-              local current=coverage.current
-              if current then
+              end
+              rule.current=t_hashed(current,t_h_cache)
+            end
+            local after=class.after
+            if after then
+              for i=1,#after do
+                after[i]=after_class[after[i]] or {}
+              end
+              rule.after=t_hashed(after,t_h_cache)
+            end
+            rule.class=nil
+          end
+          lookup.before_class=nil
+          lookup.current_class=nil
+          lookup.after_class=nil
+          lookup.format="coverage"
+        elseif format=="coverage" then
+          for i=1,#rules do
+            local rule=rules[i]
+            local coverage=rule.coverage
+            if coverage then
+              local before=coverage.before
+              if before then
+                before=t_uncover(splitter,t_u_cache,reversed(before))
+                rule.before=t_hashed(before,t_h_cache)
+              end
+              local current=coverage.current
+              if current then
                 current=t_uncover(splitter,t_u_cache,current)
-                local lookups=rule.lookups
-                if lookups then
-                  for i=1,#current do
-                    if not lookups[i] then
+                local lookups=rule.lookups
+                if lookups then
+                  for i=1,#current do
+                    if not lookups[i] then
                       lookups[i]="" 
-                    end
-                  end
+                    end
+                  end
                 end
-                rule.current=t_hashed(current,t_h_cache)
-              end
-              local after=coverage.after
-              if after then
-                after=t_uncover(splitter,t_u_cache,after)
-                rule.after=t_hashed(after,t_h_cache)
-              end
-              rule.coverage=nil
-            end
-          end
+                rule.current=t_hashed(current,t_h_cache)
+              end
+              local after=coverage.after
+              if after then
+                after=t_uncover(splitter,t_u_cache,after)
+                rule.after=t_hashed(after,t_h_cache)
+              end
+              rule.coverage=nil
+            end
+          end
         elseif format=="reversecoverage" then 
-          for i=1,#rules do
-            local rule=rules[i]
-            local reversecoverage=rule.reversecoverage
-            if reversecoverage then
-              local before=reversecoverage.before
-              if before then
-                before=t_uncover(splitter,t_u_cache,reversed(before))
-                rule.before=t_hashed(before,t_h_cache)
-              end
-              local current=reversecoverage.current
-              if current then
-                current=t_uncover(splitter,t_u_cache,current)
-                rule.current=t_hashed(current,t_h_cache)
-              end
-              local after=reversecoverage.after
-              if after then
-                after=t_uncover(splitter,t_u_cache,after)
-                rule.after=t_hashed(after,t_h_cache)
-              end
-              local replacements=reversecoverage.replacements
-              if replacements then
-                rule.replacements=r_uncover(splitter,r_u_cache,current,replacements)
-              end
-              rule.reversecoverage=nil
-            end
-          end
+          for i=1,#rules do
+            local rule=rules[i]
+            local reversecoverage=rule.reversecoverage
+            if reversecoverage then
+              local before=reversecoverage.before
+              if before then
+                before=t_uncover(splitter,t_u_cache,reversed(before))
+                rule.before=t_hashed(before,t_h_cache)
+              end
+              local current=reversecoverage.current
+              if current then
+                current=t_uncover(splitter,t_u_cache,current)
+                rule.current=t_hashed(current,t_h_cache)
+              end
+              local after=reversecoverage.after
+              if after then
+                after=t_uncover(splitter,t_u_cache,after)
+                rule.after=t_hashed(after,t_h_cache)
+              end
+              local replacements=reversecoverage.replacements
+              if replacements then
+                rule.replacements=r_uncover(splitter,r_u_cache,current,replacements)
+              end
+              rule.reversecoverage=nil
+            end
+          end
         elseif format=="glyphs" then
-          for i=1,#rules do
-            local rule=rules[i]
-            local glyphs=rule.glyphs
-            if glyphs then
-              local fore=glyphs.fore
-              if fore and fore~="" then
-                fore=s_uncover(splitter,s_u_cache,fore)
-                rule.before=s_hashed(fore,s_h_cache)
-              end
-              local back=glyphs.back
-              if back then
-                back=s_uncover(splitter,s_u_cache,back)
-                rule.after=s_hashed(back,s_h_cache)
-              end
-              local names=glyphs.names
-              if names then
-                names=s_uncover(splitter,s_u_cache,names)
-                rule.current=s_hashed(names,s_h_cache)
-              end
-              rule.glyphs=nil
-            end
-          end
-        end
-      end
-    end
-  end
-end
-local function check_variants(unicode,the_variants,splitter,unicodes)
-  local variants=the_variants.variants
+          for i=1,#rules do
+            local rule=rules[i]
+            local glyphs=rule.glyphs
+            if glyphs then
+              local fore=glyphs.fore
+              if fore and fore~="" then
+                fore=s_uncover(splitter,s_u_cache,fore)
+                rule.before=s_hashed(fore,s_h_cache)
+              end
+              local back=glyphs.back
+              if back then
+                back=s_uncover(splitter,s_u_cache,back)
+                rule.after=s_hashed(back,s_h_cache)
+              end
+              local names=glyphs.names
+              if names then
+                names=s_uncover(splitter,s_u_cache,names)
+                rule.current=s_hashed(names,s_h_cache)
+              end
+              rule.glyphs=nil
+            end
+          end
+        end
+      end
+    end
+  end
+end
+local function check_variants(unicode,the_variants,splitter,unicodes)
+  local variants=the_variants.variants
   if variants then 
-    local glyphs=lpegmatch(splitter,variants)
-    local done={ [unicode]=true }
-    local n=0
-    for i=1,#glyphs do
-      local g=glyphs[i]
-      if done[g] then
-        report_otf("skipping cyclic reference %U in math variant %U",g,unicode)
-      else
-        if n==0 then
-          n=1
-          variants={ g }
-        else
-          n=n+1
-          variants[n]=g
-        end
-        done[g]=true
-      end
-    end
-    if n==0 then
-      variants=nil
-    end
-  end
-  local parts=the_variants.parts
-  if parts then
-    local p=#parts
-    if p>0 then
-      for i=1,p do
-        local pi=parts[i]
-        pi.glyph=unicodes[pi.component] or 0
-        pi.component=nil
-      end
-    else
-      parts=nil
-    end
-  end
-  local italic_correction=the_variants.italic_correction
-  if italic_correction and italic_correction==0 then
-    italic_correction=nil
-  end
-  return variants,parts,italic_correction
-end
-actions["analyze math"]=function(data,filename,raw)
-  if raw.math then
-    data.metadata.math=raw.math
-    local unicodes=data.resources.unicodes
-    local splitter=data.helpers.tounicodetable
-    for unicode,description in next,data.descriptions do
-      local glyph=description.glyph
+    local glyphs=lpegmatch(splitter,variants)
+    local done={ [unicode]=true }
+    local n=0
+    for i=1,#glyphs do
+      local g=glyphs[i]
+      if done[g] then
+        report_otf("skipping cyclic reference %U in math variant %U",g,unicode)
+      else
+        if n==0 then
+          n=1
+          variants={ g }
+        else
+          n=n+1
+          variants[n]=g
+        end
+        done[g]=true
+      end
+    end
+    if n==0 then
+      variants=nil
+    end
+  end
+  local parts=the_variants.parts
+  if parts then
+    local p=#parts
+    if p>0 then
+      for i=1,p do
+        local pi=parts[i]
+        pi.glyph=unicodes[pi.component] or 0
+        pi.component=nil
+      end
+    else
+      parts=nil
+    end
+  end
+  local italic_correction=the_variants.italic_correction
+  if italic_correction and italic_correction==0 then
+    italic_correction=nil
+  end
+  return variants,parts,italic_correction
+end
+actions["analyze math"]=function(data,filename,raw)
+  if raw.math then
+    data.metadata.math=raw.math
+    local unicodes=data.resources.unicodes
+    local splitter=data.helpers.tounicodetable
+    for unicode,description in next,data.descriptions do
+      local glyph=description.glyph
       local mathkerns=glyph.mathkern 
-      local horiz_variants=glyph.horiz_variants
-      local vert_variants=glyph.vert_variants
-      local top_accent=glyph.top_accent
-      if mathkerns or horiz_variants or vert_variants or top_accent then
-        local math={}
-        if top_accent then
-          math.top_accent=top_accent
-        end
-        if mathkerns then
-          for k,v in next,mathkerns do
-            if not next(v) then
-              mathkerns[k]=nil
-            else
-              for k,v in next,v do
-                if v==0 then
+      local horiz_variants=glyph.horiz_variants
+      local vert_variants=glyph.vert_variants
+      local top_accent=glyph.top_accent
+      if mathkerns or horiz_variants or vert_variants or top_accent then
+        local math={}
+        if top_accent then
+          math.top_accent=top_accent
+        end
+        if mathkerns then
+          for k,v in next,mathkerns do
+            if not next(v) then
+              mathkerns[k]=nil
+            else
+              for k,v in next,v do
+                if v==0 then
                   k[v]=nil 
-                end
-              end
-            end
-          end
-          math.kerns=mathkerns
-        end
-        if horiz_variants then
-          math.horiz_variants,math.horiz_parts,math.horiz_italic_correction=check_variants(unicode,horiz_variants,splitter,unicodes)
-        end
-        if vert_variants then
-          math.vert_variants,math.vert_parts,math.vert_italic_correction=check_variants(unicode,vert_variants,splitter,unicodes)
-        end
-        local italic_correction=description.italic
-        if italic_correction and italic_correction~=0 then
-          math.italic_correction=italic_correction
-        end
-        description.math=math
-      end
-    end
-  end
-end
-actions["reorganize glyph kerns"]=function(data,filename,raw)
-  local descriptions=data.descriptions
-  local resources=data.resources
-  local unicodes=resources.unicodes
-  for unicode,description in next,descriptions do
-    local kerns=description.glyph.kerns
-    if kerns then
-      local newkerns={}
-      for k,kern in next,kerns do
-        local name=kern.char
-        local offset=kern.off
-        local lookup=kern.lookup
-        if name and offset and lookup then
-          local unicode=unicodes[name]
-          if unicode then
-            if type(lookup)=="table" then
-              for l=1,#lookup do
-                local lookup=lookup[l]
-                local lookupkerns=newkerns[lookup]
-                if lookupkerns then
-                  lookupkerns[unicode]=offset
-                else
-                  newkerns[lookup]={ [unicode]=offset }
-                end
-              end
-            else
-              local lookupkerns=newkerns[lookup]
-              if lookupkerns then
-                lookupkerns[unicode]=offset
-              else
-                newkerns[lookup]={ [unicode]=offset }
-              end
-            end
-          elseif trace_loading then
-            report_otf("problems with unicode %a of kern %a of glyph %U",name,k,unicode)
-          end
-        end
-      end
-      description.kerns=newkerns
-    end
-  end
-end
-actions["merge kern classes"]=function(data,filename,raw)
-  local gposlist=raw.gpos
-  if gposlist then
-    local descriptions=data.descriptions
-    local resources=data.resources
-    local unicodes=resources.unicodes
-    local splitter=data.helpers.tounicodetable
-    for gp=1,#gposlist do
-      local gpos=gposlist[gp]
-      local subtables=gpos.subtables
-      if subtables then
-        for s=1,#subtables do
-          local subtable=subtables[s]
+                end
+              end
+            end
+          end
+          math.kerns=mathkerns
+        end
+        if horiz_variants then
+          math.horiz_variants,math.horiz_parts,math.horiz_italic_correction=check_variants(unicode,horiz_variants,splitter,unicodes)
+        end
+        if vert_variants then
+          math.vert_variants,math.vert_parts,math.vert_italic_correction=check_variants(unicode,vert_variants,splitter,unicodes)
+        end
+        local italic_correction=description.italic
+        if italic_correction and italic_correction~=0 then
+          math.italic_correction=italic_correction
+        end
+        description.math=math
+      end
+    end
+  end
+end
+actions["reorganize glyph kerns"]=function(data,filename,raw)
+  local descriptions=data.descriptions
+  local resources=data.resources
+  local unicodes=resources.unicodes
+  for unicode,description in next,descriptions do
+    local kerns=description.glyph.kerns
+    if kerns then
+      local newkerns={}
+      for k,kern in next,kerns do
+        local name=kern.char
+        local offset=kern.off
+        local lookup=kern.lookup
+        if name and offset and lookup then
+          local unicode=unicodes[name]
+          if unicode then
+            if type(lookup)=="table" then
+              for l=1,#lookup do
+                local lookup=lookup[l]
+                local lookupkerns=newkerns[lookup]
+                if lookupkerns then
+                  lookupkerns[unicode]=offset
+                else
+                  newkerns[lookup]={ [unicode]=offset }
+                end
+              end
+            else
+              local lookupkerns=newkerns[lookup]
+              if lookupkerns then
+                lookupkerns[unicode]=offset
+              else
+                newkerns[lookup]={ [unicode]=offset }
+              end
+            end
+          elseif trace_loading then
+            report_otf("problems with unicode %a of kern %a of glyph %U",name,k,unicode)
+          end
+        end
+      end
+      description.kerns=newkerns
+    end
+  end
+end
+actions["merge kern classes"]=function(data,filename,raw)
+  local gposlist=raw.gpos
+  if gposlist then
+    local descriptions=data.descriptions
+    local resources=data.resources
+    local unicodes=resources.unicodes
+    local splitter=data.helpers.tounicodetable
+    for gp=1,#gposlist do
+      local gpos=gposlist[gp]
+      local subtables=gpos.subtables
+      if subtables then
+        for s=1,#subtables do
+          local subtable=subtables[s]
           local kernclass=subtable.kernclass 
           if kernclass then 
             local split={} 
-            for k=1,#kernclass do
-              local kcl=kernclass[k]
-              local firsts=kcl.firsts
-              local seconds=kcl.seconds
-              local offsets=kcl.offsets
+            for k=1,#kernclass do
+              local kcl=kernclass[k]
+              local firsts=kcl.firsts
+              local seconds=kcl.seconds
+              local offsets=kcl.offsets
               local lookups=kcl.lookup 
-              if type(lookups)~="table" then
-                lookups={ lookups }
+              if type(lookups)~="table" then
+                lookups={ lookups }
               end
-              for n,s in next,firsts do
-                split[s]=split[s] or lpegmatch(splitter,s)
-              end
-              local maxseconds=0
-              for n,s in next,seconds do
-                if n>maxseconds then
-                  maxseconds=n
-                end
-                split[s]=split[s] or lpegmatch(splitter,s)
-              end
-              for l=1,#lookups do
-                local lookup=lookups[l]
+              for n,s in next,firsts do
+                split[s]=split[s] or lpegmatch(splitter,s)
+              end
+              local maxseconds=0
+              for n,s in next,seconds do
+                if n>maxseconds then
+                  maxseconds=n
+                end
+                split[s]=split[s] or lpegmatch(splitter,s)
+              end
+              for l=1,#lookups do
+                local lookup=lookups[l]
                 for fk=1,#firsts do 
-                  local fv=firsts[fk]
-                  local splt=split[fv]
-                  if splt then
-                    local extrakerns={}
-                    local baseoffset=(fk-1)*maxseconds
+                  local fv=firsts[fk]
+                  local splt=split[fv]
+                  if splt then
+                    local extrakerns={}
+                    local baseoffset=(fk-1)*maxseconds
                     for sk=2,maxseconds do 
                       local sv=seconds[sk]
-                      local splt=split[sv]
+                      local splt=split[sv]
                       if splt then 
-                        local offset=offsets[baseoffset+sk]
-                        if offset then
-                          for i=1,#splt do
-                            extrakerns[splt[i]]=offset
-                          end
-                        end
-                      end
-                    end
-                    for i=1,#splt do
-                      local first_unicode=splt[i]
-                      local description=descriptions[first_unicode]
-                      if description then
-                        local kerns=description.kerns
-                        if not kerns then
+                        local offset=offsets[baseoffset+sk]
+                        if offset then
+                          for i=1,#splt do
+                            extrakerns[splt[i]]=offset
+                          end
+                        end
+                      end
+                    end
+                    for i=1,#splt do
+                      local first_unicode=splt[i]
+                      local description=descriptions[first_unicode]
+                      if description then
+                        local kerns=description.kerns
+                        if not kerns then
                           kerns={} 
-                          description.kerns=kerns
-                        end
-                        local lookupkerns=kerns[lookup]
-                        if not lookupkerns then
-                          lookupkerns={}
-                          kerns[lookup]=lookupkerns
-                        end
-                        for second_unicode,kern in next,extrakerns do
-                          lookupkerns[second_unicode]=kern
-                        end
-                      elseif trace_loading then
-                        report_otf("no glyph data for %U",first_unicode)
-                      end
-                    end
-                  end
-                end
-              end
-            end
-            subtable.kernclass={}
-          end
-        end
-      end
-    end
-  end
-end
-actions["check glyphs"]=function(data,filename,raw)
-  for unicode,description in next,data.descriptions do
-    description.glyph=nil
-  end
-end
-actions["check metadata"]=function(data,filename,raw)
-  local metadata=data.metadata
-  for _,k in next,mainfields do
-    if valid_fields[k] then
-      local v=raw[k]
-      if not metadata[k] then
-        metadata[k]=v
-      end
-    end
-  end
-  local ttftables=metadata.ttf_tables
-  if ttftables then
-    for i=1,#ttftables do
-      ttftables[i].data="deleted"
-    end
-  end
-end
-actions["cleanup tables"]=function(data,filename,raw)
+                          description.kerns=kerns
+                        end
+                        local lookupkerns=kerns[lookup]
+                        if not lookupkerns then
+                          lookupkerns={}
+                          kerns[lookup]=lookupkerns
+                        end
+                        for second_unicode,kern in next,extrakerns do
+                          lookupkerns[second_unicode]=kern
+                        end
+                      elseif trace_loading then
+                        report_otf("no glyph data for %U",first_unicode)
+                      end
+                    end
+                  end
+                end
+              end
+            end
+            subtable.kernclass={}
+          end
+        end
+      end
+    end
+  end
+end
+actions["check glyphs"]=function(data,filename,raw)
+  for unicode,description in next,data.descriptions do
+    description.glyph=nil
+  end
+end
+actions["check metadata"]=function(data,filename,raw)
+  local metadata=data.metadata
+  for _,k in next,mainfields do
+    if valid_fields[k] then
+      local v=raw[k]
+      if not metadata[k] then
+        metadata[k]=v
+      end
+    end
+  end
+  local ttftables=metadata.ttf_tables
+  if ttftables then
+    for i=1,#ttftables do
+      ttftables[i].data="deleted"
+    end
+  end
+end
+actions["cleanup tables"]=function(data,filename,raw)
   data.resources.indices=nil 
-  data.helpers=nil
+  data.helpers=nil
 end
-actions["reorganize glyph lookups"]=function(data,filename,raw)
-  local resources=data.resources
-  local unicodes=resources.unicodes
-  local descriptions=data.descriptions
+actions["reorganize glyph lookups"]=function(data,filename,raw)
+  local resources=data.resources
+  local unicodes=resources.unicodes
+  local descriptions=data.descriptions
   local splitter=data.helpers.tounicodelist
   local lookuptypes=resources.lookuptypes
-  for unicode,description in next,descriptions do
-    local lookups=description.glyph.lookups
-    if lookups then
-      for tag,lookuplist in next,lookups do
-        for l=1,#lookuplist do
-          local lookup=lookuplist[l]
-          local specification=lookup.specification
-          local lookuptype=lookup.type
-          local lt=lookuptypes[tag]
-          if not lt then
-            lookuptypes[tag]=lookuptype
-          elseif lt~=lookuptype then
-            report_otf("conflicting lookuptypes, %a points to %a and %a",tag,lt,lookuptype)
-          end
-          if lookuptype=="ligature" then
-            lookuplist[l]={ lpegmatch(splitter,specification.components) }
-          elseif lookuptype=="alternate" then
-            lookuplist[l]={ lpegmatch(splitter,specification.components) }
-          elseif lookuptype=="substitution" then
-            lookuplist[l]=unicodes[specification.variant]
-          elseif lookuptype=="multiple" then
-            lookuplist[l]={ lpegmatch(splitter,specification.components) }
-          elseif lookuptype=="position" then
-            lookuplist[l]={
-              specification.x or 0,
-              specification.y or 0,
-              specification.h or 0,
-              specification.v or 0
-            }
-          elseif lookuptype=="pair" then
-            local one=specification.offsets[1]
-            local two=specification.offsets[2]
-            local paired=unicodes[specification.paired]
-            if one then
-              if two then
-                lookuplist[l]={ paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 },{ two.x or 0,two.y or 0,two.h or 0,two.v or 0 } }
-              else
-                lookuplist[l]={ paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 } }
-              end
-            else
-              if two then
+  for unicode,description in next,descriptions do
+    local lookups=description.glyph.lookups
+    if lookups then
+      for tag,lookuplist in next,lookups do
+        for l=1,#lookuplist do
+          local lookup=lookuplist[l]
+          local specification=lookup.specification
+          local lookuptype=lookup.type
+          local lt=lookuptypes[tag]
+          if not lt then
+            lookuptypes[tag]=lookuptype
+          elseif lt~=lookuptype then
+            report_otf("conflicting lookuptypes, %a points to %a and %a",tag,lt,lookuptype)
+          end
+          if lookuptype=="ligature" then
+            lookuplist[l]={ lpegmatch(splitter,specification.components) }
+          elseif lookuptype=="alternate" then
+            lookuplist[l]={ lpegmatch(splitter,specification.components) }
+          elseif lookuptype=="substitution" then
+            lookuplist[l]=unicodes[specification.variant]
+          elseif lookuptype=="multiple" then
+            lookuplist[l]={ lpegmatch(splitter,specification.components) }
+          elseif lookuptype=="position" then
+            lookuplist[l]={
+              specification.x or 0,
+              specification.y or 0,
+              specification.h or 0,
+              specification.v or 0
+            }
+          elseif lookuptype=="pair" then
+            local one=specification.offsets[1]
+            local two=specification.offsets[2]
+            local paired=unicodes[specification.paired]
+            if one then
+              if two then
+                lookuplist[l]={ paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 },{ two.x or 0,two.y or 0,two.h or 0,two.v or 0 } }
+              else
+                lookuplist[l]={ paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 } }
+              end
+            else
+              if two then
                 lookuplist[l]={ paired,{},{ two.x or 0,two.y or 0,two.h or 0,two.v or 0} } 
-              else
-                lookuplist[l]={ paired }
-              end
-            end
-          end
-        end
-      end
-      local slookups,mlookups
-      for tag,lookuplist in next,lookups do
-        if #lookuplist==1 then
-          if slookups then
-            slookups[tag]=lookuplist[1]
-          else
-            slookups={ [tag]=lookuplist[1] }
-          end
-        else
-          if mlookups then
-            mlookups[tag]=lookuplist
-          else
-            mlookups={ [tag]=lookuplist }
-          end
-        end
-      end
-      if slookups then
-        description.slookups=slookups
-      end
-      if mlookups then
-        description.mlookups=mlookups
-      end
-    end
+              else
+                lookuplist[l]={ paired }
+              end
+            end
+          end
+        end
+      end
+      local slookups,mlookups
+      for tag,lookuplist in next,lookups do
+        if #lookuplist==1 then
+          if slookups then
+            slookups[tag]=lookuplist[1]
+          else
+            slookups={ [tag]=lookuplist[1] }
+          end
+        else
+          if mlookups then
+            mlookups[tag]=lookuplist
+          else
+            mlookups={ [tag]=lookuplist }
+          end
+        end
+      end
+      if slookups then
+        description.slookups=slookups
+      end
+      if mlookups then
+        description.mlookups=mlookups
+      end
+    end
   end
 end
 actions["reorganize glyph anchors"]=function(data,filename,raw) 
-  local descriptions=data.descriptions
-  for unicode,description in next,descriptions do
-    local anchors=description.glyph.anchors
-    if anchors then
-      for class,data in next,anchors do
-        if class=="baselig" then
-          for tag,specification in next,data do
-            for i=1,#specification do
-              local si=specification[i]
-              specification[i]={ si.x or 0,si.y or 0 }
-            end
-          end
-        else
-          for tag,specification in next,data do
-            data[tag]={ specification.x or 0,specification.y or 0 }
-          end
-        end
-      end
-      description.anchors=anchors
-    end
-  end
-end
-function otf.setfeatures(tfmdata,features)
-  local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
-  if okay then
-    return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
-  else
+  local descriptions=data.descriptions
+  for unicode,description in next,descriptions do
+    local anchors=description.glyph.anchors
+    if anchors then
+      for class,data in next,anchors do
+        if class=="baselig" then
+          for tag,specification in next,data do
+            for i=1,#specification do
+              local si=specification[i]
+              specification[i]={ si.x or 0,si.y or 0 }
+            end
+          end
+        else
+          for tag,specification in next,data do
+            data[tag]={ specification.x or 0,specification.y or 0 }
+          end
+        end
+      end
+      description.anchors=anchors
+    end
+  end
+end
+function otf.setfeatures(tfmdata,features)
+  local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
+  if okay then
+    return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
+  else
     return {} 
-  end
-end
-local function copytotfm(data,cache_id)
-  if data then
-    local metadata=data.metadata
-    local resources=data.resources
-    local properties=derivetable(data.properties)
-    local descriptions=derivetable(data.descriptions)
-    local goodies=derivetable(data.goodies)
-    local characters={}
-    local parameters={}
+  end
+end
+local function copytotfm(data,cache_id)
+  if data then
+    local metadata=data.metadata
+    local resources=data.resources
+    local properties=derivetable(data.properties)
+    local descriptions=derivetable(data.descriptions)
+    local goodies=derivetable(data.goodies)
+    local characters={}
+    local parameters={}
     local mathparameters={}
-    local pfminfo=metadata.pfminfo or {}
-    local resources=data.resources
+    local pfminfo=metadata.pfminfo or {}
+    local resources=data.resources
     local unicodes=resources.unicodes
-    local spaceunits=500
-    local spacer="space"
-    local designsize=metadata.designsize or metadata.design_size or 100
+    local spaceunits=500
+    local spacer="space"
+    local designsize=metadata.designsize or metadata.design_size or 100
     local mathspecs=metadata.math
-    if designsize==0 then
-      designsize=100
-    end
-    if mathspecs then
-      for name,value in next,mathspecs do
-        mathparameters[name]=value
-      end
-    end
+    if designsize==0 then
+      designsize=100
+    end
+    if mathspecs then
+      for name,value in next,mathspecs do
+        mathparameters[name]=value
+      end
+    end
     for unicode,_ in next,data.descriptions do 
-      characters[unicode]={}
-    end
+      characters[unicode]={}
+    end
     if mathspecs then
-      for unicode,character in next,characters do
-        local d=descriptions[unicode]
-        local m=d.math
+      for unicode,character in next,characters do
+        local d=descriptions[unicode]
+        local m=d.math
         if m then
-          local variants=m.horiz_variants
+          local variants=m.horiz_variants
           local parts=m.horiz_parts
-          if variants then
-            local c=character
-            for i=1,#variants do
+          if variants then
+            local c=character
+            for i=1,#variants do
               local un=variants[i]
-                c.next=un
+                c.next=un
                 c=characters[un]
             end 
-            c.horiz_variants=parts
-          elseif parts then
-            character.horiz_variants=parts
-          end
-          local variants=m.vert_variants
+            c.horiz_variants=parts
+          elseif parts then
+            character.horiz_variants=parts
+          end
+          local variants=m.vert_variants
           local parts=m.vert_parts
-          if variants then
-            local c=character
-            for i=1,#variants do
+          if variants then
+            local c=character
+            for i=1,#variants do
               local un=variants[i]
-                c.next=un
+                c.next=un
                 c=characters[un]
             end 
-            c.vert_variants=parts
-          elseif parts then
-            character.vert_variants=parts
-          end
-          local italic_correction=m.vert_italic_correction
-          if italic_correction then
+            c.vert_variants=parts
+          elseif parts then
+            character.vert_variants=parts
+          end
+          local italic_correction=m.vert_italic_correction
+          if italic_correction then
             character.vert_italic_correction=italic_correction 
-          end
-          local top_accent=m.top_accent
-          if top_accent then
-            character.top_accent=top_accent
-          end
-          local kerns=m.kerns
-          if kerns then
-            character.mathkerns=kerns
-          end
-        end
-      end
-    end
-    local monospaced=metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
+          end
+          local top_accent=m.top_accent
+          if top_accent then
+            character.top_accent=top_accent
+          end
+          local kerns=m.kerns
+          if kerns then
+            character.mathkerns=kerns
+          end
+        end
+      end
+    end
+    local monospaced=metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion=="Monospaced")
     local charwidth=pfminfo.avgwidth 
-    local italicangle=metadata.italicangle
-    local charxheight=pfminfo.os2_xheight and pfminfo.os2_xheight>0 and pfminfo.os2_xheight
-    properties.monospaced=monospaced
-    parameters.italicangle=italicangle
-    parameters.charwidth=charwidth
+    local italicangle=metadata.italicangle
+    local charxheight=pfminfo.os2_xheight and pfminfo.os2_xheight>0 and pfminfo.os2_xheight
+    properties.monospaced=monospaced
+    parameters.italicangle=italicangle
+    parameters.charwidth=charwidth
     parameters.charxheight=charxheight
     local space=0x0020 
     local emdash=0x2014 
-    if monospaced then
-      if descriptions[space] then
-        spaceunits,spacer=descriptions[space].width,"space"
-      end
-      if not spaceunits and descriptions[emdash] then
-        spaceunits,spacer=descriptions[emdash].width,"emdash"
-      end
-      if not spaceunits and charwidth then
-        spaceunits,spacer=charwidth,"charwidth"
-      end
-    else
-      if descriptions[space] then
-        spaceunits,spacer=descriptions[space].width,"space"
-      end
-      if not spaceunits and descriptions[emdash] then
-        spaceunits,spacer=descriptions[emdash].width/2,"emdash/2"
-      end
-      if not spaceunits and charwidth then
-        spaceunits,spacer=charwidth,"charwidth"
-      end
-    end
+    if monospaced then
+      if descriptions[space] then
+        spaceunits,spacer=descriptions[space].width,"space"
+      end
+      if not spaceunits and descriptions[emdash] then
+        spaceunits,spacer=descriptions[emdash].width,"emdash"
+      end
+      if not spaceunits and charwidth then
+        spaceunits,spacer=charwidth,"charwidth"
+      end
+    else
+      if descriptions[space] then
+        spaceunits,spacer=descriptions[space].width,"space"
+      end
+      if not spaceunits and descriptions[emdash] then
+        spaceunits,spacer=descriptions[emdash].width/2,"emdash/2"
+      end
+      if not spaceunits and charwidth then
+        spaceunits,spacer=charwidth,"charwidth"
+      end
+    end
     spaceunits=tonumber(spaceunits) or 500
-    local filename=constructors.checkedfilename(resources)
-    local fontname=metadata.fontname
-    local fullname=metadata.fullname or fontname
+    local filename=constructors.checkedfilename(resources)
+    local fontname=metadata.fontname
+    local fullname=metadata.fullname or fontname
     local units=metadata.units_per_em or 1000
     if units==0 then 
-      units=1000
-      metadata.units_per_em=1000
+      units=1000
+      metadata.units_per_em=1000
     end
-    parameters.slant=0
+    parameters.slant=0
     parameters.space=spaceunits     
     parameters.space_stretch=units/2  
     parameters.space_shrink=1*units/3 
     parameters.x_height=2*units/5 
     parameters.quad=units   
     if spaceunits<2*units/5 then
-    end
-    if italicangle then
-      parameters.italicangle=italicangle
-      parameters.italicfactor=math.cos(math.rad(90+italicangle))
-      parameters.slant=- math.round(math.tan(italicangle*math.pi/180))
-    end
-    if monospaced then
-      parameters.space_stretch=0
-      parameters.space_shrink=0
+    end
+    if italicangle then
+      parameters.italicangle=italicangle
+      parameters.italicfactor=math.cos(math.rad(90+italicangle))
+      parameters.slant=- math.round(math.tan(italicangle*math.pi/180))
+    end
+    if monospaced then
+      parameters.space_stretch=0
+      parameters.space_shrink=0
     elseif syncspace then 
-      parameters.space_stretch=spaceunits/2
-      parameters.space_shrink=spaceunits/3
-    end
+      parameters.space_stretch=spaceunits/2
+      parameters.space_shrink=spaceunits/3
+    end
     parameters.extra_space=parameters.space_shrink 
-    if charxheight then
-      parameters.x_height=charxheight
-    else
+    if charxheight then
+      parameters.x_height=charxheight
+    else
       local x=0x78 
-      if x then
-        local x=descriptions[x]
-        if x then
-          parameters.x_height=x.height
-        end
-      end
-    end
-    parameters.designsize=(designsize/10)*65536
-    parameters.ascender=abs(metadata.ascent or 0)
-    parameters.descender=abs(metadata.descent or 0)
+      if x then
+        local x=descriptions[x]
+        if x then
+          parameters.x_height=x.height
+        end
+      end
+    end
+    parameters.designsize=(designsize/10)*65536
+    parameters.ascender=abs(metadata.ascent or 0)
+    parameters.descender=abs(metadata.descent or 0)
     parameters.units=units
-    properties.space=spacer
-    properties.encodingbytes=2
-    properties.format=data.format or fonts.formats[filename] or "opentype"
-    properties.noglyphnames=true
-    properties.filename=filename
-    properties.fontname=fontname
-    properties.fullname=fullname
-    properties.psname=fontname or fullname
+    properties.space=spacer
+    properties.encodingbytes=2
+    properties.format=data.format or fonts.formats[filename] or "opentype"
+    properties.noglyphnames=true
+    properties.filename=filename
+    properties.fontname=fontname
+    properties.fullname=fullname
+    properties.psname=fontname or fullname
     properties.name=filename or fullname
-    return {
-      characters=characters,
-      descriptions=descriptions,
-      parameters=parameters,
-      mathparameters=mathparameters,
-      resources=resources,
-      properties=properties,
-      goodies=goodies,
-    }
-  end
-end
-local function otftotfm(specification)
-  local cache_id=specification.hash
-  local tfmdata=containers.read(constructors.cache,cache_id)
-  if not tfmdata then
-    local name=specification.name
-    local sub=specification.sub
-    local filename=specification.filename
-    local format=specification.format
-    local features=specification.features.normal
-    local rawdata=otf.load(filename,format,sub,features and features.featurefile)
-    if rawdata and next(rawdata) then
-      rawdata.lookuphash={}
-      tfmdata=copytotfm(rawdata,cache_id)
+    return {
+      characters=characters,
+      descriptions=descriptions,
+      parameters=parameters,
+      mathparameters=mathparameters,
+      resources=resources,
+      properties=properties,
+      goodies=goodies,
+    }
+  end
+end
+local function otftotfm(specification)
+  local cache_id=specification.hash
+  local tfmdata=containers.read(constructors.cache,cache_id)
+  if not tfmdata then
+    local name=specification.name
+    local sub=specification.sub
+    local filename=specification.filename
+    local format=specification.format
+    local features=specification.features.normal
+    local rawdata=otf.load(filename,format,sub,features and features.featurefile)
+    if rawdata and next(rawdata) then
+      rawdata.lookuphash={}
+      tfmdata=copytotfm(rawdata,cache_id)
       if tfmdata and next(tfmdata) then
-        local features=constructors.checkedfeatures("otf",features)
-        local shared=tfmdata.shared
-        if not shared then
-          shared={}
-          tfmdata.shared=shared
-        end
+        local features=constructors.checkedfeatures("otf",features)
+        local shared=tfmdata.shared
+        if not shared then
+          shared={}
+          tfmdata.shared=shared
+        end
         shared.rawdata=rawdata
         shared.dynamics={}
-        tfmdata.changed={}
-        shared.features=features
-        shared.processes=otf.setfeatures(tfmdata,features)
-      end
-    end
-    containers.write(constructors.cache,cache_id,tfmdata)
-  end
-  return tfmdata
-end
-local function read_from_otf(specification)
-  local tfmdata=otftotfm(specification)
+        tfmdata.changed={}
+        shared.features=features
+        shared.processes=otf.setfeatures(tfmdata,features)
+      end
+    end
+    containers.write(constructors.cache,cache_id,tfmdata)
+  end
+  return tfmdata
+end
+local function read_from_otf(specification)
+  local tfmdata=otftotfm(specification)
   if tfmdata then
-    tfmdata.properties.name=specification.name
+    tfmdata.properties.name=specification.name
     tfmdata.properties.sub=specification.sub
-    tfmdata=constructors.scale(tfmdata,specification)
-    local allfeatures=tfmdata.shared.features or specification.features.normal
-    constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
+    tfmdata=constructors.scale(tfmdata,specification)
+    local allfeatures=tfmdata.shared.features or specification.features.normal
+    constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
     constructors.setname(tfmdata,specification) 
-    fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
-  end
-  return tfmdata
+    fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
+  end
+  return tfmdata
 end
-local function checkmathsize(tfmdata,mathsize)
-  local mathdata=tfmdata.shared.rawdata.metadata.math
-  local mathsize=tonumber(mathsize)
+local function checkmathsize(tfmdata,mathsize)
+  local mathdata=tfmdata.shared.rawdata.metadata.math
+  local mathsize=tonumber(mathsize)
   if mathdata then 
-    local parameters=tfmdata.parameters
-    parameters.scriptpercentage=mathdata.ScriptPercentScaleDown
-    parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown
-    parameters.mathsize=mathsize
-  end
-end
-registerotffeature {
-  name="mathsize",
-  description="apply mathsize specified in the font",
-  initializers={
-    base=checkmathsize,
-    node=checkmathsize,
-  }
+    local parameters=tfmdata.parameters
+    parameters.scriptpercentage=mathdata.ScriptPercentScaleDown
+    parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown
+    parameters.mathsize=mathsize
+  end
+end
+registerotffeature {
+  name="mathsize",
+  description="apply mathsize specified in the font",
+  initializers={
+    base=checkmathsize,
+    node=checkmathsize,
+  }
 }
-function otf.collectlookups(rawdata,kind,script,language)
-  local sequences=rawdata.resources.sequences
-  if sequences then
-    local featuremap,featurelist={},{}
-    for s=1,#sequences do
-      local sequence=sequences[s]
-      local features=sequence.features
-      features=features and features[kind]
-      features=features and (features[script]  or features[default] or features[wildcard])
-      features=features and (features[language] or features[default] or features[wildcard])
-      if features then
-        local subtables=sequence.subtables
-        if subtables then
-          for s=1,#subtables do
-            local ss=subtables[s]
-            if not featuremap[s] then
-              featuremap[ss]=true
-              featurelist[#featurelist+1]=ss
-            end
-          end
-        end
-      end
-    end
-    if #featurelist>0 then
-      return featuremap,featurelist
-    end
-  end
-  return nil,nil
-end
-local function check_otf(forced,specification,suffix,what)
-  local name=specification.name
-  if forced then
-    name=file.addsuffix(name,suffix,true)
-  end
-  local fullname=findbinfile(name,suffix) or ""
-  if fullname=="" then
-    fullname=fonts.names.getfilename(name,suffix) or ""
-  end
-  if fullname~="" then
-    specification.filename=fullname
-    specification.format=what
-    return read_from_otf(specification)
-  end
-end
-local function opentypereader(specification,suffix,what)
-  local forced=specification.forced or ""
-  if forced=="otf" then
-    return check_otf(true,specification,forced,"opentype")
-  elseif forced=="ttf" or forced=="ttc" or forced=="dfont" then
-    return check_otf(true,specification,forced,"truetype")
-  else
-    return check_otf(false,specification,suffix,what)
-  end
+function otf.collectlookups(rawdata,kind,script,language)
+  local sequences=rawdata.resources.sequences
+  if sequences then
+    local featuremap,featurelist={},{}
+    for s=1,#sequences do
+      local sequence=sequences[s]
+      local features=sequence.features
+      features=features and features[kind]
+      features=features and (features[script]  or features[default] or features[wildcard])
+      features=features and (features[language] or features[default] or features[wildcard])
+      if features then
+        local subtables=sequence.subtables
+        if subtables then
+          for s=1,#subtables do
+            local ss=subtables[s]
+            if not featuremap[s] then
+              featuremap[ss]=true
+              featurelist[#featurelist+1]=ss
+            end
+          end
+        end
+      end
+    end
+    if #featurelist>0 then
+      return featuremap,featurelist
+    end
+  end
+  return nil,nil
+end
+local function check_otf(forced,specification,suffix,what)
+  local name=specification.name
+  if forced then
+    name=file.addsuffix(name,suffix,true)
+  end
+  local fullname=findbinfile(name,suffix) or ""
+  if fullname=="" then
+    fullname=fonts.names.getfilename(name,suffix) or ""
+  end
+  if fullname~="" then
+    specification.filename=fullname
+    specification.format=what
+    return read_from_otf(specification)
+  end
+end
+local function opentypereader(specification,suffix,what)
+  local forced=specification.forced or ""
+  if forced=="otf" then
+    return check_otf(true,specification,forced,"opentype")
+  elseif forced=="ttf" or forced=="ttc" or forced=="dfont" then
+    return check_otf(true,specification,forced,"truetype")
+  else
+    return check_otf(false,specification,suffix,what)
+  end
 end
 readers.opentype=opentypereader
 local formats=fonts.formats
-formats.otf="opentype"
-formats.ttf="truetype"
-formats.ttc="truetype"
+formats.otf="opentype"
+formats.ttf="truetype"
+formats.ttc="truetype"
 formats.dfont="truetype"
-function readers.otf (specification) return opentypereader(specification,"otf",formats.otf ) end
-function readers.ttf (specification) return opentypereader(specification,"ttf",formats.ttf ) end
-function readers.ttc (specification) return opentypereader(specification,"ttf",formats.ttc ) end
+function readers.otf (specification) return opentypereader(specification,"otf",formats.otf ) end
+function readers.ttf (specification) return opentypereader(specification,"ttf",formats.ttf ) end
+function readers.ttc (specification) return opentypereader(specification,"ttf",formats.ttc ) end
 function readers.dfont(specification) return opentypereader(specification,"ttf",formats.dfont) end
-function otf.scriptandlanguage(tfmdata,attr)
-  local properties=tfmdata.properties
-  return properties.script or "dflt",properties.language or "dflt"
-end
+function otf.scriptandlanguage(tfmdata,attr)
+  local properties=tfmdata.properties
+  return properties.script or "dflt",properties.language or "dflt"
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-otb']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
-}
-local concat=table.concat
-local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring=type,next,tonumber,tostring
-local lpegmatch=lpeg.match
+if not modules then modules={} end modules ['font-otb']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
+}
+local concat=table.concat
+local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
+local type,next,tonumber,tostring=type,next,tonumber,tostring
+local lpegmatch=lpeg.match
 local utfchar=utf.char
-local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end)
-local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end)
-local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end)
-local trace_alternatives=false trackers.register("otf.alternatives",function(v) trace_alternatives=v end)
-local trace_ligatures=false trackers.register("otf.ligatures",function(v) trace_ligatures=v end)
-local trace_ligatures_detail=false trackers.register("otf.ligatures.detail",function(v) trace_ligatures_detail=v end)
-local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end)
+local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end)
+local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end)
+local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end)
+local trace_alternatives=false trackers.register("otf.alternatives",function(v) trace_alternatives=v end)
+local trace_ligatures=false trackers.register("otf.ligatures",function(v) trace_ligatures=v end)
+local trace_ligatures_detail=false trackers.register("otf.ligatures.detail",function(v) trace_ligatures_detail=v end)
+local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end)
 local trace_preparing=false trackers.register("otf.preparing",function(v) trace_preparing=v end)
 local report_prepare=logs.reporter("fonts","otf prepare")
-local fonts=fonts
+local fonts=fonts
 local otf=fonts.handlers.otf
-local otffeatures=otf.features
+local otffeatures=otf.features
 local registerotffeature=otffeatures.register
 otf.defaultbasealternate="none" 
-local wildcard="*"
+local wildcard="*"
 local default="dflt"
-local formatters=string.formatters
-local f_unicode=formatters["%U"]
-local f_uniname=formatters["%U (%s)"]
+local formatters=string.formatters
+local f_unicode=formatters["%U"]
+local f_uniname=formatters["%U (%s)"]
 local f_unilist=formatters["% t (% t)"]
-local function gref(descriptions,n)
-  if type(n)=="number" then
-    local name=descriptions[n].name
-    if name then
-      return f_uniname(n,name)
-    else
-      return f_unicode(n)
-    end
-  elseif n then
-    local num,nam={},{}
-    for i=2,#n do
-      local ni=n[i]
+local function gref(descriptions,n)
+  if type(n)=="number" then
+    local name=descriptions[n].name
+    if name then
+      return f_uniname(n,name)
+    else
+      return f_unicode(n)
+    end
+  elseif n then
+    local num,nam={},{}
+    for i=2,#n do
+      local ni=n[i]
       if tonumber(ni) then 
-        local di=descriptions[ni]
-        num[i]=f_unicode(ni)
-        nam[i]=di and di.name or "-"
-      end
-    end
-    return f_unilist(num,nam)
-  else
-    return "<error in base mode tracing>"
-  end
-end
-local function cref(feature,lookupname)
-  if lookupname then
-    return formatters["feature %a, lookup %a"](feature,lookupname)
-  else
-    return formatters["feature %a"](feature)
-  end
-end
-local function report_alternate(feature,lookupname,descriptions,unicode,replacement,value,comment)
-  report_prepare("%s: base alternate %s => %s (%S => %S)",
-    cref(feature,lookupname),
-    gref(descriptions,unicode),
-    replacement and gref(descriptions,replacement),
-    value,
-    comment)
-end
-local function report_substitution(feature,lookupname,descriptions,unicode,substitution)
-  report_prepare("%s: base substitution %s => %S",
-    cref(feature,lookupname),
-    gref(descriptions,unicode),
-    gref(descriptions,substitution))
-end
-local function report_ligature(feature,lookupname,descriptions,unicode,ligature)
-  report_prepare("%s: base ligature %s => %S",
-    cref(feature,lookupname),
-    gref(descriptions,ligature),
-    gref(descriptions,unicode))
-end
-local function report_kern(feature,lookupname,descriptions,unicode,otherunicode,value)
-  report_prepare("%s: base kern %s + %s => %S",
-    cref(feature,lookupname),
-    gref(descriptions,unicode),
-    gref(descriptions,otherunicode),
-    value)
-end
-local basemethods={}
+        local di=descriptions[ni]
+        num[i]=f_unicode(ni)
+        nam[i]=di and di.name or "-"
+      end
+    end
+    return f_unilist(num,nam)
+  else
+    return "<error in base mode tracing>"
+  end
+end
+local function cref(feature,lookupname)
+  if lookupname then
+    return formatters["feature %a, lookup %a"](feature,lookupname)
+  else
+    return formatters["feature %a"](feature)
+  end
+end
+local function report_alternate(feature,lookupname,descriptions,unicode,replacement,value,comment)
+  report_prepare("%s: base alternate %s => %s (%S => %S)",
+    cref(feature,lookupname),
+    gref(descriptions,unicode),
+    replacement and gref(descriptions,replacement),
+    value,
+    comment)
+end
+local function report_substitution(feature,lookupname,descriptions,unicode,substitution)
+  report_prepare("%s: base substitution %s => %S",
+    cref(feature,lookupname),
+    gref(descriptions,unicode),
+    gref(descriptions,substitution))
+end
+local function report_ligature(feature,lookupname,descriptions,unicode,ligature)
+  report_prepare("%s: base ligature %s => %S",
+    cref(feature,lookupname),
+    gref(descriptions,ligature),
+    gref(descriptions,unicode))
+end
+local function report_kern(feature,lookupname,descriptions,unicode,otherunicode,value)
+  report_prepare("%s: base kern %s + %s => %S",
+    cref(feature,lookupname),
+    gref(descriptions,unicode),
+    gref(descriptions,otherunicode),
+    value)
+end
+local basemethods={}
 local basemethod="<unset>"
-local function applybasemethod(what,...)
-  local m=basemethods[basemethod][what]
-  if m then
-    return m(...)
-  end
+local function applybasemethod(what,...)
+  local m=basemethods[basemethod][what]
+  if m then
+    return m(...)
+  end
 end
 local basehash,basehashes,applied={},1,{}
-local function registerbasehash(tfmdata)
-  local properties=tfmdata.properties
-  local hash=concat(applied," ")
-  local base=basehash[hash]
-  if not base then
-    basehashes=basehashes+1
-    base=basehashes
-    basehash[hash]=base
-  end
-  properties.basehash=base
+local function registerbasehash(tfmdata)
+  local properties=tfmdata.properties
+  local hash=concat(applied," ")
+  local base=basehash[hash]
+  if not base then
+    basehashes=basehashes+1
+    base=basehashes
+    basehash[hash]=base
+  end
+  properties.basehash=base
   properties.fullname=properties.fullname.."-"..base
-  applied={}
+  applied={}
 end
-local function registerbasefeature(feature,value)
-  applied[#applied+1]=feature.."="..tostring(value)
+local function registerbasefeature(feature,value)
+  applied[#applied+1]=feature.."="..tostring(value)
 end
 local trace=false
-local function finalize_ligatures(tfmdata,ligatures)
-  local nofligatures=#ligatures
-  if nofligatures>0 then
-    local characters=tfmdata.characters
-    local descriptions=tfmdata.descriptions
-    local resources=tfmdata.resources
-    local unicodes=resources.unicodes
-    local private=resources.private
-    local alldone=false
-    while not alldone do
-      local done=0
-      for i=1,nofligatures do
-        local ligature=ligatures[i]
-        if ligature then
-          local unicode,lookupdata=ligature[1],ligature[2]
-          if trace then
-            trace_ligatures_detail("building % a into %a",lookupdata,unicode)
-          end
-          local size=#lookupdata
+local function finalize_ligatures(tfmdata,ligatures)
+  local nofligatures=#ligatures
+  if nofligatures>0 then
+    local characters=tfmdata.characters
+    local descriptions=tfmdata.descriptions
+    local resources=tfmdata.resources
+    local unicodes=resources.unicodes
+    local private=resources.private
+    local alldone=false
+    while not alldone do
+      local done=0
+      for i=1,nofligatures do
+        local ligature=ligatures[i]
+        if ligature then
+          local unicode,lookupdata=ligature[1],ligature[2]
+          if trace then
+            trace_ligatures_detail("building % a into %a",lookupdata,unicode)
+          end
+          local size=#lookupdata
           local firstcode=lookupdata[1] 
-          local firstdata=characters[firstcode]
-          local okay=false
-          if firstdata then
-            local firstname="ctx_"..firstcode
+          local firstdata=characters[firstcode]
+          local okay=false
+          if firstdata then
+            local firstname="ctx_"..firstcode
             for i=1,size-1 do 
-              local firstdata=characters[firstcode]
-              if not firstdata then
-                firstcode=private
-                if trace then
-                  trace_ligatures_detail("defining %a as %a",firstname,firstcode)
-                end
-                unicodes[firstname]=firstcode
-                firstdata={ intermediate=true,ligatures={} }
-                characters[firstcode]=firstdata
-                descriptions[firstcode]={ name=firstname }
-                private=private+1
-              end
-              local target
-              local secondcode=lookupdata[i+1]
-              local secondname=firstname.."_"..secondcode
-              if i==size-1 then
-                target=unicode
-                if not unicodes[secondname] then
+              local firstdata=characters[firstcode]
+              if not firstdata then
+                firstcode=private
+                if trace then
+                  trace_ligatures_detail("defining %a as %a",firstname,firstcode)
+                end
+                unicodes[firstname]=firstcode
+                firstdata={ intermediate=true,ligatures={} }
+                characters[firstcode]=firstdata
+                descriptions[firstcode]={ name=firstname }
+                private=private+1
+              end
+              local target
+              local secondcode=lookupdata[i+1]
+              local secondname=firstname.."_"..secondcode
+              if i==size-1 then
+                target=unicode
+                if not unicodes[secondname] then
                   unicodes[secondname]=unicode 
-                end
-                okay=true
-              else
-                target=unicodes[secondname]
-                if not target then
-                  break
-                end
-              end
-              if trace then
-                trace_ligatures_detail("codes (%a,%a) + (%a,%a) -> %a",firstname,firstcode,secondname,secondcode,target)
-              end
-              local firstligs=firstdata.ligatures
-              if firstligs then
-                firstligs[secondcode]={ char=target }
-              else
-                firstdata.ligatures={ [secondcode]={ char=target } }
-              end
-              firstcode=target
-              firstname=secondname
-            end
-          end
-          if okay then
-            ligatures[i]=false
-            done=done+1
-          end
-        end
-      end
-      alldone=done==0
-    end
-    if trace then
-      for k,v in next,characters do
-        if v.ligatures then table.print(v,k) end
-      end
-    end
-    tfmdata.resources.private=private
-  end
-end
-local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
-  local characters=tfmdata.characters
-  local descriptions=tfmdata.descriptions
-  local resources=tfmdata.resources
-  local changed=tfmdata.changed
-  local unicodes=resources.unicodes
-  local lookuphash=resources.lookuphash
+                end
+                okay=true
+              else
+                target=unicodes[secondname]
+                if not target then
+                  break
+                end
+              end
+              if trace then
+                trace_ligatures_detail("codes (%a,%a) + (%a,%a) -> %a",firstname,firstcode,secondname,secondcode,target)
+              end
+              local firstligs=firstdata.ligatures
+              if firstligs then
+                firstligs[secondcode]={ char=target }
+              else
+                firstdata.ligatures={ [secondcode]={ char=target } }
+              end
+              firstcode=target
+              firstname=secondname
+            end
+          end
+          if okay then
+            ligatures[i]=false
+            done=done+1
+          end
+        end
+      end
+      alldone=done==0
+    end
+    if trace then
+      for k,v in next,characters do
+        if v.ligatures then table.print(v,k) end
+      end
+    end
+    tfmdata.resources.private=private
+  end
+end
+local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+  local characters=tfmdata.characters
+  local descriptions=tfmdata.descriptions
+  local resources=tfmdata.resources
+  local changed=tfmdata.changed
+  local unicodes=resources.unicodes
+  local lookuphash=resources.lookuphash
   local lookuptypes=resources.lookuptypes
-  local ligatures={}
-  local alternate=tonumber(value)
+  local ligatures={}
+  local alternate=tonumber(value)
   local defaultalt=otf.defaultbasealternate
-  local trace_singles=trace_baseinit and trace_singles
-  local trace_alternatives=trace_baseinit and trace_alternatives
+  local trace_singles=trace_baseinit and trace_singles
+  local trace_alternatives=trace_baseinit and trace_alternatives
   local trace_ligatures=trace_baseinit and trace_ligatures
-  local actions={
-    substitution=function(lookupdata,lookupname,description,unicode)
-      if trace_singles then
-        report_substitution(feature,lookupname,descriptions,unicode,lookupdata)
-      end
-      changed[unicode]=lookupdata
-    end,
-    alternate=function(lookupdata,lookupname,description,unicode)
-      local replacement=lookupdata[alternate]
-      if replacement then
-        changed[unicode]=replacement
-        if trace_alternatives then
-          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
-        end
-      elseif defaultalt=="first" then
-        replacement=lookupdata[1]
-        changed[unicode]=replacement
-        if trace_alternatives then
-          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
-        end
-      elseif defaultalt=="last" then
-        replacement=lookupdata[#data]
-        if trace_alternatives then
-          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
-        end
-      else
-        if trace_alternatives then
-          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
-        end
-      end
-    end,
-    ligature=function(lookupdata,lookupname,description,unicode)
-      if trace_ligatures then
-        report_ligature(feature,lookupname,descriptions,unicode,lookupdata)
-      end
-      ligatures[#ligatures+1]={ unicode,lookupdata }
-    end,
+  local actions={
+    substitution=function(lookupdata,lookupname,description,unicode)
+      if trace_singles then
+        report_substitution(feature,lookupname,descriptions,unicode,lookupdata)
+      end
+      changed[unicode]=lookupdata
+    end,
+    alternate=function(lookupdata,lookupname,description,unicode)
+      local replacement=lookupdata[alternate]
+      if replacement then
+        changed[unicode]=replacement
+        if trace_alternatives then
+          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+        end
+      elseif defaultalt=="first" then
+        replacement=lookupdata[1]
+        changed[unicode]=replacement
+        if trace_alternatives then
+          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+        end
+      elseif defaultalt=="last" then
+        replacement=lookupdata[#data]
+        if trace_alternatives then
+          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+        end
+      else
+        if trace_alternatives then
+          report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+        end
+      end
+    end,
+    ligature=function(lookupdata,lookupname,description,unicode)
+      if trace_ligatures then
+        report_ligature(feature,lookupname,descriptions,unicode,lookupdata)
+      end
+      ligatures[#ligatures+1]={ unicode,lookupdata }
+    end,
   }
-  for unicode,character in next,characters do
-    local description=descriptions[unicode]
-    local lookups=description.slookups
-    if lookups then
-      for l=1,#lookuplist do
-        local lookupname=lookuplist[l]
-        local lookupdata=lookups[lookupname]
-        if lookupdata then
-          local lookuptype=lookuptypes[lookupname]
-          local action=actions[lookuptype]
-          if action then
-            action(lookupdata,lookupname,description,unicode)
-          end
-        end
-      end
-    end
-    local lookups=description.mlookups
-    if lookups then
-      for l=1,#lookuplist do
-        local lookupname=lookuplist[l]
-        local lookuplist=lookups[lookupname]
-        if lookuplist then
-          local lookuptype=lookuptypes[lookupname]
-          local action=actions[lookuptype]
-          if action then
-            for i=1,#lookuplist do
-              action(lookuplist[i],lookupname,description,unicode)
-            end
-          end
-        end
-      end
-    end
-  end
-  finalize_ligatures(tfmdata,ligatures)
+  for unicode,character in next,characters do
+    local description=descriptions[unicode]
+    local lookups=description.slookups
+    if lookups then
+      for l=1,#lookuplist do
+        local lookupname=lookuplist[l]
+        local lookupdata=lookups[lookupname]
+        if lookupdata then
+          local lookuptype=lookuptypes[lookupname]
+          local action=actions[lookuptype]
+          if action then
+            action(lookupdata,lookupname,description,unicode)
+          end
+        end
+      end
+    end
+    local lookups=description.mlookups
+    if lookups then
+      for l=1,#lookuplist do
+        local lookupname=lookuplist[l]
+        local lookuplist=lookups[lookupname]
+        if lookuplist then
+          local lookuptype=lookuptypes[lookupname]
+          local action=actions[lookuptype]
+          if action then
+            for i=1,#lookuplist do
+              action(lookuplist[i],lookupname,description,unicode)
+            end
+          end
+        end
+      end
+    end
+  end
+  finalize_ligatures(tfmdata,ligatures)
 end
 local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) 
-  local characters=tfmdata.characters
-  local descriptions=tfmdata.descriptions
-  local resources=tfmdata.resources
-  local unicodes=resources.unicodes
-  local sharedkerns={}
-  local traceindeed=trace_baseinit and trace_kerns
-  for unicode,character in next,characters do
-    local description=descriptions[unicode]
+  local characters=tfmdata.characters
+  local descriptions=tfmdata.descriptions
+  local resources=tfmdata.resources
+  local unicodes=resources.unicodes
+  local sharedkerns={}
+  local traceindeed=trace_baseinit and trace_kerns
+  for unicode,character in next,characters do
+    local description=descriptions[unicode]
     local rawkerns=description.kerns 
-    if rawkerns then
-      local s=sharedkerns[rawkerns]
+    if rawkerns then
+      local s=sharedkerns[rawkerns]
       if s==false then
-      elseif s then
-        character.kerns=s
-      else
-        local newkerns=character.kerns
-        local done=false
-        for l=1,#lookuplist do
-          local lookup=lookuplist[l]
-          local kerns=rawkerns[lookup]
-          if kerns then
-            for otherunicode,value in next,kerns do
+      elseif s then
+        character.kerns=s
+      else
+        local newkerns=character.kerns
+        local done=false
+        for l=1,#lookuplist do
+          local lookup=lookuplist[l]
+          local kerns=rawkerns[lookup]
+          if kerns then
+            for otherunicode,value in next,kerns do
               if value==0 then
-              elseif not newkerns then
-                newkerns={ [otherunicode]=value }
-                done=true
-                if traceindeed then
-                  report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
-                end
+              elseif not newkerns then
+                newkerns={ [otherunicode]=value }
+                done=true
+                if traceindeed then
+                  report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
+                end
               elseif not newkerns[otherunicode] then 
-                newkerns[otherunicode]=value
-                done=true
-                if traceindeed then
-                  report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
-                end
-              end
-            end
-          end
-        end
-        if done then
-          sharedkerns[rawkerns]=newkerns
+                newkerns[otherunicode]=value
+                done=true
+                if traceindeed then
+                  report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
+                end
+              end
+            end
+          end
+        end
+        if done then
+          sharedkerns[rawkerns]=newkerns
           character.kerns=newkerns 
-        else
-          sharedkerns[rawkerns]=false
-        end
-      end
-    end
-  end
-end
-basemethods.independent={
-  preparesubstitutions=preparesubstitutions,
-  preparepositionings=preparepositionings,
+        else
+          sharedkerns[rawkerns]=false
+        end
+      end
+    end
+  end
+end
+basemethods.independent={
+  preparesubstitutions=preparesubstitutions,
+  preparepositionings=preparepositionings,
 }
-local function makefake(tfmdata,name,present)
-  local resources=tfmdata.resources
-  local private=resources.private
-  local character={ intermediate=true,ligatures={} }
-  resources.unicodes[name]=private
-  tfmdata.characters[private]=character
-  tfmdata.descriptions[private]={ name=name }
-  resources.private=private+1
-  present[name]=private
-  return character
-end
-local function make_1(present,tree,name)
-  for k,v in next,tree do
-    if k=="ligature" then
-      present[name]=v
-    else
-      make_1(present,v,name.."_"..k)
-    end
-  end
-end
-local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookupname)
-  for k,v in next,tree do
-    if k=="ligature" then
-      local character=characters[preceding]
-      if not character then
-        if trace_baseinit then
-          report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookupname,v,preceding)
-        end
-        character=makefake(tfmdata,name,present)
-      end
-      local ligatures=character.ligatures
-      if ligatures then
-        ligatures[unicode]={ char=v }
-      else
-        character.ligatures={ [unicode]={ char=v } }
-      end
-      if done then
-        local d=done[lookupname]
-        if not d then
-          done[lookupname]={ "dummy",v }
-        else
-          d[#d+1]=v
-        end
-      end
-    else
-      local code=present[name] or unicode
-      local name=name.."_"..k
-      make_2(present,tfmdata,characters,v,name,code,k,done,lookupname)
-    end
-  end
-end
-local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
-  local characters=tfmdata.characters
-  local descriptions=tfmdata.descriptions
-  local resources=tfmdata.resources
-  local changed=tfmdata.changed
-  local lookuphash=resources.lookuphash
+local function makefake(tfmdata,name,present)
+  local resources=tfmdata.resources
+  local private=resources.private
+  local character={ intermediate=true,ligatures={} }
+  resources.unicodes[name]=private
+  tfmdata.characters[private]=character
+  tfmdata.descriptions[private]={ name=name }
+  resources.private=private+1
+  present[name]=private
+  return character
+end
+local function make_1(present,tree,name)
+  for k,v in next,tree do
+    if k=="ligature" then
+      present[name]=v
+    else
+      make_1(present,v,name.."_"..k)
+    end
+  end
+end
+local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookupname)
+  for k,v in next,tree do
+    if k=="ligature" then
+      local character=characters[preceding]
+      if not character then
+        if trace_baseinit then
+          report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookupname,v,preceding)
+        end
+        character=makefake(tfmdata,name,present)
+      end
+      local ligatures=character.ligatures
+      if ligatures then
+        ligatures[unicode]={ char=v }
+      else
+        character.ligatures={ [unicode]={ char=v } }
+      end
+      if done then
+        local d=done[lookupname]
+        if not d then
+          done[lookupname]={ "dummy",v }
+        else
+          d[#d+1]=v
+        end
+      end
+    else
+      local code=present[name] or unicode
+      local name=name.."_"..k
+      make_2(present,tfmdata,characters,v,name,code,k,done,lookupname)
+    end
+  end
+end
+local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
+  local characters=tfmdata.characters
+  local descriptions=tfmdata.descriptions
+  local resources=tfmdata.resources
+  local changed=tfmdata.changed
+  local lookuphash=resources.lookuphash
   local lookuptypes=resources.lookuptypes
-  local ligatures={}
-  local alternate=tonumber(value)
+  local ligatures={}
+  local alternate=tonumber(value)
   local defaultalt=otf.defaultbasealternate
-  local trace_singles=trace_baseinit and trace_singles
-  local trace_alternatives=trace_baseinit and trace_alternatives
+  local trace_singles=trace_baseinit and trace_singles
+  local trace_alternatives=trace_baseinit and trace_alternatives
   local trace_ligatures=trace_baseinit and trace_ligatures
-  for l=1,#lookuplist do
-    local lookupname=lookuplist[l]
-    local lookupdata=lookuphash[lookupname]
-    local lookuptype=lookuptypes[lookupname]
-    for unicode,data in next,lookupdata do
-      if lookuptype=="substitution" then
-        if trace_singles then
-          report_substitution(feature,lookupname,descriptions,unicode,data)
-        end
-        changed[unicode]=data
-      elseif lookuptype=="alternate" then
-        local replacement=data[alternate]
-        if replacement then
-          changed[unicode]=replacement
-          if trace_alternatives then
-            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
-          end
-        elseif defaultalt=="first" then
-          replacement=data[1]
-          changed[unicode]=replacement
-          if trace_alternatives then
-            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
-          end
-        elseif defaultalt=="last" then
-          replacement=data[#data]
-          if trace_alternatives then
-            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
-          end
-        else
-          if trace_alternatives then
-            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
-          end
-        end
-      elseif lookuptype=="ligature" then
-        ligatures[#ligatures+1]={ unicode,data,lookupname }
-        if trace_ligatures then
-          report_ligature(feature,lookupname,descriptions,unicode,data)
-        end
-      end
-    end
+  for l=1,#lookuplist do
+    local lookupname=lookuplist[l]
+    local lookupdata=lookuphash[lookupname]
+    local lookuptype=lookuptypes[lookupname]
+    for unicode,data in next,lookupdata do
+      if lookuptype=="substitution" then
+        if trace_singles then
+          report_substitution(feature,lookupname,descriptions,unicode,data)
+        end
+        changed[unicode]=data
+      elseif lookuptype=="alternate" then
+        local replacement=data[alternate]
+        if replacement then
+          changed[unicode]=replacement
+          if trace_alternatives then
+            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+          end
+        elseif defaultalt=="first" then
+          replacement=data[1]
+          changed[unicode]=replacement
+          if trace_alternatives then
+            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+          end
+        elseif defaultalt=="last" then
+          replacement=data[#data]
+          if trace_alternatives then
+            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+          end
+        else
+          if trace_alternatives then
+            report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+          end
+        end
+      elseif lookuptype=="ligature" then
+        ligatures[#ligatures+1]={ unicode,data,lookupname }
+        if trace_ligatures then
+          report_ligature(feature,lookupname,descriptions,unicode,data)
+        end
+      end
+    end
   end
   local nofligatures=#ligatures
   if nofligatures>0 then
-    local characters=tfmdata.characters
-    local present={}
+    local characters=tfmdata.characters
+    local present={}
     local done=trace_baseinit and trace_ligatures and {}
-    for i=1,nofligatures do
-      local ligature=ligatures[i]
-      local unicode,tree=ligature[1],ligature[2]
-      make_1(present,tree,"ctx_"..unicode)
+    for i=1,nofligatures do
+      local ligature=ligatures[i]
+      local unicode,tree=ligature[1],ligature[2]
+      make_1(present,tree,"ctx_"..unicode)
     end
-    for i=1,nofligatures do
-      local ligature=ligatures[i]
-      local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3]
-      make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookupname)
+    for i=1,nofligatures do
+      local ligature=ligatures[i]
+      local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3]
+      make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookupname)
     end
   end
 end
-local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
-  local characters=tfmdata.characters
-  local descriptions=tfmdata.descriptions
-  local resources=tfmdata.resources
-  local lookuphash=resources.lookuphash
+local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
+  local characters=tfmdata.characters
+  local descriptions=tfmdata.descriptions
+  local resources=tfmdata.resources
+  local lookuphash=resources.lookuphash
   local traceindeed=trace_baseinit and trace_kerns
-  for l=1,#lookuplist do
-    local lookupname=lookuplist[l]
-    local lookupdata=lookuphash[lookupname]
-    for unicode,data in next,lookupdata do
-      local character=characters[unicode]
-      local kerns=character.kerns
-      if not kerns then
-        kerns={}
-        character.kerns=kerns
-      end
-      if traceindeed then
-        for otherunicode,kern in next,data do
-          if not kerns[otherunicode] and kern~=0 then
-            kerns[otherunicode]=kern
-            report_kern(feature,lookup,descriptions,unicode,otherunicode,kern)
-          end
-        end
-      else
-        for otherunicode,kern in next,data do
-          if not kerns[otherunicode] and kern~=0 then
-            kerns[otherunicode]=kern
-          end
-        end
-      end
-    end
-  end
-end
-local function initializehashes(tfmdata)
-  nodeinitializers.features(tfmdata)
-end
-basemethods.shared={
-  initializehashes=initializehashes,
-  preparesubstitutions=preparesubstitutions,
-  preparepositionings=preparepositionings,
+  for l=1,#lookuplist do
+    local lookupname=lookuplist[l]
+    local lookupdata=lookuphash[lookupname]
+    for unicode,data in next,lookupdata do
+      local character=characters[unicode]
+      local kerns=character.kerns
+      if not kerns then
+        kerns={}
+        character.kerns=kerns
+      end
+      if traceindeed then
+        for otherunicode,kern in next,data do
+          if not kerns[otherunicode] and kern~=0 then
+            kerns[otherunicode]=kern
+            report_kern(feature,lookup,descriptions,unicode,otherunicode,kern)
+          end
+        end
+      else
+        for otherunicode,kern in next,data do
+          if not kerns[otherunicode] and kern~=0 then
+            kerns[otherunicode]=kern
+          end
+        end
+      end
+    end
+  end
+end
+local function initializehashes(tfmdata)
+  nodeinitializers.features(tfmdata)
+end
+basemethods.shared={
+  initializehashes=initializehashes,
+  preparesubstitutions=preparesubstitutions,
+  preparepositionings=preparepositionings,
 }
 basemethod="independent"
-local function featuresinitializer(tfmdata,value)
+local function featuresinitializer(tfmdata,value)
   if true then 
-    local t=trace_preparing and os.clock()
-    local features=tfmdata.shared.features
-    if features then
-      applybasemethod("initializehashes",tfmdata)
-      local collectlookups=otf.collectlookups
-      local rawdata=tfmdata.shared.rawdata
-      local properties=tfmdata.properties
-      local script=properties.script
-      local language=properties.language
-      local basesubstitutions=rawdata.resources.features.gsub
-      local basepositionings=rawdata.resources.features.gpos
-      if basesubstitutions then
-        for feature,data in next,basesubstitutions do
-          local value=features[feature]
-          if value then
-            local validlookups,lookuplist=collectlookups(rawdata,feature,script,language)
-            if validlookups then
-              applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
-              registerbasefeature(feature,value)
-            end
-          end
-        end
-      end
-      if basepositionings then
-        for feature,data in next,basepositionings do
-          local value=features[feature]
-          if value then
-            local validlookups,lookuplist=collectlookups(rawdata,feature,script,language)
-            if validlookups then
-              applybasemethod("preparepositionings",tfmdata,feature,features[feature],validlookups,lookuplist)
-              registerbasefeature(feature,value)
-            end
-          end
-        end
-      end
-      registerbasehash(tfmdata)
-    end
-    if trace_preparing then
-      report_prepare("preparation time is %0.3f seconds for %a",os.clock()-t,tfmdata.properties.fullname)
-    end
-  end
-end
-registerotffeature {
-  name="features",
-  description="features",
-  default=true,
+    local t=trace_preparing and os.clock()
+    local features=tfmdata.shared.features
+    if features then
+      applybasemethod("initializehashes",tfmdata)
+      local collectlookups=otf.collectlookups
+      local rawdata=tfmdata.shared.rawdata
+      local properties=tfmdata.properties
+      local script=properties.script
+      local language=properties.language
+      local basesubstitutions=rawdata.resources.features.gsub
+      local basepositionings=rawdata.resources.features.gpos
+      if basesubstitutions then
+        for feature,data in next,basesubstitutions do
+          local value=features[feature]
+          if value then
+            local validlookups,lookuplist=collectlookups(rawdata,feature,script,language)
+            if validlookups then
+              applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
+              registerbasefeature(feature,value)
+            end
+          end
+        end
+      end
+      if basepositionings then
+        for feature,data in next,basepositionings do
+          local value=features[feature]
+          if value then
+            local validlookups,lookuplist=collectlookups(rawdata,feature,script,language)
+            if validlookups then
+              applybasemethod("preparepositionings",tfmdata,feature,features[feature],validlookups,lookuplist)
+              registerbasefeature(feature,value)
+            end
+          end
+        end
+      end
+      registerbasehash(tfmdata)
+    end
+    if trace_preparing then
+      report_prepare("preparation time is %0.3f seconds for %a",os.clock()-t,tfmdata.properties.fullname)
+    end
+  end
+end
+registerotffeature {
+  name="features",
+  description="features",
+  default=true,
   initializers={
-    base=featuresinitializer,
-  }
+    base=featuresinitializer,
+  }
 }
-directives.register("fonts.otf.loader.basemethod",function(v)
-  if basemethods[v] then
-    basemethod=v
-  end
-end)
+directives.register("fonts.otf.loader.basemethod",function(v)
+  if basemethods[v] then
+    basemethod=v
+  end
+end)
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['node-inj']={
-  version=1.001,
-  comment="companion to node-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files",
+if not modules then modules={} end modules ['node-inj']={
+  version=1.001,
+  comment="companion to node-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files",
 }
-local next=next
+local next=next
 local utfchar=utf.char
 local trace_injections=false trackers.register("nodes.injections",function(v) trace_injections=v end)
 local report_injections=logs.reporter("nodes","injections")
 local attributes,nodes,node=attributes,nodes,node
-fonts=fonts
+fonts=fonts
 local fontdata=fonts.hashes.identifiers
-nodes.injections=nodes.injections or {}
+nodes.injections=nodes.injections or {}
 local injections=nodes.injections
-local nodecodes=nodes.nodecodes
-local glyph_code=nodecodes.glyph
-local kern_code=nodecodes.kern
-local nodepool=nodes.pool
+local nodecodes=nodes.nodecodes
+local glyph_code=nodecodes.glyph
+local kern_code=nodecodes.kern
+local nodepool=nodes.pool
 local newkern=nodepool.kern
-local traverse_id=node.traverse_id
-local insert_node_before=node.insert_before
+local traverse_id=node.traverse_id
+local insert_node_before=node.insert_before
 local insert_node_after=node.insert_after
-local a_kernpair=attributes.private('kernpair')
-local a_ligacomp=attributes.private('ligacomp')
-local a_markbase=attributes.private('markbase')
-local a_markmark=attributes.private('markmark')
-local a_markdone=attributes.private('markdone')
-local a_cursbase=attributes.private('cursbase')
-local a_curscurs=attributes.private('curscurs')
+local a_kernpair=attributes.private('kernpair')
+local a_ligacomp=attributes.private('ligacomp')
+local a_markbase=attributes.private('markbase')
+local a_markmark=attributes.private('markmark')
+local a_markdone=attributes.private('markdone')
+local a_cursbase=attributes.private('cursbase')
+local a_curscurs=attributes.private('curscurs')
 local a_cursdone=attributes.private('cursdone')
-function injections.installnewkern(nk)
-  newkern=nk or newkern
+function injections.installnewkern(nk)
+  newkern=nk or newkern
 end
-local cursives={}
-local marks={}
+local cursives={}
+local marks={}
 local kerns={}
-function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
-  local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2])
-  local ws,wn=tfmstart.width,tfmnext.width
-  local bound=#cursives+1
-  start[a_cursbase]=bound
-  nxt[a_curscurs]=bound
-  cursives[bound]={ rlmode,dx,dy,ws,wn }
-  return dx,dy,bound
-end
-function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
+function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
+  local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2])
+  local ws,wn=tfmstart.width,tfmnext.width
+  local bound=#cursives+1
+  start[a_cursbase]=bound
+  nxt[a_curscurs]=bound
+  cursives[bound]={ rlmode,dx,dy,ws,wn }
+  return dx,dy,bound
+end
+function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
   local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
-  if x~=0 or w~=0 or y~=0 or h~=0 then
-    local bound=current[a_kernpair]
-    if bound then
+  if x~=0 or w~=0 or y~=0 or h~=0 then
+    local bound=current[a_kernpair]
+    if bound then
       local kb=kerns[bound]
-      kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h
-    else
-      bound=#kerns+1
-      current[a_kernpair]=bound
-      kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width }
-    end
-    return x,y,w,h,bound
-  end
+      kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h
+    else
+      bound=#kerns+1
+      current[a_kernpair]=bound
+      kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width }
+    end
+    return x,y,w,h,bound
+  end
   return x,y,w,h 
 end
-function injections.setkern(current,factor,rlmode,x,tfmchr)
-  local dx=factor*x
-  if dx~=0 then
-    local bound=#kerns+1
-    current[a_kernpair]=bound
-    kerns[bound]={ rlmode,dx }
-    return dx,bound
-  else
-    return 0,0
-  end
+function injections.setkern(current,factor,rlmode,x,tfmchr)
+  local dx=factor*x
+  if dx~=0 then
+    local bound=#kerns+1
+    current[a_kernpair]=bound
+    kerns[bound]={ rlmode,dx }
+    return dx,bound
+  else
+    return 0,0
+  end
 end
 function injections.setmark(start,base,factor,rlmode,ba,ma,index) 
   local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])   
   local bound=base[a_markbase]          
-  local index=1
-  if bound then
-    local mb=marks[bound]
+  local index=1
+  if bound then
+    local mb=marks[bound]
     if mb then
-      index=#mb+1
-      mb[index]={ dx,dy,rlmode }
-      start[a_markmark]=bound
-      start[a_markdone]=index
-      return dx,dy,bound
-    else
-      report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound)
-    end
-  end
-  index=index or 1
-  bound=#marks+1
-  base[a_markbase]=bound
-  start[a_markmark]=bound
-  start[a_markdone]=index
-  marks[bound]={ [index]={ dx,dy,rlmode } }
-  return dx,dy,bound
-end
-local function dir(n)
-  return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
-end
-local function trace(head)
-  report_injections("begin run")
-  for n in traverse_id(glyph_code,head) do
-    if n.subtype<256 then
-      local kp=n[a_kernpair]
-      local mb=n[a_markbase]
-      local mm=n[a_markmark]
-      local md=n[a_markdone]
-      local cb=n[a_cursbase]
-      local cc=n[a_curscurs]
-      local char=n.char
-      report_injections("font %s, char %U, glyph %c",n.font,char,char)
-      if kp then
-        local k=kerns[kp]
-        if k[3] then
-          report_injections("  pairkern: dir %a, x %p, y %p, w %p, h %p",dir(k[1]),k[2],k[3],k[4],k[5])
-        else
-          report_injections("  kern: dir %a, dx %p",dir(k[1]),k[2])
-        end
-      end
-      if mb then
-        report_injections("  markbase: bound %a",mb)
-      end
-      if mm then
-        local m=marks[mm]
-        if mb then
-          local m=m[mb]
-          if m then
-            report_injections("  markmark: bound %a, index %a, dx %p, dy %p",mm,md,m[1],m[2])
-          else
-            report_injections("  markmark: bound %a, missing index",mm)
-          end
-        else
-          m=m[1]
-          report_injections("  markmark: bound %a, dx %p, dy %p",mm,m and m[1],m and m[2])
-        end
-      end
-      if cb then
-        report_injections("  cursbase: bound %a",cb)
-      end
-      if cc then
-        local c=cursives[cc]
-        report_injections("  curscurs: bound %a, dir %a, dx %p, dy %p",cc,dir(c[1]),c[2],c[3])
-      end
-    end
-  end
-  report_injections("end run")
-end
-local function show_result(head)
-  local current=head
-  local skipping=false
-  while current do
-    local id=current.id
-    if id==glyph_code then
-      report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset)
-      skipping=false
-    elseif id==kern_code then
-      report_injections("kern: %p",current.kern)
-      skipping=false
-    elseif not skipping then
-      report_injections()
-      skipping=true
-    end
-    current=current.next
-  end
-end
-function injections.handler(head,where,keep)
-  local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns)
-  if has_marks or has_cursives then
-    if trace_injections then
-      trace(head)
-    end
-    local done,ky,rl,valid,cx,wx,mk,nofvalid=false,{},{},{},{},{},{},0
+      index=#mb+1
+      mb[index]={ dx,dy,rlmode }
+      start[a_markmark]=bound
+      start[a_markdone]=index
+      return dx,dy,bound
+    else
+      report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound)
+    end
+  end
+  index=index or 1
+  bound=#marks+1
+  base[a_markbase]=bound
+  start[a_markmark]=bound
+  start[a_markdone]=index
+  marks[bound]={ [index]={ dx,dy,rlmode } }
+  return dx,dy,bound
+end
+local function dir(n)
+  return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
+end
+local function trace(head)
+  report_injections("begin run")
+  for n in traverse_id(glyph_code,head) do
+    if n.subtype<256 then
+      local kp=n[a_kernpair]
+      local mb=n[a_markbase]
+      local mm=n[a_markmark]
+      local md=n[a_markdone]
+      local cb=n[a_cursbase]
+      local cc=n[a_curscurs]
+      local char=n.char
+      report_injections("font %s, char %U, glyph %c",n.font,char,char)
+      if kp then
+        local k=kerns[kp]
+        if k[3] then
+          report_injections("  pairkern: dir %a, x %p, y %p, w %p, h %p",dir(k[1]),k[2],k[3],k[4],k[5])
+        else
+          report_injections("  kern: dir %a, dx %p",dir(k[1]),k[2])
+        end
+      end
+      if mb then
+        report_injections("  markbase: bound %a",mb)
+      end
+      if mm then
+        local m=marks[mm]
+        if mb then
+          local m=m[mb]
+          if m then
+            report_injections("  markmark: bound %a, index %a, dx %p, dy %p",mm,md,m[1],m[2])
+          else
+            report_injections("  markmark: bound %a, missing index",mm)
+          end
+        else
+          m=m[1]
+          report_injections("  markmark: bound %a, dx %p, dy %p",mm,m and m[1],m and m[2])
+        end
+      end
+      if cb then
+        report_injections("  cursbase: bound %a",cb)
+      end
+      if cc then
+        local c=cursives[cc]
+        report_injections("  curscurs: bound %a, dir %a, dx %p, dy %p",cc,dir(c[1]),c[2],c[3])
+      end
+    end
+  end
+  report_injections("end run")
+end
+local function show_result(head)
+  local current=head
+  local skipping=false
+  while current do
+    local id=current.id
+    if id==glyph_code then
+      report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset)
+      skipping=false
+    elseif id==kern_code then
+      report_injections("kern: %p",current.kern)
+      skipping=false
+    elseif not skipping then
+      report_injections()
+      skipping=true
+    end
+    current=current.next
+  end
+end
+function injections.handler(head,where,keep)
+  local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns)
+  if has_marks or has_cursives then
+    if trace_injections then
+      trace(head)
+    end
+    local done,ky,rl,valid,cx,wx,mk,nofvalid=false,{},{},{},{},{},{},0
     if has_kerns then 
-      local nf,tm=nil,nil
+      local nf,tm=nil,nil
       for n in traverse_id(glyph_code,head) do 
-        if n.subtype<256 then
-          nofvalid=nofvalid+1
-          valid[nofvalid]=n
-          if n.font~=nf then
-            nf=n.font
-            tm=fontdata[nf].resources.marks
-          end
-          if tm then
-            mk[n]=tm[n.char]
-          end
-          local k=n[a_kernpair]
-          if k then
-            local kk=kerns[k]
-            if kk then
-              local x,y,w,h=kk[2] or 0,kk[3] or 0,kk[4] or 0,kk[5] or 0
-              local dy=y-h
-              if dy~=0 then
-                ky[n]=dy
-              end
-              if w~=0 or x~=0 then
-                wx[n]=kk
-              end
+        if n.subtype<256 then
+          nofvalid=nofvalid+1
+          valid[nofvalid]=n
+          if n.font~=nf then
+            nf=n.font
+            tm=fontdata[nf].resources.marks
+          end
+          if tm then
+            mk[n]=tm[n.char]
+          end
+          local k=n[a_kernpair]
+          if k then
+            local kk=kerns[k]
+            if kk then
+              local x,y,w,h=kk[2] or 0,kk[3] or 0,kk[4] or 0,kk[5] or 0
+              local dy=y-h
+              if dy~=0 then
+                ky[n]=dy
+              end
+              if w~=0 or x~=0 then
+                wx[n]=kk
+              end
               rl[n]=kk[1] 
-            end
-          end
-        end
-      end
-    else
-      local nf,tm=nil,nil
-      for n in traverse_id(glyph_code,head) do
-        if n.subtype<256 then
-          nofvalid=nofvalid+1
-          valid[nofvalid]=n
-          if n.font~=nf then
-            nf=n.font
-            tm=fontdata[nf].resources.marks
-          end
-          if tm then
-            mk[n]=tm[n.char]
-          end
-        end
-      end
-    end
+            end
+          end
+        end
+      end
+    else
+      local nf,tm=nil,nil
+      for n in traverse_id(glyph_code,head) do
+        if n.subtype<256 then
+          nofvalid=nofvalid+1
+          valid[nofvalid]=n
+          if n.font~=nf then
+            nf=n.font
+            tm=fontdata[nf].resources.marks
+          end
+          if tm then
+            mk[n]=tm[n.char]
+          end
+        end
+      end
+    end
     if nofvalid>0 then
-      local cx={}
-      if has_kerns and next(ky) then
-        for n,k in next,ky do
-          n.yoffset=k
-        end
+      local cx={}
+      if has_kerns and next(ky) then
+        for n,k in next,ky do
+          n.yoffset=k
+        end
       end
-      if has_cursives then
+      if has_cursives then
         local p_cursbase,p=nil,nil
-        local t,d,maxt={},{},0
+        local t,d,maxt={},{},0
         for i=1,nofvalid do 
-          local n=valid[i]
-          if not mk[n] then
-            local n_cursbase=n[a_cursbase]
-            if p_cursbase then
-              local n_curscurs=n[a_curscurs]
-              if p_cursbase==n_curscurs then
-                local c=cursives[n_curscurs]
-                if c then
-                  local rlmode,dx,dy,ws,wn=c[1],c[2],c[3],c[4],c[5]
-                  if rlmode>=0 then
-                    dx=dx-ws
-                  else
-                    dx=dx+wn
-                  end
-                  if dx~=0 then
-                    cx[n]=dx
-                    rl[n]=rlmode
-                  end
-                    dy=-dy
-                  maxt=maxt+1
-                  t[maxt]=p
-                  d[maxt]=dy
-                else
-                  maxt=0
-                end
-              end
-            elseif maxt>0 then
-              local ny=n.yoffset
-              for i=maxt,1,-1 do
-                ny=ny+d[i]
-                local ti=t[i]
-                ti.yoffset=ti.yoffset+ny
-              end
-              maxt=0
-            end
-            if not n_cursbase and maxt>0 then
-              local ny=n.yoffset
-              for i=maxt,1,-1 do
-                ny=ny+d[i]
-                local ti=t[i]
-                ti.yoffset=ny
-              end
-              maxt=0
-            end
-            p_cursbase,p=n_cursbase,n
-          end
-        end
-        if maxt>0 then
-          local ny=n.yoffset
-          for i=maxt,1,-1 do
-            ny=ny+d[i]
-            local ti=t[i]
-            ti.yoffset=ny
-          end
-          maxt=0
-        end
-        if not keep then
-          cursives={}
-        end
-      end
-      if has_marks then
-        for i=1,nofvalid do
-          local p=valid[i]
-          local p_markbase=p[a_markbase]
-          if p_markbase then
-            local mrks=marks[p_markbase]
-            local nofmarks=#mrks
-            for n in traverse_id(glyph_code,p.next) do
-              local n_markmark=n[a_markmark]
-              if p_markbase==n_markmark then
-                local index=n[a_markdone] or 1
-                local d=mrks[index]
-                if d then
-                  local rlmode=d[3]
-                  local k=wx[p]
-                  if k then
-                    local x=k[2]
-                    local w=k[4]
-                    if w then
-                      if rlmode and rlmode>=0 then
-                        n.xoffset=p.xoffset-p.width+d[1]-(w-x)
-                      else
-                        n.xoffset=p.xoffset-d[1]-x
-                      end
-                    else
-                      if rlmode and rlmode>=0 then
-                        n.xoffset=p.xoffset-p.width+d[1]
-                      else
-                        n.xoffset=p.xoffset-d[1]-x
-                      end
-                    end
-                  else
-                    if rlmode and rlmode>=0 then
-                      n.xoffset=p.xoffset-p.width+d[1]
-                    else
-                      n.xoffset=p.xoffset-d[1]
-                    end
+          local n=valid[i]
+          if not mk[n] then
+            local n_cursbase=n[a_cursbase]
+            if p_cursbase then
+              local n_curscurs=n[a_curscurs]
+              if p_cursbase==n_curscurs then
+                local c=cursives[n_curscurs]
+                if c then
+                  local rlmode,dx,dy,ws,wn=c[1],c[2],c[3],c[4],c[5]
+                  if rlmode>=0 then
+                    dx=dx-ws
+                  else
+                    dx=dx+wn
                   end
-                  if mk[p] then
-                    n.yoffset=p.yoffset+d[2]
-                  else
-                    n.yoffset=n.yoffset+p.yoffset+d[2]
+                  if dx~=0 then
+                    cx[n]=dx
+                    rl[n]=rlmode
                   end
-                  if nofmarks==1 then
-                    break
-                  else
-                    nofmarks=nofmarks-1
-                  end
-                end
-              else
-              end
-            end
-          end
-        end
-        if not keep then
-          marks={}
-        end
-      end
-      if next(wx) then
-        for n,k in next,wx do
-          local x=k[2]
-          local w=k[4]
-          if w then
-            local rl=k[1] 
-            local wx=w-x
-            if rl<0 then	
-              if wx~=0 then
-                insert_node_before(head,n,newkern(wx)) 
-              end
-              if x~=0 then
+                    dy=-dy
+                  maxt=maxt+1
+                  t[maxt]=p
+                  d[maxt]=dy
+                else
+                  maxt=0
+                end
+              end
+            elseif maxt>0 then
+              local ny=n.yoffset
+              for i=maxt,1,-1 do
+                ny=ny+d[i]
+                local ti=t[i]
+                ti.yoffset=ti.yoffset+ny
+              end
+              maxt=0
+            end
+            if not n_cursbase and maxt>0 then
+              local ny=n.yoffset
+              for i=maxt,1,-1 do
+                ny=ny+d[i]
+                local ti=t[i]
+                ti.yoffset=ny
+              end
+              maxt=0
+            end
+            p_cursbase,p=n_cursbase,n
+          end
+        end
+        if maxt>0 then
+          local ny=n.yoffset
+          for i=maxt,1,-1 do
+            ny=ny+d[i]
+            local ti=t[i]
+            ti.yoffset=ny
+          end
+          maxt=0
+        end
+        if not keep then
+          cursives={}
+        end
+      end
+      if has_marks then
+        for i=1,nofvalid do
+          local p=valid[i]
+          local p_markbase=p[a_markbase]
+          if p_markbase then
+            local mrks=marks[p_markbase]
+            local nofmarks=#mrks
+            for n in traverse_id(glyph_code,p.next) do
+              local n_markmark=n[a_markmark]
+              if p_markbase==n_markmark then
+                local index=n[a_markdone] or 1
+                local d=mrks[index]
+                if d then
+                  local rlmode=d[3]
+                  local k=wx[p]
+                  if k then
+                    local x=k[2]
+                    local w=k[4]
+                    if w then
+                      if rlmode and rlmode>=0 then
+                        n.xoffset=p.xoffset-p.width+d[1]-(w-x)
+                      else
+                        n.xoffset=p.xoffset-d[1]-x
+                      end
+                    else
+                      if rlmode and rlmode>=0 then
+                        n.xoffset=p.xoffset-p.width+d[1]
+                      else
+                        n.xoffset=p.xoffset-d[1]-x
+                      end
+                    end
+                  else
+                    if rlmode and rlmode>=0 then
+                      n.xoffset=p.xoffset-p.width+d[1]
+                    else
+                      n.xoffset=p.xoffset-d[1]
+                    end
+                  end
+                  if mk[p] then
+                    n.yoffset=p.yoffset+d[2]
+                  else
+                    n.yoffset=n.yoffset+p.yoffset+d[2]
+                  end
+                  if nofmarks==1 then
+                    break
+                  else
+                    nofmarks=nofmarks-1
+                  end
+                end
+              else
+              end
+            end
+          end
+        end
+        if not keep then
+          marks={}
+        end
+      end
+      if next(wx) then
+        for n,k in next,wx do
+          local x=k[2]
+          local w=k[4]
+          if w then
+            local rl=k[1] 
+            local wx=w-x
+            if rl<0 then	
+              if wx~=0 then
+                insert_node_before(head,n,newkern(wx)) 
+              end
+              if x~=0 then
                 insert_node_after (head,n,newkern(x)) 
-              end
-            else
-              if x~=0 then
+              end
+            else
+              if x~=0 then
                 insert_node_before(head,n,newkern(x)) 
-              end
-              if wx~=0 then
+              end
+              if wx~=0 then
                 insert_node_after (head,n,newkern(wx)) 
-              end
-            end
+              end
+            end
           elseif x~=0 then
             insert_node_before(head,n,newkern(x)) 
-          end
-        end
-      end
-      if next(cx) then
-        for n,k in next,cx do
-          if k~=0 then
-            local rln=rl[n]
-            if rln and rln<0 then
+          end
+        end
+      end
+      if next(cx) then
+        for n,k in next,cx do
+          if k~=0 then
+            local rln=rl[n]
+            if rln and rln<0 then
               insert_node_before(head,n,newkern(-k)) 
-            else
+            else
               insert_node_before(head,n,newkern(k)) 
-            end
-          end
-        end
-      end
-      if not keep then
-        kerns={}
-      end
-      return head,true
-    elseif not keep then
-      kerns,cursives,marks={},{},{}
-    end
-  elseif has_kerns then
-    if trace_injections then
-      trace(head)
-    end
-    for n in traverse_id(glyph_code,head) do
-      if n.subtype<256 then
-        local k=n[a_kernpair]
-        if k then
-          local kk=kerns[k]
-          if kk then
-            local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4]
-            if y and y~=0 then
+            end
+          end
+        end
+      end
+      if not keep then
+        kerns={}
+      end
+      return head,true
+    elseif not keep then
+      kerns,cursives,marks={},{},{}
+    end
+  elseif has_kerns then
+    if trace_injections then
+      trace(head)
+    end
+    for n in traverse_id(glyph_code,head) do
+      if n.subtype<256 then
+        local k=n[a_kernpair]
+        if k then
+          local kk=kerns[k]
+          if kk then
+            local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4]
+            if y and y~=0 then
               n.yoffset=y 
-            end
+            end
             if w then
-              local wx=w-x
+              local wx=w-x
               if rl<0 then 
-                if wx~=0 then
-                  insert_node_before(head,n,newkern(wx))
-                end
-                if x~=0 then
-                  insert_node_after (head,n,newkern(x))
-                end
-              else
-                if x~=0 then
-                  insert_node_before(head,n,newkern(x))
-                end
-                if wx~=0 then
-                  insert_node_after(head,n,newkern(wx))
-                end
-              end
+                if wx~=0 then
+                  insert_node_before(head,n,newkern(wx))
+                end
+                if x~=0 then
+                  insert_node_after (head,n,newkern(x))
+                end
+              else
+                if x~=0 then
+                  insert_node_before(head,n,newkern(x))
+                end
+                if wx~=0 then
+                  insert_node_after(head,n,newkern(wx))
+                end
+              end
             else
-              if x~=0 then
-                insert_node_before(head,n,newkern(x))
-              end
-            end
-          end
-        end
-      end
-    end
-    if not keep then
-      kerns={}
-    end
-    return head,true
+              if x~=0 then
+                insert_node_before(head,n,newkern(x))
+              end
+            end
+          end
+        end
+      end
+    end
+    if not keep then
+      kerns={}
+    end
+    return head,true
   else
-  end
-  return head,false
-end
+  end
+  return head,false
+end
 
 end -- closure
 
@@ -10387,877 +10387,877 @@ local function prepare_contextchains(tfmdata)
               end
             end
           end
-        else
+        else
+        end
+      else
+        report_prepare("missing lookuptype for lookupname %a",lookupname)
+      end
+    end
+  end
+end
+local function featuresinitializer(tfmdata,value)
+  if true then
+    local rawdata=tfmdata.shared.rawdata
+    local properties=rawdata.properties
+    if not properties.initialized then
+      local starttime=trace_preparing and os.clock()
+      local resources=rawdata.resources
+      resources.lookuphash=resources.lookuphash or {}
+      prepare_contextchains(tfmdata)
+      prepare_lookups(tfmdata)
+      properties.initialized=true
+      if trace_preparing then
+        report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname)
+      end
+    end
+  end
+end
+registerotffeature {
+  name="features",
+  description="features",
+  default=true,
+  initializers={
+    position=1,
+    node=featuresinitializer,
+  },
+  processors={
+    node=featuresprocessor,
+  }
+}
+otf.handlers=handlers
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules={} end modules ['font-otp']={
+  version=1.001,
+  comment="companion to font-otf.lua (packing)",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
+}
+local next,type=next,type
+local sort,concat=table.sort,table.concat
+local sortedhash=table.sortedhash
+local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end)
+local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
+local report_otf=logs.reporter("fonts","otf loading")
+fonts=fonts or {}
+local handlers=fonts.handlers or {}
+fonts.handlers=handlers
+local otf=handlers.otf or {}
+handlers.otf=otf
+local enhancers=otf.enhancers or {}
+otf.enhancers=enhancers
+local glists=otf.glists or { "gsub","gpos" }
+otf.glists=glists
+local criterium=1
+local threshold=0
+local function tabstr_normal(t)
+  local s={}
+  local n=0
+  for k,v in next,t do
+    n=n+1
+    if type(v)=="table" then
+      s[n]=k..">"..tabstr_normal(v)
+    elseif v==true then
+      s[n]=k.."+" 
+    elseif v then
+      s[n]=k.."="..v
+    else
+      s[n]=k.."-" 
+    end
+  end
+  if n==0 then
+    return ""
+  elseif n==1 then
+    return s[1]
+  else
+    sort(s) 
+    return concat(s,",")
+  end
+end
+local function tabstr_flat(t)
+  local s={}
+  local n=0
+  for k,v in next,t do
+    n=n+1
+    s[n]=k.."="..v
+  end
+  if n==0 then
+    return ""
+  elseif n==1 then
+    return s[1]
+  else
+    sort(s) 
+    return concat(s,",")
+  end
+end
+local function tabstr_mixed(t) 
+  local s={}
+  local n=#t
+  if n==0 then
+    return ""
+  elseif n==1 then
+    local k=t[1]
+    if k==true then
+      return "++" 
+    elseif k==false then
+      return "--" 
+    else
+      return tostring(k) 
+    end
+  else
+    for i=1,n do
+      local k=t[i]
+      if k==true then
+        s[i]="++" 
+      elseif k==false then
+        s[i]="--" 
+      else
+        s[i]=k 
+      end
+    end
+    return concat(s,",")
+  end
+end
+local function tabstr_boolean(t)
+  local s={}
+  local n=0
+  for k,v in next,t do
+    n=n+1
+    if v then
+      s[n]=k.."+"
+    else
+      s[n]=k.."-"
+    end
+  end
+  if n==0 then
+    return ""
+  elseif n==1 then
+    return s[1]
+  else
+    sort(s) 
+    return concat(s,",")
+  end
+end
+local function packdata(data)
+  if data then
+    local h,t,c={},{},{}
+    local hh,tt,cc={},{},{}
+    local nt,ntt=0,0
+    local function pack_normal(v)
+      local tag=tabstr_normal(v)
+      local ht=h[tag]
+      if ht then
+        c[ht]=c[ht]+1
+        return ht
+      else
+        nt=nt+1
+        t[nt]=v
+        h[tag]=nt
+        c[nt]=1
+        return nt
+      end
+    end
+    local function pack_flat(v)
+      local tag=tabstr_flat(v)
+      local ht=h[tag]
+      if ht then
+        c[ht]=c[ht]+1
+        return ht
+      else
+        nt=nt+1
+        t[nt]=v
+        h[tag]=nt
+        c[nt]=1
+        return nt
+      end
+    end
+    local function pack_boolean(v)
+      local tag=tabstr_boolean(v)
+      local ht=h[tag]
+      if ht then
+        c[ht]=c[ht]+1
+        return ht
+      else
+        nt=nt+1
+        t[nt]=v
+        h[tag]=nt
+        c[nt]=1
+        return nt
+      end
+    end
+    local function pack_indexed(v)
+      local tag=concat(v," ")
+      local ht=h[tag]
+      if ht then
+        c[ht]=c[ht]+1
+        return ht
+      else
+        nt=nt+1
+        t[nt]=v
+        h[tag]=nt
+        c[nt]=1
+        return nt
+      end
+    end
+    local function pack_mixed(v)
+      local tag=tabstr_mixed(v)
+      local ht=h[tag]
+      if ht then
+        c[ht]=c[ht]+1
+        return ht
+      else
+        nt=nt+1
+        t[nt]=v
+        h[tag]=nt
+        c[nt]=1
+        return nt
+      end
+    end
+    local function pack_final(v)
+      if c[v]<=criterium then
+        return t[v]
+      else
+        local hv=hh[v]
+        if hv then
+          return hv
+        else
+          ntt=ntt+1
+          tt[ntt]=t[v]
+          hh[v]=ntt
+          cc[ntt]=c[v]
+          return ntt
+        end
+      end
+    end
+    local function success(stage,pass)
+      if nt==0 then
+        if trace_loading or trace_packing then
+          report_otf("pack quality: nothing to pack")
+        end
+        return false
+      elseif nt>=threshold then
+        local one,two,rest=0,0,0
+        if pass==1 then
+          for k,v in next,c do
+            if v==1 then
+              one=one+1
+            elseif v==2 then
+              two=two+1
+            else
+              rest=rest+1
+            end
+          end
+        else
+          for k,v in next,cc do
+            if v>20 then
+              rest=rest+1
+            elseif v>10 then
+              two=two+1
+            else
+              one=one+1
+            end
+          end
+          data.tables=tt
+        end
+        if trace_loading or trace_packing then
+          report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)",stage,pass,one+two+rest,one,two,rest,criterium)
+        end
+        return true
+      else
+        if trace_loading or trace_packing then
+          report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)",stage,pass,nt,threshold)
+        end
+        return false
+      end
+    end
+    local function packers(pass)
+      if pass==1 then
+        return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed
+      else
+        return pack_final,pack_final,pack_final,pack_final,pack_final
+      end
+    end
+    local resources=data.resources
+    local lookuptypes=resources.lookuptypes
+    for pass=1,2 do
+      if trace_packing then
+        report_otf("start packing: stage 1, pass %s",pass)
+      end
+      local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+      for unicode,description in next,data.descriptions do
+        local boundingbox=description.boundingbox
+        if boundingbox then
+          description.boundingbox=pack_indexed(boundingbox)
+        end
+        local slookups=description.slookups
+        if slookups then
+          for tag,slookup in next,slookups do
+            local what=lookuptypes[tag]
+            if what=="pair" then
+              local t=slookup[2] if t then slookup[2]=pack_indexed(t) end
+              local t=slookup[3] if t then slookup[3]=pack_indexed(t) end
+            elseif what~="substitution" then
+              slookups[tag]=pack_indexed(slookup) 
+            end
+          end
+        end
+        local mlookups=description.mlookups
+        if mlookups then
+          for tag,mlookup in next,mlookups do
+            local what=lookuptypes[tag]
+            if what=="pair" then
+              for i=1,#mlookup do
+                local lookup=mlookup[i]
+                local t=lookup[2] if t then lookup[2]=pack_indexed(t) end
+                local t=lookup[3] if t then lookup[3]=pack_indexed(t) end
+              end
+            elseif what~="substitution" then
+              for i=1,#mlookup do
+                mlookup[i]=pack_indexed(mlookup[i]) 
+              end
+            end
+          end
+        end
+        local kerns=description.kerns
+        if kerns then
+          for tag,kern in next,kerns do
+            kerns[tag]=pack_flat(kern)
+          end
+        end
+        local math=description.math
+        if math then
+          local kerns=math.kerns
+          if kerns then
+            for tag,kern in next,kerns do
+              kerns[tag]=pack_normal(kern)
+            end
+          end
+        end
+        local anchors=description.anchors
+        if anchors then
+          for what,anchor in next,anchors do
+            if what=="baselig" then
+              for _,a in next,anchor do
+                for k=1,#a do
+                  a[k]=pack_indexed(a[k])
+                end
+              end
+            else
+              for k,v in next,anchor do
+                anchor[k]=pack_indexed(v)
+              end
+            end
+          end
+        end
+        local altuni=description.altuni
+        if altuni then
+          for i=1,#altuni do
+            altuni[i]=pack_flat(altuni[i])
+          end
+        end
+      end
+      local lookups=data.lookups
+      if lookups then
+        for _,lookup in next,lookups do
+          local rules=lookup.rules
+          if rules then
+            for i=1,#rules do
+              local rule=rules[i]
+              local r=rule.before    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
+              local r=rule.after    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
+              local r=rule.current   if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
+              local r=rule.replacements if r then rule.replacements=pack_flat  (r)  end 
+              local r=rule.lookups   if r then rule.lookups=pack_indexed(r)  end
+            end
+          end
+        end
+      end
+      local anchor_to_lookup=resources.anchor_to_lookup
+      if anchor_to_lookup then
+        for anchor,lookup in next,anchor_to_lookup do
+          anchor_to_lookup[anchor]=pack_normal(lookup)
+        end
+      end
+      local lookup_to_anchor=resources.lookup_to_anchor
+      if lookup_to_anchor then
+        for lookup,anchor in next,lookup_to_anchor do
+          lookup_to_anchor[lookup]=pack_normal(anchor)
+        end
+      end
+      local sequences=resources.sequences
+      if sequences then
+        for feature,sequence in next,sequences do
+          local flags=sequence.flags
+          if flags then
+            sequence.flags=pack_normal(flags)
+          end
+          local subtables=sequence.subtables
+          if subtables then
+            sequence.subtables=pack_normal(subtables)
+          end
+          local features=sequence.features
+          if features then
+            for script,feature in next,features do
+              features[script]=pack_normal(feature)
+            end
+          end
+        end
+      end
+      local lookups=resources.lookups
+      if lookups then
+        for name,lookup in next,lookups do
+          local flags=lookup.flags
+          if flags then
+            lookup.flags=pack_normal(flags)
+          end
+          local subtables=lookup.subtables
+          if subtables then
+            lookup.subtables=pack_normal(subtables)
+          end
+        end
+      end
+      local features=resources.features
+      if features then
+        for _,what in next,glists do
+          local list=features[what]
+          if list then
+            for feature,spec in next,list do
+              list[feature]=pack_normal(spec)
+            end
+          end
+        end
+      end
+      if not success(1,pass) then
+        return
+      end
+    end
+    if nt>0 then
+      for pass=1,2 do
+        if trace_packing then
+          report_otf("start packing: stage 2, pass %s",pass)
+        end
+        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+        for unicode,description in next,data.descriptions do
+          local kerns=description.kerns
+          if kerns then
+            description.kerns=pack_normal(kerns)
+          end
+          local math=description.math
+          if math then
+            local kerns=math.kerns
+            if kerns then
+              math.kerns=pack_normal(kerns)
+            end
+          end
+          local anchors=description.anchors
+          if anchors then
+            description.anchors=pack_normal(anchors)
+          end
+          local mlookups=description.mlookups
+          if mlookups then
+            for tag,mlookup in next,mlookups do
+              mlookups[tag]=pack_normal(mlookup)
+            end
+          end
+          local altuni=description.altuni
+          if altuni then
+            description.altuni=pack_normal(altuni)
+          end
+        end
+        local lookups=data.lookups
+        if lookups then
+          for _,lookup in next,lookups do
+            local rules=lookup.rules
+            if rules then
+              for i=1,#rules do 
+                local rule=rules[i]
+                local r=rule.before if r then rule.before=pack_normal(r) end
+                local r=rule.after  if r then rule.after=pack_normal(r) end
+                local r=rule.current if r then rule.current=pack_normal(r) end
+              end
+            end
+          end
+        end
+        local sequences=resources.sequences
+        if sequences then
+          for feature,sequence in next,sequences do
+            sequence.features=pack_normal(sequence.features)
+          end
+        end
+        if not success(2,pass) then
+        end
+      end
+      for pass=1,2 do
+        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+        for unicode,description in next,data.descriptions do
+          local slookups=description.slookups
+          if slookups then
+            description.slookups=pack_normal(slookups)
+          end
+          local mlookups=description.mlookups
+          if mlookups then
+            description.mlookups=pack_normal(mlookups)
+          end
+        end
+      end
+    end
+  end
+end
+local unpacked_mt={
+  __index=function(t,k)
+      t[k]=false
+      return k 
+    end
+}
+local function unpackdata(data)
+  if data then
+    local tables=data.tables
+    if tables then
+      local resources=data.resources
+      local lookuptypes=resources.lookuptypes
+      local unpacked={}
+      setmetatable(unpacked,unpacked_mt)
+      for unicode,description in next,data.descriptions do
+        local tv=tables[description.boundingbox]
+        if tv then
+          description.boundingbox=tv
+        end
+        local slookups=description.slookups
+        if slookups then
+          local tv=tables[slookups]
+          if tv then
+            description.slookups=tv
+            slookups=unpacked[tv]
+          end
+          if slookups then
+            for tag,lookup in next,slookups do
+              local what=lookuptypes[tag]
+              if what=="pair" then
+                local tv=tables[lookup[2]]
+                if tv then
+                  lookup[2]=tv
+                end
+                local tv=tables[lookup[3]]
+                if tv then
+                  lookup[3]=tv
+                end
+              elseif what~="substitution" then
+                local tv=tables[lookup]
+                if tv then
+                  slookups[tag]=tv
+                end
+              end
+            end
+          end
+        end
+        local mlookups=description.mlookups
+        if mlookups then
+          local tv=tables[mlookups]
+          if tv then
+            description.mlookups=tv
+            mlookups=unpacked[tv]
+          end
+          if mlookups then
+            for tag,list in next,mlookups do
+              local tv=tables[list]
+              if tv then
+                mlookups[tag]=tv
+                list=unpacked[tv]
+              end
+              if list then
+                local what=lookuptypes[tag]
+                if what=="pair" then
+                  for i=1,#list do
+                    local lookup=list[i]
+                    local tv=tables[lookup[2]]
+                    if tv then
+                      lookup[2]=tv
+                    end
+                    local tv=tables[lookup[3]]
+                    if tv then
+                      lookup[3]=tv
+                    end
+                  end
+                elseif what~="substitution" then
+                  for i=1,#list do
+                    local tv=tables[list[i]]
+                    if tv then
+                      list[i]=tv
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+        local kerns=description.kerns
+        if kerns then
+          local tm=tables[kerns]
+          if tm then
+            description.kerns=tm
+            kerns=unpacked[tm]
+          end
+          if kerns then
+            for k,kern in next,kerns do
+              local tv=tables[kern]
+              if tv then
+                kerns[k]=tv
+              end
+            end
+          end
+        end
+        local math=description.math
+        if math then
+          local kerns=math.kerns
+          if kerns then
+            local tm=tables[kerns]
+            if tm then
+              math.kerns=tm
+              kerns=unpacked[tm]
+            end
+            if kerns then
+              for k,kern in next,kerns do
+                local tv=tables[kern]
+                if tv then
+                  kerns[k]=tv
+                end
+              end
+            end
+          end
+        end
+        local anchors=description.anchors
+        if anchors then
+          local ta=tables[anchors]
+          if ta then
+            description.anchors=ta
+            anchors=unpacked[ta]
+          end
+          if anchors then
+            for tag,anchor in next,anchors do
+              if tag=="baselig" then
+                for _,list in next,anchor do
+                  for i=1,#list do
+                    local tv=tables[list[i]]
+                    if tv then
+                      list[i]=tv
+                    end
+                  end
+                end
+              else
+                for a,data in next,anchor do
+                  local tv=tables[data]
+                  if tv then
+                    anchor[a]=tv
+                  end
+                end
+              end
+            end
+          end
+        end
+        local altuni=description.altuni
+        if altuni then
+          local altuni=tables[altuni]
+          if altuni then
+            description.altuni=altuni
+            for i=1,#altuni do
+              local tv=tables[altuni[i]]
+              if tv then
+                altuni[i]=tv
+              end
+            end
+          end
+        end
+      end
+      local lookups=data.lookups
+      if lookups then
+        for _,lookup in next,lookups do
+          local rules=lookup.rules
+          if rules then
+            for i=1,#rules do 
+              local rule=rules[i]
+              local before=rule.before
+              if before then
+                local tv=tables[before]
+                if tv then
+                  rule.before=tv
+                  before=unpacked[tv]
+                end
+                if before then
+                  for i=1,#before do
+                    local tv=tables[before[i]]
+                    if tv then
+                      before[i]=tv
+                    end
+                  end
+                end
+              end
+              local after=rule.after
+              if after then
+                local tv=tables[after]
+                if tv then
+                  rule.after=tv
+                  after=unpacked[tv]
+                end
+                if after then
+                  for i=1,#after do
+                    local tv=tables[after[i]]
+                    if tv then
+                      after[i]=tv
+                    end
+                  end
+                end
+              end
+              local current=rule.current
+              if current then
+                local tv=tables[current]
+                if tv then
+                  rule.current=tv
+                  current=unpacked[tv]
+                end
+                if current then
+                  for i=1,#current do
+                    local tv=tables[current[i]]
+                    if tv then
+                      current[i]=tv
+                    end
+                  end
+                end
+              end
+              local replacements=rule.replacements
+              if replacements then
+                local tv=tables[replacements]
+                if tv then
+                  rule.replacements=tv
+                end
+              end
+              local fore=rule.fore
+              if fore then
+                local tv=tables[fore]
+                if tv then
+                  rule.fore=tv
+                end
+              end
+              local back=rule.back
+              if back then
+                local tv=tables[back]
+                if tv then
+                  rule.back=tv
+                end
+              end
+              local names=rule.names
+              if names then
+                local tv=tables[names]
+                if tv then
+                  rule.names=tv
+                end
+              end
+              local lookups=rule.lookups
+              if lookups then
+                local tv=tables[lookups]
+                if tv then
+                  rule.lookups=tv
+                end
+              end
+            end
+          end
+        end
+      end
+      local anchor_to_lookup=resources.anchor_to_lookup
+      if anchor_to_lookup then
+        for anchor,lookup in next,anchor_to_lookup do
+          local tv=tables[lookup]
+          if tv then
+            anchor_to_lookup[anchor]=tv
+          end
+        end
+      end
+      local lookup_to_anchor=resources.lookup_to_anchor
+      if lookup_to_anchor then
+        for lookup,anchor in next,lookup_to_anchor do
+          local tv=tables[anchor]
+          if tv then
+            lookup_to_anchor[lookup]=tv
+          end
+        end
+      end
+      local ls=resources.sequences
+      if ls then
+        for _,feature in next,ls do
+          local flags=feature.flags
+          if flags then
+            local tv=tables[flags]
+            if tv then
+              feature.flags=tv
+            end
+          end
+          local subtables=feature.subtables
+          if subtables then
+            local tv=tables[subtables]
+            if tv then
+              feature.subtables=tv
+            end
+          end
+          local features=feature.features
+          if features then
+            local tv=tables[features]
+            if tv then
+              feature.features=tv
+              features=unpacked[tv]
+            end
+            if features then
+              for script,data in next,features do
+                local tv=tables[data]
+                if tv then
+                  features[script]=tv
+                end
+              end
+            end
+          end
         end
-      else
-        report_prepare("missing lookuptype for lookupname %a",lookupname)
       end
-    end
-  end
-end
-local function featuresinitializer(tfmdata,value)
-  if true then
-    local rawdata=tfmdata.shared.rawdata
-    local properties=rawdata.properties
-    if not properties.initialized then
-      local starttime=trace_preparing and os.clock()
-      local resources=rawdata.resources
-      resources.lookuphash=resources.lookuphash or {}
-      prepare_contextchains(tfmdata)
-      prepare_lookups(tfmdata)
-      properties.initialized=true
-      if trace_preparing then
-        report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname)
+      local lookups=resources.lookups
+      if lookups then
+        for _,lookup in next,lookups do
+          local flags=lookup.flags
+          if flags then
+            local tv=tables[flags]
+            if tv then
+              lookup.flags=tv
+            end
+          end
+          local subtables=lookup.subtables
+          if subtables then
+            local tv=tables[subtables]
+            if tv then
+              lookup.subtables=tv
+            end
+          end
+        end
+      end
+      local features=resources.features
+      if features then
+        for _,what in next,glists do
+          local feature=features[what]
+          if feature then
+            for tag,spec in next,feature do
+              local tv=tables[spec]
+              if tv then
+                feature[tag]=tv
+              end
+            end
+          end
+        end
       end
+      data.tables=nil
     end
   end
 end
-registerotffeature {
-  name="features",
-  description="features",
-  default=true,
-  initializers={
-    position=1,
-    node=featuresinitializer,
-  },
-  processors={
-    node=featuresprocessor,
-  }
-}
-otf.handlers=handlers
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['font-otp']={
-  version=1.001,
-  comment="companion to font-otf.lua (packing)",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
-}
-local next,type=next,type
-local sort,concat=table.sort,table.concat
-local sortedhash=table.sortedhash
-local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end)
-local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
-local report_otf=logs.reporter("fonts","otf loading")
-fonts=fonts or {}
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
-local otf=handlers.otf or {}
-handlers.otf=otf
-local enhancers=otf.enhancers or {}
-otf.enhancers=enhancers
-local glists=otf.glists or { "gsub","gpos" }
-otf.glists=glists
-local criterium=1
-local threshold=0
-local function tabstr_normal(t)
-  local s={}
-  local n=0
-  for k,v in next,t do
-    n=n+1
-    if type(v)=="table" then
-      s[n]=k..">"..tabstr_normal(v)
-    elseif v==true then
-      s[n]=k.."+" 
-    elseif v then
-      s[n]=k.."="..v
-    else
-      s[n]=k.."-" 
-    end
-  end
-  if n==0 then
-    return ""
-  elseif n==1 then
-    return s[1]
-  else
-    sort(s) 
-    return concat(s,",")
-  end
-end
-local function tabstr_flat(t)
-  local s={}
-  local n=0
-  for k,v in next,t do
-    n=n+1
-    s[n]=k.."="..v
-  end
-  if n==0 then
-    return ""
-  elseif n==1 then
-    return s[1]
-  else
-    sort(s) 
-    return concat(s,",")
-  end
-end
-local function tabstr_mixed(t) 
-  local s={}
-  local n=#t
-  if n==0 then
-    return ""
-  elseif n==1 then
-    local k=t[1]
-    if k==true then
-      return "++" 
-    elseif k==false then
-      return "--" 
-    else
-      return tostring(k) 
-    end
-  else
-    for i=1,n do
-      local k=t[i]
-      if k==true then
-        s[i]="++" 
-      elseif k==false then
-        s[i]="--" 
-      else
-        s[i]=k 
-      end
-    end
-    return concat(s,",")
-  end
-end
-local function tabstr_boolean(t)
-  local s={}
-  local n=0
-  for k,v in next,t do
-    n=n+1
-    if v then
-      s[n]=k.."+"
-    else
-      s[n]=k.."-"
-    end
-  end
-  if n==0 then
-    return ""
-  elseif n==1 then
-    return s[1]
-  else
-    sort(s) 
-    return concat(s,",")
-  end
-end
-local function packdata(data)
-  if data then
-    local h,t,c={},{},{}
-    local hh,tt,cc={},{},{}
-    local nt,ntt=0,0
-    local function pack_normal(v)
-      local tag=tabstr_normal(v)
-      local ht=h[tag]
-      if ht then
-        c[ht]=c[ht]+1
-        return ht
-      else
-        nt=nt+1
-        t[nt]=v
-        h[tag]=nt
-        c[nt]=1
-        return nt
-      end
-    end
-    local function pack_flat(v)
-      local tag=tabstr_flat(v)
-      local ht=h[tag]
-      if ht then
-        c[ht]=c[ht]+1
-        return ht
-      else
-        nt=nt+1
-        t[nt]=v
-        h[tag]=nt
-        c[nt]=1
-        return nt
-      end
-    end
-    local function pack_boolean(v)
-      local tag=tabstr_boolean(v)
-      local ht=h[tag]
-      if ht then
-        c[ht]=c[ht]+1
-        return ht
-      else
-        nt=nt+1
-        t[nt]=v
-        h[tag]=nt
-        c[nt]=1
-        return nt
-      end
-    end
-    local function pack_indexed(v)
-      local tag=concat(v," ")
-      local ht=h[tag]
-      if ht then
-        c[ht]=c[ht]+1
-        return ht
-      else
-        nt=nt+1
-        t[nt]=v
-        h[tag]=nt
-        c[nt]=1
-        return nt
-      end
-    end
-    local function pack_mixed(v)
-      local tag=tabstr_mixed(v)
-      local ht=h[tag]
-      if ht then
-        c[ht]=c[ht]+1
-        return ht
-      else
-        nt=nt+1
-        t[nt]=v
-        h[tag]=nt
-        c[nt]=1
-        return nt
-      end
-    end
-    local function pack_final(v)
-      if c[v]<=criterium then
-        return t[v]
-      else
-        local hv=hh[v]
-        if hv then
-          return hv
-        else
-          ntt=ntt+1
-          tt[ntt]=t[v]
-          hh[v]=ntt
-          cc[ntt]=c[v]
-          return ntt
-        end
-      end
-    end
-    local function success(stage,pass)
-      if nt==0 then
-        if trace_loading or trace_packing then
-          report_otf("pack quality: nothing to pack")
-        end
-        return false
-      elseif nt>=threshold then
-        local one,two,rest=0,0,0
-        if pass==1 then
-          for k,v in next,c do
-            if v==1 then
-              one=one+1
-            elseif v==2 then
-              two=two+1
-            else
-              rest=rest+1
-            end
-          end
-        else
-          for k,v in next,cc do
-            if v>20 then
-              rest=rest+1
-            elseif v>10 then
-              two=two+1
-            else
-              one=one+1
-            end
-          end
-          data.tables=tt
-        end
-        if trace_loading or trace_packing then
-          report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)",stage,pass,one+two+rest,one,two,rest,criterium)
-        end
-        return true
-      else
-        if trace_loading or trace_packing then
-          report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)",stage,pass,nt,threshold)
-        end
-        return false
-      end
-    end
-    local function packers(pass)
-      if pass==1 then
-        return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed
-      else
-        return pack_final,pack_final,pack_final,pack_final,pack_final
-      end
-    end
-    local resources=data.resources
-    local lookuptypes=resources.lookuptypes
-    for pass=1,2 do
-      if trace_packing then
-        report_otf("start packing: stage 1, pass %s",pass)
-      end
-      local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
-      for unicode,description in next,data.descriptions do
-        local boundingbox=description.boundingbox
-        if boundingbox then
-          description.boundingbox=pack_indexed(boundingbox)
-        end
-        local slookups=description.slookups
-        if slookups then
-          for tag,slookup in next,slookups do
-            local what=lookuptypes[tag]
-            if what=="pair" then
-              local t=slookup[2] if t then slookup[2]=pack_indexed(t) end
-              local t=slookup[3] if t then slookup[3]=pack_indexed(t) end
-            elseif what~="substitution" then
-              slookups[tag]=pack_indexed(slookup) 
-            end
-          end
-        end
-        local mlookups=description.mlookups
-        if mlookups then
-          for tag,mlookup in next,mlookups do
-            local what=lookuptypes[tag]
-            if what=="pair" then
-              for i=1,#mlookup do
-                local lookup=mlookup[i]
-                local t=lookup[2] if t then lookup[2]=pack_indexed(t) end
-                local t=lookup[3] if t then lookup[3]=pack_indexed(t) end
-              end
-            elseif what~="substitution" then
-              for i=1,#mlookup do
-                mlookup[i]=pack_indexed(mlookup[i]) 
-              end
-            end
-          end
-        end
-        local kerns=description.kerns
-        if kerns then
-          for tag,kern in next,kerns do
-            kerns[tag]=pack_flat(kern)
-          end
-        end
-        local math=description.math
-        if math then
-          local kerns=math.kerns
-          if kerns then
-            for tag,kern in next,kerns do
-              kerns[tag]=pack_normal(kern)
-            end
-          end
-        end
-        local anchors=description.anchors
-        if anchors then
-          for what,anchor in next,anchors do
-            if what=="baselig" then
-              for _,a in next,anchor do
-                for k=1,#a do
-                  a[k]=pack_indexed(a[k])
-                end
-              end
-            else
-              for k,v in next,anchor do
-                anchor[k]=pack_indexed(v)
-              end
-            end
-          end
-        end
-        local altuni=description.altuni
-        if altuni then
-          for i=1,#altuni do
-            altuni[i]=pack_flat(altuni[i])
-          end
-        end
-      end
-      local lookups=data.lookups
-      if lookups then
-        for _,lookup in next,lookups do
-          local rules=lookup.rules
-          if rules then
-            for i=1,#rules do
-              local rule=rules[i]
-              local r=rule.before    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
-              local r=rule.after    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
-              local r=rule.current   if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
-              local r=rule.replacements if r then rule.replacements=pack_flat  (r)  end 
-              local r=rule.lookups   if r then rule.lookups=pack_indexed(r)  end
-            end
-          end
-        end
-      end
-      local anchor_to_lookup=resources.anchor_to_lookup
-      if anchor_to_lookup then
-        for anchor,lookup in next,anchor_to_lookup do
-          anchor_to_lookup[anchor]=pack_normal(lookup)
-        end
-      end
-      local lookup_to_anchor=resources.lookup_to_anchor
-      if lookup_to_anchor then
-        for lookup,anchor in next,lookup_to_anchor do
-          lookup_to_anchor[lookup]=pack_normal(anchor)
-        end
-      end
-      local sequences=resources.sequences
-      if sequences then
-        for feature,sequence in next,sequences do
-          local flags=sequence.flags
-          if flags then
-            sequence.flags=pack_normal(flags)
-          end
-          local subtables=sequence.subtables
-          if subtables then
-            sequence.subtables=pack_normal(subtables)
-          end
-          local features=sequence.features
-          if features then
-            for script,feature in next,features do
-              features[script]=pack_normal(feature)
-            end
-          end
-        end
-      end
-      local lookups=resources.lookups
-      if lookups then
-        for name,lookup in next,lookups do
-          local flags=lookup.flags
-          if flags then
-            lookup.flags=pack_normal(flags)
-          end
-          local subtables=lookup.subtables
-          if subtables then
-            lookup.subtables=pack_normal(subtables)
-          end
-        end
-      end
-      local features=resources.features
-      if features then
-        for _,what in next,glists do
-          local list=features[what]
-          if list then
-            for feature,spec in next,list do
-              list[feature]=pack_normal(spec)
-            end
-          end
-        end
-      end
-      if not success(1,pass) then
-        return
-      end
-    end
-    if nt>0 then
-      for pass=1,2 do
-        if trace_packing then
-          report_otf("start packing: stage 2, pass %s",pass)
-        end
-        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
-        for unicode,description in next,data.descriptions do
-          local kerns=description.kerns
-          if kerns then
-            description.kerns=pack_normal(kerns)
-          end
-          local math=description.math
-          if math then
-            local kerns=math.kerns
-            if kerns then
-              math.kerns=pack_normal(kerns)
-            end
-          end
-          local anchors=description.anchors
-          if anchors then
-            description.anchors=pack_normal(anchors)
-          end
-          local mlookups=description.mlookups
-          if mlookups then
-            for tag,mlookup in next,mlookups do
-              mlookups[tag]=pack_normal(mlookup)
-            end
-          end
-          local altuni=description.altuni
-          if altuni then
-            description.altuni=pack_normal(altuni)
-          end
-        end
-        local lookups=data.lookups
-        if lookups then
-          for _,lookup in next,lookups do
-            local rules=lookup.rules
-            if rules then
-              for i=1,#rules do 
-                local rule=rules[i]
-                local r=rule.before if r then rule.before=pack_normal(r) end
-                local r=rule.after  if r then rule.after=pack_normal(r) end
-                local r=rule.current if r then rule.current=pack_normal(r) end
-              end
-            end
-          end
-        end
-        local sequences=resources.sequences
-        if sequences then
-          for feature,sequence in next,sequences do
-            sequence.features=pack_normal(sequence.features)
-          end
-        end
-        if not success(2,pass) then
-        end
-      end
-      for pass=1,2 do
-        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
-        for unicode,description in next,data.descriptions do
-          local slookups=description.slookups
-          if slookups then
-            description.slookups=pack_normal(slookups)
-          end
-          local mlookups=description.mlookups
-          if mlookups then
-            description.mlookups=pack_normal(mlookups)
-          end
-        end
-      end
-    end
-  end
-end
-local unpacked_mt={
-  __index=function(t,k)
-      t[k]=false
-      return k 
-    end
-}
-local function unpackdata(data)
-  if data then
-    local tables=data.tables
-    if tables then
-      local resources=data.resources
-      local lookuptypes=resources.lookuptypes
-      local unpacked={}
-      setmetatable(unpacked,unpacked_mt)
-      for unicode,description in next,data.descriptions do
-        local tv=tables[description.boundingbox]
-        if tv then
-          description.boundingbox=tv
-        end
-        local slookups=description.slookups
-        if slookups then
-          local tv=tables[slookups]
-          if tv then
-            description.slookups=tv
-            slookups=unpacked[tv]
-          end
-          if slookups then
-            for tag,lookup in next,slookups do
-              local what=lookuptypes[tag]
-              if what=="pair" then
-                local tv=tables[lookup[2]]
-                if tv then
-                  lookup[2]=tv
-                end
-                local tv=tables[lookup[3]]
-                if tv then
-                  lookup[3]=tv
-                end
-              elseif what~="substitution" then
-                local tv=tables[lookup]
-                if tv then
-                  slookups[tag]=tv
-                end
-              end
-            end
-          end
-        end
-        local mlookups=description.mlookups
-        if mlookups then
-          local tv=tables[mlookups]
-          if tv then
-            description.mlookups=tv
-            mlookups=unpacked[tv]
-          end
-          if mlookups then
-            for tag,list in next,mlookups do
-              local tv=tables[list]
-              if tv then
-                mlookups[tag]=tv
-                list=unpacked[tv]
-              end
-              if list then
-                local what=lookuptypes[tag]
-                if what=="pair" then
-                  for i=1,#list do
-                    local lookup=list[i]
-                    local tv=tables[lookup[2]]
-                    if tv then
-                      lookup[2]=tv
-                    end
-                    local tv=tables[lookup[3]]
-                    if tv then
-                      lookup[3]=tv
-                    end
-                  end
-                elseif what~="substitution" then
-                  for i=1,#list do
-                    local tv=tables[list[i]]
-                    if tv then
-                      list[i]=tv
-                    end
-                  end
-                end
-              end
-            end
-          end
-        end
-        local kerns=description.kerns
-        if kerns then
-          local tm=tables[kerns]
-          if tm then
-            description.kerns=tm
-            kerns=unpacked[tm]
-          end
-          if kerns then
-            for k,kern in next,kerns do
-              local tv=tables[kern]
-              if tv then
-                kerns[k]=tv
-              end
-            end
-          end
-        end
-        local math=description.math
-        if math then
-          local kerns=math.kerns
-          if kerns then
-            local tm=tables[kerns]
-            if tm then
-              math.kerns=tm
-              kerns=unpacked[tm]
-            end
-            if kerns then
-              for k,kern in next,kerns do
-                local tv=tables[kern]
-                if tv then
-                  kerns[k]=tv
-                end
-              end
-            end
-          end
-        end
-        local anchors=description.anchors
-        if anchors then
-          local ta=tables[anchors]
-          if ta then
-            description.anchors=ta
-            anchors=unpacked[ta]
-          end
-          if anchors then
-            for tag,anchor in next,anchors do
-              if tag=="baselig" then
-                for _,list in next,anchor do
-                  for i=1,#list do
-                    local tv=tables[list[i]]
-                    if tv then
-                      list[i]=tv
-                    end
-                  end
-                end
-              else
-                for a,data in next,anchor do
-                  local tv=tables[data]
-                  if tv then
-                    anchor[a]=tv
-                  end
-                end
-              end
-            end
-          end
-        end
-        local altuni=description.altuni
-        if altuni then
-          local altuni=tables[altuni]
-          if altuni then
-            description.altuni=altuni
-            for i=1,#altuni do
-              local tv=tables[altuni[i]]
-              if tv then
-                altuni[i]=tv
-              end
-            end
-          end
-        end
-      end
-      local lookups=data.lookups
-      if lookups then
-        for _,lookup in next,lookups do
-          local rules=lookup.rules
-          if rules then
-            for i=1,#rules do 
-              local rule=rules[i]
-              local before=rule.before
-              if before then
-                local tv=tables[before]
-                if tv then
-                  rule.before=tv
-                  before=unpacked[tv]
-                end
-                if before then
-                  for i=1,#before do
-                    local tv=tables[before[i]]
-                    if tv then
-                      before[i]=tv
-                    end
-                  end
-                end
-              end
-              local after=rule.after
-              if after then
-                local tv=tables[after]
-                if tv then
-                  rule.after=tv
-                  after=unpacked[tv]
-                end
-                if after then
-                  for i=1,#after do
-                    local tv=tables[after[i]]
-                    if tv then
-                      after[i]=tv
-                    end
-                  end
-                end
-              end
-              local current=rule.current
-              if current then
-                local tv=tables[current]
-                if tv then
-                  rule.current=tv
-                  current=unpacked[tv]
-                end
-                if current then
-                  for i=1,#current do
-                    local tv=tables[current[i]]
-                    if tv then
-                      current[i]=tv
-                    end
-                  end
-                end
-              end
-              local replacements=rule.replacements
-              if replacements then
-                local tv=tables[replacements]
-                if tv then
-                  rule.replacements=tv
-                end
-              end
-              local fore=rule.fore
-              if fore then
-                local tv=tables[fore]
-                if tv then
-                  rule.fore=tv
-                end
-              end
-              local back=rule.back
-              if back then
-                local tv=tables[back]
-                if tv then
-                  rule.back=tv
-                end
-              end
-              local names=rule.names
-              if names then
-                local tv=tables[names]
-                if tv then
-                  rule.names=tv
-                end
-              end
-              local lookups=rule.lookups
-              if lookups then
-                local tv=tables[lookups]
-                if tv then
-                  rule.lookups=tv
-                end
-              end
-            end
-          end
-        end
-      end
-      local anchor_to_lookup=resources.anchor_to_lookup
-      if anchor_to_lookup then
-        for anchor,lookup in next,anchor_to_lookup do
-          local tv=tables[lookup]
-          if tv then
-            anchor_to_lookup[anchor]=tv
-          end
-        end
-      end
-      local lookup_to_anchor=resources.lookup_to_anchor
-      if lookup_to_anchor then
-        for lookup,anchor in next,lookup_to_anchor do
-          local tv=tables[anchor]
-          if tv then
-            lookup_to_anchor[lookup]=tv
-          end
-        end
-      end
-      local ls=resources.sequences
-      if ls then
-        for _,feature in next,ls do
-          local flags=feature.flags
-          if flags then
-            local tv=tables[flags]
-            if tv then
-              feature.flags=tv
-            end
-          end
-          local subtables=feature.subtables
-          if subtables then
-            local tv=tables[subtables]
-            if tv then
-              feature.subtables=tv
-            end
-          end
-          local features=feature.features
-          if features then
-            local tv=tables[features]
-            if tv then
-              feature.features=tv
-              features=unpacked[tv]
-            end
-            if features then
-              for script,data in next,features do
-                local tv=tables[data]
-                if tv then
-                  features[script]=tv
-                end
-              end
-            end
-          end
-        end
-      end
-      local lookups=resources.lookups
-      if lookups then
-        for _,lookup in next,lookups do
-          local flags=lookup.flags
-          if flags then
-            local tv=tables[flags]
-            if tv then
-              lookup.flags=tv
-            end
-          end
-          local subtables=lookup.subtables
-          if subtables then
-            local tv=tables[subtables]
-            if tv then
-              lookup.subtables=tv
-            end
-          end
-        end
-      end
-      local features=resources.features
-      if features then
-        for _,what in next,glists do
-          local feature=features[what]
-          if feature then
-            for tag,spec in next,feature do
-              local tv=tables[spec]
-              if tv then
-                feature[tag]=tv
-              end
-            end
-          end
-        end
-      end
-      data.tables=nil
-    end
-  end
-end
 if otf.enhancers.register then
-  otf.enhancers.register("pack",packdata)
+  otf.enhancers.register("pack",packdata)
   otf.enhancers.register("unpack",unpackdata)
 end
 otf.enhancers.unpack=unpackdata 
@@ -11266,118 +11266,118 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-fonts-lua']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-fonts-lua']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
-local fonts=fonts
+local fonts=fonts
 fonts.formats.lua="lua"
-function fonts.readers.lua(specification)
-  local fullname=specification.filename or ""
-  if fullname=="" then
-    local forced=specification.forced or ""
-    if forced~="" then
-      fullname=specification.name.."."..forced
-    else
-      fullname=specification.name
-    end
-  end
-  local fullname=resolvers.findfile(fullname) or ""
-  if fullname~="" then
-    local loader=loadfile(fullname)
-    loader=loader and loader()
-    return loader and loader(specification)
-  end
-end
+function fonts.readers.lua(specification)
+  local fullname=specification.filename or ""
+  if fullname=="" then
+    local forced=specification.forced or ""
+    if forced~="" then
+      fullname=specification.name.."."..forced
+    else
+      fullname=specification.name
+    end
+  end
+  local fullname=resolvers.findfile(fullname) or ""
+  if fullname~="" then
+    local loader=loadfile(fullname)
+    loader=loader and loader()
+    return loader and loader(specification)
+  end
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-def']={
-  version=1.001,
-  comment="companion to font-ini.mkiv",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['font-def']={
+  version=1.001,
+  comment="companion to font-ini.mkiv",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
-local tostring,next=tostring,next
+local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
+local tostring,next=tostring,next
 local lpegmatch=lpeg.match
 local allocate=utilities.storage.allocate
-local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
+local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
 local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
-trackers.register("fonts.loading","fonts.defining","otf.loading","afm.loading","tfm.loading")
+trackers.register("fonts.loading","fonts.defining","otf.loading","afm.loading","tfm.loading")
 trackers.register("fonts.all","fonts.*","otf.*","afm.*","tfm.*")
 local report_defining=logs.reporter("fonts","defining")
-local fonts=fonts
-local fontdata=fonts.hashes.identifiers
-local readers=fonts.readers
-local definers=fonts.definers
-local specifiers=fonts.specifiers
-local constructors=fonts.constructors
+local fonts=fonts
+local fontdata=fonts.hashes.identifiers
+local readers=fonts.readers
+local definers=fonts.definers
+local specifiers=fonts.specifiers
+local constructors=fonts.constructors
 local fontgoodies=fonts.goodies
 readers.sequence=allocate { 'otf','ttf','afm','tfm','lua' } 
-local variants=allocate()
+local variants=allocate()
 specifiers.variants=variants
 definers.methods=definers.methods or {}
 local internalized=allocate() 
 local lastdefined=nil 
-local loadedfonts=constructors.loadedfonts
+local loadedfonts=constructors.loadedfonts
 local designsizes=constructors.designsizes
 local resolvefile=fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end
 local splitter,splitspecifiers=nil,"" 
 local P,C,S,Cc=lpeg.P,lpeg.C,lpeg.S,lpeg.Cc
-local left=P("(")
-local right=P(")")
-local colon=P(":")
+local left=P("(")
+local right=P(")")
+local colon=P(":")
 local space=P(" ")
 definers.defaultlookup="file"
 local prefixpattern=P(false)
-local function addspecifier(symbol)
-  splitspecifiers=splitspecifiers..symbol
-  local method=S(splitspecifiers)
-  local lookup=C(prefixpattern)*colon
-  local sub=left*C(P(1-left-right-method)^1)*right
-  local specification=C(method)*C(P(1)^1)
-  local name=C((1-sub-specification)^1)
-  splitter=P((lookup+Cc(""))*name*(sub+Cc(""))*(specification+Cc("")))
-end
-local function addlookup(str,default)
-  prefixpattern=prefixpattern+P(str)
+local function addspecifier(symbol)
+  splitspecifiers=splitspecifiers..symbol
+  local method=S(splitspecifiers)
+  local lookup=C(prefixpattern)*colon
+  local sub=left*C(P(1-left-right-method)^1)*right
+  local specification=C(method)*C(P(1)^1)
+  local name=C((1-sub-specification)^1)
+  splitter=P((lookup+Cc(""))*name*(sub+Cc(""))*(specification+Cc("")))
+end
+local function addlookup(str,default)
+  prefixpattern=prefixpattern+P(str)
 end
 definers.addlookup=addlookup
-addlookup("file")
-addlookup("name")
+addlookup("file")
+addlookup("name")
 addlookup("spec")
-local function getspecification(str)
-  return lpegmatch(splitter,str)
+local function getspecification(str)
+  return lpegmatch(splitter,str)
 end
 definers.getspecification=getspecification
-function definers.registersplit(symbol,action,verbosename)
-  addspecifier(symbol)
-  variants[symbol]=action
-  if verbosename then
-    variants[verbosename]=action
-  end
-end
-local function makespecification(specification,lookup,name,sub,method,detail,size)
-  size=size or 655360
-  if not lookup or lookup=="" then
-    lookup=definers.defaultlookup
-  end
-  if trace_defining then
-    report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a",
-      specification,lookup,name,sub,method,detail)
-  end
-  local t={
+function definers.registersplit(symbol,action,verbosename)
+  addspecifier(symbol)
+  variants[symbol]=action
+  if verbosename then
+    variants[verbosename]=action
+  end
+end
+local function makespecification(specification,lookup,name,sub,method,detail,size)
+  size=size or 655360
+  if not lookup or lookup=="" then
+    lookup=definers.defaultlookup
+  end
+  if trace_defining then
+    report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a",
+      specification,lookup,name,sub,method,detail)
+  end
+  local t={
     lookup=lookup,
     specification=specification,
     size=size,
@@ -11388,477 +11388,477 @@ local function makespecification(specification,lookup,name,sub,method,detail,siz
     resolved="",
     forced="",
     features={},
-  }
-  return t
+  }
+  return t
 end
 definers.makespecification=makespecification
 function definers.analyze(specification,size)
-  local lookup,name,sub,method,detail=getspecification(specification or "")
-  return makespecification(specification,lookup,name,sub,method,detail,size)
+  local lookup,name,sub,method,detail=getspecification(specification or "")
+  return makespecification(specification,lookup,name,sub,method,detail,size)
 end
-definers.resolvers=definers.resolvers or {}
+definers.resolvers=definers.resolvers or {}
 local resolvers=definers.resolvers
-function resolvers.file(specification)
+function resolvers.file(specification)
   local name=resolvefile(specification.name) 
-  local suffix=file.suffix(name)
-  if fonts.formats[suffix] then
-    specification.forced=suffix
-    specification.name=file.removesuffix(name)
-  else
+  local suffix=file.suffix(name)
+  if fonts.formats[suffix] then
+    specification.forced=suffix
+    specification.name=file.removesuffix(name)
+  else
     specification.name=name 
-  end
+  end
 end
-function resolvers.name(specification)
-  local resolve=fonts.names.resolve
-  if resolve then
+function resolvers.name(specification)
+  local resolve=fonts.names.resolve
+  if resolve then
     local resolved,sub=resolve(specification.name,specification.sub,specification) 
-    if resolved then
-      specification.resolved=resolved
-      specification.sub=sub
-      local suffix=file.suffix(resolved)
-      if fonts.formats[suffix] then
-        specification.forced=suffix
-        specification.name=file.removesuffix(resolved)
-      else
-        specification.name=resolved
-      end
-    end
-  else
-    resolvers.file(specification)
-  end
-end
-function resolvers.spec(specification)
-  local resolvespec=fonts.names.resolvespec
-  if resolvespec then
+    if resolved then
+      specification.resolved=resolved
+      specification.sub=sub
+      local suffix=file.suffix(resolved)
+      if fonts.formats[suffix] then
+        specification.forced=suffix
+        specification.name=file.removesuffix(resolved)
+      else
+        specification.name=resolved
+      end
+    end
+  else
+    resolvers.file(specification)
+  end
+end
+function resolvers.spec(specification)
+  local resolvespec=fonts.names.resolvespec
+  if resolvespec then
     local resolved,sub=resolvespec(specification.name,specification.sub,specification) 
-    if resolved then
-      specification.resolved=resolved
-      specification.sub=sub
-      specification.forced=file.suffix(resolved)
-      specification.name=file.removesuffix(resolved)
-    end
-  else
-    resolvers.name(specification)
-  end
-end
-function definers.resolve(specification)
+    if resolved then
+      specification.resolved=resolved
+      specification.sub=sub
+      specification.forced=file.suffix(resolved)
+      specification.name=file.removesuffix(resolved)
+    end
+  else
+    resolvers.name(specification)
+  end
+end
+function definers.resolve(specification)
   if not specification.resolved or specification.resolved=="" then 
-    local r=resolvers[specification.lookup]
-    if r then
-      r(specification)
-    end
-  end
-  if specification.forced=="" then
-    specification.forced=nil
-  else
-    specification.forced=specification.forced
-  end
-  specification.hash=lower(specification.name..' @ '..constructors.hashfeatures(specification))
-  if specification.sub and specification.sub~="" then
-    specification.hash=specification.sub..' @ '..specification.hash
-  end
-  return specification
-end
-function definers.applypostprocessors(tfmdata)
-  local postprocessors=tfmdata.postprocessors
-  if postprocessors then
-    local properties=tfmdata.properties
-    for i=1,#postprocessors do
+    local r=resolvers[specification.lookup]
+    if r then
+      r(specification)
+    end
+  end
+  if specification.forced=="" then
+    specification.forced=nil
+  else
+    specification.forced=specification.forced
+  end
+  specification.hash=lower(specification.name..' @ '..constructors.hashfeatures(specification))
+  if specification.sub and specification.sub~="" then
+    specification.hash=specification.sub..' @ '..specification.hash
+  end
+  return specification
+end
+function definers.applypostprocessors(tfmdata)
+  local postprocessors=tfmdata.postprocessors
+  if postprocessors then
+    local properties=tfmdata.properties
+    for i=1,#postprocessors do
       local extrahash=postprocessors[i](tfmdata) 
       if type(extrahash)=="string" and extrahash~="" then
-        extrahash=gsub(lower(extrahash),"[^a-z]","-")
-        properties.fullname=format("%s-%s",properties.fullname,extrahash)
-      end
-    end
-  end
-  return tfmdata
-end
-local function checkembedding(tfmdata)
-  local properties=tfmdata.properties
-  local embedding
-  if directive_embedall then
-    embedding="full"
-  elseif properties and properties.filename and constructors.dontembed[properties.filename] then
-    embedding="no"
-  else
-    embedding="subset"
-  end
-  if properties then
-    properties.embedding=embedding
-  else
-    tfmdata.properties={ embedding=embedding }
-  end
-  tfmdata.embedding=embedding
-end
-function definers.loadfont(specification)
-  local hash=constructors.hashinstance(specification)
+        extrahash=gsub(lower(extrahash),"[^a-z]","-")
+        properties.fullname=format("%s-%s",properties.fullname,extrahash)
+      end
+    end
+  end
+  return tfmdata
+end
+local function checkembedding(tfmdata)
+  local properties=tfmdata.properties
+  local embedding
+  if directive_embedall then
+    embedding="full"
+  elseif properties and properties.filename and constructors.dontembed[properties.filename] then
+    embedding="no"
+  else
+    embedding="subset"
+  end
+  if properties then
+    properties.embedding=embedding
+  else
+    tfmdata.properties={ embedding=embedding }
+  end
+  tfmdata.embedding=embedding
+end
+function definers.loadfont(specification)
+  local hash=constructors.hashinstance(specification)
   local tfmdata=loadedfonts[hash] 
-  if not tfmdata then
-    local forced=specification.forced or ""
-    if forced~="" then
-      local reader=readers[lower(forced)]
-      tfmdata=reader and reader(specification)
-      if not tfmdata then
-        report_defining("forced type %a of %a not found",forced,specification.name)
-      end
-    else
+  if not tfmdata then
+    local forced=specification.forced or ""
+    if forced~="" then
+      local reader=readers[lower(forced)]
+      tfmdata=reader and reader(specification)
+      if not tfmdata then
+        report_defining("forced type %a of %a not found",forced,specification.name)
+      end
+    else
       local sequence=readers.sequence 
-      for s=1,#sequence do
-        local reader=sequence[s]
+      for s=1,#sequence do
+        local reader=sequence[s]
         if readers[reader] then 
-          if trace_defining then
-            report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename)
-          end
-          tfmdata=readers[reader](specification)
-          if tfmdata then
-            break
-          else
-            specification.filename=nil
-          end
-        end
-      end
-    end
-    if tfmdata then
-      tfmdata=definers.applypostprocessors(tfmdata)
+          if trace_defining then
+            report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename)
+          end
+          tfmdata=readers[reader](specification)
+          if tfmdata then
+            break
+          else
+            specification.filename=nil
+          end
+        end
+      end
+    end
+    if tfmdata then
+      tfmdata=definers.applypostprocessors(tfmdata)
       checkembedding(tfmdata) 
-      loadedfonts[hash]=tfmdata
-      designsizes[specification.hash]=tfmdata.parameters.designsize
-    end
-  end
-  if not tfmdata then
-    report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup)
-  end
-  return tfmdata
+      loadedfonts[hash]=tfmdata
+      designsizes[specification.hash]=tfmdata.parameters.designsize
+    end
+  end
+  if not tfmdata then
+    report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup)
+  end
+  return tfmdata
 end
 function constructors.checkvirtualids()
 end
 function constructors.readanddefine(name,size) 
-  local specification=definers.analyze(name,size)
-  local method=specification.method
-  if method and variants[method] then
-    specification=variants[method](specification)
-  end
-  specification=definers.resolve(specification)
-  local hash=constructors.hashinstance(specification)
-  local id=definers.registered(hash)
-  if not id then
-    local tfmdata=definers.loadfont(specification)
-    if tfmdata then
-      tfmdata.properties.hash=hash
+  local specification=definers.analyze(name,size)
+  local method=specification.method
+  if method and variants[method] then
+    specification=variants[method](specification)
+  end
+  specification=definers.resolve(specification)
+  local hash=constructors.hashinstance(specification)
+  local id=definers.registered(hash)
+  if not id then
+    local tfmdata=definers.loadfont(specification)
+    if tfmdata then
+      tfmdata.properties.hash=hash
       constructors.checkvirtualids(tfmdata) 
-      id=font.define(tfmdata)
-      definers.register(tfmdata,id)
-    else
+      id=font.define(tfmdata)
+      definers.register(tfmdata,id)
+    else
       id=0 
-    end
-  end
-  return fontdata[id],id
+    end
+  end
+  return fontdata[id],id
 end
 function definers.current() 
-  return lastdefined
-end
-function definers.registered(hash)
-  local id=internalized[hash]
-  return id,id and fontdata[id]
-end
-function definers.register(tfmdata,id)
-  if tfmdata and id then
-    local hash=tfmdata.properties.hash
-    if not hash then
-      report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?")
-    elseif not internalized[hash] then
-      internalized[hash]=id
-      if trace_defining then
-        report_defining("registering font, id %s, hash %a",id,hash)
-      end
-      fontdata[id]=tfmdata
-    end
-  end
+  return lastdefined
+end
+function definers.registered(hash)
+  local id=internalized[hash]
+  return id,id and fontdata[id]
+end
+function definers.register(tfmdata,id)
+  if tfmdata and id then
+    local hash=tfmdata.properties.hash
+    if not hash then
+      report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?")
+    elseif not internalized[hash] then
+      internalized[hash]=id
+      if trace_defining then
+        report_defining("registering font, id %s, hash %a",id,hash)
+      end
+      fontdata[id]=tfmdata
+    end
+  end
 end
 function definers.read(specification,size,id) 
-  statistics.starttiming(fonts)
-  if type(specification)=="string" then
-    specification=definers.analyze(specification,size)
-  end
-  local method=specification.method
-  if method and variants[method] then
-    specification=variants[method](specification)
-  end
-  specification=definers.resolve(specification)
-  local hash=constructors.hashinstance(specification)
+  statistics.starttiming(fonts)
+  if type(specification)=="string" then
+    specification=definers.analyze(specification,size)
+  end
+  local method=specification.method
+  if method and variants[method] then
+    specification=variants[method](specification)
+  end
+  specification=definers.resolve(specification)
+  local hash=constructors.hashinstance(specification)
   local tfmdata=definers.registered(hash) 
-  if tfmdata then
-    if trace_defining then
-      report_defining("already hashed: %s",hash)
-    end
-  else
+  if tfmdata then
+    if trace_defining then
+      report_defining("already hashed: %s",hash)
+    end
+  else
     tfmdata=definers.loadfont(specification) 
-    if tfmdata then
-      if trace_defining then
-        report_defining("loaded and hashed: %s",hash)
-      end
-      tfmdata.properties.hash=hash
-      if id then
-        definers.register(tfmdata,id)
-      end
-    else
-      if trace_defining then
-        report_defining("not loaded and hashed: %s",hash)
-      end
-    end
-  end
+    if tfmdata then
+      if trace_defining then
+        report_defining("loaded and hashed: %s",hash)
+      end
+      tfmdata.properties.hash=hash
+      if id then
+        definers.register(tfmdata,id)
+      end
+    else
+      if trace_defining then
+        report_defining("not loaded and hashed: %s",hash)
+      end
+    end
+  end
   lastdefined=tfmdata or id 
   if not tfmdata then 
-    report_defining("unknown font %a, loading aborted",specification.name)
-  elseif trace_defining and type(tfmdata)=="table" then
-    local properties=tfmdata.properties or {}
-    local parameters=tfmdata.parameters or {}
-    report_defining("using %s font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
-      properties.format,id,properties.name,parameters.size,properties.encodingbytes,
-      properties.encodingname,properties.fullname,file.basename(properties.filename))
-  end
-  statistics.stoptiming(fonts)
-  return tfmdata
-end
-function font.getfont(id)
+    report_defining("unknown font %a, loading aborted",specification.name)
+  elseif trace_defining and type(tfmdata)=="table" then
+    local properties=tfmdata.properties or {}
+    local parameters=tfmdata.parameters or {}
+    report_defining("using %s font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
+      properties.format,id,properties.name,parameters.size,properties.encodingbytes,
+      properties.encodingname,properties.fullname,file.basename(properties.filename))
+  end
+  statistics.stoptiming(fonts)
+  return tfmdata
+end
+function font.getfont(id)
   return fontdata[id] 
 end
-callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
+callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-font-def']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-font-def']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
 local fonts=fonts
 fonts.constructors.namemode="specification"
-function fonts.definers.getspecification(str)
-  return "",str,"",":",str
+function fonts.definers.getspecification(str)
+  return "",str,"",":",str
 end
 local list={}
 local function issome ()  list.lookup='name'     end 
-local function isfile ()  list.lookup='file'     end
-local function isname ()  list.lookup='name'     end
-local function thename(s)  list.name=s        end
-local function issub (v)  list.sub=v        end
-local function iscrap (s)  list.crap=string.lower(s) end
-local function iskey (k,v) list[k]=v        end
-local function istrue (s)  list[s]=true      end
+local function isfile ()  list.lookup='file'     end
+local function isname ()  list.lookup='name'     end
+local function thename(s)  list.name=s        end
+local function issub (v)  list.sub=v        end
+local function iscrap (s)  list.crap=string.lower(s) end
+local function iskey (k,v) list[k]=v        end
+local function istrue (s)  list[s]=true      end
 local function isfalse(s)  list[s]=false      end
 local P,S,R,C=lpeg.P,lpeg.S,lpeg.R,lpeg.C
-local spaces=P(" ")^0
+local spaces=P(" ")^0
 local namespec=(1-S("/:("))^0 
-local crapspec=spaces*P("/")*(((1-P(":"))^0)/iscrap)*spaces
-local filename_1=P("file:")/isfile*(namespec/thename)
-local filename_2=P("[")*P(true)/isname*(((1-P("]"))^0)/thename)*P("]")
-local fontname_1=P("name:")/isname*(namespec/thename)
-local fontname_2=P(true)/issome*(namespec/thename)
-local sometext=(R("az","AZ","09")+S("+-."))^1
-local truevalue=P("+")*spaces*(sometext/istrue)
-local falsevalue=P("-")*spaces*(sometext/isfalse)
-local keyvalue=(C(sometext)*spaces*P("=")*spaces*C(sometext))/iskey
-local somevalue=sometext/istrue
+local crapspec=spaces*P("/")*(((1-P(":"))^0)/iscrap)*spaces
+local filename_1=P("file:")/isfile*(namespec/thename)
+local filename_2=P("[")*P(true)/isname*(((1-P("]"))^0)/thename)*P("]")
+local fontname_1=P("name:")/isname*(namespec/thename)
+local fontname_2=P(true)/issome*(namespec/thename)
+local sometext=(R("az","AZ","09")+S("+-."))^1
+local truevalue=P("+")*spaces*(sometext/istrue)
+local falsevalue=P("-")*spaces*(sometext/isfalse)
+local keyvalue=(C(sometext)*spaces*P("=")*spaces*C(sometext))/iskey
+local somevalue=sometext/istrue
 local subvalue=P("(")*(C(P(1-S("()"))^1)/issub)*P(")") 
-local option=spaces*(keyvalue+falsevalue+truevalue+somevalue)*spaces
+local option=spaces*(keyvalue+falsevalue+truevalue+somevalue)*spaces
 local options=P(":")*spaces*(P(";")^0*option)^0
 local pattern=(filename_1+filename_2+fontname_1+fontname_2)*subvalue^0*crapspec^0*options^0
 local function colonized(specification) 
-  list={}
-  lpeg.match(pattern,specification.specification)
+  list={}
+  lpeg.match(pattern,specification.specification)
   list.crap=nil 
-  if list.name then
-    specification.name=list.name
-    list.name=nil
-  end
-  if list.lookup then
-    specification.lookup=list.lookup
-    list.lookup=nil
-  end
-  if list.sub then
-    specification.sub=list.sub
-    list.sub=nil
-  end
-  specification.features.normal=fonts.handlers.otf.features.normalize(list)
-  return specification
-end
-fonts.definers.registersplit(":",colonized,"cryptic")
+  if list.name then
+    specification.name=list.name
+    list.name=nil
+  end
+  if list.lookup then
+    specification.lookup=list.lookup
+    list.lookup=nil
+  end
+  if list.sub then
+    specification.sub=list.sub
+    list.sub=nil
+  end
+  specification.features.normal=fonts.handlers.otf.features.normalize(list)
+  return specification
+end
+fonts.definers.registersplit(":",colonized,"cryptic")
 fonts.definers.registersplit("",colonized,"more cryptic") 
-function fonts.definers.applypostprocessors(tfmdata)
-  local postprocessors=tfmdata.postprocessors
-  if postprocessors then
-    for i=1,#postprocessors do
+function fonts.definers.applypostprocessors(tfmdata)
+  local postprocessors=tfmdata.postprocessors
+  if postprocessors then
+    for i=1,#postprocessors do
       local extrahash=postprocessors[i](tfmdata) 
       if type(extrahash)=="string" and extrahash~="" then
-        extrahash=string.gsub(lower(extrahash),"[^a-z]","-")
-        tfmdata.properties.fullname=format("%s-%s",tfmdata.properties.fullname,extrahash)
-      end
-    end
-  end
-  return tfmdata
-end
+        extrahash=string.gsub(lower(extrahash),"[^a-z]","-")
+        tfmdata.properties.fullname=format("%s-%s",tfmdata.properties.fullname,extrahash)
+      end
+    end
+  end
+  return tfmdata
+end
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-fonts-ext']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-fonts-ext']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
-local fonts=fonts
+local fonts=fonts
 local otffeatures=fonts.constructors.newfeatures("otf")
-local function initializeitlc(tfmdata,value)
+local function initializeitlc(tfmdata,value)
   if value then
-    local parameters=tfmdata.parameters
-    local italicangle=parameters.italicangle
-    if italicangle and italicangle~=0 then
-      local properties=tfmdata.properties
-      local factor=tonumber(value) or 1
-      properties.hasitalics=true
-      properties.autoitalicamount=factor*(parameters.uwidth or 40)/2
-    end
-  end
-end
-otffeatures.register {
-  name="itlc",
-  description="italic correction",
-  initializers={
-    base=initializeitlc,
-    node=initializeitlc,
-  }
+    local parameters=tfmdata.parameters
+    local italicangle=parameters.italicangle
+    if italicangle and italicangle~=0 then
+      local properties=tfmdata.properties
+      local factor=tonumber(value) or 1
+      properties.hasitalics=true
+      properties.autoitalicamount=factor*(parameters.uwidth or 40)/2
+    end
+  end
+end
+otffeatures.register {
+  name="itlc",
+  description="italic correction",
+  initializers={
+    base=initializeitlc,
+    node=initializeitlc,
+  }
 }
-local function initializeslant(tfmdata,value)
-  value=tonumber(value)
-  if not value then
-    value=0
-  elseif value>1 then
-    value=1
-  elseif value<-1 then
-    value=-1
-  end
-  tfmdata.parameters.slantfactor=value
-end
-otffeatures.register {
-  name="slant",
-  description="slant glyphs",
-  initializers={
-    base=initializeslant,
-    node=initializeslant,
-  }
+local function initializeslant(tfmdata,value)
+  value=tonumber(value)
+  if not value then
+    value=0
+  elseif value>1 then
+    value=1
+  elseif value<-1 then
+    value=-1
+  end
+  tfmdata.parameters.slantfactor=value
+end
+otffeatures.register {
+  name="slant",
+  description="slant glyphs",
+  initializers={
+    base=initializeslant,
+    node=initializeslant,
+  }
 }
-local function initializeextend(tfmdata,value)
-  value=tonumber(value)
-  if not value then
-    value=0
-  elseif value>10 then
-    value=10
-  elseif value<-10 then
-    value=-10
-  end
-  tfmdata.parameters.extendfactor=value
-end
-otffeatures.register {
-  name="extend",
-  description="scale glyphs horizontally",
-  initializers={
-    base=initializeextend,
-    node=initializeextend,
-  }
+local function initializeextend(tfmdata,value)
+  value=tonumber(value)
+  if not value then
+    value=0
+  elseif value>10 then
+    value=10
+  elseif value<-10 then
+    value=-10
+  end
+  tfmdata.parameters.extendfactor=value
+end
+otffeatures.register {
+  name="extend",
+  description="scale glyphs horizontally",
+  initializers={
+    base=initializeextend,
+    node=initializeextend,
+  }
 }
-fonts.protrusions=fonts.protrusions    or {}
+fonts.protrusions=fonts.protrusions    or {}
 fonts.protrusions.setups=fonts.protrusions.setups or {}
 local setups=fonts.protrusions.setups
-local function initializeprotrusion(tfmdata,value)
-  if value then
-    local setup=setups[value]
-    if setup then
-      local factor,left,right=setup.factor or 1,setup.left or 1,setup.right or 1
-      local emwidth=tfmdata.parameters.quad
-      tfmdata.parameters.protrusion={
-        auto=true,
-      }
-      for i,chr in next,tfmdata.characters do
-        local v,pl,pr=setup[i],nil,nil
-        if v then
-          pl,pr=v[1],v[2]
-        end
-        if pl and pl~=0 then chr.left_protruding=left*pl*factor end
-        if pr and pr~=0 then chr.right_protruding=right*pr*factor end
-      end
-    end
-  end
-end
-otffeatures.register {
-  name="protrusion",
-  description="shift characters into the left and or right margin",
-  initializers={
-    base=initializeprotrusion,
-    node=initializeprotrusion,
-  }
+local function initializeprotrusion(tfmdata,value)
+  if value then
+    local setup=setups[value]
+    if setup then
+      local factor,left,right=setup.factor or 1,setup.left or 1,setup.right or 1
+      local emwidth=tfmdata.parameters.quad
+      tfmdata.parameters.protrusion={
+        auto=true,
+      }
+      for i,chr in next,tfmdata.characters do
+        local v,pl,pr=setup[i],nil,nil
+        if v then
+          pl,pr=v[1],v[2]
+        end
+        if pl and pl~=0 then chr.left_protruding=left*pl*factor end
+        if pr and pr~=0 then chr.right_protruding=right*pr*factor end
+      end
+    end
+  end
+end
+otffeatures.register {
+  name="protrusion",
+  description="shift characters into the left and or right margin",
+  initializers={
+    base=initializeprotrusion,
+    node=initializeprotrusion,
+  }
 }
-fonts.expansions=fonts.expansions    or {}
+fonts.expansions=fonts.expansions    or {}
 fonts.expansions.setups=fonts.expansions.setups or {}
 local setups=fonts.expansions.setups
-local function initializeexpansion(tfmdata,value)
-  if value then
-    local setup=setups[value]
-    if setup then
-      local factor=setup.factor or 1
-      tfmdata.parameters.expansion={
-        stretch=10*(setup.stretch or 0),
-        shrink=10*(setup.shrink or 0),
-        step=10*(setup.step  or 0),
-        auto=true,
-      }
-      for i,chr in next,tfmdata.characters do
-        local v=setup[i]
-        if v and v~=0 then
-          chr.expansion_factor=v*factor
+local function initializeexpansion(tfmdata,value)
+  if value then
+    local setup=setups[value]
+    if setup then
+      local factor=setup.factor or 1
+      tfmdata.parameters.expansion={
+        stretch=10*(setup.stretch or 0),
+        shrink=10*(setup.shrink or 0),
+        step=10*(setup.step  or 0),
+        auto=true,
+      }
+      for i,chr in next,tfmdata.characters do
+        local v=setup[i]
+        if v and v~=0 then
+          chr.expansion_factor=v*factor
         else 
-          chr.expansion_factor=factor
-        end
-      end
-    end
-  end
-end
-otffeatures.register {
-  name="expansion",
-  description="apply hz optimization",
-  initializers={
-    base=initializeexpansion,
-    node=initializeexpansion,
-  }
+          chr.expansion_factor=factor
+        end
+      end
+    end
+  end
+end
+otffeatures.register {
+  name="expansion",
+  description="apply hz optimization",
+  initializers={
+    base=initializeexpansion,
+    node=initializeexpansion,
+  }
 }
 function fonts.loggers.onetimemessage() end
 local byte=string.byte
 fonts.expansions.setups['default']={
   stretch=2,shrink=2,step=.5,factor=1,
-  [byte('A')]=0.5,[byte('B')]=0.7,[byte('C')]=0.7,[byte('D')]=0.5,[byte('E')]=0.7,
-  [byte('F')]=0.7,[byte('G')]=0.5,[byte('H')]=0.7,[byte('K')]=0.7,[byte('M')]=0.7,
-  [byte('N')]=0.7,[byte('O')]=0.5,[byte('P')]=0.7,[byte('Q')]=0.5,[byte('R')]=0.7,
-  [byte('S')]=0.7,[byte('U')]=0.7,[byte('W')]=0.7,[byte('Z')]=0.7,
-  [byte('a')]=0.7,[byte('b')]=0.7,[byte('c')]=0.7,[byte('d')]=0.7,[byte('e')]=0.7,
-  [byte('g')]=0.7,[byte('h')]=0.7,[byte('k')]=0.7,[byte('m')]=0.7,[byte('n')]=0.7,
-  [byte('o')]=0.7,[byte('p')]=0.7,[byte('q')]=0.7,[byte('s')]=0.7,[byte('u')]=0.7,
-  [byte('w')]=0.7,[byte('z')]=0.7,
-  [byte('2')]=0.7,[byte('3')]=0.7,[byte('6')]=0.7,[byte('8')]=0.7,[byte('9')]=0.7,
+  [byte('A')]=0.5,[byte('B')]=0.7,[byte('C')]=0.7,[byte('D')]=0.5,[byte('E')]=0.7,
+  [byte('F')]=0.7,[byte('G')]=0.5,[byte('H')]=0.7,[byte('K')]=0.7,[byte('M')]=0.7,
+  [byte('N')]=0.7,[byte('O')]=0.5,[byte('P')]=0.7,[byte('Q')]=0.5,[byte('R')]=0.7,
+  [byte('S')]=0.7,[byte('U')]=0.7,[byte('W')]=0.7,[byte('Z')]=0.7,
+  [byte('a')]=0.7,[byte('b')]=0.7,[byte('c')]=0.7,[byte('d')]=0.7,[byte('e')]=0.7,
+  [byte('g')]=0.7,[byte('h')]=0.7,[byte('k')]=0.7,[byte('m')]=0.7,[byte('n')]=0.7,
+  [byte('o')]=0.7,[byte('p')]=0.7,[byte('q')]=0.7,[byte('s')]=0.7,[byte('u')]=0.7,
+  [byte('w')]=0.7,[byte('z')]=0.7,
+  [byte('2')]=0.7,[byte('3')]=0.7,[byte('6')]=0.7,[byte('8')]=0.7,[byte('9')]=0.7,
 }
 fonts.protrusions.setups['default']={
   factor=1,left=1,right=1,
@@ -11875,120 +11875,120 @@ fonts.protrusions.setups['default']={
   [0x061B]={ 0,1  },
   [0x06D4]={ 0,1  },
 }
-fonts.handlers.otf.features.normalize=function(t)
-  if t.rand then
-    t.rand="random"
-  end
-  return t
-end
-function fonts.helpers.nametoslot(name)
-  local t=type(name)
-  if t=="string" then
-    local tfmdata=fonts.hashes.identifiers[currentfont()]
-    local shared=tfmdata and tfmdata.shared
-    local fntdata=shared and shared.rawdata
-    return fntdata and fntdata.resources.unicodes[name]
-  elseif t=="number" then
-    return n
-  end
-end
-fonts.encodings=fonts.encodings or {}
-local reencodings={}
+fonts.handlers.otf.features.normalize=function(t)
+  if t.rand then
+    t.rand="random"
+  end
+  return t
+end
+function fonts.helpers.nametoslot(name)
+  local t=type(name)
+  if t=="string" then
+    local tfmdata=fonts.hashes.identifiers[currentfont()]
+    local shared=tfmdata and tfmdata.shared
+    local fntdata=shared and shared.rawdata
+    return fntdata and fntdata.resources.unicodes[name]
+  elseif t=="number" then
+    return n
+  end
+end
+fonts.encodings=fonts.encodings or {}
+local reencodings={}
 fonts.encodings.reencodings=reencodings
 local function specialreencode(tfmdata,value)
-  local encoding=value and reencodings[value]
-  if encoding then
-    local temp={}
-    local char=tfmdata.characters
-    for k,v in next,encoding do
-      temp[k]=char[v]
-    end
-    for k,v in next,temp do
-      char[k]=temp[k]
-    end
-    return string.format("reencoded:%s",value)
-  end
-end
-local function reencode(tfmdata,value)
-  tfmdata.postprocessors=tfmdata.postprocessors or {}
-  table.insert(tfmdata.postprocessors,
-    function(tfmdata)
-      return specialreencode(tfmdata,value)
-    end
-  )
-end
-otffeatures.register {
-  name="reencode",
-  description="reencode characters",
-  manipulators={
-    base=reencode,
-    node=reencode,
-  }
-}
+  local encoding=value and reencodings[value]
+  if encoding then
+    local temp={}
+    local char=tfmdata.characters
+    for k,v in next,encoding do
+      temp[k]=char[v]
+    end
+    for k,v in next,temp do
+      char[k]=temp[k]
+    end
+    return string.format("reencoded:%s",value)
+  end
+end
+local function reencode(tfmdata,value)
+  tfmdata.postprocessors=tfmdata.postprocessors or {}
+  table.insert(tfmdata.postprocessors,
+    function(tfmdata)
+      return specialreencode(tfmdata,value)
+    end
+  )
+end
+otffeatures.register {
+  name="reencode",
+  description="reencode characters",
+  manipulators={
+    base=reencode,
+    node=reencode,
+  }
+}
 
 end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-fonts-cbk']={
-  version=1.001,
-  comment="companion to luatex-*.tex",
-  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
-  copyright="PRAGMA ADE / ConTeXt Development Team",
-  license="see context related readme files"
+if not modules then modules={} end modules ['luatex-fonts-cbk']={
+  version=1.001,
+  comment="companion to luatex-*.tex",
+  author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+  copyright="PRAGMA ADE / ConTeXt Development Team",
+  license="see context related readme files"
 }
-if context then
-  texio.write_nl("fatal error: this module is not for context")
-  os.exit()
+if context then
+  texio.write_nl("fatal error: this module is not for context")
+  os.exit()
 end
-local fonts=fonts
+local fonts=fonts
 local nodes=nodes
-local traverse_id=node.traverse_id
+local traverse_id=node.traverse_id
 local glyph_code=nodes.nodecodes.glyph
-function nodes.handlers.characters(head)
-  local fontdata=fonts.hashes.identifiers
-  if fontdata then
-    local usedfonts,done,prevfont={},false,nil
-    for n in traverse_id(glyph_code,head) do
-      local font=n.font
-      if font~=prevfont then
-        prevfont=font
-        local used=usedfonts[font]
-        if not used then
+function nodes.handlers.characters(head)
+  local fontdata=fonts.hashes.identifiers
+  if fontdata then
+    local usedfonts,done,prevfont={},false,nil
+    for n in traverse_id(glyph_code,head) do
+      local font=n.font
+      if font~=prevfont then
+        prevfont=font
+        local used=usedfonts[font]
+        if not used then
           local tfmdata=fontdata[font] 
-          if tfmdata then
+          if tfmdata then
             local shared=tfmdata.shared 
-            if shared then
-              local processors=shared.processes
-              if processors and #processors>0 then
-                usedfonts[font]=processors
-                done=true
-              end
-            end
-          end
-        end
-      end
-    end
-    if done then
-      for font,processors in next,usedfonts do
-        for i=1,#processors do
-          local h,d=processors[i](head,font,0)
-          head,done=h or head,done or d
-        end
-      end
-    end
-    return head,true
-  else
-    return head,false
-  end
+            if shared then
+              local processors=shared.processes
+              if processors and #processors>0 then
+                usedfonts[font]=processors
+                done=true
+              end
+            end
+          end
+        end
+      end
+    end
+    if done then
+      for font,processors in next,usedfonts do
+        for i=1,#processors do
+          local h,d=processors[i](head,font,0)
+          head,done=h or head,done or d
+        end
+      end
+    end
+    return head,true
+  else
+    return head,false
+  end
 end
 function nodes.simple_font_handler(head)
-  head=nodes.handlers.characters(head)
-  nodes.injections.handler(head)
-  nodes.handlers.protectglyphs(head)
-  head=node.ligaturing(head)
-  head=node.kerning(head)
-  return head
-end
+  head=nodes.handlers.characters(head)
+  nodes.injections.handler(head)
+  nodes.handlers.protectglyphs(head)
+  head=node.ligaturing(head)
+  head=node.kerning(head)
+  return head
+end
 
 end -- closure
diff --git a/tex/generic/context/luatex/luatex-fonts-syn.lua b/tex/generic/context/luatex/luatex-fonts-syn.lua
index 50c43bce7..ea6e3cab5 100644
--- a/tex/generic/context/luatex/luatex-fonts-syn.lua
+++ b/tex/generic/context/luatex/luatex-fonts-syn.lua
@@ -1,102 +1,102 @@
-if not modules then modules = { } end modules ['luatex-fonts-syn'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
--- Generic font names support.
---
--- Watch out, the version number is the same as the one used in
--- the mtx-fonts.lua function scripts.fonts.names as we use a
--- simplified font database in the plain solution and by using
--- a different number we're less dependent on context.
---
--- mtxrun --script font --reload --simple
---
--- The format of the file is as follows:
---
--- return {
---     ["version"]       = 1.001,
---     ["cache_version"] = 1.001,
---     ["mappings"]      = {
---         ["somettcfontone"] = { "Some TTC Font One", "SomeFontA.ttc", 1 },
---         ["somettcfonttwo"] = { "Some TTC Font Two", "SomeFontA.ttc", 2 },
---         ["somettffont"]    = { "Some TTF Font",     "SomeFontB.ttf"    },
---         ["someotffont"]    = { "Some OTF Font",     "SomeFontC.otf"    },
---     },
--- }
-
-local fonts = fonts
-fonts.names = fonts.names or { }
-
-fonts.names.version    = 1.001 -- not the same as in context but matches mtx-fonts --simple
-fonts.names.basename   = "luatex-fonts-names"
-fonts.names.new_to_old = { }
-fonts.names.old_to_new = { }
-fonts.names.cache      = containers.define("fonts","data",fonts.names.version,true)
-
-local data, loaded = nil, false
-
-local fileformats = { "lua", "tex", "other text files" }
-
-function fonts.names.reportmissingbase()
-    texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>")
-    fonts.names.reportmissingbase = nil
-end
-
-function fonts.names.reportmissingname()
-    texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>")
-    fonts.names.reportmissingname = nil
-end
-
-function fonts.names.resolve(name,sub)
-    if not loaded then
-        local basename = fonts.names.basename
-        if basename and basename ~= "" then
-            data = containers.read(fonts.names.cache,basename)
-            if not data then
-                basename = file.addsuffix(basename,"lua")
-                for i=1,#fileformats do
-                    local format = fileformats[i]
-                    local foundname = resolvers.findfile(basename,format) or ""
-                    if foundname ~= "" then
-                        data = dofile(foundname)
-                        texio.write("<font database loaded: ",foundname,">")
-                        break
-                    end
-                end
-            end
-        end
-        loaded = true
-    end
-    if type(data) == "table" and data.version == fonts.names.version then
-        local condensed = string.gsub(string.lower(name),"[^%a%d]","")
-        local found = data.mappings and data.mappings[condensed]
-        if found then
-            local fontname, filename, subfont = found[1], found[2], found[3]
-            if subfont then
-                return filename, fontname
-            else
-                return filename, false
-            end
-        elseif fonts.names.reportmissingname then
-            fonts.names.reportmissingname()
-            return name, false -- fallback to filename
-        end
-    elseif fonts.names.reportmissingbase then
-        fonts.names.reportmissingbase()
-    end
-end
-
-fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv
-
-function fonts.names.getfilename(askedname,suffix)  -- only supported in mkiv
-    return ""
-end
+if not modules then modules = { } end modules ['luatex-fonts-syn'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+-- Generic font names support.
+--
+-- Watch out, the version number is the same as the one used in
+-- the mtx-fonts.lua function scripts.fonts.names as we use a
+-- simplified font database in the plain solution and by using
+-- a different number we're less dependent on context.
+--
+-- mtxrun --script font --reload --simple
+--
+-- The format of the file is as follows:
+--
+-- return {
+--     ["version"]       = 1.001,
+--     ["cache_version"] = 1.001,
+--     ["mappings"]      = {
+--         ["somettcfontone"] = { "Some TTC Font One", "SomeFontA.ttc", 1 },
+--         ["somettcfonttwo"] = { "Some TTC Font Two", "SomeFontA.ttc", 2 },
+--         ["somettffont"]    = { "Some TTF Font",     "SomeFontB.ttf"    },
+--         ["someotffont"]    = { "Some OTF Font",     "SomeFontC.otf"    },
+--     },
+-- }
+
+local fonts = fonts
+fonts.names = fonts.names or { }
+
+fonts.names.version    = 1.001 -- not the same as in context but matches mtx-fonts --simple
+fonts.names.basename   = "luatex-fonts-names"
+fonts.names.new_to_old = { }
+fonts.names.old_to_new = { }
+fonts.names.cache      = containers.define("fonts","data",fonts.names.version,true)
+
+local data, loaded = nil, false
+
+local fileformats = { "lua", "tex", "other text files" }
+
+function fonts.names.reportmissingbase()
+    texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>")
+    fonts.names.reportmissingbase = nil
+end
+
+function fonts.names.reportmissingname()
+    texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>")
+    fonts.names.reportmissingname = nil
+end
+
+function fonts.names.resolve(name,sub)
+    if not loaded then
+        local basename = fonts.names.basename
+        if basename and basename ~= "" then
+            data = containers.read(fonts.names.cache,basename)
+            if not data then
+                basename = file.addsuffix(basename,"lua")
+                for i=1,#fileformats do
+                    local format = fileformats[i]
+                    local foundname = resolvers.findfile(basename,format) or ""
+                    if foundname ~= "" then
+                        data = dofile(foundname)
+                        texio.write("<font database loaded: ",foundname,">")
+                        break
+                    end
+                end
+            end
+        end
+        loaded = true
+    end
+    if type(data) == "table" and data.version == fonts.names.version then
+        local condensed = string.gsub(string.lower(name),"[^%a%d]","")
+        local found = data.mappings and data.mappings[condensed]
+        if found then
+            local fontname, filename, subfont = found[1], found[2], found[3]
+            if subfont then
+                return filename, fontname
+            else
+                return filename, false
+            end
+        elseif fonts.names.reportmissingname then
+            fonts.names.reportmissingname()
+            return name, false -- fallback to filename
+        end
+    elseif fonts.names.reportmissingbase then
+        fonts.names.reportmissingbase()
+    end
+end
+
+fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv
+
+function fonts.names.getfilename(askedname,suffix)  -- only supported in mkiv
+    return ""
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-tfm.lua b/tex/generic/context/luatex/luatex-fonts-tfm.lua
index 3939d8000..b9bb1bd0f 100644
--- a/tex/generic/context/luatex/luatex-fonts-tfm.lua
+++ b/tex/generic/context/luatex/luatex-fonts-tfm.lua
@@ -1,38 +1,38 @@
-if not modules then modules = { } end modules ['luatex-fonts-tfm'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-if context then
-    texio.write_nl("fatal error: this module is not for context")
-    os.exit()
-end
-
-local fonts        = fonts
-local tfm          = { }
-fonts.handlers.tfm = tfm
-fonts.formats.tfm  = "type1" -- we need to have at least a value here
-
-function fonts.readers.tfm(specification)
-    local fullname = specification.filename or ""
-    if fullname == "" then
-        local forced = specification.forced or ""
-        if forced ~= "" then
-            fullname = specification.name .. "." .. forced
-        else
-            fullname = specification.name
-        end
-    end
-    local foundname = resolvers.findbinfile(fullname, 'tfm') or ""
-    if foundname == "" then
-        foundname = resolvers.findbinfile(fullname, 'ofm') or ""
-    end
-    if foundname ~= "" then
-        specification.filename = foundname
-        specification.format   = "ofm"
-        return font.read_tfm(specification.filename,specification.size)
-    end
-end
+if not modules then modules = { } end modules ['luatex-fonts-tfm'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-*.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+if context then
+    texio.write_nl("fatal error: this module is not for context")
+    os.exit()
+end
+
+local fonts        = fonts
+local tfm          = { }
+fonts.handlers.tfm = tfm
+fonts.formats.tfm  = "type1" -- we need to have at least a value here
+
+function fonts.readers.tfm(specification)
+    local fullname = specification.filename or ""
+    if fullname == "" then
+        local forced = specification.forced or ""
+        if forced ~= "" then
+            fullname = specification.name .. "." .. forced
+        else
+            fullname = specification.name
+        end
+    end
+    local foundname = resolvers.findbinfile(fullname, 'tfm') or ""
+    if foundname == "" then
+        foundname = resolvers.findbinfile(fullname, 'ofm') or ""
+    end
+    if foundname ~= "" then
+        specification.filename = foundname
+        specification.format   = "ofm"
+        return font.read_tfm(specification.filename,specification.size)
+    end
+end
diff --git a/tex/generic/context/luatex/luatex-languages.lua b/tex/generic/context/luatex/luatex-languages.lua
index f7be83c84..1ea8c1fd1 100644
--- a/tex/generic/context/luatex/luatex-languages.lua
+++ b/tex/generic/context/luatex/luatex-languages.lua
@@ -1,45 +1,45 @@
-if not modules then modules = { } end modules ['luatex-languages'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-languages.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
--- We borrow from ConTeXt.
-
-languages = languages or { }
-
-local loaded = { }
-
-function languages.loadpatterns(tag)
-    if not loaded[tag] then
-        loaded[tag] = 0
-        local filename = kpse.find_file("lang-" .. tag .. ".lua")
-        if filename and filename == "" then
-            print("<unknown language file for: " .. tag .. ">")
-        else
-            local whatever = loadfile(filename)
-            if type(whatever) == "function" then
-                whatever = whatever()
-                if type(whatever) == "table" then
-                    local characters = whatever.patterns.characters or ""
-                    local patterns = whatever.patterns.data or ""
-                    local exceptions = whatever.exceptions.data or ""
-                    local language = lang.new()
-                    for b in string.utfvalues(characters) do
-                        tex.setlccode(b,b)
-                    end
-                    lang.patterns(language, patterns)
-                    lang.hyphenation(language, exceptions)
-                    loaded[tag] = lang.id(language)
-                else
-                    print("<invalid language table: " .. tag .. ">")
-                end
-            else
-                print("<invalid language file: " .. tag .. ">")
-            end
-        end
-    end
-    return loaded[tag]
-end
+if not modules then modules = { } end modules ['luatex-languages'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-languages.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- We borrow from ConTeXt.
+
+languages = languages or { }
+
+local loaded = { }
+
+function languages.loadpatterns(tag)
+    if not loaded[tag] then
+        loaded[tag] = 0
+        local filename = kpse.find_file("lang-" .. tag .. ".lua")
+        if filename and filename == "" then
+            print("<unknown language file for: " .. tag .. ">")
+        else
+            local whatever = loadfile(filename)
+            if type(whatever) == "function" then
+                whatever = whatever()
+                if type(whatever) == "table" then
+                    local characters = whatever.patterns.characters or ""
+                    local patterns = whatever.patterns.data or ""
+                    local exceptions = whatever.exceptions.data or ""
+                    local language = lang.new()
+                    for b in string.utfvalues(characters) do
+                        tex.setlccode(b,b)
+                    end
+                    lang.patterns(language, patterns)
+                    lang.hyphenation(language, exceptions)
+                    loaded[tag] = lang.id(language)
+                else
+                    print("<invalid language table: " .. tag .. ">")
+                end
+            else
+                print("<invalid language file: " .. tag .. ">")
+            end
+        end
+    end
+    return loaded[tag]
+end
diff --git a/tex/generic/context/luatex/luatex-math.lua b/tex/generic/context/luatex/luatex-math.lua
index 66d712d64..c316182ba 100644
--- a/tex/generic/context/luatex/luatex-math.lua
+++ b/tex/generic/context/luatex/luatex-math.lua
@@ -1,53 +1,53 @@
-if not modules then modules = { } end modules ['luatex-math'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-math.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local gaps = {
-    [0x1D455] = 0x0210E,
-    [0x1D49D] = 0x0212C,
-    [0x1D4A0] = 0x02130,
-    [0x1D4A1] = 0x02131,
-    [0x1D4A3] = 0x0210B,
-    [0x1D4A4] = 0x02110,
-    [0x1D4A7] = 0x02112,
-    [0x1D4A8] = 0x02133,
-    [0x1D4AD] = 0x0211B,
-    [0x1D4BA] = 0x0212F,
-    [0x1D4BC] = 0x0210A,
-    [0x1D4C4] = 0x02134,
-    [0x1D506] = 0x0212D,
-    [0x1D50B] = 0x0210C,
-    [0x1D50C] = 0x02111,
-    [0x1D515] = 0x0211C,
-    [0x1D51D] = 0x02128,
-    [0x1D53A] = 0x02102,
-    [0x1D53F] = 0x0210D,
-    [0x1D545] = 0x02115,
-    [0x1D547] = 0x02119,
-    [0x1D548] = 0x0211A,
-    [0x1D549] = 0x0211D,
-    [0x1D551] = 0x02124,
-}
-
-
-local function fixmath(tfmdata,key,value)
-    if value then
-        local characters = tfmdata.characters
-        for gap, mess in pairs(gaps) do
-            characters[gap] = characters[mess]
-        end
-    end
-end
-
-fonts.handlers.otf.features.register {
-    name         = "fixmath",
-    description  = "math font fixing",
-    manipulators = {
-        base = fixmath,
-        node = fixmath,
-    }
-}
+if not modules then modules = { } end modules ['luatex-math'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-math.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local gaps = {
+    [0x1D455] = 0x0210E,
+    [0x1D49D] = 0x0212C,
+    [0x1D4A0] = 0x02130,
+    [0x1D4A1] = 0x02131,
+    [0x1D4A3] = 0x0210B,
+    [0x1D4A4] = 0x02110,
+    [0x1D4A7] = 0x02112,
+    [0x1D4A8] = 0x02133,
+    [0x1D4AD] = 0x0211B,
+    [0x1D4BA] = 0x0212F,
+    [0x1D4BC] = 0x0210A,
+    [0x1D4C4] = 0x02134,
+    [0x1D506] = 0x0212D,
+    [0x1D50B] = 0x0210C,
+    [0x1D50C] = 0x02111,
+    [0x1D515] = 0x0211C,
+    [0x1D51D] = 0x02128,
+    [0x1D53A] = 0x02102,
+    [0x1D53F] = 0x0210D,
+    [0x1D545] = 0x02115,
+    [0x1D547] = 0x02119,
+    [0x1D548] = 0x0211A,
+    [0x1D549] = 0x0211D,
+    [0x1D551] = 0x02124,
+}
+
+
+local function fixmath(tfmdata,key,value)
+    if value then
+        local characters = tfmdata.characters
+        for gap, mess in pairs(gaps) do
+            characters[gap] = characters[mess]
+        end
+    end
+end
+
+fonts.handlers.otf.features.register {
+    name         = "fixmath",
+    description  = "math font fixing",
+    manipulators = {
+        base = fixmath,
+        node = fixmath,
+    }
+}
diff --git a/tex/generic/context/luatex/luatex-mplib.lua b/tex/generic/context/luatex/luatex-mplib.lua
index 74f7dbced..c6628acb3 100644
--- a/tex/generic/context/luatex/luatex-mplib.lua
+++ b/tex/generic/context/luatex/luatex-mplib.lua
@@ -1,491 +1,491 @@
-if not modules then modules = { } end modules ['luatex-mplib'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-mplib.tex",
-    author    = "Hans Hagen & Taco Hoekwater",
-    copyright = "ConTeXt Development Team",
-    license   = "public domain",
-}
-
---[[ldx--
-<p>This module is a stripped down version of libraries that are used
-by <l n='context'/>. It can be used in other macro packages and/or
-serve as an example. Embedding in a macro package is upto others and
-normally boils down to inputting <t>supp-mpl.tex</t>.</p>
---ldx]]--
-
-if metapost and metapost.version then
-
-    --[[ldx--
-    <p>Let's silently quit and make sure that no one loads it
-    manually in <l n='context'/>.</p>
-    --ldx]]--
-
-else
-
-    local format, concat, abs, match = string.format, table.concat, math.abs, string.match
-
-    local mplib = require ('mplib')
-    local kpse  = require ('kpse')
-
-    --[[ldx--
-    <p>We create a namespace and some variables to it. If a namespace is
-    already defined it wil not be initialized. This permits hooking
-    in code beforehand.</p>
-
-    <p>We don't make a format automatically. After all, distributions
-    might have their own preferences and normally a format (mem) file will
-    have some special place in the <l n='tex'/> tree. Also, there can already
-    be format files, different memort settings and other nasty pitfalls that
-    we don't want to interfere with. If you want, you can define a function
-    <t>metapost.make(name,mem_name) that does the job.</t></p>
-    --ldx]]--
-
-    metapost          = metapost or { }
-    metapost.version  = 1.00
-    metapost.showlog  = metapost.showlog or false
-    metapost.lastlog  = ""
-
-    --[[ldx--
-    <p>A few helpers, taken from <t>l-file.lua</t>.</p>
-    --ldx]]--
-
-    local file = file or { }
-
-    function file.replacesuffix(filename, suffix)
-        return (string.gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
-    end
-
-    function file.stripsuffix(filename)
-        return (string.gsub(filename,"%.[%a%d]+$",""))
-    end
-
-    --[[ldx--
-    <p>We use the <l n='kpse'/> library unless a finder is already
-    defined.</p>
-    --ldx]]--
-
-    local mpkpse = kpse.new("luatex","mpost")
-
-    metapost.finder = metapost.finder or function(name, mode, ftype)
-        if mode == "w" then
-            return name
-        else
-            return mpkpse:find_file(name,ftype)
-        end
-    end
-
-    --[[ldx--
-    <p>You can use your own reported if needed, as long as it handles multiple
-    arguments and formatted strings.</p>
-    --ldx]]--
-
-    metapost.report = metapost.report or function(...)
-        texio.write(format("<mplib: %s>",format(...)))
-    end
-
-    --[[ldx--
-    <p>The rest of this module is not documented. More info can be found in the
-    <l n='luatex'/> manual, articles in user group journals and the files that
-    ship with <l n='context'/>.</p>
-    --ldx]]--
-
-    function metapost.resetlastlog()
-        metapost.lastlog = ""
-    end
-
-    local mplibone = tonumber(mplib.version()) <= 1.50
-
-    if mplibone then
-
-        metapost.make = metapost.make or function(name,mem_name,dump)
-            local t = os.clock()
-            local mpx = mplib.new {
-                ini_version = true,
-                find_file = metapost.finder,
-                job_name = file.stripsuffix(name)
-            }
-            mpx:execute(string.format("input %s ;",name))
-            if dump then
-                mpx:execute("dump ;")
-                metapost.report("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
-            else
-                metapost.report("%s read in %0.3f seconds",name,os.clock()-t)
-            end
-            return mpx
-        end
-
-        function metapost.load(name)
-            local mem_name = file.replacesuffix(name,"mem")
-            local mpx = mplib.new {
-                ini_version = false,
-                mem_name = mem_name,
-                find_file = metapost.finder
-            }
-            if not mpx and type(metapost.make) == "function" then
-                -- when i have time i'll locate the format and dump
-                mpx = metapost.make(name,mem_name)
-            end
-            if mpx then
-                metapost.report("using format %s",mem_name,false)
-                return mpx, nil
-            else
-                return nil, { status = 99, error = "out of memory or invalid format" }
-            end
-        end
-
-    else
-
-        local preamble = [[
-            boolean mplib ; mplib := true ;
-            let dump = endinput ;
-            input %s ;
-        ]]
-
-        metapost.make = metapost.make or function()
-        end
-
-        function metapost.load(name)
-            local mpx = mplib.new {
-                ini_version = true,
-                find_file = metapost.finder,
-            }
-            local result
-            if not mpx then
-                result = { status = 99, error = "out of memory"}
-            else
-                result = mpx:execute(format(preamble, file.replacesuffix(name,"mp")))
-            end
-            metapost.reporterror(result)
-            return mpx, result
-        end
-
-    end
-
-    function metapost.unload(mpx)
-        if mpx then
-            mpx:finish()
-        end
-    end
-
-    function metapost.reporterror(result)
-        if not result then
-            metapost.report("mp error: no result object returned")
-        elseif result.status > 0 then
-            local t, e, l = result.term, result.error, result.log
-            if t then
-                metapost.report("mp terminal: %s",t)
-            end
-            if e then
-                metapost.report("mp error: %s", e)
-            end
-            if not t and not e and l then
-                metapost.lastlog = metapost.lastlog .. "\n " .. l
-                metapost.report("mp log: %s",l)
-            else
-                metapost.report("mp error: unknown, no error, terminal or log messages")
-            end
-        else
-            return false
-        end
-        return true
-    end
-
-    function metapost.process(mpx, data)
-        local converted, result = false, {}
-        mpx = metapost.load(mpx)
-        if mpx and data then
-            local result = mpx:execute(data)
-            if not result then
-                metapost.report("mp error: no result object returned")
-            elseif result.status > 0 then
-                metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
-            elseif metapost.showlog then
-                metapost.lastlog = metapost.lastlog .. "\n" .. result.term
-                metapost.report("mp info: %s",result.term or "no-term")
-            elseif result.fig then
-                converted = metapost.convert(result)
-            else
-                metapost.report("mp error: unknown error, maybe no beginfig/endfig")
-            end
-        else
-           metapost.report("mp error: mem file not found")
-        end
-        return converted, result
-    end
-
-    local function getobjects(result,figure,f)
-        return figure:objects()
-    end
-
-    function metapost.convert(result, flusher)
-        metapost.flush(result, flusher)
-        return true -- done
-    end
-
-    --[[ldx--
-    <p>We removed some message and tracing code. We might even remove the flusher</p>
-    --ldx]]--
-
-    local function pdf_startfigure(n,llx,lly,urx,ury)
-        tex.sprint(format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
-    end
-
-    local function pdf_stopfigure()
-        tex.sprint("\\stopMPLIBtoPDF")
-    end
-
-    function pdf_literalcode(fmt,...) -- table
-        tex.sprint(format("\\MPLIBtoPDF{%s}",format(fmt,...)))
-    end
-
-    function pdf_textfigure(font,size,text,width,height,depth)
-        text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost
-        tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-( 7200/ 7227)/65536*depth))
-    end
-
-    local bend_tolerance = 131/65536
-
-    local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
-
-    local function pen_characteristics(object)
-        local t = mplib.pen_info(object)
-        rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
-        divider = sx*sy - rx*ry
-        return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
-    end
-
-    local function concat(px, py) -- no tx, ty here
-        return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
-    end
-
-    local function curved(ith,pth)
-        local d = pth.left_x - ith.right_x
-        if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
-            d = pth.left_y - ith.right_y
-            if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
-                return false
-            end
-        end
-        return true
-    end
-
-    local function flushnormalpath(path,open)
-        local pth, ith
-        for i=1,#path do
-            pth = path[i]
-            if not ith then
-                pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord)
-            elseif curved(ith,pth) then
-                pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
-            else
-                pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord)
-            end
-            ith = pth
-        end
-        if not open then
-            local one = path[1]
-            if curved(pth,one) then
-                pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
-            else
-                pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
-            end
-        elseif #path == 1 then
-            -- special case .. draw point
-            local one = path[1]
-            pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
-        end
-        return t
-    end
-
-    local function flushconcatpath(path,open)
-        pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
-        local pth, ith
-        for i=1,#path do
-            pth = path[i]
-            if not ith then
-               pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord))
-            elseif curved(ith,pth) then
-                local a, b = concat(ith.right_x,ith.right_y)
-                local c, d = concat(pth.left_x,pth.left_y)
-                pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
-            else
-               pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord))
-            end
-            ith = pth
-        end
-        if not open then
-            local one = path[1]
-            if curved(pth,one) then
-                local a, b = concat(pth.right_x,pth.right_y)
-                local c, d = concat(one.left_x,one.left_y)
-                pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
-            else
-                pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
-            end
-        elseif #path == 1 then
-            -- special case .. draw point
-            local one = path[1]
-            pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
-        end
-        return t
-    end
-
-    --[[ldx--
-    <p>Support for specials has been removed.</p>
-    --ldx]]--
-
-    function metapost.flush(result,flusher)
-        if result then
-            local figures = result.fig
-            if figures then
-                for f=1, #figures do
-                    metapost.report("flushing figure %s",f)
-                    local figure = figures[f]
-                    local objects = getobjects(result,figure,f)
-                    local fignum = tonumber(match(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
-                    local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
-                    local bbox = figure:boundingbox()
-                    local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
-                    if urx < llx then
-                        -- invalid
-                        pdf_startfigure(fignum,0,0,0,0)
-                        pdf_stopfigure()
-                    else
-                        pdf_startfigure(fignum,llx,lly,urx,ury)
-                        pdf_literalcode("q")
-                        if objects then
-                            for o=1,#objects do
-                                local object = objects[o]
-                                local objecttype = object.type
-                                if objecttype == "start_bounds" or objecttype == "stop_bounds" then
-                                    -- skip
-                                elseif objecttype == "start_clip" then
-                                    pdf_literalcode("q")
-                                    flushnormalpath(object.path,t,false)
-                                    pdf_literalcode("W n")
-                                elseif objecttype == "stop_clip" then
-                                    pdf_literalcode("Q")
-                                    miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
-                                elseif objecttype == "special" then
-                                    -- not supported
-                                elseif objecttype == "text" then
-                                    local ot = object.transform -- 3,4,5,6,1,2
-                                    pdf_literalcode("q %f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2])
-                                    pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
-                                    pdf_literalcode("Q")
-                                else
-                                    local cs = object.color
-                                    if cs and #cs > 0 then
-                                        pdf_literalcode(metapost.colorconverter(cs))
-                                    end
-                                    local ml = object.miterlimit
-                                    if ml and ml ~= miterlimit then
-                                        miterlimit = ml
-                                        pdf_literalcode("%f M",ml)
-                                    end
-                                    local lj = object.linejoin
-                                    if lj and lj ~= linejoin then
-                                        linejoin = lj
-                                        pdf_literalcode("%i j",lj)
-                                    end
-                                    local lc = object.linecap
-                                    if lc and lc ~= linecap then
-                                        linecap = lc
-                                        pdf_literalcode("%i J",lc)
-                                    end
-                                    local dl = object.dash
-                                    if dl then
-                                        local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
-                                        if d ~= dashed then
-                                            dashed = d
-                                            pdf_literalcode(dashed)
-                                        end
-                                    elseif dashed then
-                                       pdf_literalcode("[] 0 d")
-                                       dashed = false
-                                    end
-                                    local path = object.path
-                                    local transformed, penwidth = false, 1
-                                    local open = path and path[1].left_type and path[#path].right_type
-                                    local pen = object.pen
-                                    if pen then
-                                       if pen.type == 'elliptical' then
-                                            transformed, penwidth = pen_characteristics(object) -- boolean, value
-                                            pdf_literalcode("%f w",penwidth)
-                                            if objecttype == 'fill' then
-                                                objecttype = 'both'
-                                            end
-                                       else -- calculated by mplib itself
-                                            objecttype = 'fill'
-                                       end
-                                    end
-                                    if transformed then
-                                        pdf_literalcode("q")
-                                    end
-                                    if path then
-                                        if transformed then
-                                            flushconcatpath(path,open)
-                                        else
-                                            flushnormalpath(path,open)
-                                        end
-                                        if objecttype == "fill" then
-                                            pdf_literalcode("h f")
-                                        elseif objecttype == "outline" then
-                                            pdf_literalcode((open and "S") or "h S")
-                                        elseif objecttype == "both" then
-                                            pdf_literalcode("h B")
-                                        end
-                                    end
-                                    if transformed then
-                                        pdf_literalcode("Q")
-                                    end
-                                    local path = object.htap
-                                    if path then
-                                        if transformed then
-                                            pdf_literalcode("q")
-                                        end
-                                        if transformed then
-                                            flushconcatpath(path,open)
-                                        else
-                                            flushnormalpath(path,open)
-                                        end
-                                        if objecttype == "fill" then
-                                            pdf_literalcode("h f")
-                                        elseif objecttype == "outline" then
-                                            pdf_literalcode((open and "S") or "h S")
-                                        elseif objecttype == "both" then
-                                            pdf_literalcode("h B")
-                                        end
-                                        if transformed then
-                                            pdf_literalcode("Q")
-                                        end
-                                    end
-                                    if cr then
-                                        pdf_literalcode(cr)
-                                    end
-                                end
-                           end
-                        end
-                        pdf_literalcode("Q")
-                        pdf_stopfigure()
-                    end
-                end
-            end
-        end
-    end
-
-    function metapost.colorconverter(cr)
-        local n = #cr
-        if n == 4 then
-            local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
-            return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G"
-        elseif n == 3 then
-            local r, g, b = cr[1], cr[2], cr[3]
-            return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G"
-        else
-            local s = cr[1]
-            return format("%.3f g %.3f G",s,s), "0 g 0 G"
-        end
-    end
-
-end
+if not modules then modules = { } end modules ['luatex-mplib'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-mplib.tex",
+    author    = "Hans Hagen & Taco Hoekwater",
+    copyright = "ConTeXt Development Team",
+    license   = "public domain",
+}
+
+--[[ldx--
+<p>This module is a stripped down version of libraries that are used
+by <l n='context'/>. It can be used in other macro packages and/or
+serve as an example. Embedding in a macro package is upto others and
+normally boils down to inputting <t>supp-mpl.tex</t>.</p>
+--ldx]]--
+
+if metapost and metapost.version then
+
+    --[[ldx--
+    <p>Let's silently quit and make sure that no one loads it
+    manually in <l n='context'/>.</p>
+    --ldx]]--
+
+else
+
+    local format, concat, abs, match = string.format, table.concat, math.abs, string.match
+
+    local mplib = require ('mplib')
+    local kpse  = require ('kpse')
+
+    --[[ldx--
+    <p>We create a namespace and some variables to it. If a namespace is
+    already defined it wil not be initialized. This permits hooking
+    in code beforehand.</p>
+
+    <p>We don't make a format automatically. After all, distributions
+    might have their own preferences and normally a format (mem) file will
+    have some special place in the <l n='tex'/> tree. Also, there can already
+    be format files, different memort settings and other nasty pitfalls that
+    we don't want to interfere with. If you want, you can define a function
+    <t>metapost.make(name,mem_name) that does the job.</t></p>
+    --ldx]]--
+
+    metapost          = metapost or { }
+    metapost.version  = 1.00
+    metapost.showlog  = metapost.showlog or false
+    metapost.lastlog  = ""
+
+    --[[ldx--
+    <p>A few helpers, taken from <t>l-file.lua</t>.</p>
+    --ldx]]--
+
+    local file = file or { }
+
+    function file.replacesuffix(filename, suffix)
+        return (string.gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+    end
+
+    function file.stripsuffix(filename)
+        return (string.gsub(filename,"%.[%a%d]+$",""))
+    end
+
+    --[[ldx--
+    <p>We use the <l n='kpse'/> library unless a finder is already
+    defined.</p>
+    --ldx]]--
+
+    local mpkpse = kpse.new("luatex","mpost")
+
+    metapost.finder = metapost.finder or function(name, mode, ftype)
+        if mode == "w" then
+            return name
+        else
+            return mpkpse:find_file(name,ftype)
+        end
+    end
+
+    --[[ldx--
+    <p>You can use your own reported if needed, as long as it handles multiple
+    arguments and formatted strings.</p>
+    --ldx]]--
+
+    metapost.report = metapost.report or function(...)
+        texio.write(format("<mplib: %s>",format(...)))
+    end
+
+    --[[ldx--
+    <p>The rest of this module is not documented. More info can be found in the
+    <l n='luatex'/> manual, articles in user group journals and the files that
+    ship with <l n='context'/>.</p>
+    --ldx]]--
+
+    function metapost.resetlastlog()
+        metapost.lastlog = ""
+    end
+
+    local mplibone = tonumber(mplib.version()) <= 1.50
+
+    if mplibone then
+
+        metapost.make = metapost.make or function(name,mem_name,dump)
+            local t = os.clock()
+            local mpx = mplib.new {
+                ini_version = true,
+                find_file = metapost.finder,
+                job_name = file.stripsuffix(name)
+            }
+            mpx:execute(string.format("input %s ;",name))
+            if dump then
+                mpx:execute("dump ;")
+                metapost.report("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
+            else
+                metapost.report("%s read in %0.3f seconds",name,os.clock()-t)
+            end
+            return mpx
+        end
+
+        function metapost.load(name)
+            local mem_name = file.replacesuffix(name,"mem")
+            local mpx = mplib.new {
+                ini_version = false,
+                mem_name = mem_name,
+                find_file = metapost.finder
+            }
+            if not mpx and type(metapost.make) == "function" then
+                -- when i have time i'll locate the format and dump
+                mpx = metapost.make(name,mem_name)
+            end
+            if mpx then
+                metapost.report("using format %s",mem_name,false)
+                return mpx, nil
+            else
+                return nil, { status = 99, error = "out of memory or invalid format" }
+            end
+        end
+
+    else
+
+        local preamble = [[
+            boolean mplib ; mplib := true ;
+            let dump = endinput ;
+            input %s ;
+        ]]
+
+        metapost.make = metapost.make or function()
+        end
+
+        function metapost.load(name)
+            local mpx = mplib.new {
+                ini_version = true,
+                find_file = metapost.finder,
+            }
+            local result
+            if not mpx then
+                result = { status = 99, error = "out of memory"}
+            else
+                result = mpx:execute(format(preamble, file.replacesuffix(name,"mp")))
+            end
+            metapost.reporterror(result)
+            return mpx, result
+        end
+
+    end
+
+    function metapost.unload(mpx)
+        if mpx then
+            mpx:finish()
+        end
+    end
+
+    function metapost.reporterror(result)
+        if not result then
+            metapost.report("mp error: no result object returned")
+        elseif result.status > 0 then
+            local t, e, l = result.term, result.error, result.log
+            if t then
+                metapost.report("mp terminal: %s",t)
+            end
+            if e then
+                metapost.report("mp error: %s", e)
+            end
+            if not t and not e and l then
+                metapost.lastlog = metapost.lastlog .. "\n " .. l
+                metapost.report("mp log: %s",l)
+            else
+                metapost.report("mp error: unknown, no error, terminal or log messages")
+            end
+        else
+            return false
+        end
+        return true
+    end
+
+    function metapost.process(mpx, data)
+        local converted, result = false, {}
+        mpx = metapost.load(mpx)
+        if mpx and data then
+            local result = mpx:execute(data)
+            if not result then
+                metapost.report("mp error: no result object returned")
+            elseif result.status > 0 then
+                metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+            elseif metapost.showlog then
+                metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+                metapost.report("mp info: %s",result.term or "no-term")
+            elseif result.fig then
+                converted = metapost.convert(result)
+            else
+                metapost.report("mp error: unknown error, maybe no beginfig/endfig")
+            end
+        else
+           metapost.report("mp error: mem file not found")
+        end
+        return converted, result
+    end
+
+    local function getobjects(result,figure,f)
+        return figure:objects()
+    end
+
+    function metapost.convert(result, flusher)
+        metapost.flush(result, flusher)
+        return true -- done
+    end
+
+    --[[ldx--
+    <p>We removed some message and tracing code. We might even remove the flusher</p>
+    --ldx]]--
+
+    local function pdf_startfigure(n,llx,lly,urx,ury)
+        tex.sprint(format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
+    end
+
+    local function pdf_stopfigure()
+        tex.sprint("\\stopMPLIBtoPDF")
+    end
+
+    function pdf_literalcode(fmt,...) -- table
+        tex.sprint(format("\\MPLIBtoPDF{%s}",format(fmt,...)))
+    end
+
+    function pdf_textfigure(font,size,text,width,height,depth)
+        text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost
+        tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-( 7200/ 7227)/65536*depth))
+    end
+
+    local bend_tolerance = 131/65536
+
+    local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+
+    local function pen_characteristics(object)
+        local t = mplib.pen_info(object)
+        rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
+        divider = sx*sy - rx*ry
+        return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
+    end
+
+    local function concat(px, py) -- no tx, ty here
+        return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+    end
+
+    local function curved(ith,pth)
+        local d = pth.left_x - ith.right_x
+        if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
+            d = pth.left_y - ith.right_y
+            if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
+                return false
+            end
+        end
+        return true
+    end
+
+    local function flushnormalpath(path,open)
+        local pth, ith
+        for i=1,#path do
+            pth = path[i]
+            if not ith then
+                pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord)
+            elseif curved(ith,pth) then
+                pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+            else
+                pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord)
+            end
+            ith = pth
+        end
+        if not open then
+            local one = path[1]
+            if curved(pth,one) then
+                pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+            else
+                pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
+            end
+        elseif #path == 1 then
+            -- special case .. draw point
+            local one = path[1]
+            pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
+        end
+        return t
+    end
+
+    local function flushconcatpath(path,open)
+        pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
+        local pth, ith
+        for i=1,#path do
+            pth = path[i]
+            if not ith then
+               pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord))
+            elseif curved(ith,pth) then
+                local a, b = concat(ith.right_x,ith.right_y)
+                local c, d = concat(pth.left_x,pth.left_y)
+                pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
+            else
+               pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord))
+            end
+            ith = pth
+        end
+        if not open then
+            local one = path[1]
+            if curved(pth,one) then
+                local a, b = concat(pth.right_x,pth.right_y)
+                local c, d = concat(one.left_x,one.left_y)
+                pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
+            else
+                pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+            end
+        elseif #path == 1 then
+            -- special case .. draw point
+            local one = path[1]
+            pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+        end
+        return t
+    end
+
+    --[[ldx--
+    <p>Support for specials has been removed.</p>
+    --ldx]]--
+
+    function metapost.flush(result,flusher)
+        if result then
+            local figures = result.fig
+            if figures then
+                for f=1, #figures do
+                    metapost.report("flushing figure %s",f)
+                    local figure = figures[f]
+                    local objects = getobjects(result,figure,f)
+                    local fignum = tonumber(match(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
+                    local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+                    local bbox = figure:boundingbox()
+                    local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+                    if urx < llx then
+                        -- invalid
+                        pdf_startfigure(fignum,0,0,0,0)
+                        pdf_stopfigure()
+                    else
+                        pdf_startfigure(fignum,llx,lly,urx,ury)
+                        pdf_literalcode("q")
+                        if objects then
+                            for o=1,#objects do
+                                local object = objects[o]
+                                local objecttype = object.type
+                                if objecttype == "start_bounds" or objecttype == "stop_bounds" then
+                                    -- skip
+                                elseif objecttype == "start_clip" then
+                                    pdf_literalcode("q")
+                                    flushnormalpath(object.path,t,false)
+                                    pdf_literalcode("W n")
+                                elseif objecttype == "stop_clip" then
+                                    pdf_literalcode("Q")
+                                    miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+                                elseif objecttype == "special" then
+                                    -- not supported
+                                elseif objecttype == "text" then
+                                    local ot = object.transform -- 3,4,5,6,1,2
+                                    pdf_literalcode("q %f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2])
+                                    pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
+                                    pdf_literalcode("Q")
+                                else
+                                    local cs = object.color
+                                    if cs and #cs > 0 then
+                                        pdf_literalcode(metapost.colorconverter(cs))
+                                    end
+                                    local ml = object.miterlimit
+                                    if ml and ml ~= miterlimit then
+                                        miterlimit = ml
+                                        pdf_literalcode("%f M",ml)
+                                    end
+                                    local lj = object.linejoin
+                                    if lj and lj ~= linejoin then
+                                        linejoin = lj
+                                        pdf_literalcode("%i j",lj)
+                                    end
+                                    local lc = object.linecap
+                                    if lc and lc ~= linecap then
+                                        linecap = lc
+                                        pdf_literalcode("%i J",lc)
+                                    end
+                                    local dl = object.dash
+                                    if dl then
+                                        local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
+                                        if d ~= dashed then
+                                            dashed = d
+                                            pdf_literalcode(dashed)
+                                        end
+                                    elseif dashed then
+                                       pdf_literalcode("[] 0 d")
+                                       dashed = false
+                                    end
+                                    local path = object.path
+                                    local transformed, penwidth = false, 1
+                                    local open = path and path[1].left_type and path[#path].right_type
+                                    local pen = object.pen
+                                    if pen then
+                                       if pen.type == 'elliptical' then
+                                            transformed, penwidth = pen_characteristics(object) -- boolean, value
+                                            pdf_literalcode("%f w",penwidth)
+                                            if objecttype == 'fill' then
+                                                objecttype = 'both'
+                                            end
+                                       else -- calculated by mplib itself
+                                            objecttype = 'fill'
+                                       end
+                                    end
+                                    if transformed then
+                                        pdf_literalcode("q")
+                                    end
+                                    if path then
+                                        if transformed then
+                                            flushconcatpath(path,open)
+                                        else
+                                            flushnormalpath(path,open)
+                                        end
+                                        if objecttype == "fill" then
+                                            pdf_literalcode("h f")
+                                        elseif objecttype == "outline" then
+                                            pdf_literalcode((open and "S") or "h S")
+                                        elseif objecttype == "both" then
+                                            pdf_literalcode("h B")
+                                        end
+                                    end
+                                    if transformed then
+                                        pdf_literalcode("Q")
+                                    end
+                                    local path = object.htap
+                                    if path then
+                                        if transformed then
+                                            pdf_literalcode("q")
+                                        end
+                                        if transformed then
+                                            flushconcatpath(path,open)
+                                        else
+                                            flushnormalpath(path,open)
+                                        end
+                                        if objecttype == "fill" then
+                                            pdf_literalcode("h f")
+                                        elseif objecttype == "outline" then
+                                            pdf_literalcode((open and "S") or "h S")
+                                        elseif objecttype == "both" then
+                                            pdf_literalcode("h B")
+                                        end
+                                        if transformed then
+                                            pdf_literalcode("Q")
+                                        end
+                                    end
+                                    if cr then
+                                        pdf_literalcode(cr)
+                                    end
+                                end
+                           end
+                        end
+                        pdf_literalcode("Q")
+                        pdf_stopfigure()
+                    end
+                end
+            end
+        end
+    end
+
+    function metapost.colorconverter(cr)
+        local n = #cr
+        if n == 4 then
+            local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+            return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G"
+        elseif n == 3 then
+            local r, g, b = cr[1], cr[2], cr[3]
+            return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G"
+        else
+            local s = cr[1]
+            return format("%.3f g %.3f G",s,s), "0 g 0 G"
+        end
+    end
+
+end
diff --git a/tex/generic/context/luatex/luatex-preprocessor.lua b/tex/generic/context/luatex/luatex-preprocessor.lua
index 610fe4b4d..8faa0b47e 100644
--- a/tex/generic/context/luatex/luatex-preprocessor.lua
+++ b/tex/generic/context/luatex/luatex-preprocessor.lua
@@ -1,163 +1,163 @@
-if not modules then modules = { } end modules ['luatex-preprocessor'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-preprocessor.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
---[[ldx
-<p>This is a stripped down version of the preprocessor. In
-<l n='context'/> we have a bit more, use a different logger, and
-use a few optimizations. A few examples are shown at the end.</p>
---ldx]]
-
-local rep, sub, gmatch = string.rep, string.sub, string.gmatch
-local insert, remove = table.insert, table.remove
-local setmetatable = setmetatable
-
-local stack, top, n, hashes = { }, nil, 0, { }
-
-local function set(s)
-    if top then
-        n = n + 1
-        if n > 9 then
-            texio.write_nl("number of arguments > 9, ignoring: " .. s)
-        else
-            local ns = #stack
-            local h = hashes[ns]
-            if not h then
-                h = rep("#",ns)
-                hashes[ns] = h
-            end
-            m = h .. n
-            top[s] = m
-            return m
-        end
-    end
-end
-
-local function get(s)
-    local m = top and top[s] or s
-    return m
-end
-
-local function push()
-    top = { }
-    n = 0
-    local s = stack[#stack]
-    if s then
-        setmetatable(top,{ __index = s })
-    end
-    insert(stack,top)
-end
-
-local function pop()
-    top = remove(stack)
-end
-
-local leftbrace   = lpeg.P("{")
-local rightbrace  = lpeg.P("}")
-local escape      = lpeg.P("\\")
-
-local space       = lpeg.P(" ")
-local spaces      = space^1
-local newline     = lpeg.S("\r\n")
-local nobrace     = 1 - leftbrace - rightbrace
-
-local name        = lpeg.R("AZ","az")^1
-local longname    = (leftbrace/"") * (nobrace^1) * (rightbrace/"")
-local variable    = lpeg.P("#") * lpeg.Cs(name + longname)
-local escapedname = escape * name
-local definer     = escape * (lpeg.P("def") + lpeg.P("egdx") * lpeg.P("def"))
-local anything    = lpeg.P(1)
-local always      = lpeg.P(true)
-
-local pushlocal   = always   / push
-local poplocal    = always   / pop
-local declaration = variable / set
-local identifier  = variable / get
-
-local function matcherror(str,pos)
-    texio.write_nl("runaway definition at: " .. sub(str,pos-30,pos))
-end
-
-local parser = lpeg.Cs { "converter",
-    definition  = pushlocal
-                * definer
-                * escapedname
-                * (declaration + (1-leftbrace))^0
-                * lpeg.V("braced")
-                * poplocal,
-    braced      = leftbrace
-                * (   lpeg.V("definition")
-                    + identifier
-                    + lpeg.V("braced")
-                    + nobrace
-                  )^0
-                * (rightbrace + lpeg.Cmt(always,matcherror)),
-    converter   = (lpeg.V("definition") + anything)^1,
-}
-
---[[ldx
-<p>We provide a few commands.</p>
---ldx]]
-
--- local texkpse
-
-local function find_file(...)
- -- texkpse = texkpse or kpse.new("luatex","tex")
- -- return texkpse:find_file(...) or ""
-    return kpse.find_file(...) or ""
-end
-
-commands = commands or { }
-
-function commands.preprocessed(str)
-    return lpeg.match(parser,str)
-end
-
-function commands.inputpreprocessed(name)
-    local name = find_file(name) or ""
-    if name ~= "" then
-     -- we could use io.loaddata as it's loaded in luatex-plain
-        local f = io.open(name,'rb')
-        if f then
-            texio.write("("..name)
-            local d = commands.preprocessed(f:read("*a"))
-            if d and d ~= "" then
-                texio.write("processed: " .. name)
-                for s in gmatch(d,"[^\n\r]+") do
-                    tex.print(s) -- we do a dumb feedback
-                end
-            end
-            f:close()
-            texio.write(")")
-        else
-            tex.error("preprocessor error, invalid file: " .. name)
-        end
-    else
-        tex.error("preprocessor error, unknown file: " .. name)
-    end
-end
-
-function commands.preprocessfile(oldfile,newfile) -- no checking
-    if oldfile and oldfile ~= newfile then
-        local f = io.open(oldfile,'rb')
-        if f then
-            local g = io.open(newfile,'wb')
-            if g then
-                g:write(lpeg.match(parser,f:read("*a") or ""))
-                g:close()
-            end
-            f:close()
-        end
-    end
-end
-
---~ print(preprocessed([[\def\test#oeps{test:#oeps}]]))
---~ print(preprocessed([[\def\test#oeps{test:#{oeps}}]]))
---~ print(preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
---~ print(preprocessed([[\def\test#{oeps}{test:#oeps}]]))
---~ preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]])
---~ print(preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
+if not modules then modules = { } end modules ['luatex-preprocessor'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-preprocessor.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+--[[ldx
+<p>This is a stripped down version of the preprocessor. In
+<l n='context'/> we have a bit more, use a different logger, and
+use a few optimizations. A few examples are shown at the end.</p>
+--ldx]]
+
+local rep, sub, gmatch = string.rep, string.sub, string.gmatch
+local insert, remove = table.insert, table.remove
+local setmetatable = setmetatable
+
+local stack, top, n, hashes = { }, nil, 0, { }
+
+local function set(s)
+    if top then
+        n = n + 1
+        if n > 9 then
+            texio.write_nl("number of arguments > 9, ignoring: " .. s)
+        else
+            local ns = #stack
+            local h = hashes[ns]
+            if not h then
+                h = rep("#",ns)
+                hashes[ns] = h
+            end
+            m = h .. n
+            top[s] = m
+            return m
+        end
+    end
+end
+
+local function get(s)
+    local m = top and top[s] or s
+    return m
+end
+
+local function push()
+    top = { }
+    n = 0
+    local s = stack[#stack]
+    if s then
+        setmetatable(top,{ __index = s })
+    end
+    insert(stack,top)
+end
+
+local function pop()
+    top = remove(stack)
+end
+
+local leftbrace   = lpeg.P("{")
+local rightbrace  = lpeg.P("}")
+local escape      = lpeg.P("\\")
+
+local space       = lpeg.P(" ")
+local spaces      = space^1
+local newline     = lpeg.S("\r\n")
+local nobrace     = 1 - leftbrace - rightbrace
+
+local name        = lpeg.R("AZ","az")^1
+local longname    = (leftbrace/"") * (nobrace^1) * (rightbrace/"")
+local variable    = lpeg.P("#") * lpeg.Cs(name + longname)
+local escapedname = escape * name
+local definer     = escape * (lpeg.P("def") + lpeg.P("egdx") * lpeg.P("def"))
+local anything    = lpeg.P(1)
+local always      = lpeg.P(true)
+
+local pushlocal   = always   / push
+local poplocal    = always   / pop
+local declaration = variable / set
+local identifier  = variable / get
+
+local function matcherror(str,pos)
+    texio.write_nl("runaway definition at: " .. sub(str,pos-30,pos))
+end
+
+local parser = lpeg.Cs { "converter",
+    definition  = pushlocal
+                * definer
+                * escapedname
+                * (declaration + (1-leftbrace))^0
+                * lpeg.V("braced")
+                * poplocal,
+    braced      = leftbrace
+                * (   lpeg.V("definition")
+                    + identifier
+                    + lpeg.V("braced")
+                    + nobrace
+                  )^0
+                * (rightbrace + lpeg.Cmt(always,matcherror)),
+    converter   = (lpeg.V("definition") + anything)^1,
+}
+
+--[[ldx
+<p>We provide a few commands.</p>
+--ldx]]
+
+-- local texkpse
+
+local function find_file(...)
+ -- texkpse = texkpse or kpse.new("luatex","tex")
+ -- return texkpse:find_file(...) or ""
+    return kpse.find_file(...) or ""
+end
+
+commands = commands or { }
+
+function commands.preprocessed(str)
+    return lpeg.match(parser,str)
+end
+
+function commands.inputpreprocessed(name)
+    local name = find_file(name) or ""
+    if name ~= "" then
+     -- we could use io.loaddata as it's loaded in luatex-plain
+        local f = io.open(name,'rb')
+        if f then
+            texio.write("("..name)
+            local d = commands.preprocessed(f:read("*a"))
+            if d and d ~= "" then
+                texio.write("processed: " .. name)
+                for s in gmatch(d,"[^\n\r]+") do
+                    tex.print(s) -- we do a dumb feedback
+                end
+            end
+            f:close()
+            texio.write(")")
+        else
+            tex.error("preprocessor error, invalid file: " .. name)
+        end
+    else
+        tex.error("preprocessor error, unknown file: " .. name)
+    end
+end
+
+function commands.preprocessfile(oldfile,newfile) -- no checking
+    if oldfile and oldfile ~= newfile then
+        local f = io.open(oldfile,'rb')
+        if f then
+            local g = io.open(newfile,'wb')
+            if g then
+                g:write(lpeg.match(parser,f:read("*a") or ""))
+                g:close()
+            end
+            f:close()
+        end
+    end
+end
+
+--~ print(preprocessed([[\def\test#oeps{test:#oeps}]]))
+--~ print(preprocessed([[\def\test#oeps{test:#{oeps}}]]))
+--~ print(preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
+--~ print(preprocessed([[\def\test#{oeps}{test:#oeps}]]))
+--~ preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]])
+--~ print(preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
diff --git a/tex/generic/context/luatex/luatex-swiglib-test.lua b/tex/generic/context/luatex/luatex-swiglib-test.lua
index 2f4cc57f6..db6a72909 100644
--- a/tex/generic/context/luatex/luatex-swiglib-test.lua
+++ b/tex/generic/context/luatex/luatex-swiglib-test.lua
@@ -1,25 +1,25 @@
-local gm = swiglib("gmwand.core")
-
-gm.InitializeMagick(".")
-
-local magick_wand  = gm.NewMagickWand()
-local drawing_wand = gm.NewDrawingWand()
-
-gm.MagickSetSize(magick_wand,800,600)
-gm.MagickReadImage(magick_wand,"xc:red")
-
-gm.DrawPushGraphicContext(drawing_wand)
-
-gm.DrawSetFillColor(drawing_wand,gm.NewPixelWand())
-
--- gm.DrawSetFont(drawing_wand, kpse.findfile("DejaVuSerifBold.ttf"))
--- gm.DrawSetFontSize(drawing_wand, 96)
--- gm.DrawAnnotation(drawing_wand,300,200, "LuaTeX")
-
-gm.DrawPopGraphicContext(drawing_wand)
-gm.MagickDrawImage(magick_wand,drawing_wand)
-
-gm.MagickWriteImages(magick_wand,"./luatex-swiglib-test.jpg",1)
-
-gm.DestroyDrawingWand(drawing_wand)
-gm.DestroyMagickWand(magick_wand)
+local gm = swiglib("gmwand.core")
+
+gm.InitializeMagick(".")
+
+local magick_wand  = gm.NewMagickWand()
+local drawing_wand = gm.NewDrawingWand()
+
+gm.MagickSetSize(magick_wand,800,600)
+gm.MagickReadImage(magick_wand,"xc:red")
+
+gm.DrawPushGraphicContext(drawing_wand)
+
+gm.DrawSetFillColor(drawing_wand,gm.NewPixelWand())
+
+-- gm.DrawSetFont(drawing_wand, kpse.findfile("DejaVuSerifBold.ttf"))
+-- gm.DrawSetFontSize(drawing_wand, 96)
+-- gm.DrawAnnotation(drawing_wand,300,200, "LuaTeX")
+
+gm.DrawPopGraphicContext(drawing_wand)
+gm.MagickDrawImage(magick_wand,drawing_wand)
+
+gm.MagickWriteImages(magick_wand,"./luatex-swiglib-test.jpg",1)
+
+gm.DestroyDrawingWand(drawing_wand)
+gm.DestroyMagickWand(magick_wand)
diff --git a/tex/generic/context/luatex/luatex-swiglib.lua b/tex/generic/context/luatex/luatex-swiglib.lua
index 45416eff4..7ffcdc375 100644
--- a/tex/generic/context/luatex/luatex-swiglib.lua
+++ b/tex/generic/context/luatex/luatex-swiglib.lua
@@ -1,62 +1,62 @@
-if not modules then modules = { } end modules ['luatex-swiglib'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-swiglib.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local savedrequire = require
-
-local libsuffix = os.type == "windows" and ".dll" or ".so"
-
-function requireswiglib(required,version)
-    local library = package.loaded[required]
-    if library then
-        return library
-    else
-        local name = string.gsub(required,"%.","/") .. libsuffix
-        local list = kpse.show_path("clua")
-        for root in string.gmatch(list,"([^;]+)") do
-            local full = false
-            if type(version) == "string" and version ~= "" then
-                full = root .. "/" .. version .. "/" .. name
-                full = lfs.isfile(full) and full
-            end
-            if not full then
-                full = root .. "/" .. name
-                full = lfs.isfile(full) and full
-            end
-            if full then
-                local path, base = string.match(full,"^(.-)([^\\/]+)" .. libsuffix .."$")
-                local savedlibrary = package.loaded[base]
-                package.loaded[base] = nil
-                local savedpath = lfs.currentdir()
-                lfs.chdir(path)
-                library = package.loadlib(full,"luaopen_" .. base)
-                if type(library) == "function" then
-                    library = library()
-                    texio.write("<swiglib: '",required,"' is loaded>")
-                end
-                lfs.chdir(savedpath)
-                package.loaded[base] = savedlibrary
-                package.loaded[required] = library
-                return library
-            end
-        end
-        texio.write("<swiglib: '",name,"'is not found on '",list,"'")
-    end
-    texio.write("<swiglib: '",required,"' is not found>")
-end
-
-function require(name)
-    if string.find(name,"^swiglib%.") then
-        return requireswiglib(name)
-    else
-        return savedrequire(name)
-    end
-end
-
-function swiglib(name,version)
-    return requireswiglib("swiglib." .. name,version)
-end
+if not modules then modules = { } end modules ['luatex-swiglib'] = {
+    version   = 1.001,
+    comment   = "companion to luatex-swiglib.tex",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local savedrequire = require
+
+local libsuffix = os.type == "windows" and ".dll" or ".so"
+
+function requireswiglib(required,version)
+    local library = package.loaded[required]
+    if library then
+        return library
+    else
+        local name = string.gsub(required,"%.","/") .. libsuffix
+        local list = kpse.show_path("clua")
+        for root in string.gmatch(list,"([^;]+)") do
+            local full = false
+            if type(version) == "string" and version ~= "" then
+                full = root .. "/" .. version .. "/" .. name
+                full = lfs.isfile(full) and full
+            end
+            if not full then
+                full = root .. "/" .. name
+                full = lfs.isfile(full) and full
+            end
+            if full then
+                local path, base = string.match(full,"^(.-)([^\\/]+)" .. libsuffix .."$")
+                local savedlibrary = package.loaded[base]
+                package.loaded[base] = nil
+                local savedpath = lfs.currentdir()
+                lfs.chdir(path)
+                library = package.loadlib(full,"luaopen_" .. base)
+                if type(library) == "function" then
+                    library = library()
+                    texio.write("<swiglib: '",required,"' is loaded>")
+                end
+                lfs.chdir(savedpath)
+                package.loaded[base] = savedlibrary
+                package.loaded[required] = library
+                return library
+            end
+        end
+        texio.write("<swiglib: '",name,"'is not found on '",list,"'")
+    end
+    texio.write("<swiglib: '",required,"' is not found>")
+end
+
+function require(name)
+    if string.find(name,"^swiglib%.") then
+        return requireswiglib(name)
+    else
+        return savedrequire(name)
+    end
+end
+
+function swiglib(name,version)
+    return requireswiglib("swiglib." .. name,version)
+end
-- 
cgit v1.2.3