167 lines
5.3 KiB
Lua
167 lines
5.3 KiB
Lua
luametalatex = luametalatex or {}
|
|
local lmlt = luametalatex
|
|
local initex = status.ini_version
|
|
|
|
if initex then
|
|
lua.prepared_code = {false}
|
|
end
|
|
|
|
bit32 = require'luametalatex-bit32' -- Why? And why so early?
|
|
status.init_kpse = 1 -- Why?
|
|
status.safer_option = 0 -- compat
|
|
status.shell_escape = 0 -- compat -- This is currently a lie.
|
|
-- require'module' -- ???
|
|
pdf = {
|
|
variable = {},
|
|
}
|
|
require'luametalatex-font-resolve' -- Replace font.define. Must be loaded before callbacks
|
|
require'luametalatex-basecallbacks'
|
|
require'luametalatex-oldnames'
|
|
local callbacks = require'luametalatex-callbacks'
|
|
|
|
local function swap_table(t)
|
|
local s = {}
|
|
for k, v in next, t do
|
|
s[v] = k
|
|
end
|
|
return s
|
|
end
|
|
|
|
local primitives = {}
|
|
do
|
|
local token_primitives = token.getprimitives()
|
|
local token_new = token.new
|
|
for i=1,#token_primitives do
|
|
local prim = token_primitives[i]
|
|
primitives[prim[3]] = token_new(prim[2], prim[1])
|
|
end
|
|
end
|
|
lmlt.primitive_tokens = primitives
|
|
|
|
do
|
|
local command_id = swap_table(token.getcommandvalues())
|
|
function token.command_id(name) return command_id[name] end
|
|
end
|
|
lmlt.value = swap_table(token.getfunctionvalues())
|
|
lmlt.flag = swap_table(tex.getflagvalues())
|
|
|
|
local functions = lua.getfunctionstable()
|
|
-- I am not sure why this is necessary, but otherwise LuaMetaTeX resets
|
|
-- the functions table every time the getter is called
|
|
function lua.get_functions_table() return functions end
|
|
local set_lua = token.set_lua
|
|
-- There are two approaches to manage luafunctions ids without triggering
|
|
-- issues with ltluatex assigned numbers: Originally we assigned numbers
|
|
-- starting with 1, then switched to luatexbase ASAP and synchronised both
|
|
-- numbering schemes. But there is a useful quirk in ltluatex's luafunction
|
|
-- allocator: It only uses numbers upto 65535, so we can just use bigger
|
|
-- numbers. (This might have negative repercussins on performance because it
|
|
-- probably doesn't store the function in the array part of the Lua table.
|
|
-- Let's reconsider if this ever becomes a problem.
|
|
-- local new_luafunction = luatexbase.new_luafunction
|
|
local predefined_luafunctions = initex and 65536 -- 1<<16 -- We start with 1<<16 + 1 (1<<16=65536 is reserved for luametalatex-local)
|
|
local new_luafunction
|
|
function new_luafunction(name)
|
|
if predefined_luafunctions then
|
|
predefined_luafunctions = predefined_luafunctions + 1
|
|
return predefined_luafunctions
|
|
else
|
|
error[[Here only preexisting luafunctions should be set]]
|
|
end
|
|
end
|
|
local undefined_cmd = token.command_id'undefined_cs'
|
|
local lua_call_cmd = token.command_id'lua_call'
|
|
local lua_value_cmd = token.command_id'lua_value'
|
|
local lua_protected_call_cmd = token.command_id'lua_protected_call'
|
|
local if_test_cmd = token.command_id'if_test'
|
|
function lmlt.luacmd(name, func, ...)
|
|
local idx
|
|
local tok = token.create(name)
|
|
local cmd = tok.command
|
|
if cmd == lua_value_cmd then
|
|
idx = tok.index
|
|
elseif cmd == lua_call_cmd then
|
|
idx = tok.index
|
|
elseif cmd == lua_protected_call_cmd then
|
|
idx = tok.index
|
|
elseif cmd == if_test_cmd and tok.index > 53 then
|
|
idx = tok.index - 53
|
|
elseif ... == 'force' then
|
|
idx = new_luafunction(name)
|
|
set_lua(name, idx, select(2, ...))
|
|
elseif cmd == undefined_cmd then
|
|
idx = new_luafunction(name)
|
|
set_lua(name, idx, ...)
|
|
else
|
|
error(tok.cmdname)
|
|
end
|
|
if functions[idx] then
|
|
error[[Already defined]]
|
|
end
|
|
functions[idx] = func
|
|
return idx
|
|
end
|
|
|
|
if initex then
|
|
local build_bytecode = nil -- To be filled
|
|
function callbacks.pre_dump()
|
|
local user_callback = callbacks.pre_dump
|
|
if user_callback then user_callback() end
|
|
|
|
local prepared = lua.prepared_code
|
|
prepared[1] = string.format("fixupluafunctions(%i)", predefined_luafunctions)
|
|
--[[
|
|
for i=0,0 do -- maybeFIXME: In practise only one language is preloaded in LuaTeX anyway
|
|
-- for i=0,tex.count[19] do -- Sometimes catches reserved language ids which are not used yet
|
|
-- for i=0,lang.new():id()-1 do -- lang.new():id() is always 0 in luametatex?!?
|
|
local l = language.new(i)
|
|
local str = string.format("do \z
|
|
local l = language.new(%i)\z
|
|
l:hyphenationmin(%i)\z
|
|
l:prehyphenchar(%i)\z
|
|
l:posthyphenchar(%i)\z
|
|
l:preexhyphenchar(%i)\z
|
|
l:postexhyphenchar(%i)",
|
|
i,
|
|
l:hyphenationmin(),
|
|
l:prehyphenchar(),
|
|
l:posthyphenchar(),
|
|
l:preexhyphenchar(),
|
|
l:postexhyphenchar())
|
|
local patterns = l:patterns()
|
|
local exceptions = l:hyphenation()
|
|
if patterns and exceptions then
|
|
str = string.format("%sl:patterns(%q)l:hyphenation(%q)end", str, patterns, exceptions)
|
|
elseif patterns then
|
|
str = string.format("%sl:patterns(%q)end", str, patterns)
|
|
elseif exceptions then
|
|
str = string.format("%sl:hyphenation(%q)end", str, exceptions)
|
|
else
|
|
str = str .. 'end'
|
|
end
|
|
prepared[#prepared+1] = str
|
|
end
|
|
]]
|
|
for i=2,#prepared do
|
|
if type(prepared[i]) ~= 'string' then
|
|
prepared[i] = assert(prepared[i]())
|
|
end
|
|
end
|
|
lua.bytecode[tex.count[262]+1] = build_bytecode(table.concat(prepared, '\n'))
|
|
end
|
|
callbacks.__freeze('pre_dump', true)
|
|
return function(f)
|
|
build_bytecode = f
|
|
return require'luametalatex-firstcode'
|
|
end
|
|
else
|
|
function fixupluafunctions(i)
|
|
predefined_luafunctions = i
|
|
fixupluafunctions = nil
|
|
end
|
|
return function(f)
|
|
f()
|
|
return require'luametalatex-firstcode'
|
|
end
|
|
end
|