summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/luat-env.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/luat-env.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/luat-env.lua389
1 files changed, 223 insertions, 166 deletions
diff --git a/Master/texmf-dist/tex/context/base/luat-env.lua b/Master/texmf-dist/tex/context/base/luat-env.lua
index 48563e2e7f2..9c05b249ca1 100644
--- a/Master/texmf-dist/tex/context/base/luat-env.lua
+++ b/Master/texmf-dist/tex/context/base/luat-env.lua
@@ -1,218 +1,275 @@
--- filename : luat-env.lua
--- comment : companion to luat-env.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-env'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
--- here we don't assume any extra libraries
-
--- A former version provides functionality for non embeded core
+-- A former version provided functionality for non embeded core
-- scripts i.e. runtime library loading. Given the amount of
-- Lua code we use now, this no longer makes sense. Much of this
--- evolved before bytecode arrays were available.
+-- evolved before bytecode arrays were available and so a lot of
+-- code has disappeared already.
-if not versions then versions = { } end versions['luat-env'] = 1.001
+local trace_verbose = false trackers.register("resolvers.verbose", function(v) trace_verbose = v end)
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v trackers.enable("resolvers.verbose") end)
--- environment
+local format = string.format
-if not environment then environment = { } end
+-- precautions
---~ environment.useluc = true -- still testing, so we don't use luc yet
+os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
-if environment.silent == nil then environment.silent = false end
-if environment.useluc == nil then environment.useluc = true end
+function os.setlocale()
+ -- no way you can mess with it
+end
--- kpse is overloaded by this time
+-- dirty tricks
+
+if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+ arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
+end
---~ if environment.formatname == nil then if tex then environment.formatname = tex.formatname end end
---~ if environment.formatpath == nil then if kpse then environment.formatpath = kpse.find_file(tex.formatname,"fmt") or "." end end
---~ if environment.jobname == nil then if tex then environment.jobname = tex.jobname end end
---~ if environment.progname == nil then environment.progname = os.getenv("progname") or "luatex" end
---~ if environment.engine == nil then environment.engine = os.getenv("engine") or "context" end
---~ if environment.enginepath == nil then environment.enginepath = os.getenv("SELFAUTOLOC") or "." end
---~ if environment.initex == nil then if tex then environment.initex = tex.formatname == "" end end
+if profiler and os.env["MTX_PROFILE_RUN"] == "YES" then
+ profiler.start("luatex-profile.log")
+end
-if not environment.formatname or environment.formatname == "" then if tex then environment.formatname = tex.formatname end end
-if not environment.jobname or environment.jobname == "" then if tex then environment.jobname = tex.jobname end end
+-- environment
-if not environment.progname or environment.progname == "" then environment.progname = "context" end
-if not environment.engine or environment.engine == "" then environment.engine = "luatex" end
-if not environment.formatname or environment.formatname == "" then environment.formatname = "cont-en" end
-if not environment.formatpath or environment.formatpath == "" then environment.formatpath = '.' end
-if not environment.enginepath or environment.enginepath == "" then environment.enginepath = '.' end
-if not environment.version or environment.version == "" then environment.version = "unknown" end
+environment = environment or { }
+environment.arguments = { }
+environment.files = { }
+environment.sortedflags = nil
-environment.formatpath = string.gsub(environment.formatpath:gsub("\\","/"),"/([^/]-)$","")
-environment.enginepath = string.gsub(environment.enginepath:gsub("\\","/"),"/([^/]-)$","")
+if not environment.jobname or environment.jobname == "" then if tex then environment.jobname = tex.jobname end end
+if not environment.version or environment.version == "" then environment.version = "unknown" end
+if not environment.jobname then environment.jobname = "unknown" end
-function environment.texfile(filename)
- return input.find_file(texmf.instance,filename,'tex')
+function environment.initialize_arguments(arg)
+ local arguments, files = { }, { }
+ environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
+ for index, argument in pairs(arg) do
+ if index > 0 then
+ local flag, value = argument:match("^%-+(.+)=(.-)$")
+ if flag then
+ arguments[flag] = string.unquote(value or "")
+ else
+ flag = argument:match("^%-+(.+)")
+ if flag then
+ arguments[flag] = true
+ else
+ files[#files+1] = argument
+ end
+ end
+ end
+ end
+ environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
end
-function environment.luafile(filename)
- return input.find_file(texmf.instance,filename,'tex') or input.find_file(texmf.instance,filename,'texmfscripts')
+function environment.setargument(name,value)
+ environment.arguments[name] = value
end
-function environment.showmessage(...) -- todo, cleaner
- if not environment.silent then
- if input and input.report then
- input.report(table.concat({...}," "))
- elseif texio and texio.write_nl then
- texio.write_nl("[[" .. table.concat({...}," ") .. "]]")
- else
- print("[[" .. table.concat({...}," ") .. "]]")
+-- todo: defaults, better checks e.g on type (boolean versus string)
+--
+-- tricky: too many hits when we support partials unless we add
+-- a registration of arguments so from now on we have 'partial'
+
+function environment.argument(name,partial)
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags = { }
+ for _,v in pairs(table.sortedkeys(arguments)) do
+ sortedflags[#sortedflags+1] = "^" .. v
+ end
+ environment.sortedflags = sortedflags
+ end
+ -- example of potential clash: ^mode ^modefile
+ for _,v in ipairs(sortedflags) do
+ if name:find(v) then
+ return arguments[v:sub(2,#v)]
+ end
end
end
+ return nil
end
-if not environment.jobname then environment.jobname = "unknown" end
+function environment.split_arguments(separator) -- rather special, cut-off before separator
+ local done, before, after = false, { }, { }
+ for _,v in ipairs(environment.original_arguments) do
+ if not done and v == separator then
+ done = true
+ elseif done then
+ after[#after+1] = v
+ else
+ before[#before+1] = v
+ end
+ end
+ return before, after
+end
-function environment.setlucpath()
- if environment.initex then
- environment.lucpath = nil
+function environment.reconstruct_commandline(arg,noquote)
+ arg = arg or environment.original_arguments
+ if noquote and #arg == 1 then
+ local a = arg[1]
+ a = resolvers.resolve(a)
+ a = a:unquote()
+ return a
+ elseif next(arg) then
+ local result = { }
+ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+ a = resolvers.resolve(a)
+ a = a:unquote()
+ a = a:gsub('"','\\"') -- tricky
+ if a:find(" ") then
+ result[#result+1] = a:quote()
+ else
+ result[#result+1] = a
+ end
+ end
+ return table.join(result," ")
else
- environment.lucpath = environment.formatpath .. "/lua/" .. environment.progname
+ return ""
end
end
-environment.setlucpath()
+if arg then
+
+ -- new, reconstruct quoted snippets (maybe better just remnove the " then and add them later)
+ local newarg, instring = { }, false
+
+ for index, argument in ipairs(arg) do
+ if argument:find("^\"") then
+ newarg[#newarg+1] = argument:gsub("^\"","")
+ if not argument:find("\"$") then
+ instring = true
+ end
+ elseif argument:find("\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument:gsub("\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initialize_arguments(newarg)
+ environment.original_arguments = newarg
+ environment.raw_arguments = arg
+
+ arg = { } -- prevent duplicate handling
-function environment.loadedluacode(fullname)
- return loadfile(fullname)
end
-function environment.luafilechunk(filename)
- local filename = filename:gsub("%.%a+$", "") .. ".lua"
- local fullname = environment.luafile(filename)
- if fullname and fullname ~= "" then
- environment.showmessage("loading file", fullname)
- return environment.loadedluacode(fullname)
- else
- environment.showmessage("unknown file", filename)
- return nil
+-- weird place ... depends on a not yet loaded module
+
+function environment.texfile(filename)
+ return resolvers.find_file(filename,'tex')
+end
+
+function environment.luafile(filename)
+ local resolved = resolvers.find_file(filename,'tex') or ""
+ if resolved ~= "" then
+ return resolved
+ end
+ resolved = resolvers.find_file(filename,'texmfscripts') or ""
+ if resolved ~= "" then
+ return resolved
end
+ return resolvers.find_file(filename,'luatexlibs') or ""
end
--- the next ones can use the previous ones
+environment.loadedluacode = loadfile -- can be overloaded
-function environment.loadluafile(filename)
- filename = filename:gsub("%.%a+$", "") .. ".lua"
+--~ function environment.loadedluacode(name)
+--~ if os.spawn("texluac -s -o texluac.luc " .. name) == 0 then
+--~ local chunk = loadstring(io.loaddata("texluac.luc"))
+--~ os.remove("texluac.luc")
+--~ return chunk
+--~ else
+--~ environment.loadedluacode = loadfile -- can be overloaded
+--~ return loadfile(name)
+--~ end
+--~ end
+
+function environment.luafilechunk(filename) -- used for loading lua bytecode in the format
+ filename = file.replacesuffix(filename, "lua")
local fullname = environment.luafile(filename)
if fullname and fullname ~= "" then
- environment.showmessage("loading", fullname)
- dofile(fullname)
+ if trace_verbose then
+ logs.report("fileio","loading file %s", fullname)
+ end
+ return environment.loadedluacode(fullname)
else
- environment.showmessage("unknown file", filename)
+ if trace_verbose then
+ logs.report("fileio","unknown file %s", filename)
+ end
+ return nil
end
end
-function environment.loadlucfile(filename,version)
- local filename = filename:gsub("%.%a+$", "")
- local fullname = nil
- if environment.initex or not environment.useluc then
- environment.loadluafile(filename)
- else
- if environment.lucpath and environment.lucpath ~= "" then
- fullname = environment.lucpath .. "/" .. filename .. ".luc"
- local chunk = loadfile(fullname) -- this way we don't need a file exists check
- if chunk then
- environment.showmessage("loading", fullname)
- assert(chunk)()
- if version then
- local v = version -- can be nil
- if modules and modules[filename] then
- v = modules[filename].version -- new
- elseif versions and versions[filename] then
- v = versions[filename] -- old
- end
- if v ~= version then
- environment.showmessage("version mismatch", filename,"lua=" .. v, "luc=" ..version)
- environment.loadluafile(filename)
- end
+-- the next ones can use the previous ones / combine
- end
+function environment.loadluafile(filename, version)
+ local lucname, luaname, chunk
+ local basename = file.removesuffix(filename)
+ if basename == filename then
+ lucname, luaname = basename .. ".luc", basename .. ".lua"
+ else
+ lucname, luaname = nil, basename -- forced suffix
+ end
+ -- when not overloaded by explicit suffix we look for a luc file first
+ local fullname = (lucname and environment.luafile(lucname)) or ""
+ if fullname ~= "" then
+ if trace_verbose then
+ logs.report("fileio","loading %s", fullname)
+ end
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ -- we check of the version number of this chunk matches
+ local v = version -- can be nil
+ if modules and modules[filename] then
+ v = modules[filename].version -- new method
+ elseif versions and versions[filename] then
+ v = versions[filename] -- old method
+ end
+ if v == version then
+ return true
else
+ if trace_verbose then
+ logs.report("fileio","version mismatch for %s: lua=%s, luc=%s", filename, v, version)
+ end
environment.loadluafile(filename)
end
else
- environment.loadluafile(filename)
+ return true
end
end
-end
-
--- -- -- the next function was posted by Peter Cawley on the lua list -- -- --
--- -- -- -- -- --
--- -- -- stripping makes the compressed format file about 1MB smaller -- -- --
--- -- -- -- -- --
--- -- -- using this trick is at your own risk -- -- --
-
-local function strip_code(dump)
- local version, format, endian, int, size, ins, num = dump:byte(5, 11)
- local subint
- if endian == 1 then
- subint = function(dump, i, l)
- local val = 0
- for n = l, 1, -1 do
- val = val * 256 + dump:byte(i + n - 1)
- end
- return val, i + l
+ fullname = (luaname and environment.luafile(luaname)) or ""
+ if fullname ~= "" then
+ if trace_verbose then
+ logs.report("fileio","loading %s", fullname)
end
- else
- subint = function(dump, i, l)
- local val = 0
- for n = 1, l, 1 do
- val = val * 256 + dump:byte(i + n - 1)
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ if not chunk then
+ if verbose then
+ logs.report("fileio","unknown file %s", filename)
end
- return val, i + l
- end
- end
- local strip_function
- strip_function = function(dump)
- local count, offset = subint(dump, 1, size)
- local stripped, dirty = string.rep("\0", size), offset + count
- offset = offset + count + int * 2 + 4
- offset = offset + int + subint(dump, offset, int) * ins
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- local t
- t, offset = subint(dump, offset, 1)
- if t == 1 then
- offset = offset + 1
- elseif t == 4 then
- offset = offset + size + subint(dump, offset, size)
- elseif t == 3 then
- offset = offset + num
- end
- end
- count, offset = subint(dump, offset, int)
- stripped = stripped .. dump:sub(dirty, offset - 1)
- for n = 1, count do
- local proto, off = strip_function(dump:sub(offset, -1))
- stripped, offset = stripped .. proto, offset + off - 1
- end
- offset = offset + subint(dump, offset, int) * int + int
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size + int * 2
- end
- count, offset = subint(dump, offset, int)
- for n = 1, count do
- offset = offset + subint(dump, offset, size) + size
+ else
+ assert(chunk)()
+ return true
end
- stripped = stripped .. string.rep("\0", int * 3)
- return stripped, offset
end
- return dump:sub(1,12) .. strip_function(dump:sub(13,-1))
+ return false
end
-
-environment.stripcode = false -- true
-
-function environment.loadedluacode(fullname)
- if environment.stripcode then
- return loadstring(strip_code(string.dump(loadstring(io.loaddata(fullname)))))
- else
- return loadfile(fullname)
- end
-end
-
--- -- end of stripping code -- --