summaryrefslogtreecommitdiff
path: root/tex/context/base/file-job.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/file-job.lua')
-rw-r--r--tex/context/base/file-job.lua2002
1 files changed, 1001 insertions, 1001 deletions
diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua
index 288a690d2..9a88cefb4 100644
--- a/tex/context/base/file-job.lua
+++ b/tex/context/base/file-job.lua
@@ -1,1001 +1,1001 @@
-if not modules then modules = { } end modules ['file-job'] = {
- version = 1.001,
- comment = "companion to file-job.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- in retrospect dealing it's not that bad to deal with the nesting
--- and push/poppign at the tex end
-
-local gsub, match, find = string.gsub, string.match, string.find
-local insert, remove, concat = table.insert, table.remove, table.concat
-local validstring = string.valid
-local sortedhash = table.sortedhash
-local formatters = string.formatters
-
-local commands, resolvers, context = commands, resolvers, context
-
-local trace_jobfiles = false trackers.register("system.jobfiles", function(v) trace_jobfiles = v end)
-
-local report_jobfiles = logs.reporter("system","jobfiles")
-
-local texsetcount = tex.setcount
-local elements = interfaces.elements
-local constants = interfaces.constants
-local variables = interfaces.variables
-local logsnewline = logs.newline
-local logspushtarget = logs.pushtarget
-local logspoptarget = logs.poptarget
-local settings_to_array = utilities.parsers.settings_to_array
-local allocate = utilities.storage.allocate
-
-local nameonly = file.nameonly
-local suffixonly = file.suffix
-local basename = file.basename
-local addsuffix = file.addsuffix
-local removesuffix = file.removesuffix
-local dirname = file.dirname
-local joinpath = file.join
-local is_qualified_path = file.is_qualified_path
-
-local cleanpath = resolvers.cleanpath
-local inputstack = resolvers.inputstack
-
-local v_outer = variables.outer
-local v_text = variables.text
-local v_project = variables.project
-local v_environment = variables.environment
-local v_product = variables.product
-local v_component = variables.component
-local c_prefix = variables.prefix
-
--- main code .. there is some overlap .. here we have loc://
-
-local function findctxfile(name) -- loc ? any ?
- if is_qualified_path(name) then -- maybe when no suffix do some test for tex
- return name
- elseif not url.hasscheme(name) then
- return resolvers.finders.byscheme("loc",name) or ""
- else
- return resolvers.findtexfile(name) or ""
- end
-end
-
-resolvers.findctxfile = findctxfile
-
-function commands.processfile(name)
- name = findctxfile(name)
- if name ~= "" then
- context.input(name)
- end
-end
-
-function commands.doifinputfileelse(name)
- commands.doifelse(findctxfile(name) ~= "")
-end
-
-function commands.locatefilepath(name)
- context(dirname(findctxfile(name)))
-end
-
-function commands.usepath(paths)
- resolvers.registerextrapath(paths)
-end
-
-function commands.usesubpath(subpaths)
- resolvers.registerextrapath(nil,subpaths)
-end
-
-function commands.allinputpaths()
- context(concat(resolvers.instance.extra_paths or { },","))
-end
-
-function commands.setdocumentfilenames()
- environment.initializefilenames()
-end
-
-function commands.usezipfile(name,tree)
- if tree and tree ~= "" then
- resolvers.usezipfile(formatters["zip:///%s?tree=%s"](name,tree))
- else
- resolvers.usezipfile(formatters["zip:///%s"](name))
- end
-end
-
-local report_system = logs.reporter("system")
-
--- moved from tex to lua:
-
-local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
-local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua" }
-local cldpatterns = { "%s.cld" }
-local xmlpatterns = { "%s.xml" }
-
-local uselibrary = commands.uselibrary
-local input = context.input
-
--- status
---
--- these need to be synced with input stream:
-
-local processstack = { }
-local processedfile = ""
-local processedfiles = { }
-
-function commands.processedfile()
- context(processedfile)
-end
-
-function commands.processedfiles()
- context(concat(processedfiles,","))
-end
-
-function commands.dostarttextfile(name)
- insert(processstack,name)
- processedfile = name
- insert(processedfiles,name)
-end
-
-function commands.dostoptextfile()
- processedfile = remove(processstack) or ""
-end
-
-local function startprocessing(name,notext)
- if not notext then
- -- report_system("begin file %a at line %a",name,status.linenumber or 0)
- context.dostarttextfile(name)
- end
-end
-
-local function stopprocessing(notext)
- if not notext then
- context.dostoptextfile()
- -- report_system("end file %a at line %a",name,status.linenumber or 0)
- end
-end
-
---
-
-local action = function(name,foundname) input(foundname) end
-local failure = function(name,foundname) report_jobfiles("unknown %s file %a","tex",name) end
-
-local function usetexfile(name,onlyonce,notext)
- startprocessing(name,notext)
- uselibrary {
- name = name,
- patterns = texpatterns,
- action = action,
- failure = failure,
- onlyonce = onlyonce,
- }
- stopprocessing(notext)
-end
-
-local action = function(name,foundname) dofile(foundname) end
-local failure = function(name,foundname) report_jobfiles("unknown %s file %a","lua",name) end
-
-local function useluafile(name,onlyonce,notext)
- uselibrary {
- name = name,
- patterns = luapatterns,
- action = action,
- failure = failure,
- onlyonce = onlyonce,
- }
-end
-
-local action = function(name,foundname) dofile(foundname) end
-local failure = function(name,foundname) report_jobfiles("unknown %s file %a","cld",name) end
-
-local function usecldfile(name,onlyonce,notext)
- startprocessing(name,notext)
- uselibrary {
- name = name,
- patterns = cldpatterns,
- action = action,
- failure = failure,
- onlyonce = onlyonce,
- }
- stopprocessing(notext)
-end
-
-local action = function(name,foundname) context.xmlprocess(foundname,"main","") end
-local failure = function(name,foundname) report_jobfiles("unknown %s file %a","xml",name) end
-
-local function usexmlfile(name,onlyonce,notext)
- startprocessing(name,notext)
- uselibrary {
- name = name,
- patterns = xmlpatterns,
- action = action,
- failure = failure,
- onlyonce = onlyonce,
- }
- stopprocessing(notext)
-end
-
-commands.usetexfile = usetexfile
-commands.useluafile = useluafile
-commands.usecldfile = usecldfile
-commands.usexmlfile = usexmlfile
-
-local suffixes = {
- mkvi = usetexfile,
- mkiv = usetexfile,
- tex = usetexfile,
- luc = useluafile,
- lua = useluafile,
- cld = usecldfile,
- xml = usexmlfile,
- [""] = usetexfile,
-}
-
-local function useanyfile(name,onlyonce)
- local s = suffixes[file.suffix(name)]
- if s then
- s(removesuffix(name),onlyonce)
- else
- usetexfile(name,onlyonce) -- e.g. ctx file
---~ resolvers.readfilename(name)
- end
-end
-
-commands.useanyfile = useanyfile
-
-function resolvers.jobs.usefile(name,onlyonce,notext)
- local s = suffixes[file.suffix(name)]
- if s then
- s(removesuffix(name),onlyonce,notext)
- end
-end
-
--- document structure
-
-local textlevel = 0 -- inaccessible for user, we need to define counter textlevel at the tex end
-
-local function dummyfunction() end
-
-local function startstoperror()
- report_system("invalid \\%s%s ... \\%s%s structure",elements.start,v_text,elements.stop,v_text)
- startstoperror = dummyfunction
-end
-
-local function starttext()
- if textlevel == 0 then
- if trace_jobfiles then
- report_jobfiles("starting text")
- end
- -- registerfileinfo[begin]jobfilename
- context.dostarttext()
- end
- textlevel = textlevel + 1
- texsetcount("global","textlevel",textlevel)
-end
-
-local function stoptext()
- if textlevel == 0 then
- startstoperror()
- elseif textlevel > 0 then
- textlevel = textlevel - 1
- end
- texsetcount("global","textlevel",textlevel)
- if textlevel <= 0 then
- if trace_jobfiles then
- report_jobfiles("stopping text")
- end
- context.dostoptext()
- -- registerfileinfo[end]jobfilename
- context.finalend()
- commands.stoptext = dummyfunction
- end
-end
-
-commands.starttext = starttext
-commands.stoptext = stoptext
-
-function commands.forcequitjob(reason)
- if reason then
- report_system("forcing quit: %s",reason)
- else
- report_system("forcing quit")
- end
- context.batchmode()
- while textlevel >= 0 do
- context.stoptext()
- end
-end
-
-function commands.forceendjob()
- report_system([[don't use \end to finish a document]])
- context.stoptext()
-end
-
-function commands.autostarttext()
- if textlevel == 0 then
- report_system([[auto \starttext ... \stoptext]])
- end
- context.starttext()
-end
-
-commands.autostoptext = stoptext
-
--- project structure
-
-function commands.processfilemany(name)
- useanyfile(name,false)
-end
-
-function commands.processfileonce(name)
- useanyfile(name,true)
-end
-
-function commands.processfilenone(name)
- -- skip file
-end
-
---
-
-local typestack = { }
-local pathstack = { }
-
-local currenttype = v_text
-local currentpath = "."
-
-local tree = { type = "text", name = "", branches = { } }
-local treestack = { }
-local top = tree.branches
-local root = tree
-
-local project_stack = { }
-local product_stack = { }
-local component_stack = { }
-local environment_stack = { }
-
-local stacks = {
- [v_project ] = project_stack,
- [v_product ] = product_stack,
- [v_component ] = component_stack,
- [v_environment] = environment_stack,
-}
-
---
-
-local report_structures = logs.reporter("system","structure")
-local report_structure = logs.reporter("used structure")
-
-local function pushtree(what,name)
- local t = { }
- top[#top+1] = { type = what, name = name, branches = t }
- insert(treestack,top)
- top = t
-end
-
-local function poptree()
- top = remove(treestack)
- -- inspect(top)
-end
-
-local function log_tree(top,depth)
- report_structure("%s%s: %s",depth,top.type,top.name)
- local branches = top.branches
- if #branches > 0 then
- depth = depth .. " "
- for i=1,#branches do
- log_tree(branches[i],depth)
- end
- end
-end
-
-luatex.registerstopactions(function()
- logspushtarget("logfile")
- logsnewline()
- report_structures("start used structure")
- logsnewline()
- root.name = environment.jobname
- log_tree(root,"")
- logsnewline()
- report_structures("stop used structure")
- logsnewline()
- logspoptarget()
-end)
-
-job.structure = job.structure or { }
-job.structure.collected = job.structure.collected or { }
-job.structure.tobesaved = root
-job.structure.components = { }
-
-local function initialize()
- local function collect(root,result)
- local branches = root.branches
- if branches then
- for i=1,#branches do
- local branch = branches[i]
- if branch.type == "component" then
- result[#result+1] = branch.name
- end
- collect(branch,result)
- end
- end
- return result
- end
- job.structure.components = collect(job.structure.collected,{})
-end
-
-job.register('job.structure.collected',root,initialize)
-
--- component: small unit, either or not components itself
--- product : combination of components
-
-local context_processfilemany = context.processfilemany
-local context_processfileonce = context.processfileonce
-local context_processfilenone = context.processfilenone
-
-local processors = utilities.storage.allocate {
- -- [v_outer] = {
- -- [v_text] = { "many", context_processfilemany },
- -- [v_project] = { "once", context_processfileonce },
- -- [v_environment] = { "once", context_processfileonce },
- -- [v_product] = { "once", context_processfileonce },
- -- [v_component] = { "many", context_processfilemany },
- -- },
- [v_text] = {
- [v_text] = { "many", context_processfilemany },
- [v_project] = { "once", context_processfileonce }, -- dubious
- [v_environment] = { "once", context_processfileonce },
- [v_product] = { "many", context_processfilemany }, -- dubious
- [v_component] = { "many", context_processfilemany },
- },
- [v_project] = {
- [v_text] = { "many", context_processfilemany },
- [v_project] = { "none", context_processfilenone },
- [v_environment] = { "once", context_processfileonce },
- [v_product] = { "none", context_processfilenone },
- [v_component] = { "none", context_processfilenone },
- },
- [v_environment] = {
- [v_text] = { "many", context_processfilemany },
- [v_project] = { "none", context_processfilenone },
- [v_environment] = { "once", context_processfileonce },
- [v_product] = { "none", context_processfilenone },
- [v_component] = { "none", context_processfilenone },
- },
- [v_product] = {
- [v_text] = { "many", context_processfilemany },
- [v_project] = { "once", context_processfileonce },
- [v_environment] = { "once", context_processfileonce },
- [v_product] = { "many", context_processfilemany },
- [v_component] = { "many", context_processfilemany },
- },
- [v_component] = {
- [v_text] = { "many", context_processfilemany },
- [v_project] = { "once", context_processfileonce },
- [v_environment] = { "once", context_processfileonce },
- [v_product] = { "none", context_processfilenone },
- [v_component] = { "many", context_processfilemany },
- }
-}
-
-local start = {
- [v_text] = nil,
- [v_project] = nil,
- [v_environment] = context.startreadingfile,
- [v_product] = context.starttext,
- [v_component] = context.starttext,
-}
-
-local stop = {
- [v_text] = nil,
- [v_project] = nil,
- [v_environment] = context.stopreadingfile,
- [v_product] = context.stoptext,
- [v_component] = context.stoptext,
-}
-
-resolvers.jobs.processors = processors
-
-local function topofstack(what)
- local stack = stacks[what]
- return stack and stack[#stack] or environment.jobname
-end
-
-local function productcomponent() -- only when in product
- local product = product_stack[#product_stack]
- if product and product ~= "" then
- local component = component_stack[1]
- if component and component ~= "" then
- return component
- end
- end
-end
-
-local function justacomponent()
- local product = product_stack[#product_stack]
- if not product or product == "" then
- local component = component_stack[1]
- if component and component ~= "" then
- return component
- end
- end
-end
-
-resolvers.jobs.productcomponent = productcomponent
-resolvers.jobs.justacomponent = justacomponent
-
-function resolvers.jobs.currentproject () return topofstack(v_project ) end
-function resolvers.jobs.currentproduct () return topofstack(v_product ) end
-function resolvers.jobs.currentcomponent () return topofstack(v_component ) end
-function resolvers.jobs.currentenvironment() return topofstack(v_environment) end
-
-local done = { }
-local tolerant = false -- too messy, mkii user with the wrong sructure should adapt
-
-local function process(what,name)
- local depth = #typestack
- local process
- --
- name = resolvers.resolve(name)
- --
--- if not tolerant then
- -- okay, would be best but not compatible with mkii
- process = processors[currenttype][what]
--- elseif depth == 0 then
--- -- could be a component, product or (brr) project
--- if trace_jobfiles then
--- report_jobfiles("%s : %s > %s (case 1)",depth,currenttype,v_outer)
--- end
--- process = processors[v_outer][what]
--- elseif depth == 1 and typestack[1] == v_text then
--- -- we're still not doing a component or product
--- if trace_jobfiles then
--- report_jobfiles("%s : %s > %s (case 2)",depth,currenttype,v_outer)
--- end
--- process = processors[v_outer][what]
--- else
--- process = processors[currenttype][what]
--- end
- if process then
- local method = process[1]
- if method == "none" then
- if trace_jobfiles then
- report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"ignoring",what,name,currenttype,topofstack(currenttype))
- end
- elseif method == "once" and done[name] then
- if trace_jobfiles then
- report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"skipping",what,name,currenttype,topofstack(currenttype))
- end
- else
- -- keep in mind that we also handle "once" at the file level
- -- so there is a double catch
- done[name] = true
- local before = start[what]
- local after = stop [what]
- if trace_jobfiles then
- report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"processing",what,name,currenttype,topofstack(currenttype))
- end
- if before then
- before()
- end
- process[2](name)
- if after then
- after()
- end
- end
- else
- if trace_jobfiles then
- report_jobfiles("%s : %s : %s %s %a in %s %a",depth,"none","ignoring",what,name,currenttype,topofstack(currenttype))
- end
- end
-end
-
-function commands.useproject (name) process(v_project, name) end
-function commands.useenvironment(name) process(v_environment,name) end
-function commands.useproduct (name) process(v_product, name) end
-function commands.usecomponent (name) process(v_component, name) end
-
--- todo: setsystemmode to currenttype
--- todo: make start/stop commands at the tex end
-
-local start = {
- [v_project] = context.startprojectindeed,
- [v_product] = context.startproductindeed,
- [v_component] = context.startcomponentindeed,
- [v_environment] = context.startenvironmentindeed,
-}
-
-local stop = {
- [v_project] = context.stopprojectindeed,
- [v_product] = context.stopproductindeed,
- [v_component] = context.stopcomponentindeed,
- [v_environment] = context.stopenvironmentindeed,
-}
-
-local function gotonextlevel(what,name) -- todo: something with suffix name
- insert(stacks[what],name)
- insert(typestack,currenttype)
- insert(pathstack,currentpath)
- currenttype = what
- currentpath = dirname(name)
- pushtree(what,name)
- if start[what] then
- start[what]()
- end
-end
-
-local function gotopreviouslevel(what)
- if stop[what] then
- stop[what]()
- end
- poptree()
- currentpath = remove(pathstack) or "."
- currenttype = remove(typestack) or v_text
- remove(stacks[what]) -- not currenttype ... weak recovery
- -- context.endinput() -- does not work
- context.signalendofinput(what)
-end
-
-local function autoname(name)
- if name == "*" then
- name = nameonly(inputstack[#inputstack] or name)
- end
- return name
-end
-
-function commands.startproject (name) gotonextlevel(v_project, autoname(name)) end
-function commands.startproduct (name) gotonextlevel(v_product, autoname(name)) end
-function commands.startcomponent (name) gotonextlevel(v_component, autoname(name)) end
-function commands.startenvironment(name) gotonextlevel(v_environment,autoname(name)) end
-
-function commands.stopproject () gotopreviouslevel(v_project ) end
-function commands.stopproduct () gotopreviouslevel(v_product ) end
-function commands.stopcomponent () gotopreviouslevel(v_component ) end
-function commands.stopenvironment() gotopreviouslevel(v_environment) end
-
-function commands.currentproject () context(topofstack(v_project )) end
-function commands.currentproduct () context(topofstack(v_product )) end
-function commands.currentcomponent () context(topofstack(v_component )) end
-function commands.currentenvironment() context(topofstack(v_environment)) end
-
--- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
---
--- <?xml version='1.0' standalone='yes'?>
--- <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
--- <exa:variable label='mode:pragma'>nee</exa:variable>
--- <exa:variable label='mode:variant'>standaard</exa:variable>
--- </exa:variables>
---
--- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
-local report_examodes = logs.reporter("system","examodes")
-
-local function convertexamodes(str)
- local x = xml.convert(str)
- for e in xml.collected(x,"exa:variable") do
- local label = e.at and e.at.label
- if label and label ~= "" then
- local data = xml.text(e)
- local mode = match(label,"^mode:(.+)$")
- if mode then
- context.enablemode { formatters["%s:%s"](mode,data) }
- end
- context.setvariable("exa:variables",label,(gsub(data,"([{}])","\\%1")))
- end
- end
-end
-
-function commands.loadexamodes(filename)
- if not filename or filename == "" then
- filename = removesuffix(tex.jobname)
- end
- filename = resolvers.findfile(addsuffix(filename,'ctm')) or ""
- if filename ~= "" then
- report_examodes("loading %a",filename) -- todo: message system
- convertexamodes(io.loaddata(filename))
- else
- report_examodes("no mode file %a",filename) -- todo: message system
- end
-end
-
--- changed in mtx-context
--- code moved from luat-ini
-
--- todo: locals when mtx-context is changed
-
-document = document or {
- arguments = allocate(),
- files = allocate(),
- variables = allocate(), -- for templates
- options = {
- commandline = {
- environments = allocate(),
- modules = allocate(),
- modes = allocate(),
- },
- ctxfile = {
- environments = allocate(),
- modules = allocate(),
- modes = allocate(),
- },
- },
-}
-
-function document.setargument(key,value)
- document.arguments[key] = value
-end
-
-function document.setdefaultargument(key,default)
- local v = document.arguments[key]
- if v == nil or v == "" then
- document.arguments[key] = default
- end
-end
-
-function document.setfilename(i,name)
- if name then
- document.files[tonumber(i)] = name
- else
- document.files[#document.files+1] = tostring(i)
- end
-end
-
-function document.getargument(key,default) -- commands
- local v = document.arguments[key]
- if type(v) == "boolean" then
- v = (v and "yes") or "no"
- document.arguments[key] = v
- end
- context(v or default or "")
-end
-
-function document.getfilename(i) -- commands
- context(document.files[tonumber(i)] or "")
-end
-
-function commands.getcommandline() -- has to happen at the tex end in order to expand
-
- -- the document[arguments|files] tables are copies
-
- local arguments = document.arguments
- local files = document.files
- local options = document.options
-
- for k, v in next, environment.arguments do
- k = gsub(k,"^c:","") -- already done, but better be safe than sorry
- if arguments[k] == nil then
- arguments[k] = v
- end
- end
-
- -- in the new mtx=context approach we always pass a stub file so we need to
- -- to trick the files table which actually only has one entry in a tex job
-
- if arguments.timing then
- context.usemodule("timing")
- end
-
- if arguments.batchmode then
- context.batchmode(false)
- end
-
- if arguments.nonstopmode then
- context.nonstopmode(false)
- end
-
- if arguments.nostatistics then
- directives.enable("system.nostatistics")
- end
-
- if arguments.paranoid then
- context.setvalue("maxreadlevel",1)
- end
-
- if validstring(arguments.path) then
- context.usepath { arguments.path }
- end
-
- local inputfile = validstring(arguments.input)
-
- if inputfile and dirname(inputfile) == "." and lfs.isfile(inputfile) then
- -- nicer in checks
- inputfile = basename(inputfile)
- end
-
- local kindofrun = arguments.kindofrun
- local currentrun = arguments.maxnofruns
- local maxnofruns = arguments.currentrun
-
- context.setupsystem {
- [constants.directory] = validstring(arguments.setuppath),
- [constants.inputfile] = inputfile,
- [constants.file] = validstring(arguments.result),
- [constants.random] = validstring(arguments.randomseed),
- -- old:
- [constants.n] = validstring(kindofrun),
- [constants.m] = validstring(currentrun),
- }
-
- environment.kindofrun = tonumber(kindofrun) or 0
- environment.maxnofruns = tonumber(maxnofruns) or 0
- environment.currentrun = tonumber(currentrun) or 0
-
- if validstring(arguments.arguments) then
- context.setupenv { arguments.arguments }
- end
-
- if arguments.once then
- directives.enable("system.runonce")
- end
-
- if arguments.noarrange then
- context.setuparranging { variables.disable }
- end
-
- --
-
- local commandline = options.commandline
-
- commandline.environments = table.append(commandline.environments,settings_to_array(validstring(arguments.environment)))
- commandline.modules = table.append(commandline.modules, settings_to_array(validstring(arguments.usemodule)))
- commandline.modes = table.append(commandline.modes, settings_to_array(validstring(arguments.mode)))
-
- --
-
- if #files == 0 then
- local list = settings_to_array(validstring(arguments.files))
- if list and #list > 0 then
- files = list
- end
- end
-
- if #files == 0 then
- files = { validstring(arguments.input) }
- end
-
- --
-
- document.arguments = arguments
- document.files = files
-
-end
-
--- commandline wins over ctxfile
-
-local function apply(list,action)
- if list then
- for i=1,#list do
- action { list[i] }
- end
- end
-end
-
-function commands.setdocumentmodes() -- was setup: *runtime:modes
- apply(document.options.ctxfile .modes,context.enablemode)
- apply(document.options.commandline.modes,context.enablemode)
-end
-
-function commands.setdocumentmodules() -- was setup: *runtime:modules
- apply(document.options.ctxfile .modules,context.usemodule)
- apply(document.options.commandline.modules,context.usemodule)
-end
-
-function commands.setdocumentenvironments() -- was setup: *runtime:environments
- apply(document.options.ctxfile .environments,context.environment)
- apply(document.options.commandline.environments,context.environment)
-end
-
-local report_files = logs.reporter("system","files")
-local report_options = logs.reporter("system","options")
-local report_file = logs.reporter("used file")
-local report_option = logs.reporter("used option")
-
-luatex.registerstopactions(function()
- local foundintrees = resolvers.instance.foundintrees
- if #foundintrees > 0 then
- logspushtarget("logfile")
- logsnewline()
- report_files("start used files")
- logsnewline()
- for i=1,#foundintrees do
- report_file("%4i: % T",i,foundintrees[i])
- end
- logsnewline()
- report_files("stop used files")
- logsnewline()
- logspoptarget()
- end
-end)
-
-luatex.registerstopactions(function()
- local files = document.files -- or environment.files
- local arguments = document.arguments -- or environment.arguments
- --
- logspushtarget("logfile")
- logsnewline()
- report_options("start commandline options")
- logsnewline()
- for argument, value in sortedhash(arguments) do
- report_option("%s=%A",argument,value)
- end
- logsnewline()
- report_options("stop commandline options")
- logsnewline()
- report_options("start commandline files")
- logsnewline()
- for i=1,#files do
- report_file("% 4i: %s",i,files[i])
- end
- logsnewline()
- report_options("stop commandline files")
- logsnewline()
- logspoptarget()
-end)
-
-if environment.initex then
-
- local report_storage = logs.reporter("system","storage")
- local report_table = logs.reporter("stored table")
- local report_module = logs.reporter("stored module")
- local report_attribute = logs.reporter("stored attribute")
- local report_catcodetable = logs.reporter("stored catcodetable")
- local report_corenamespace = logs.reporter("stored corenamespace")
-
- luatex.registerstopactions(function()
- logspushtarget("logfile")
- logsnewline()
- report_storage("start stored tables")
- logsnewline()
- for k,v in sortedhash(storage.data) do
- report_table("%03i %s",k,v[1])
- end
- logsnewline()
- report_storage("stop stored tables")
- logsnewline()
- report_storage("start stored modules")
- logsnewline()
- for k,v in sortedhash(lua.bytedata) do
- report_module("%03i %s %s",k,v[2],v[1])
- end
- logsnewline()
- report_storage("stop stored modules")
- logsnewline()
- report_storage("start stored attributes")
- logsnewline()
- for k,v in sortedhash(attributes.names) do
- report_attribute("%03i %s",k,v)
- end
- logsnewline()
- report_storage("stop stored attributes")
- logsnewline()
- report_storage("start stored catcodetables")
- logsnewline()
- for k,v in sortedhash(catcodes.names) do
- report_catcodetable("%03i % t",k,v)
- end
- logsnewline()
- report_storage("stop stored catcodetables")
- logsnewline()
- report_storage("start stored corenamespaces")
- for k,v in sortedhash(interfaces.corenamespaces) do
- report_corenamespace("%03i %s",k,v)
- end
- logsnewline()
- report_storage("stop stored corenamespaces")
- logsnewline()
- logspoptarget()
- end)
-
-end
-
-function commands.doifelsecontinuewithfile(inpname,basetoo)
- local inpnamefull = addsuffix(inpname,"tex")
- local inpfilefull = addsuffix(environment.inputfilename,"tex")
- local continue = inpnamefull == inpfilefull
- if basetoo and not continue then
- continue = inpnamefull == basename(inpfilefull)
- end
- if continue then
- report_system("continuing input file %a",inpname)
- end
- commands.doifelse(continue)
-end
+if not modules then modules = { } end modules ['file-job'] = {
+ version = 1.001,
+ comment = "companion to file-job.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- in retrospect dealing it's not that bad to deal with the nesting
+-- and push/poppign at the tex end
+
+local gsub, match, find = string.gsub, string.match, string.find
+local insert, remove, concat = table.insert, table.remove, table.concat
+local validstring = string.valid
+local sortedhash = table.sortedhash
+local formatters = string.formatters
+
+local commands, resolvers, context = commands, resolvers, context
+
+local trace_jobfiles = false trackers.register("system.jobfiles", function(v) trace_jobfiles = v end)
+
+local report_jobfiles = logs.reporter("system","jobfiles")
+
+local texsetcount = tex.setcount
+local elements = interfaces.elements
+local constants = interfaces.constants
+local variables = interfaces.variables
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+local settings_to_array = utilities.parsers.settings_to_array
+local allocate = utilities.storage.allocate
+
+local nameonly = file.nameonly
+local suffixonly = file.suffix
+local basename = file.basename
+local addsuffix = file.addsuffix
+local removesuffix = file.removesuffix
+local dirname = file.dirname
+local joinpath = file.join
+local is_qualified_path = file.is_qualified_path
+
+local cleanpath = resolvers.cleanpath
+local inputstack = resolvers.inputstack
+
+local v_outer = variables.outer
+local v_text = variables.text
+local v_project = variables.project
+local v_environment = variables.environment
+local v_product = variables.product
+local v_component = variables.component
+local c_prefix = variables.prefix
+
+-- main code .. there is some overlap .. here we have loc://
+
+local function findctxfile(name) -- loc ? any ?
+ if is_qualified_path(name) then -- maybe when no suffix do some test for tex
+ return name
+ elseif not url.hasscheme(name) then
+ return resolvers.finders.byscheme("loc",name) or ""
+ else
+ return resolvers.findtexfile(name) or ""
+ end
+end
+
+resolvers.findctxfile = findctxfile
+
+function commands.processfile(name)
+ name = findctxfile(name)
+ if name ~= "" then
+ context.input(name)
+ end
+end
+
+function commands.doifinputfileelse(name)
+ commands.doifelse(findctxfile(name) ~= "")
+end
+
+function commands.locatefilepath(name)
+ context(dirname(findctxfile(name)))
+end
+
+function commands.usepath(paths)
+ resolvers.registerextrapath(paths)
+end
+
+function commands.usesubpath(subpaths)
+ resolvers.registerextrapath(nil,subpaths)
+end
+
+function commands.allinputpaths()
+ context(concat(resolvers.instance.extra_paths or { },","))
+end
+
+function commands.setdocumentfilenames()
+ environment.initializefilenames()
+end
+
+function commands.usezipfile(name,tree)
+ if tree and tree ~= "" then
+ resolvers.usezipfile(formatters["zip:///%s?tree=%s"](name,tree))
+ else
+ resolvers.usezipfile(formatters["zip:///%s"](name))
+ end
+end
+
+local report_system = logs.reporter("system")
+
+-- moved from tex to lua:
+
+local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
+local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua" }
+local cldpatterns = { "%s.cld" }
+local xmlpatterns = { "%s.xml" }
+
+local uselibrary = commands.uselibrary
+local input = context.input
+
+-- status
+--
+-- these need to be synced with input stream:
+
+local processstack = { }
+local processedfile = ""
+local processedfiles = { }
+
+function commands.processedfile()
+ context(processedfile)
+end
+
+function commands.processedfiles()
+ context(concat(processedfiles,","))
+end
+
+function commands.dostarttextfile(name)
+ insert(processstack,name)
+ processedfile = name
+ insert(processedfiles,name)
+end
+
+function commands.dostoptextfile()
+ processedfile = remove(processstack) or ""
+end
+
+local function startprocessing(name,notext)
+ if not notext then
+ -- report_system("begin file %a at line %a",name,status.linenumber or 0)
+ context.dostarttextfile(name)
+ end
+end
+
+local function stopprocessing(notext)
+ if not notext then
+ context.dostoptextfile()
+ -- report_system("end file %a at line %a",name,status.linenumber or 0)
+ end
+end
+
+--
+
+local action = function(name,foundname) input(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","tex",name) end
+
+local function usetexfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = texpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","lua",name) end
+
+local function useluafile(name,onlyonce,notext)
+ uselibrary {
+ name = name,
+ patterns = luapatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","cld",name) end
+
+local function usecldfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = cldpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) context.xmlprocess(foundname,"main","") end
+local failure = function(name,foundname) report_jobfiles("unknown %s file %a","xml",name) end
+
+local function usexmlfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = xmlpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+commands.usetexfile = usetexfile
+commands.useluafile = useluafile
+commands.usecldfile = usecldfile
+commands.usexmlfile = usexmlfile
+
+local suffixes = {
+ mkvi = usetexfile,
+ mkiv = usetexfile,
+ tex = usetexfile,
+ luc = useluafile,
+ lua = useluafile,
+ cld = usecldfile,
+ xml = usexmlfile,
+ [""] = usetexfile,
+}
+
+local function useanyfile(name,onlyonce)
+ local s = suffixes[file.suffix(name)]
+ if s then
+ s(removesuffix(name),onlyonce)
+ else
+ usetexfile(name,onlyonce) -- e.g. ctx file
+--~ resolvers.readfilename(name)
+ end
+end
+
+commands.useanyfile = useanyfile
+
+function resolvers.jobs.usefile(name,onlyonce,notext)
+ local s = suffixes[file.suffix(name)]
+ if s then
+ s(removesuffix(name),onlyonce,notext)
+ end
+end
+
+-- document structure
+
+local textlevel = 0 -- inaccessible for user, we need to define counter textlevel at the tex end
+
+local function dummyfunction() end
+
+local function startstoperror()
+ report_system("invalid \\%s%s ... \\%s%s structure",elements.start,v_text,elements.stop,v_text)
+ startstoperror = dummyfunction
+end
+
+local function starttext()
+ if textlevel == 0 then
+ if trace_jobfiles then
+ report_jobfiles("starting text")
+ end
+ -- registerfileinfo[begin]jobfilename
+ context.dostarttext()
+ end
+ textlevel = textlevel + 1
+ texsetcount("global","textlevel",textlevel)
+end
+
+local function stoptext()
+ if textlevel == 0 then
+ startstoperror()
+ elseif textlevel > 0 then
+ textlevel = textlevel - 1
+ end
+ texsetcount("global","textlevel",textlevel)
+ if textlevel <= 0 then
+ if trace_jobfiles then
+ report_jobfiles("stopping text")
+ end
+ context.dostoptext()
+ -- registerfileinfo[end]jobfilename
+ context.finalend()
+ commands.stoptext = dummyfunction
+ end
+end
+
+commands.starttext = starttext
+commands.stoptext = stoptext
+
+function commands.forcequitjob(reason)
+ if reason then
+ report_system("forcing quit: %s",reason)
+ else
+ report_system("forcing quit")
+ end
+ context.batchmode()
+ while textlevel >= 0 do
+ context.stoptext()
+ end
+end
+
+function commands.forceendjob()
+ report_system([[don't use \end to finish a document]])
+ context.stoptext()
+end
+
+function commands.autostarttext()
+ if textlevel == 0 then
+ report_system([[auto \starttext ... \stoptext]])
+ end
+ context.starttext()
+end
+
+commands.autostoptext = stoptext
+
+-- project structure
+
+function commands.processfilemany(name)
+ useanyfile(name,false)
+end
+
+function commands.processfileonce(name)
+ useanyfile(name,true)
+end
+
+function commands.processfilenone(name)
+ -- skip file
+end
+
+--
+
+local typestack = { }
+local pathstack = { }
+
+local currenttype = v_text
+local currentpath = "."
+
+local tree = { type = "text", name = "", branches = { } }
+local treestack = { }
+local top = tree.branches
+local root = tree
+
+local project_stack = { }
+local product_stack = { }
+local component_stack = { }
+local environment_stack = { }
+
+local stacks = {
+ [v_project ] = project_stack,
+ [v_product ] = product_stack,
+ [v_component ] = component_stack,
+ [v_environment] = environment_stack,
+}
+
+--
+
+local report_structures = logs.reporter("system","structure")
+local report_structure = logs.reporter("used structure")
+
+local function pushtree(what,name)
+ local t = { }
+ top[#top+1] = { type = what, name = name, branches = t }
+ insert(treestack,top)
+ top = t
+end
+
+local function poptree()
+ top = remove(treestack)
+ -- inspect(top)
+end
+
+local function log_tree(top,depth)
+ report_structure("%s%s: %s",depth,top.type,top.name)
+ local branches = top.branches
+ if #branches > 0 then
+ depth = depth .. " "
+ for i=1,#branches do
+ log_tree(branches[i],depth)
+ end
+ end
+end
+
+luatex.registerstopactions(function()
+ logspushtarget("logfile")
+ logsnewline()
+ report_structures("start used structure")
+ logsnewline()
+ root.name = environment.jobname
+ log_tree(root,"")
+ logsnewline()
+ report_structures("stop used structure")
+ logsnewline()
+ logspoptarget()
+end)
+
+job.structure = job.structure or { }
+job.structure.collected = job.structure.collected or { }
+job.structure.tobesaved = root
+job.structure.components = { }
+
+local function initialize()
+ local function collect(root,result)
+ local branches = root.branches
+ if branches then
+ for i=1,#branches do
+ local branch = branches[i]
+ if branch.type == "component" then
+ result[#result+1] = branch.name
+ end
+ collect(branch,result)
+ end
+ end
+ return result
+ end
+ job.structure.components = collect(job.structure.collected,{})
+end
+
+job.register('job.structure.collected',root,initialize)
+
+-- component: small unit, either or not components itself
+-- product : combination of components
+
+local context_processfilemany = context.processfilemany
+local context_processfileonce = context.processfileonce
+local context_processfilenone = context.processfilenone
+
+local processors = utilities.storage.allocate {
+ -- [v_outer] = {
+ -- [v_text] = { "many", context_processfilemany },
+ -- [v_project] = { "once", context_processfileonce },
+ -- [v_environment] = { "once", context_processfileonce },
+ -- [v_product] = { "once", context_processfileonce },
+ -- [v_component] = { "many", context_processfilemany },
+ -- },
+ [v_text] = {
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce }, -- dubious
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "many", context_processfilemany }, -- dubious
+ [v_component] = { "many", context_processfilemany },
+ },
+ [v_project] = {
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "none", context_processfilenone },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "none", context_processfilenone },
+ },
+ [v_environment] = {
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "none", context_processfilenone },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "none", context_processfilenone },
+ },
+ [v_product] = {
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "many", context_processfilemany },
+ [v_component] = { "many", context_processfilemany },
+ },
+ [v_component] = {
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "many", context_processfilemany },
+ }
+}
+
+local start = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.startreadingfile,
+ [v_product] = context.starttext,
+ [v_component] = context.starttext,
+}
+
+local stop = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.stopreadingfile,
+ [v_product] = context.stoptext,
+ [v_component] = context.stoptext,
+}
+
+resolvers.jobs.processors = processors
+
+local function topofstack(what)
+ local stack = stacks[what]
+ return stack and stack[#stack] or environment.jobname
+end
+
+local function productcomponent() -- only when in product
+ local product = product_stack[#product_stack]
+ if product and product ~= "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+local function justacomponent()
+ local product = product_stack[#product_stack]
+ if not product or product == "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+resolvers.jobs.productcomponent = productcomponent
+resolvers.jobs.justacomponent = justacomponent
+
+function resolvers.jobs.currentproject () return topofstack(v_project ) end
+function resolvers.jobs.currentproduct () return topofstack(v_product ) end
+function resolvers.jobs.currentcomponent () return topofstack(v_component ) end
+function resolvers.jobs.currentenvironment() return topofstack(v_environment) end
+
+local done = { }
+local tolerant = false -- too messy, mkii user with the wrong sructure should adapt
+
+local function process(what,name)
+ local depth = #typestack
+ local process
+ --
+ name = resolvers.resolve(name)
+ --
+-- if not tolerant then
+ -- okay, would be best but not compatible with mkii
+ process = processors[currenttype][what]
+-- elseif depth == 0 then
+-- -- could be a component, product or (brr) project
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 1)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- elseif depth == 1 and typestack[1] == v_text then
+-- -- we're still not doing a component or product
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 2)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- else
+-- process = processors[currenttype][what]
+-- end
+ if process then
+ local method = process[1]
+ if method == "none" then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"ignoring",what,name,currenttype,topofstack(currenttype))
+ end
+ elseif method == "once" and done[name] then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"skipping",what,name,currenttype,topofstack(currenttype))
+ end
+ else
+ -- keep in mind that we also handle "once" at the file level
+ -- so there is a double catch
+ done[name] = true
+ local before = start[what]
+ local after = stop [what]
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,method,"processing",what,name,currenttype,topofstack(currenttype))
+ end
+ if before then
+ before()
+ end
+ process[2](name)
+ if after then
+ after()
+ end
+ end
+ else
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : %s %s %a in %s %a",depth,"none","ignoring",what,name,currenttype,topofstack(currenttype))
+ end
+ end
+end
+
+function commands.useproject (name) process(v_project, name) end
+function commands.useenvironment(name) process(v_environment,name) end
+function commands.useproduct (name) process(v_product, name) end
+function commands.usecomponent (name) process(v_component, name) end
+
+-- todo: setsystemmode to currenttype
+-- todo: make start/stop commands at the tex end
+
+local start = {
+ [v_project] = context.startprojectindeed,
+ [v_product] = context.startproductindeed,
+ [v_component] = context.startcomponentindeed,
+ [v_environment] = context.startenvironmentindeed,
+}
+
+local stop = {
+ [v_project] = context.stopprojectindeed,
+ [v_product] = context.stopproductindeed,
+ [v_component] = context.stopcomponentindeed,
+ [v_environment] = context.stopenvironmentindeed,
+}
+
+local function gotonextlevel(what,name) -- todo: something with suffix name
+ insert(stacks[what],name)
+ insert(typestack,currenttype)
+ insert(pathstack,currentpath)
+ currenttype = what
+ currentpath = dirname(name)
+ pushtree(what,name)
+ if start[what] then
+ start[what]()
+ end
+end
+
+local function gotopreviouslevel(what)
+ if stop[what] then
+ stop[what]()
+ end
+ poptree()
+ currentpath = remove(pathstack) or "."
+ currenttype = remove(typestack) or v_text
+ remove(stacks[what]) -- not currenttype ... weak recovery
+ -- context.endinput() -- does not work
+ context.signalendofinput(what)
+end
+
+local function autoname(name)
+ if name == "*" then
+ name = nameonly(inputstack[#inputstack] or name)
+ end
+ return name
+end
+
+function commands.startproject (name) gotonextlevel(v_project, autoname(name)) end
+function commands.startproduct (name) gotonextlevel(v_product, autoname(name)) end
+function commands.startcomponent (name) gotonextlevel(v_component, autoname(name)) end
+function commands.startenvironment(name) gotonextlevel(v_environment,autoname(name)) end
+
+function commands.stopproject () gotopreviouslevel(v_project ) end
+function commands.stopproduct () gotopreviouslevel(v_product ) end
+function commands.stopcomponent () gotopreviouslevel(v_component ) end
+function commands.stopenvironment() gotopreviouslevel(v_environment) end
+
+function commands.currentproject () context(topofstack(v_project )) end
+function commands.currentproduct () context(topofstack(v_product )) end
+function commands.currentcomponent () context(topofstack(v_component )) end
+function commands.currentenvironment() context(topofstack(v_environment)) end
+
+-- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+--
+-- <?xml version='1.0' standalone='yes'?>
+-- <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
+-- <exa:variable label='mode:pragma'>nee</exa:variable>
+-- <exa:variable label='mode:variant'>standaard</exa:variable>
+-- </exa:variables>
+--
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+local report_examodes = logs.reporter("system","examodes")
+
+local function convertexamodes(str)
+ local x = xml.convert(str)
+ for e in xml.collected(x,"exa:variable") do
+ local label = e.at and e.at.label
+ if label and label ~= "" then
+ local data = xml.text(e)
+ local mode = match(label,"^mode:(.+)$")
+ if mode then
+ context.enablemode { formatters["%s:%s"](mode,data) }
+ end
+ context.setvariable("exa:variables",label,(gsub(data,"([{}])","\\%1")))
+ end
+ end
+end
+
+function commands.loadexamodes(filename)
+ if not filename or filename == "" then
+ filename = removesuffix(tex.jobname)
+ end
+ filename = resolvers.findfile(addsuffix(filename,'ctm')) or ""
+ if filename ~= "" then
+ report_examodes("loading %a",filename) -- todo: message system
+ convertexamodes(io.loaddata(filename))
+ else
+ report_examodes("no mode file %a",filename) -- todo: message system
+ end
+end
+
+-- changed in mtx-context
+-- code moved from luat-ini
+
+-- todo: locals when mtx-context is changed
+
+document = document or {
+ arguments = allocate(),
+ files = allocate(),
+ variables = allocate(), -- for templates
+ options = {
+ commandline = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ ctxfile = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ },
+}
+
+function document.setargument(key,value)
+ document.arguments[key] = value
+end
+
+function document.setdefaultargument(key,default)
+ local v = document.arguments[key]
+ if v == nil or v == "" then
+ document.arguments[key] = default
+ end
+end
+
+function document.setfilename(i,name)
+ if name then
+ document.files[tonumber(i)] = name
+ else
+ document.files[#document.files+1] = tostring(i)
+ end
+end
+
+function document.getargument(key,default) -- commands
+ local v = document.arguments[key]
+ if type(v) == "boolean" then
+ v = (v and "yes") or "no"
+ document.arguments[key] = v
+ end
+ context(v or default or "")
+end
+
+function document.getfilename(i) -- commands
+ context(document.files[tonumber(i)] or "")
+end
+
+function commands.getcommandline() -- has to happen at the tex end in order to expand
+
+ -- the document[arguments|files] tables are copies
+
+ local arguments = document.arguments
+ local files = document.files
+ local options = document.options
+
+ for k, v in next, environment.arguments do
+ k = gsub(k,"^c:","") -- already done, but better be safe than sorry
+ if arguments[k] == nil then
+ arguments[k] = v
+ end
+ end
+
+ -- in the new mtx=context approach we always pass a stub file so we need to
+ -- to trick the files table which actually only has one entry in a tex job
+
+ if arguments.timing then
+ context.usemodule("timing")
+ end
+
+ if arguments.batchmode then
+ context.batchmode(false)
+ end
+
+ if arguments.nonstopmode then
+ context.nonstopmode(false)
+ end
+
+ if arguments.nostatistics then
+ directives.enable("system.nostatistics")
+ end
+
+ if arguments.paranoid then
+ context.setvalue("maxreadlevel",1)
+ end
+
+ if validstring(arguments.path) then
+ context.usepath { arguments.path }
+ end
+
+ local inputfile = validstring(arguments.input)
+
+ if inputfile and dirname(inputfile) == "." and lfs.isfile(inputfile) then
+ -- nicer in checks
+ inputfile = basename(inputfile)
+ end
+
+ local kindofrun = arguments.kindofrun
+ local currentrun = arguments.maxnofruns
+ local maxnofruns = arguments.currentrun
+
+ context.setupsystem {
+ [constants.directory] = validstring(arguments.setuppath),
+ [constants.inputfile] = inputfile,
+ [constants.file] = validstring(arguments.result),
+ [constants.random] = validstring(arguments.randomseed),
+ -- old:
+ [constants.n] = validstring(kindofrun),
+ [constants.m] = validstring(currentrun),
+ }
+
+ environment.kindofrun = tonumber(kindofrun) or 0
+ environment.maxnofruns = tonumber(maxnofruns) or 0
+ environment.currentrun = tonumber(currentrun) or 0
+
+ if validstring(arguments.arguments) then
+ context.setupenv { arguments.arguments }
+ end
+
+ if arguments.once then
+ directives.enable("system.runonce")
+ end
+
+ if arguments.noarrange then
+ context.setuparranging { variables.disable }
+ end
+
+ --
+
+ local commandline = options.commandline
+
+ commandline.environments = table.append(commandline.environments,settings_to_array(validstring(arguments.environment)))
+ commandline.modules = table.append(commandline.modules, settings_to_array(validstring(arguments.usemodule)))
+ commandline.modes = table.append(commandline.modes, settings_to_array(validstring(arguments.mode)))
+
+ --
+
+ if #files == 0 then
+ local list = settings_to_array(validstring(arguments.files))
+ if list and #list > 0 then
+ files = list
+ end
+ end
+
+ if #files == 0 then
+ files = { validstring(arguments.input) }
+ end
+
+ --
+
+ document.arguments = arguments
+ document.files = files
+
+end
+
+-- commandline wins over ctxfile
+
+local function apply(list,action)
+ if list then
+ for i=1,#list do
+ action { list[i] }
+ end
+ end
+end
+
+function commands.setdocumentmodes() -- was setup: *runtime:modes
+ apply(document.options.ctxfile .modes,context.enablemode)
+ apply(document.options.commandline.modes,context.enablemode)
+end
+
+function commands.setdocumentmodules() -- was setup: *runtime:modules
+ apply(document.options.ctxfile .modules,context.usemodule)
+ apply(document.options.commandline.modules,context.usemodule)
+end
+
+function commands.setdocumentenvironments() -- was setup: *runtime:environments
+ apply(document.options.ctxfile .environments,context.environment)
+ apply(document.options.commandline.environments,context.environment)
+end
+
+local report_files = logs.reporter("system","files")
+local report_options = logs.reporter("system","options")
+local report_file = logs.reporter("used file")
+local report_option = logs.reporter("used option")
+
+luatex.registerstopactions(function()
+ local foundintrees = resolvers.instance.foundintrees
+ if #foundintrees > 0 then
+ logspushtarget("logfile")
+ logsnewline()
+ report_files("start used files")
+ logsnewline()
+ for i=1,#foundintrees do
+ report_file("%4i: % T",i,foundintrees[i])
+ end
+ logsnewline()
+ report_files("stop used files")
+ logsnewline()
+ logspoptarget()
+ end
+end)
+
+luatex.registerstopactions(function()
+ local files = document.files -- or environment.files
+ local arguments = document.arguments -- or environment.arguments
+ --
+ logspushtarget("logfile")
+ logsnewline()
+ report_options("start commandline options")
+ logsnewline()
+ for argument, value in sortedhash(arguments) do
+ report_option("%s=%A",argument,value)
+ end
+ logsnewline()
+ report_options("stop commandline options")
+ logsnewline()
+ report_options("start commandline files")
+ logsnewline()
+ for i=1,#files do
+ report_file("% 4i: %s",i,files[i])
+ end
+ logsnewline()
+ report_options("stop commandline files")
+ logsnewline()
+ logspoptarget()
+end)
+
+if environment.initex then
+
+ local report_storage = logs.reporter("system","storage")
+ local report_table = logs.reporter("stored table")
+ local report_module = logs.reporter("stored module")
+ local report_attribute = logs.reporter("stored attribute")
+ local report_catcodetable = logs.reporter("stored catcodetable")
+ local report_corenamespace = logs.reporter("stored corenamespace")
+
+ luatex.registerstopactions(function()
+ logspushtarget("logfile")
+ logsnewline()
+ report_storage("start stored tables")
+ logsnewline()
+ for k,v in sortedhash(storage.data) do
+ report_table("%03i %s",k,v[1])
+ end
+ logsnewline()
+ report_storage("stop stored tables")
+ logsnewline()
+ report_storage("start stored modules")
+ logsnewline()
+ for k,v in sortedhash(lua.bytedata) do
+ report_module("%03i %s %s",k,v[2],v[1])
+ end
+ logsnewline()
+ report_storage("stop stored modules")
+ logsnewline()
+ report_storage("start stored attributes")
+ logsnewline()
+ for k,v in sortedhash(attributes.names) do
+ report_attribute("%03i %s",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored attributes")
+ logsnewline()
+ report_storage("start stored catcodetables")
+ logsnewline()
+ for k,v in sortedhash(catcodes.names) do
+ report_catcodetable("%03i % t",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored catcodetables")
+ logsnewline()
+ report_storage("start stored corenamespaces")
+ for k,v in sortedhash(interfaces.corenamespaces) do
+ report_corenamespace("%03i %s",k,v)
+ end
+ logsnewline()
+ report_storage("stop stored corenamespaces")
+ logsnewline()
+ logspoptarget()
+ end)
+
+end
+
+function commands.doifelsecontinuewithfile(inpname,basetoo)
+ local inpnamefull = addsuffix(inpname,"tex")
+ local inpfilefull = addsuffix(environment.inputfilename,"tex")
+ local continue = inpnamefull == inpfilefull
+ if basetoo and not continue then
+ continue = inpnamefull == basename(inpfilefull)
+ end
+ if continue then
+ report_system("continuing input file %a",inpname)
+ end
+ commands.doifelse(continue)
+end