if not modules then modules = { } end modules ['luat-run'] = { version = 1.001, comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local next = next local find = string.find local insert, remove = table.insert, table.remove local osexit = os.exit -- trace_job_status is also controlled by statistics.enable that is set via the directive system.nostatistics local trace_lua_dump = false trackers.register("system.dump", function(v) trace_lua_dump = v end) local trace_temp_files = false trackers.register("system.tempfiles", function(v) trace_temp_files = v end) local trace_job_status = true trackers.register("system.jobstatus", function(v) trace_job_status = v end) local trace_tex_status = false trackers.register("system.texstatus", function(v) trace_tex_status = v end) local report_lua = logs.reporter("system","lua") local report_tex = logs.reporter("system","status") local report_tempfiles = logs.reporter("resolvers","tempfiles") luatex = luatex or { } local luatex = luatex local synctex = luatex.synctex if not synctex then synctex = table.setmetatableindex(function() return function() end end) luatex.synctex = synctex end local startactions = { } local stopactions = { } local dumpactions = { } local pageactions = { } function luatex.registerstartactions(...) insert(startactions, ...) end function luatex.registerstopactions (...) insert(stopactions, ...) end function luatex.registerdumpactions (...) insert(dumpactions, ...) end function luatex.registerpageactions (...) insert(pageactions, ...) end local setexitcode = lua.setexitcode or status.setexitcode or function() end local function start_run() if logs.start_run then logs.start_run() end for i=1,#startactions do startactions[i]() end end local function stop_run(badrun) for i=1,#stopactions do stopactions[i]() end local quit = logs.finalactions() if trace_job_status then statistics.show() end if trace_tex_status then logs.newline() for k, v in table.sortedhash(status.list()) do if type(v) ~= "table" then report_tex("%S=%S",k,v) end end end if quit then setexitcode(1) if type(quit) == "table" then logs.newline() report_tex("quitting due to: %, t",quit) logs.newline() end elseif badrun and badrun > 0 then setexitcode(1) end if logs.stop_run then logs.stop_run() end end -- watch out for synctex here: function callbacks.functions.start_page_number() synctex.start() logs.start_page_number() end function callbacks.functions.stop_page_number() logs.stop_page_number() for i=1,#pageactions do pageactions[i]() end synctex.stop() end local function pre_dump_actions() for i=1,#dumpactions do dumpactions[i]() end lua.finalizeinitex(trace_lua_dump and report_lua or nil) end local function wrapup_synctex() synctex.wrapup() end -- For Taco ... local sequencers = utilities.sequencers local appendgroup = sequencers.appendgroup local appendaction = sequencers.appendaction local wrapupactions = sequencers.new { } local cleanupactions = sequencers.new { } appendgroup(wrapupactions,"system") appendgroup(wrapupactions,"user") appendgroup(cleanupactions,"system") appendgroup(cleanupactions,"user") local function wrapup_run(someerror) local runner = wrapupactions.runner if runner then runner(someerror) -- we could use the error flag in lmtx end end local function cleanup_run() local runner = cleanupactions.runner if runner then runner() end end function luatex.wrapup(action) appendaction(wrapupactions,"user",action) end function luatex.cleanup(action) appendaction(cleanupactions,"user",action) end function luatex.abort() cleanup_run() setexitcode(1) osexit(1) end appendaction(wrapupactions,"system",synctex.wrapup) -- this can be done later callbacks.register("start_run", start_run, "actions performed at the beginning of a run") callbacks.register("stop_run", stop_run, "actions performed at the end of a run") callbacks.register("pre_dump", pre_dump_actions, "lua related finalizers called before we dump the format") -- comes after \everydump callbacks.register("wrapup_run", wrapup_run, "actions performed after closing files") -- an example: local tempfiles = { } function luatex.registertempfile(name,extrasuffix,keep) -- namespace might change if extrasuffix then name = name .. ".mkiv-tmp" -- maybe just .tmp end if trace_temp_files and not tempfiles[name] then if keep then report_tempfiles("%s temporary file %a","registering",name) else report_tempfiles("%s temporary file %a","unregistering",name) end end tempfiles[name] = keep or false return name end function luatex.cleanuptempfiles() for name, keep in next, tempfiles do if not keep then if trace_temp_files then report_tempfiles("%s temporary file %a","removing",name) end os.remove(name) end end tempfiles = { } end luatex.registerstopactions(luatex.cleanuptempfiles) -- Reporting filenames has been simplified since lmtx because we don't need the -- traditional () {} <> etc methods (read: that directive option was never chosen). local report_open = logs.reporter("open source") local report_close = logs.reporter("close source") local report_load = logs.reporter("load resource") local level = 0 local total = 0 local stack = { } function luatex.currentfile() return stack[#stack] or tex.jobname end function luatex.currentlevel() return level end function luatex.currenttotal() return total end local enabled = true directives.register("system.reportfiles", function(v) enabled = v end) local function report_start(name,rest) if enabled then if rest then -- luatex if name ~= 1 then insert(stack,false) return end name = rest end if find(name,"virtual://",1,true) then insert(stack,false) else insert(stack,name) total = total + 1 level = level + 1 -- report_open("%i > %i > %s",level,total,name or "?") report_open("level %i, order %i, name %a",level,total,name or "?") synctex.setfilename(name) end end end local function report_stop() if enabled then local name = remove(stack) if name then -- report_close("%i > %i > %s",level,total,name or "?") report_close("level %i, order %i, name %a",level,total,name or "?") level = level - 1 name = stack[#stack] -- synctex.setfilename(stack[#stack] or tex.jobname) if name then synctex.setfilename(name) end end end end callbacks.register("start_file",report_start,"report opening of a file") callbacks.register("stop_file", report_stop, "report closing of a file") -- start_run doesn't work -- luatex.registerstartactions(function() -- if environment.arguments.sandbox then -- sandbox.enable() -- end -- end) local report = logs.reporter("csname overload") local reported = { } callbacks.register("handle_overload", function(fatal,overload,csname,flags) if not reported[csname] then logs.newline() local readstate = status.readstate local filename = readstate.filename local linenumber = readstate.linenumber local flags = tokens.flags and tokens.flags(csname) or { } if filename and linenumber then report("%s, protection level %i, control sequence %a, properties '% t', file %a, line %i", fatal and "fatal error" or "warning",overload,csname,flags,filename,linenumber) else report("%s, protection level %i, control sequence %a, properties '% t'", fatal and "fatal error" or "warning",overload,csname,flags) end reported[csname] = true logs.newline() if fatal then cleanup_run() setexitcode(1) osexit(1) end end end,"handle primitive and macro overload protection") -- bonus if environment.initex then luatex.registerdumpactions(statistics.showmemory) end