diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/luat-env.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/luat-env.lua | 389 |
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 -- -- |