[latex3-commits] [git/LaTeX3-latex3-luaotfload] lessglobals-dev: Isolate fontloader environment (18dd128)

Marcel Fabian Krüger tex at 2krueger.de
Mon Sep 2 15:46:20 CEST 2019


Repository : https://github.com/latex3/luaotfload
On branch  : lessglobals-dev
Link       : https://github.com/latex3/luaotfload/commit/18dd1288010a5b2dbe384831e0b7cb991dcfa815

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

commit 18dd1288010a5b2dbe384831e0b7cb991dcfa815
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Mon Sep 2 14:19:22 2019 +0200

    Isolate fontloader environment


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

18dd1288010a5b2dbe384831e0b7cb991dcfa815
 src/luaotfload-configuration.lua                   |   2 +-
 src/luaotfload-database.lua                        |  14 +-
 src/luaotfload-init.lua                            | 391 +++++----------------
 src/luaotfload-main.lua                            |  30 +-
 src/luaotfload-resolvers.lua                       |   3 +-
 src/luaotfload-tool.lua                            |   1 +
 .../luaotfload/luaotfload-configuration.lua        |   2 +-
 .../latex-dev/luaotfload/luaotfload-database.lua   |  14 +-
 texmf/tex/latex-dev/luaotfload/luaotfload-init.lua | 391 +++++----------------
 texmf/tex/latex-dev/luaotfload/luaotfload-main.lua |  30 +-
 .../latex-dev/luaotfload/luaotfload-resolvers.lua  |   3 +-
 11 files changed, 223 insertions(+), 658 deletions(-)

diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
index 33eb797..da2de26 100644
--- a/src/luaotfload-configuration.lua
+++ b/src/luaotfload-configuration.lua
@@ -62,7 +62,7 @@ local filejoin                = file.join
 local filereplacesuffix       = file.replacesuffix
 
 local logreport               = print -- overloaded later
-local getwritablepath         = caches.getwritablepath
+local getwritablepath         = luaotfload.fontloader.caches.getwritablepath
 
 
 local config_parser -- set later during init
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 009d2d9..4c210a3 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -148,7 +148,6 @@ local gzipload                 = gzip.load
 local gzipsave                 = gzip.save
 local iolines                  = io.lines
 local ioopen                   = io.open
-local iopopen                  = io.popen
 local kpseexpand_path          = kpse.expand_path
 local kpsefind_file            = kpse.find_file
 local kpselookup               = kpse.lookup
@@ -168,13 +167,14 @@ local stringgmatch             = string.gmatch
 local stringgsub               = string.gsub
 local stringlower              = string.lower
 local stringsub                = string.sub
-local stringupper              = string.upper
 local tableconcat              = table.concat
 local tablesort                = table.sort
 local utf8len                  = utf8.len
 local utf8offset               = utf8.offset
 
 --- these come from Lualibs/Context
+local context_environment      = luaotfload.fontloader
+local caches                   = context_environment.caches
 local filebasename             = file.basename
 local filecollapsepath         = file.collapsepath or file.collapse_path
 local filedirname              = file.dirname
@@ -198,9 +198,9 @@ local tablecontains            = table.contains
 local tablecopy                = table.copy
 local tablefastcopy            = table.fastcopy
 local tabletofile              = table.tofile
-local tabletohash              = table.tohash
 local tableserialize           = table.serialize
 local names                    = fonts and fonts.names or { }
+local resolversfindfile        = context_environment.resolvers.findfile
 
 --- some of our own
 local unicode                  = require'luaotfload-unicode'
@@ -736,7 +736,7 @@ lookup_font_file = function (filename)
     if not found then
         local type = file.suffix(filename)
         if type ~= "" then
-            found = resolvers.findfile(filename, type)
+            found = resolversfindfile(filename, type)
         end
     end
 
@@ -746,7 +746,7 @@ lookup_font_file = function (filename)
 
     for i=1, #type1_metrics do
         local format = type1_metrics[i]
-        if resolvers.findfile(filename, format) then
+        if resolversfindfile(filename, format) then
             return file.addsuffix(filename, format), format, true
         end
     end
@@ -785,7 +785,7 @@ local get_font_file = function (index)
     end
     local basename = entry.basename
     if entry.location == "texmf" then
-        local fullname = resolvers.findfile(basename, entry.format)
+        local fullname = resolversfindfile(basename, entry.format)
         if fullname then
             return true, fullname, entry.subfont
         end
@@ -809,7 +809,7 @@ local verify_font_file = function (basename)
     if path and lfsisfile(path) then
         return true
     end
-    if resolvers.findfile(basename) then
+    if resolversfindfile(basename) then
         return true
     end
     return false
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index cefbc4a..94c534b 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -78,122 +78,6 @@ local logreport  --- filled in after loading the log module
 
 --doc]]--
 
