luat-cod.lmt /size: 9164 b    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['luat-cod'] = {
2    version   = 1.001,
3    comment   = "companion to luat-cod.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 type, loadfile, tonumber = type, loadfile, tonumber
10local match, gsub, find, format, gmatch = string.match, string.gsub, string.find, string.format, string.gmatch
11
12local texconfig, lua = texconfig, lua
13
14-- maybe pick up from commandline:
15--
16-- texconfig.interaction: 0=batchmode 1=nonstopmode 2=scrollmode 3=errornonstopmode 4=normal
17
18-- some basic housekeeping
19
20---------.kpse_init       = false     -- not needed in lmtx
21---------.shell_escape    = 't'       -- not needed in lmtx
22
23-- texconfig.max_in_open     =     2000
24-- texconfig.nest_size       =    10000
25-- texconfig.param_size      =   100000
26-- texconfig.save_size       =   500000
27-- texconfig.stack_size      =   100000
28-- texconfig.buffer_size     = 10000000
29-- texconfig.token_size      = 10000000
30-- texconfig.token_size      = { size = 10000000, step = 2000000 }
31-- texconfig.node_size       = 50000000
32
33---------.max_print_line  =   100000
34-- texconfig.max_strings     =   500000
35-- texconfig.max_strings     = { size = 600000, step = 200000 }
36-- texconfig.max_pool        = 10000000
37-- texconfig.hash_extra      =   250000
38-- texconfig.expand_depth    =    10000
39
40-- texconfig.error_line      =      250
41-- texconfig.half_error_line =      125
42
43texconfig.functionsize   = 32768
44texconfig.propertiessize = 10000
45
46-- registering bytecode chunks
47
48local bytedata    = lua.bytedata or { }
49local bytedone    = lua.bytedone or { }
50
51---.bytecode      = bytecode
52lua.bytedata      = bytedata
53lua.bytedone      = bytedone
54
55local setbytecode = lua.setbytecode
56----- getbytecode = lua.getbytecode
57
58lua.firstbytecode = 501
59lua.lastbytecode  = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier
60
61function lua.registeredcodes()
62    return lua.lastbytecode - lua.firstbytecode + 1
63end
64
65-- no file.* and utilities.parsers.* functions yet
66
67local strip = false if arg then for i=-1,#arg do if arg[i] == "--c:strip" then strip = true break end end end
68
69function lua.registercode(filename,options)
70    local barename = gsub(filename,"%.[%a%d]+$","")
71    local basename = match(barename,"^.+[/\\](.-)$") or barename
72    if not bytedone[basename] then
73        local opts = { }
74        if type(options) == "string" and options ~= "" then
75            for s in gmatch(options,"([a-z]+)") do
76                opts[s] = true
77            end
78        end
79        if barename == filename then
80            filename = filename .. (opts.autosuffix and ".lmt" or ".lua")
81        end
82        local code = environment.luafilechunk(filename,false,opts.optimize,opts.optional)
83        if code then
84            bytedone[basename] = true
85            if environment.initex and not opts.initexonly then
86                local n = lua.lastbytecode + 1
87                bytedata[n] = { name = barename, options = opts }
88                if strip or opts.strip then
89                    setbytecode(n,code,true)
90                else
91                    setbytecode(n,code)
92                end
93                lua.lastbytecode = n
94            end
95        elseif opts.optional then
96            -- we're fine
97        elseif environment.initex then
98            texio.writenl(format("\nerror loading file: %s (aborting)",filename))
99            os.exit()
100        end
101    end
102end
103
104-- A first start with environments. This will be overloaded later.
105
106environment       = environment or { }
107local environment = environment
108
109-- no string.unquoted yet
110
111local sourcefile = gsub(arg and arg[1] or "","^\"(.*)\"$","%1")
112local sourcepath = find(sourcefile,"/",1,true) and gsub(sourcefile,"/[^/]+$","") or ""
113local targetpath = "."
114
115-- delayed (via metatable):
116--
117-- environment.jobname = tex.jobname
118-- environment.version = tostring(tex.toks.contextversiontoks)
119
120-- traditionally the revision has been a one character string and only
121-- pdftex went beyond "9" but anyway we test for it
122
123if LUATEXENGINE == nil then
124    LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) or "luametatex"
125end
126
127if LUATEXVERSION == nil then
128    LUATEXVERSION = status.version
129end
130
131if LUATEXVERBOSE == nil then
132    LUATEXVERBOSE = status.luatex_verbose
133end
134
135if CONTEXTLMTXMODE == nil then
136    CONTEXTLMTXMODE = 1
137end
138
139if LUATEXFUNCTIONALITY == nil then
140    LUATEXFUNCTIONALITY = status.development_id or 6346
141end
142
143if LUATEXFORMATID == nil then
144    LUATEXFORMATID = status.format_id or 0
145end
146
147if INITEXMODE == nil then
148    INITEXMODE = status.run_state == 0 -- initializing updating production
149end
150
151environment.luatexengine        = LUATEXENGINE
152environment.luatexversion       = LUATEXVERSION
153environment.luatexverbose       = LUATEXVERBOSE
154environment.luatexfunctionality = LUATEXFUNCTIONALITY
155environment.initex              = INITEXMODE
156environment.initexmode          = INITEXMODE
157
158if INITEXMODE then
159
160    local finalizers = { }
161
162    function lua.registerinitexfinalizer(f,comment)
163        comment = comment or "unknown"
164        if type(f) == "function" then
165            finalizers[#finalizers+1] = { action = f, comment = comment }
166        else
167            print(format("\nfatal error: invalid finalizer, action: %s\n",comment))
168            os.exit()
169        end
170    end
171
172    function lua.finalizeinitex(logger)
173        for i=1,#finalizers do
174            local finalizer = finalizers[i]
175            finalizer.action()
176            if logger then
177                logger("finalize action: %s",finalizer.comment)
178            end
179        end
180    end
181
182else
183
184    function lua.registerinitexfinalizer() end
185    function lua.finalizeinitex         () end
186
187end
188
189-- if INITEXMODE then
190--     -- we have about that amount so we preallocate then which gives less
191--     -- reallocations (we're talking tiny record so no real gain)
192--     lua.setbytecode(1024,nil)
193--     -- but we don't want to lie about the amount either so ...
194-- end
195
196if not environment.luafilechunk then
197
198    function environment.luafilechunk(filename)
199        local fullname = filename
200        if sourcepath ~= "" then
201            fullname = sourcepath .. "/" .. filename
202        end
203        if not lfs.isfile(fullname) then
204            fullname = gsub(fullname,"mkxl","mkiv")
205        end
206        local data = loadfile(fullname)
207        texio.write("terminal_and_logfile","<",data and "+ " or "- ",fullname,">")
208        if data then
209-- package.loaded[gsub(filename,"%..-$"] =
210            data()
211        end
212        return data
213    end
214
215end
216
217if not environment.engineflags then -- raw flags
218
219    local engineflags = { }
220
221    for i=-10,#arg do
222        local a = arg[i]
223        if a then
224            local flag, content = match(a,"^%-%-([^=]+)=?(.-)$")
225            if flag then
226                engineflags[flag] = content or ""
227            end
228        end
229    end
230
231    environment.engineflags = engineflags
232
233end
234
235-- We need a few premature callbacks in the format generator. We
236-- also do this when the format is loaded as otherwise we get
237-- a kpse error when disabled. This is an engine issue that will
238-- be sorted out in due time.
239
240-- print("!!!!!!!!!!!!!!!!!!!!!!",lfs.isfile) os.exit()
241
242if not lfs.isfile then
243
244    local attributes = lfs.attributes
245
246    function lfs.isdir(name)
247        return attributes(name,"mode") == "directory"
248    end
249
250    function lfs.isfile(name)
251        local a = attributes(name,"mode")
252        return a == "file" or a == "link" or nil
253    end
254
255end
256
257local isfile = lfs.isfile
258
259local function source_file(name)
260    local fullname = sourcepath .. "/" .. name
261    if isfile(fullname) then
262        return fullname
263    end
264    fullname = fullname .. ".tex"
265    if isfile(fullname) then
266        return fullname
267    end
268    if isfile(name) then
269        return name
270    end
271    name = name .. ".tex"
272    if isfile(name) then
273        return name
274    end
275    return nil
276end
277
278local function target_file(name)
279    return targetpath .. "/" .. name
280end
281
282local function find_log_file(name)
283    return target_file(name)
284end
285
286local function find_data_file(name)
287    return source_file(name)
288end
289
290local function open_data_file(name)
291    local fullname = source_file(name)
292    if fullname then
293        local f = io.open(fullname,'rb')
294        return {
295            reader = function()
296                return f:read("*line")
297            end,
298         -- close = function()
299         --     f:close()
300         -- end
301        }
302    else
303        return false
304    end
305end
306
307callback.register('find_log_file',   find_log_file)
308callback.register('find_data_file' , find_data_file )
309callback.register('open_data_file' , open_data_file )
310
311callback.register("trace_memory", function(what,success)
312    success = success and "succeeded" or "failed"
313    if logs then
314        logs.report("tex memory","bumping category %a %s, details: %s",
315            what,success,table.sequenced(status["get"..what.."state"]()))
316    elseif texio then
317        texio.writenl(format("bumping tex '%s' memory %s",
318            what,success))
319    end
320 -- os.exit()
321end)
322