luat-run.lua /size: 9948 b    last modification: 2025-02-21 11:03
1if not modules then modules = { } end modules ['luat-run'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local next = next
10local find = string.find
11local insert, remove = table.insert, table.remove
12local osexit = os.exit
13
14-- trace_job_status is also controlled by statistics.enable that is set via the directive system.nostatistics
15
16local trace_lua_dump   = false  trackers.register("system.dump",      function(v) trace_lua_dump   = v end)
17local trace_temp_files = false  trackers.register("system.tempfiles", function(v) trace_temp_files = v end)
18local trace_job_status = true   trackers.register("system.jobstatus", function(v) trace_job_status = v end)
19local trace_tex_status = false  trackers.register("system.texstatus", function(v) trace_tex_status = v end)
20
21local report_lua       = logs.reporter("system","lua")
22local report_tex       = logs.reporter("system","status")
23local report_tempfiles = logs.reporter("resolvers","tempfiles")
24
25luatex        = luatex or { }
26local luatex  = luatex
27local synctex = luatex.synctex
28
29if not synctex then
30    synctex        = table.setmetatableindex(function() return function() end end)
31    luatex.synctex = synctex
32end
33
34local startactions = { }
35local stopactions  = { }
36local dumpactions  = { }
37local pageactions  = { }
38
39function luatex.registerstartactions(...) insert(startactions, ...) end
40function luatex.registerstopactions (...) insert(stopactions,  ...) end
41function luatex.registerdumpactions (...) insert(dumpactions,  ...) end
42function luatex.registerpageactions (...) insert(pageactions,  ...) end
43
44local function start_run()
45    if logs.start_run then
46        logs.start_run()
47    end
48    for i=1,#startactions do
49        startactions[i]()
50    end
51end
52
53local function stop_run()
54    for i=1,#stopactions do
55        stopactions[i]()
56    end
57    local quit = logs.finalactions()
58    if trace_job_status then
59        statistics.show()
60    end
61    if trace_tex_status then
62        logs.newline()
63        for k, v in table.sortedhash(status.list()) do
64            if type(v) ~= "table" then
65                report_tex("%S=%S",k,v)
66            end
67        end
68    end
69    if quit then
70        local setexitcode = lua.setexitcode or status.setexitcode
71        if setexitcode then
72            setexitcode(1)
73            if type(quit) == "table" then
74                logs.newline()
75                report_tex("quitting due to: %, t",quit)
76                logs.newline()
77            end
78        end
79    end
80    if logs.stop_run then
81        logs.stop_run()
82    end
83end
84
85local function start_shipout_page()
86    synctex.start()
87    logs.start_page_number()
88end
89
90local function stop_shipout_page()
91    logs.stop_page_number()
92    for i=1,#pageactions do
93        pageactions[i]()
94    end
95    synctex.stop()
96end
97
98local function report_output_pages()
99end
100
101local function report_output_log()
102end
103
104local function pre_dump_actions()
105    for i=1,#dumpactions do
106        dumpactions[i]()
107    end
108    lua.finalizeinitex(trace_lua_dump and report_lua or nil)
109end
110
111local function wrapup_synctex()
112    synctex.wrapup()
113end
114
115-- For Taco ...
116
117local sequencers     = utilities.sequencers
118local appendgroup    = sequencers.appendgroup
119local appendaction   = sequencers.appendaction
120local wrapupactions  = sequencers.new { }
121local cleanupactions = sequencers.new { }
122
123appendgroup(wrapupactions,"system")
124appendgroup(wrapupactions,"user")
125
126appendgroup(cleanupactions,"system")
127appendgroup(cleanupactions,"user")
128
129local function wrapup_run(someerror)
130    local runner = wrapupactions.runner
131    if runner then
132        runner(someerror) -- we could use the error flag in lmtx
133    end
134end
135
136local function cleanup_run()
137    local runner = cleanupactions.runner
138    if runner then
139        runner()
140    end
141end
142
143function luatex.wrapup(action)
144    appendaction(wrapupactions,"user",action)
145end
146
147function luatex.cleanup(action)
148    appendaction(cleanupactions,"user",action)
149end
150
151function luatex.abort()
152    cleanup_run()
153    osexit(1)
154end
155
156appendaction(wrapupactions,"system",synctex.wrapup)
157
158-- this can be done later
159
160callbacks.register('start_run',               start_run,           "actions performed at the beginning of a run")
161callbacks.register('stop_run',                stop_run,            "actions performed at the end of a run")
162
163---------.register('show_open',               show_open,           "actions performed when opening a file")
164---------.register('show_close',              show_close,          "actions performed when closing a file")
165
166callbacks.register('report_output_pages',     report_output_pages, "actions performed when reporting pages")
167callbacks.register('report_output_log',       report_output_log,   "actions performed when reporting log file")
168
169---------.register('start_page_number',       start_shipout_page,  "actions performed at the beginning of a shipout")
170---------.register('stop_page_number',        stop_shipout_page,   "actions performed at the end of a shipout")
171
172callbacks.register('start_page_number',       function() end,      "actions performed at the beginning of a shipout")
173callbacks.register('stop_page_number',        function() end,      "actions performed at the end of a shipout")
174
175callbacks.register('process_input_buffer',    false,               "actions performed when reading data")
176callbacks.register('process_output_buffer',   false,               "actions performed when writing data")
177
178callbacks.register("pre_dump",                pre_dump_actions,    "lua related finalizers called before we dump the format") -- comes after \everydump
179
180-- finish_synctex might go away (move to wrapup_run)
181
182callbacks.register("finish_synctex",          wrapup_synctex,      "rename temporary synctex file")
183callbacks.register('wrapup_run',              wrapup_run,          "actions performed after closing files")
184
185-- temp hack for testing:
186
187callbacks.functions.start_page_number = start_shipout_page
188callbacks.functions.stop_page_number  = stop_shipout_page
189
190-- an example:
191
192local tempfiles = { }
193
194function luatex.registertempfile(name,extrasuffix,keep) -- namespace might change
195    if extrasuffix then
196        name = name .. ".mkiv-tmp" -- maybe just .tmp
197    end
198    if trace_temp_files and not tempfiles[name] then
199        if keep then
200            report_tempfiles("%s temporary file %a","registering",name)
201        else
202            report_tempfiles("%s temporary file %a","unregistering",name)
203        end
204    end
205    tempfiles[name] = keep or false
206    return name
207end
208
209function luatex.cleanuptempfiles()
210    for name, keep in next, tempfiles do
211        if not keep then
212            if trace_temp_files then
213                report_tempfiles("%s temporary file %a","removing",name)
214            end
215            os.remove(name)
216        end
217    end
218    tempfiles = { }
219end
220
221luatex.registerstopactions(luatex.cleanuptempfiles)
222
223-- Reporting filenames has been simplified since lmtx because we don't need  the
224-- traditional () {} <> etc methods (read: that directive option was never chosen).
225
226local report_open  = logs.reporter("open source")
227local report_close = logs.reporter("close source")
228local report_load  = logs.reporter("load resource")
229
230local register     = callbacks.register
231
232local level = 0
233local total = 0
234local stack = { }
235
236function luatex.currentfile()
237    return stack[#stack] or tex.jobname
238end
239
240local function report_start(name,rest)
241    if rest then
242        -- luatex
243        if name ~= 1 then
244            insert(stack,false)
245            return
246        end
247        name = rest
248    end
249    if find(name,"virtual://",1,true) then
250        insert(stack,false)
251    else
252        insert(stack,name)
253        total = total + 1
254        level = level + 1
255     -- report_open("%i > %i > %s",level,total,name or "?")
256        report_open("level %i, order %i, name %a",level,total,name or "?")
257        synctex.setfilename(name)
258    end
259end
260
261local function report_stop()
262    local name = remove(stack)
263    if name then
264     -- report_close("%i > %i > %s",level,total,name or "?")
265        report_close("level %i, order %i, name %a",level,total,name or "?")
266        level = level - 1
267        synctex.setfilename(stack[#stack] or tex.jobname)
268    end
269end
270
271local function report_none()
272end
273
274register("start_file",report_start)
275register("stop_file", report_stop)
276
277directives.register("system.reportfiles", function(v)
278    if v then
279        register("start_file",report_start)
280        register("stop_file", report_stop)
281    else
282        register("start_file",report_none)
283        register("stop_file", report_none)
284    end
285end)
286
287-- start_run doesn't work
288
289-- luatex.registerstartactions(function()
290--     if environment.arguments.sandbox then
291--         sandbox.enable()
292--     end
293-- end)
294
295local report   = logs.reporter("csname overload")
296local reported = { }
297
298callback.register("handle_overload", function(fatal,overload,csname,flags)
299    if not reported[csname] then
300        logs.newline()
301        local readstate  = status.readstate
302        local filename   = readstate.filename
303        local linenumber = readstate.linenumber
304        local flags      = tokens.flags and tokens.flags(csname) or { }
305        if filename and linenumber then
306            report("%s, protection level %i, control sequence %a, properties '% t', file %a, line %i",
307                fatal and "fatal error" or "warning",overload,csname,flags,filename,linenumber)
308        else
309            report("%s, protection level %i, control sequence %a, properties '% t'",
310                fatal and "fatal error" or "warning",overload,csname,flags)
311        end
312        reported[csname] = true
313        logs.newline()
314        if fatal then
315            cleanup_run()
316            osexit(1)
317        end
318    end
319end)
320
321-- bonus
322
323if environment.initex then
324
325    luatex.registerdumpactions(statistics.showmemory)
326
327end
328