-local init_early = function ()
-
-  local store                  = { }
-  config                       = config or { } --- global
-  config.luaotfload            = config.luaotfload or { }
-  config.lualibs               = config.lualibs    or { }
-  config.lualibs.verbose       = false
-  config.lualibs.prefer_merged = true
-  config.lualibs.load_extended = true
-  fonts                        = fonts or { }
-
-  require "lualibs"
-
-  if not lualibs    then error "this module requires Luaotfload" end
-  if not luaotfload then error "this module requires Luaotfload" end
-
-  --[[doc--
-
-    The logger needs to be in place prior to loading the fontloader due
-    to order of initialization being crucial for the logger functions
-    that are swapped.
-
-  --doc]]--
-
-  luaotfload.loaders.luaotfload "log"
-  log       = luaotfload.log
-  logreport = log.report
-  log.set_loglevel (default_log_level)
-
-  logreport ("log", 4, "init", "Concealing callback.register().")
-  store.trapped_register = callback.register
-
-  callback.register = function (id)
-    logreport ("log", 4, "init",
-               "Dummy callback.register() invoked on %s.",
-               id)
-  end
-
-  --[[doc--
-
-    By default, the fontloader requires a number of \emphasis{private
-    attributes} for internal use.
-    These must be kept consistent with the attribute handling methods
-    as provided by \identifier{luatexbase}.
-    Our strategy is to override the function that allocates new
-    attributes before we initialize the font loader, making it a
-    wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
-        Many thanks, again, to Hans Hagen for making this part
-        configurable!
-    }
-    The attribute identifiers are prefixed “\fileent{luaotfload@}” to
-    avoid name clashes.
-
-  --doc]]--
-
-  local new_attribute    = luatexbase.new_attribute
-  local the_attributes   = luatexbase.attributes
-
-  attributes = attributes or { } --- this writes a global, sorry
-
-  attributes.private = function (name)
-    local attr   = "luaotfload@" .. name --- used to be: “otfl@”
-    local number = the_attributes[attr]
-    if not number then number = new_attribute(attr) end
-    return number
-  end
-
-  luaotfload.loaders.fontloader "basics-gen"
-
-  return store
-end --- [init_early]
-
---[[doc--
-
-    These next lines replicate the behavior of
-    \fileent{luatex-fonts.lua}.
-
---doc]]--
-
-local push_namespaces = function ()
-    logreport ("log", 4, "init", "push namespace for font loader")
-    local normalglobal = { }
-    for k, v in next, _G do
-        normalglobal[k] = v
-    end
-    return normalglobal
-end
-
-local pop_namespaces = function (normalglobal,
-                                 isolate,
-                                 context_environment)
-    if normalglobal then
-        local _G = _G
-        local mode = "non-destructive"
-        if isolate then mode = "destructive" end
-        logreport ("log", 4, "init", "pop namespace from font loader -- " . mode)
-        for k, v in next, _G do
-            if not normalglobal[k] then
-                context_environment[k] = v
-                if isolate then
-                    _G[k] = nil
-                end
-            end
-        end
-        for k, v in next, normalglobal do
-            _G[k] = v
-        end
-        -- just to be sure:
-        setmetatable(context_environment, _G)
-    else
-        logreport ("both", 0, "init",
-                   "irrecoverable error during pop_namespace: no globals to restore")
-        os.exit ()
-    end
-end
-
 --- below paths are relative to the texmf-context
 local ltx = "tex/generic/context/luatex"
 local ctx = { "tex/context/base/mkiv", "tex/context/base" }
@@ -308,159 +192,71 @@ local load_context_modules = function (pth)
 
 end
 
-local init_adapt = function ()
+local function init_main(early_hook)
+  config                       = config or { } --- global
+  config.luaotfload            = config.luaotfload or { }
+  config.lualibs               = config.lualibs    or { }
+  config.lualibs.verbose       = false
+  config.lualibs.prefer_merged = true
+  config.lualibs.load_extended = true
+  fonts                        = fonts or { }
+
+  require "lualibs"
 
-  local context_environment  = { }
-  local our_environment      = push_namespaces ()
+  if not lualibs    then error "this module requires Luaotfload" end
+  if not luaotfload then error "this module requires Luaotfload" end
 
   --[[doc--
 
-      The font loader requires that the attribute with index zero be
-      zero. We happily oblige.
-      (Cf. \fileent{luatex-fonts-nod.lua}.)
+    The logger needs to be in place prior to loading the fontloader due
+    to order of initialization being crucial for the logger functions
+    that are swapped.
 
   --doc]]--
 
-  tex.attribute[0] = 0
-
-  return our_environment, context_environment
-
-end --- [init_adapt]
-
---[[doc--
+  luaotfload.loaders.luaotfload "log"
+  log       = luaotfload.log
+  logreport = log.report
+  log.set_loglevel (default_log_level)
 
-  In Context, characters.data is where the data from char-def.lua
-  resides. The file is huge (>4.4 MB as of 2016) and only a stripped
-  down version is part of the isolated font loader. Nevertheless, we
-  include an excerpt generated by the mkcharacters script that contains
-  a subset of the fields of each character defined and some extra
-  metadata.
+  logreport ("log", 4, "init", "Concealing callback.register().")
+  local trapped_register = callback.register
 
-  Currently, these are (compare the mkcharacters script!)
+  callback.register = function (id)
+    logreport ("log", 4, "init",
+               "Dummy callback.register() invoked on %s.",
+               id)
+  end
 
-    · "direction"
-    · "mirror"
-    · "category"
-    · "textclass"
+  --[[doc--
 
-  The directional information is required for packages like Simurgh [0]
-  to work correctly. In an early stage [1] it was necessary to load
-  further files from Context directly, including the full blown version
-  of char-def.  Since we have no use for most of the so imported
-  functionality, the required parts have been isolated and are now
-  instated along with luaotfload-characters.lua. We can extend the set
-  of imported features easily should it not be enough.
+    By default, the fontloader requires a number of \emphasis{private
+    attributes} for internal use.
+    These must be kept consistent with the attribute handling methods
+    as provided by \identifier{luatexbase}.
+    Our strategy is to override the function that allocates new
+    attributes before we initialize the font loader, making it a
+    wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
+        Many thanks, again, to Hans Hagen for making this part
+        configurable!
+    }
+    The attribute identifiers are prefixed “\fileent{luaotfload@}” to
+    avoid name clashes.
 
-  [0] https://github.com/persian-tex/simurgh
-  [1] http://tex.stackexchange.com/a/132301/14066
+  --doc]]--
 
---doc]]--
+  local new_attribute    = luatexbase.new_attribute
+  local the_attributes   = luatexbase.attributes
 
---[[--14.12.2018disable characters 
---characters         = characters or { } --- should be created in basics-gen
---characters.data    = nil
---local chardef      = "luaotfload-characters"
---
---do
---  local setmetatableindex = function (t, f)
---    local mt = getmetatable (t)
---    if mt then
---      mt.__index = f
---    else
---      setmetatable (t, { __index = f })
---    end
---  end
---
---  --- there are some special tables for each field that provide access
---  --- to fields of the character table by means of a metatable
---
---  local mkcharspecial = function (characters, tablename, field)
---
---    local chardata = characters.data
---
---    if chardata then
---      local newspecial        = { }
---      characters [tablename]  = newspecial --> e.g. “characters.data.mirrors”
---
---      local idx = function (t, char)
---        local c = chardata [char]
---        if c then
---          local m = c [field] --> e.g. “mirror”
---          if m then
---            t [char] = m
---            return m
---          end
---        end
---        newspecial [char] = false
---        return char
---      end
---
---      setmetatableindex (newspecial, idx)
---    end
---
---  end
---
---  local mkcategories = function (characters) -- different from the others
---
---    local chardata         = characters.data
---    local categories       = characters.categories or { }
---    characters.categories  = categories
---
---    setmetatable (categories, { __index = function (t, char)
---      if char then
---        local c = chardata [char]
---        c = c.category or char
---        t [char] = c
---        return c
---      end
---    end})
---
---  end
---
---  local load_failed = false
---  local chardata --> characters.data; loaded on demand
---
---  local load_chardef = function ()
---
---    logreport ("both", 1, "aux", "Loading character metadata from %s.", chardef)
---    chardata = dofile (kpse.find_file (chardef, "lua"))
---
---    if chardata == nil then
---      logreport ("both", 0, "aux",
---                 "Could not load %s; continuing with empty character table.",
---                 chardef)
---      chardata    = { }
---      load_failed = true
---    end
---
---    characters             = { } --- nuke metatable
---    characters.data        = chardata
---    characters.classifiers = chardata.classifiers
---    chardata.classifiers   = nil
---
---    --- institute some of the functionality from char-ini.lua
---
---    mkcharspecial (characters, "mirrors",     "mirror")
---    mkcharspecial (characters, "directions",  "direction")
---    mkcharspecial (characters, "textclasses", "textclass")
---    mkcategories  (characters)
---
---  end
---
---  local charindex = function (t, k)
---    if chardata == nil and load_failed ~= true then
---      load_chardef ()
---    end
---
---    return rawget (characters, k)
---  end
---
---  setmetatableindex (characters, charindex)
---
---end
---]] --14.12.2018disable characters 
-
-local init_main = function ()
+  local context_environment = luaotfload.fontloader
+  context_environment.attributes = {
+    private = function (name)
+      local attr   = "luaotfload@" .. name --- used to be: “otfl@”
+      local number = the_attributes[attr]
+      if not number then number = new_attribute(attr) end
+      return number
+    end
+  }
 
   --[[doc--
 
@@ -473,6 +269,20 @@ local init_main = function ()
   local load_fontloader_module = luaotfload.loaders.fontloader
   local ignore_module          = luaotfload.loaders.ignore
 
+  load_fontloader_module "basics-gen"
+
+  if early_hook then early_hook() end
+
+  --[[doc--
+
+      The font loader requires that the attribute with index zero be
+      zero. We happily oblige.
+      (Cf. \fileent{luatex-fonts-nod.lua}.)
+
+  --doc]]--
+
+  tex.attribute[0] = 0
+
   --[[doc--
 
       Now that things are sorted out we can finally load the
@@ -574,14 +384,14 @@ local init_main = function ()
     logreport ("log", 0, "init",
                "Loading fontloader from absolute path “%s”.",
                fontloader)
-    local _void = require (fontloader)
+    local _void = assert (loadfile (fontloader, nil, context_environment)) ()
 
   elseif kpsefind_file (fontloader) then
     local path = kpsefind_file (fontloader)
     logreport ("log", 0, "init",
                "Loading fontloader “%s” from kpse-resolved path “%s”.",
                fontloader, path)
-    local _void = require (path)
+    local _void = assert (loadfile (path, nil, context_environment)) ()
 
   elseif kpsefind_file (("fontloader-%s.lua"):format(fontloader)) then
     logreport ("log", 0, "init",
@@ -605,43 +415,12 @@ local init_main = function ()
   logreport ("log", 0, "init",
              "Context OpenType loader version “%s”",
              fonts.handlers.otf.version)
+  callback.register = trapped_register
+  nodes = context_environment.nodes
+  -- setmetatable(context_environment, nil) -- Would be nice, might break the
+  -- fontloader
 end --- [init_main]
 
-local init_cleanup = function (store)
-  --- reinstate all the stuff we had to move out of the way to
-  --- accomodate the loader
-
-  --[[doc--
-
-      Here we adjust the globals created during font loader
-      initialization. If the second argument to
-      \luafunction{pop_namespaces()} is \verb|true| this will restore the
-      state of \luafunction{_G}, eliminating every global generated since
-      the last call to \luafunction{push_namespaces()}. At the moment we
-      see no reason to do this, and since the font loader is considered
-      an essential part of \identifier{luatex} as well as a very well
-      organized piece of code, we happily concede it the right to add to
-      \luafunction{_G} if needed.
-
-  --doc]]--
-
-  pop_namespaces (store.our_environment,
-                  false,
-                  store.context_environment)
-
-  --[[doc--
-
-      \subsection{Callbacks}
-        After the fontloader is ready we can restore the callback trap
-        from \identifier{luatexbase}.
-
-  --doc]]--
-
-  logreport ("log", 4, "init",
-             "Restoring original callback.register().")
-  callback.register = store.trapped_register
-end --- [init_cleanup]
-
 local init_post_install_callbacks = function ()
   --[[doc--
 
@@ -654,7 +433,7 @@ local init_post_install_callbacks = function ()
   --doc]]--
 
   -- MK Pass current text direction to simple_font_handler
-  local handler = nodes.simple_font_handler
+  local handler = luaotfload.fontloader.nodes.simple_font_handler
   local callback = function(head, groupcode, _, _, direction)
     if not direction then
       direction = tex.get'textdir'
@@ -774,20 +553,14 @@ local init_post = function ()
   return n
 end --- [init_post]
 
-return {
-  early = init_early,
-  main = function (store)
-    local starttime = os.gettimeofday ()
-    store.our_environment, store.context_environment = init_adapt ()
-    init_main ()
-    init_cleanup (store)
-    logreport ("both", 1, "init",
-               "fontloader loaded in %0.3f seconds",
-               os.gettimeofday() - starttime)
-    local n = init_post ()
-    logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
-    return true
-  end
-}
-
+return function (early_hook)
+  local starttime = os.gettimeofday ()
+  init_main (early_hook)
+  logreport ("both", 1, "init",
+             "fontloader loaded in %0.3f seconds",
+             os.gettimeofday() - starttime)
+  local n = init_post ()
+  logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
+  return true
+end
 -- vim:tw=79:sw=2:ts=2:expandtab
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 970e020..10e31ae 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -142,12 +142,12 @@ local timing_info = {
     t_init = { },
 }
 
-local make_loader = function (prefix)
+local make_loader = function (prefix, load_helper)
     return function (name)
         local t_0 = osgettimeofday ()
         local modname = make_loader_name (prefix, name)
         --- We don’t want the stack info from inside, so just pcall().
-        local ok, data = pcall (require, modname)
+        local ok, data = pcall (load_helper or require, modname)
         local t_end = osgettimeofday ()
         timing_info.t_load [name] = t_end - t_0
         if not ok then
@@ -190,6 +190,16 @@ local dummy_loader = function (name)
                            name)
 end
 
+local context_environment = setmetatable({}, {__index = _G})
+luaotfload.fontloader = context_environment
+local function context_isolated_load(name)
+    local fullname = kpse.find_file(name, 'lua')
+    if not fullname then
+        error(string.format('Fontloader module "%s" could not be found.', name))
+    end
+    return assert(loadfile(fullname, nil, context_environment))(name)
+end
+
 local context_loader = function (name, path)
     luaotfload.log.report ("log", 3, "load",
                            "Loading module “%s” from Context.",
@@ -209,7 +219,7 @@ local context_loader = function (name, path)
                                    path)
         end
     end
-    local ret = require (modpath)
+    local ret = context_isolated_load (modpath)
     local t_end = osgettimeofday ()
     timing_info.t_load [name] = t_end - t_0
 
@@ -228,7 +238,7 @@ local install_loaders = function ()
     local loaders      = { }
     local loadmodule   = make_loader "luaotfload"
     loaders.luaotfload = loadmodule
-    loaders.fontloader = make_loader "fontloader"
+    loaders.fontloader = make_loader ("fontloader", context_isolated_load)
     loaders.context    = context_loader
     loaders.ignore     = dummy_loader
 ----loaders.plaintex   = make_loader "luatex" --=> for Luatex-Plain
@@ -275,15 +285,13 @@ luaotfload.main = function ()
 
     local starttime = osgettimeofday ()
     local init      = loadmodule "init" --- fontloader initialization
-    local store     = init.early ()     --- injects the log module too
-    local logreport = luaotfload.log.report
+    init (function ()
 
-    initialize "parsers"         --- fonts.conf and syntax
-    initialize "configuration"   --- configuration options
+        initialize "parsers"         --- fonts.conf and syntax
+        initialize "configuration"   --- configuration options
+    end)
 
-    if not init.main (store) then
-        logreport ("log", 0, "load", "Main fontloader initialization failed.")
-    end
+    local logreport = luaotfload.log.report
 
     initialize "loaders"         --- Font loading; callbacks
     initialize "database"        --- Font management.
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index 1cc5fdc..9ed16aa 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -148,11 +148,12 @@ end
 
 local tex_formats = { "tfm", "ofm" }
 
+local resolvers_findfile = luaotfload.fontloader.resolvers.findfile
 local resolve_tex_format = function (specification)
     local name = specification.name
     for i=1, #tex_formats do
         local format = tex_formats [i]
-        local resolved = resolvers.findfile(name, format)
+        local resolved = resolvers_findfile(name, format)
         if resolved then
             return resolved, format
         end
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 3a5b168..9058db8 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -25,6 +25,7 @@ local version                  = ProvidesLuaModule.version
 luaotfload.version             = ProvidesLuaModule.version
 luaotfload.min_luatex_version  = { 0, 95, 0 }
 luaotfload.self                = "luaotfload-tool"
+luaotfload.fontloader          = _G -- We don't isolate the fontloader here
 
 --[[doc--
 
diff --git a/texmf/tex/latex-dev/luaotfload/luaotfload-configuration.lua b/texmf/tex/latex-dev/luaotfload/luaotfload-configuration.lua
index 33eb797..da2de26 100644
--- a/texmf/tex/latex-dev/luaotfload/luaotfload-configuration.lua
+++ b/texmf/tex/latex-dev/luaotfload/luaotfload-configuration.lua
@@ -62,7 +62,7 @@ local filejoin                = file.join
 local filereplacesuffix       = file.replacesuffix
 
 local logreport               = print -- overloaded later
-local getwritablepath         = caches.getwritablepath
+local getwritablepath         = luaotfload.fontloader.caches.getwritablepath
 
 
 local config_parser -- set later during init
diff --git a/texmf/tex/latex-dev/luaotfload/luaotfload-database.lua b/texmf/tex/latex-dev/luaotfload/luaotfload-database.lua
index 009d2d9..4c210a3 100644
--- a/texmf/tex/latex-dev/luaotfload/luaotfload-database.lua
+++ b/texmf/tex/latex-dev/luaotfload/luaotfload-database.lua
@@ -148,7 +148,6 @@ local gzipload                 = gzip.load
 local gzipsave                 = gzip.save
 local iolines                  = io.lines
 local ioopen                   = io.open
-local iopopen                  = io.popen
 local kpseexpand_path          = kpse.expand_path
 local kpsefind_file            = kpse.find_file
 local kpselookup               = kpse.lookup
@@ -168,13 +167,14 @@ local stringgmatch             = string.gmatch
 local stringgsub               = string.gsub
 local stringlower              = string.lower
 local stringsub                = string.sub
-local stringupper              = string.upper
 local tableconcat              = table.concat
 local tablesort                = table.sort
 local utf8len                  = utf8.len
 local utf8offset               = utf8.offset
 
 --- these come from Lualibs/Context
+local context_environment      = luaotfload.fontloader
+local caches                   = context_environment.caches
 local filebasename             = file.basename
 local filecollapsepath         = file.collapsepath or file.collapse_path
 local filedirname              = file.dirname
@@ -198,9 +198,9 @@ local tablecontains            = table.contains
 local tablecopy                = table.copy
 local tablefastcopy            = table.fastcopy
 local tabletofile              = table.tofile
-local tabletohash              = table.tohash
 local tableserialize           = table.serialize
 local names                    = fonts and fonts.names or { }
+local resolversfindfile        = context_environment.resolvers.findfile
 
 --- some of our own
 local unicode                  = require'luaotfload-unicode'
@@ -736,7 +736,7 @@ lookup_font_file = function (filename)
     if not found then
         local type = file.suffix(filename)
         if type ~= "" then
-            found = resolvers.findfile(filename, type)
+            found = resolversfindfile(filename, type)
         end
     end
 
@@ -746,7 +746,7 @@ lookup_font_file = function (filename)
 
     for i=1, #type1_metrics do
         local format = type1_metrics[i]
-        if resolvers.findfile(filename, format) then
+        if resolversfindfile(filename, format) then
             return file.addsuffix(filename, format), format, true
         end
     end
@@ -785,7 +785,7 @@ local get_font_file = function (index)
     end
     local basename = entry.basename
     if entry.location == "texmf" then
-        local fullname = resolvers.findfile(basename, entry.format)
+        local fullname = resolversfindfile(basename, entry.format)
         if fullname then
             return true, fullname, entry.subfont
         end
@@ -809,7 +809,7 @@ local verify_font_file = function (basename)
     if path and lfsisfile(path) then
         return true
     end
-    if resolvers.findfile(basename) then
+    if resolversfindfile(basename) then
         return true
     end
     return false
diff --git a/texmf/tex/latex-dev/luaotfload/luaotfload-init.lua b/texmf/tex/latex-dev/luaotfload/luaotfload-init.lua
index cefbc4a..94c534b 100644
--- a/texmf/tex/latex-dev/luaotfload/luaotfload-init.lua
+++ b/texmf/tex/latex-dev/luaotfload/luaotfload-init.lua
@@ -78,122 +78,6 @@ local logreport  --- filled in after loading the log module
 
 --doc]]--
 
-local init_early = function ()
-
-  local store                  = { }
-  config                       = config or { } --- global
-  config.luaotfload            = config.luaotfload or { }
-  config.lualibs               = config.lualibs    or { }
-  config.lualibs.verbose       = false
-  config.lualibs.prefer_merged = true
-  config.lualibs.load_extended = true
-  fonts                        = fonts or { }
-
-  require "lualibs"
-
-  if not lualibs    then error "this module requires Luaotfload" end
-  if not luaotfload then error "this module requires Luaotfload" end
-
-  --[[doc--
-
-    The logger needs to be in place prior to loading the fontloader due
-    to order of initialization being crucial for the logger functions
-    that are swapped.
-
-  --doc]]--
-
-  luaotfload.loaders.luaotfload "log"
-  log       = luaotfload.log
-  logreport = log.report
-  log.set_loglevel (default_log_level)
-
-  logreport ("log", 4, "init", "Concealing callback.register().")
-  store.trapped_register = callback.register
-
-  callback.register = function (id)
-    logreport ("log", 4, "init",
-               "Dummy callback.register() invoked on %s.",
-               id)
-  end
-
-  --[[doc--
-
-    By default, the fontloader requires a number of \emphasis{private
-    attributes} for internal use.
-    These must be kept consistent with the attribute handling methods
-    as provided by \identifier{luatexbase}.
-    Our strategy is to override the function that allocates new
-    attributes before we initialize the font loader, making it a
-    wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
-        Many thanks, again, to Hans Hagen for making this part
-        configurable!
-    }
-    The attribute identifiers are prefixed “\fileent{luaotfload@}” to
-    avoid name clashes.
-
-  --doc]]--
-
-  local new_attribute    = luatexbase.new_attribute
-  local the_attributes   = luatexbase.attributes
-
-  attributes = attributes or { } --- this writes a global, sorry
-
-  attributes.private = function (name)
-    local attr   = "luaotfload@" .. name --- used to be: “otfl@”
-    local number = the_attributes[attr]
-    if not number then number = new_attribute(attr) end
-    return number
-  end
-
-  luaotfload.loaders.fontloader "basics-gen"
-
-  return store
-end --- [init_early]
-
---[[doc--
-
-    These next lines replicate the behavior of
-    \fileent{luatex-fonts.lua}.
-
---doc]]--
-
-local push_namespaces = function ()
-    logreport ("log", 4, "init", "push namespace for font loader")
-    local normalglobal = { }
-    for k, v in next, _G do
-        normalglobal[k] = v
-    end
-    return normalglobal
-end
-
-local pop_namespaces = function (normalglobal,
-                                 isolate,
-                                 context_environment)
-    if normalglobal then
-        local _G = _G
-        local mode = "non-destructive"
-        if isolate then mode = "destructive" end
-        logreport ("log", 4, "init", "pop namespace from font loader -- " . mode)
-        for k, v in next, _G do
-            if not normalglobal[k] then
-                context_environment[k] = v
-                if isolate then
-                    _G[k] = nil
-                end
-            end
-        end
-        for k, v in next, normalglobal do
-            _G[k] = v
-        end
-        -- just to be sure:
-        setmetatable(context_environment, _G)
-    else
-        logreport ("both", 0, "init",
-                   "irrecoverable error during pop_namespace: no globals to restore")
-        os.exit ()
-    end
-end
-
 --- below paths are relative to the texmf-context
 local ltx = "tex/generic/context/luatex"
 local ctx = { "tex/context/base/mkiv", "tex/context/base" }
@@ -308,159 +192,71 @@ local load_context_modules = function (pth)
 
 end
 
-local init_adapt = function ()
+local function init_main(early_hook)
+  config                       = config or { } --- global
+  config.luaotfload            = config.luaotfload or { }
+  config.lualibs               = config.lualibs    or { }
+  config.lualibs.verbose       = false
+  config.lualibs.prefer_merged = true
+  config.lualibs.load_extended = true
+  fonts                        = fonts or { }
+
+  require "lualibs"
 
-  local context_environment  = { }
-  local our_environment      = push_namespaces ()
+  if not lualibs    then error "this module requires Luaotfload" end
+  if not luaotfload then error "this module requires Luaotfload" end
 
   --[[doc--
 
-      The font loader requires that the attribute with index zero be
-      zero. We happily oblige.
-      (Cf. \fileent{luatex-fonts-nod.lua}.)
+    The logger needs to be in place prior to loading the fontloader due
+    to order of initialization being crucial for the logger functions
+    that are swapped.
 
   --doc]]--
 
-  tex.attribute[0] = 0
-
-  return our_environment, context_environment
-
-end --- [init_adapt]
-
---[[doc--
+  luaotfload.loaders.luaotfload "log"
+  log       = luaotfload.log
+  logreport = log.report
+  log.set_loglevel (default_log_level)
 
-  In Context, characters.data is where the data from char-def.lua
-  resides. The file is huge (>4.4 MB as of 2016) and only a stripped
-  down version is part of the isolated font loader. Nevertheless, we
-  include an excerpt generated by the mkcharacters script that contains
-  a subset of the fields of each character defined and some extra
-  metadata.
+  logreport ("log", 4, "init", "Concealing callback.register().")
+  local trapped_register = callback.register
 
-  Currently, these are (compare the mkcharacters script!)
+  callback.register = function (id)
+    logreport ("log", 4, "init",
+               "Dummy callback.register() invoked on %s.",
+               id)
+  end
 
-    · "direction"
-    · "mirror"
-    · "category"
-    · "textclass"
+  --[[doc--
 
-  The directional information is required for packages like Simurgh [0]
-  to work correctly. In an early stage [1] it was necessary to load
-  further files from Context directly, including the full blown version
-  of char-def.  Since we have no use for most of the so imported
-  functionality, the required parts have been isolated and are now
-  instated along with luaotfload-characters.lua. We can extend the set
-  of imported features easily should it not be enough.
+    By default, the fontloader requires a number of \emphasis{private
+    attributes} for internal use.
+    These must be kept consistent with the attribute handling methods
+    as provided by \identifier{luatexbase}.
+    Our strategy is to override the function that allocates new
+    attributes before we initialize the font loader, making it a
+    wrapper around \luafunction{luatexbase.new_attribute}.\footnote{%
+        Many thanks, again, to Hans Hagen for making this part
+        configurable!
+    }
+    The attribute identifiers are prefixed “\fileent{luaotfload@}” to
+    avoid name clashes.
 
-  [0] https://github.com/persian-tex/simurgh
-  [1] http://tex.stackexchange.com/a/132301/14066
+  --doc]]--
 
---doc]]--
+  local new_attribute    = luatexbase.new_attribute
+  local the_attributes   = luatexbase.attributes
 
---[[--14.12.2018disable characters 
---characters         = characters or { } --- should be created in basics-gen
---characters.data    = nil
---local chardef      = "luaotfload-characters"
---
---do
---  local setmetatableindex = function (t, f)
---    local mt = getmetatable (t)
---    if mt then
---      mt.__index = f
---    else
---      setmetatable (t, { __index = f })
---    end
---  end
---
---  --- there are some special tables for each field that provide access
---  --- to fields of the character table by means of a metatable
---
---  local mkcharspecial = function (characters, tablename, field)
---
---    local chardata = characters.data
---
---    if chardata then
---      local newspecial        = { }
---      characters [tablename]  = newspecial --> e.g. “characters.data.mirrors”
---
---      local idx = function (t, char)
---        local c = chardata [char]
---        if c then
---          local m = c [field] --> e.g. “mirror”
---          if m then
---            t [char] = m
---            return m
---          end
---        end
---        newspecial [char] = false
---        return char
---      end
---
---      setmetatableindex (newspecial, idx)
---    end
---
---  end
---
---  local mkcategories = function (characters) -- different from the others
---
---    local chardata         = characters.data
---    local categories       = characters.categories or { }
---    characters.categories  = categories
---
---    setmetatable (categories, { __index = function (t, char)
---      if char then
---        local c = chardata [char]
---        c = c.category or char
---        t [char] = c
---        return c
---      end
---    end})
---
---  end
---
---  local load_failed = false
---  local chardata --> characters.data; loaded on demand
---
---  local load_chardef = function ()
---
---    logreport ("both", 1, "aux", "Loading character metadata from %s.", chardef)
---    chardata = dofile (kpse.find_file (chardef, "lua"))
---
---    if chardata == nil then
---      logreport ("both", 0, "aux",
---                 "Could not load %s; continuing with empty character table.",
---                 chardef)
---      chardata    = { }
---      load_failed = true
---    end
---
---    characters             = { } --- nuke metatable
---    characters.data        = chardata
---    characters.classifiers = chardata.classifiers
---    chardata.classifiers   = nil
---
---    --- institute some of the functionality from char-ini.lua
---
---    mkcharspecial (characters, "mirrors",     "mirror")
---    mkcharspecial (characters, "directions",  "direction")
---    mkcharspecial (characters, "textclasses", "textclass")
---    mkcategories  (characters)
---
---  end
---
---  local charindex = function (t, k)
---    if chardata == nil and load_failed ~= true then
---      load_chardef ()
---    end
---
---    return rawget (characters, k)
---  end
---
---  setmetatableindex (characters, charindex)
---
---end
---]] --14.12.2018disable characters 
-
-local init_main = function ()
+  local context_environment = luaotfload.fontloader
+  context_environment.attributes = {
+    private = function (name)
+      local attr   = "luaotfload@" .. name --- used to be: “otfl@”
+      local number = the_attributes[attr]
+      if not number then number = new_attribute(attr) end
+      return number
+    end
+  }
 
   --[[doc--
 
@@ -473,6 +269,20 @@ local init_main = function ()
   local load_fontloader_module = luaotfload.loaders.fontloader
   local ignore_module          = luaotfload.loaders.ignore
 
+  load_fontloader_module "basics-gen"
+
+  if early_hook then early_hook() end
+
+  --[[doc--
+
+      The font loader requires that the attribute with index zero be
+      zero. We happily oblige.
+      (Cf. \fileent{luatex-fonts-nod.lua}.)
+
+  --doc]]--
+
+  tex.attribute[0] = 0
+
   --[[doc--
 
       Now that things are sorted out we can finally load the
@@ -574,14 +384,14 @@ local init_main = function ()
     logreport ("log", 0, "init",
                "Loading fontloader from absolute path “%s”.",
                fontloader)
-    local _void = require (fontloader)
+    local _void = assert (loadfile (fontloader, nil, context_environment)) ()
 
   elseif kpsefind_file (fontloader) then
     local path = kpsefind_file (fontloader)
     logreport ("log", 0, "init",
                "Loading fontloader “%s” from kpse-resolved path “%s”.",
                fontloader, path)
-    local _void = require (path)
+    local _void = assert (loadfile (path, nil, context_environment)) ()
 
   elseif kpsefind_file (("fontloader-%s.lua"):format(fontloader)) then
     logreport ("log", 0, "init",
@@ -605,43 +415,12 @@ local init_main = function ()
   logreport ("log", 0, "init",
              "Context OpenType loader version “%s”",
              fonts.handlers.otf.version)
+  callback.register = trapped_register
+  nodes = context_environment.nodes
+  -- setmetatable(context_environment, nil) -- Would be nice, might break the
+  -- fontloader
 end --- [init_main]
 
-local init_cleanup = function (store)
-  --- reinstate all the stuff we had to move out of the way to
-  --- accomodate the loader
-
-  --[[doc--
-
-      Here we adjust the globals created during font loader
-      initialization. If the second argument to
-      \luafunction{pop_namespaces()} is \verb|true| this will restore the
-      state of \luafunction{_G}, eliminating every global generated since
-      the last call to \luafunction{push_namespaces()}. At the moment we
-      see no reason to do this, and since the font loader is considered
-      an essential part of \identifier{luatex} as well as a very well
-      organized piece of code, we happily concede it the right to add to
-      \luafunction{_G} if needed.
-
-  --doc]]--
-
-  pop_namespaces (store.our_environment,
-                  false,
-                  store.context_environment)
-
-  --[[doc--
-
-      \subsection{Callbacks}
-        After the fontloader is ready we can restore the callback trap
-        from \identifier{luatexbase}.
-
-  --doc]]--
-
-  logreport ("log", 4, "init",
-             "Restoring original callback.register().")
-  callback.register = store.trapped_register
-end --- [init_cleanup]
-
 local init_post_install_callbacks = function ()
   --[[doc--
 
@@ -654,7 +433,7 @@ local init_post_install_callbacks = function ()
   --doc]]--
 
   -- MK Pass current text direction to simple_font_handler
-  local handler = nodes.simple_font_handler
+  local handler = luaotfload.fontloader.nodes.simple_font_handler
   local callback = function(head, groupcode, _, _, direction)
     if not direction then
       direction = tex.get'textdir'
@@ -774,20 +553,14 @@ local init_post = function ()
   return n
 end --- [init_post]
 
-return {
-  early = init_early,
-  main = function (store)
-    local starttime = os.gettimeofday ()
-    store.our_environment, store.context_environment = init_adapt ()
-    init_main ()
-    init_cleanup (store)
-    logreport ("both", 1, "init",
-               "fontloader loaded in %0.3f seconds",
-               os.gettimeofday() - starttime)
-    local n = init_post ()
-    logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
-    return true
-  end
-}
-
+return function (early_hook)
+  local starttime = os.gettimeofday ()
+  init_main (early_hook)
+  logreport ("both", 1, "init",
+             "fontloader loaded in %0.3f seconds",
+             os.gettimeofday() - starttime)
+  local n = init_post ()
+  logreport ("both", 5, "init", "post hook terminated, %d actions performed", n)
+  return true
+end
 -- vim:tw=79:sw=2:ts=2:expandtab
diff --git a/texmf/tex/latex-dev/luaotfload/luaotfload-main.lua b/texmf/tex/latex-dev/luaotfload/luaotfload-main.lua
index 970e020..10e31ae 100644
--- a/texmf/tex/latex-dev/luaotfload/luaotfload-main.lua
+++ b/texmf/tex/latex-dev/luaotfload/luaotfload-main.lua
@@ -142,12 +142,12 @@ local timing_info = {
     t_init = { },
 }
 
-local make_loader = function (prefix)
+local make_loader = function (prefix, load_helper)
     return function (name)
         local t_0 = osgettimeofday ()
         local modname = make_loader_name (prefix, name)
         --- We don’t want the stack info from inside, so just pcall().
-        local ok, data = pcall (require, modname)
+        local ok, data = pcall (load_helper or require, modname)
         local t_end = osgettimeofday ()
         timing_info.t_load [name] = t_end - t_0
         if not ok then
@@ -190,6 +190,16 @@ local dummy_loader = function (name)
                            name)
 end
 
+local context_environment = setmetatable({}, {__index = _G})
+luaotfload.fontloader = context_environment
+local function context_isolated_load(name)
+    local fullname = kpse.find_file(name, 'lua')
+    if not fullname then
+        error(string.format('Fontloader module "%s" could not be found.', name))
+    end
+    return assert(loadfile(fullname, nil, context_environment))(name)
+end
+
 local context_loader = function (name, path)
     luaotfload.log.report ("log", 3, "load",
                            "Loading module “%s” from Context.",
@@ -209,7 +219,7 @@ local context_loader = function (name, path)
                                    path)
         end
     end
-    local ret = require (modpath)
+    local ret = context_isolated_load (modpath)
     local t_end = osgettimeofday ()
     timing_info.t_load [name] = t_end - t_0
 
@@ -228,7 +238,7 @@ local install_loaders = function ()
     local loaders      = { }
     local loadmodule   = make_loader "luaotfload"
     loaders.luaotfload = loadmodule
-    loaders.fontloader = make_loader "fontloader"
+    loaders.fontloader = make_loader ("fontloader", context_isolated_load)
     loaders.context    = context_loader
     loaders.ignore     = dummy_loader
 ----loaders.plaintex   = make_loader "luatex" --=> for Luatex-Plain
@@ -275,15 +285,13 @@ luaotfload.main = function ()
 
     local starttime = osgettimeofday ()
     local init      = loadmodule "init" --- fontloader initialization
-    local store     = init.early ()     --- injects the log module too
-    local logreport = luaotfload.log.report
+    init (function ()
 
-    initialize "parsers"         --- fonts.conf and syntax
-    initialize "configuration"   --- configuration options
+        initialize "parsers"         --- fonts.conf and syntax
+        initialize "configuration"   --- configuration options
+    end)
 
-    if not init.main (store) then
-        logreport ("log", 0, "load", "Main fontloader initialization failed.")
-    end
+    local logreport = luaotfload.log.report
 
     initialize "loaders"         --- Font loading; callbacks
     initialize "database"        --- Font management.
diff --git a/texmf/tex/latex-dev/luaotfload/luaotfload-resolvers.lua b/texmf/tex/latex-dev/luaotfload/luaotfload-resolvers.lua
index 1cc5fdc..9ed16aa 100644
--- a/texmf/tex/latex-dev/luaotfload/luaotfload-resolvers.lua
+++ b/texmf/tex/latex-dev/luaotfload/luaotfload-resolvers.lua
@@ -148,11 +148,12 @@ end
 
 local tex_formats = { "tfm", "ofm" }
 
+local resolvers_findfile = luaotfload.fontloader.resolvers.findfile
 local resolve_tex_format = function (specification)
     local name = specification.name
     for i=1, #tex_formats do
         local format = tex_formats [i]
-        local resolved = resolvers.findfile(name, format)
+        local resolved = resolvers_findfile(name, format)
         if resolved then
             return resolved, format
         end





More information about the latex3-commits mailing list