Better luafunction handling and fixes

This commit is contained in:
Marcel Krüger 2020-05-28 14:37:19 +02:00
parent 63de6d8141
commit c0954fe7f6
6 changed files with 128 additions and 55 deletions

View File

@ -1,7 +1,7 @@
local pdf = pdf
local writer = require'luametalatex-nodewriter'
local newpdf = require'luametalatex-pdf'
local pfile = newpdf.open(tex.jobname .. '.pdf')
local pfile
local fontdirs = setmetatable({}, {__index=function(t, k)t[k] = pfile:getobj() return t[k] end})
local usedglyphs = {}
local colorstacks = {{
@ -12,6 +12,9 @@ local colorstacks = {{
}}
token.scan_list = token.scan_box -- They are equal if no parameter is present
token.luacmd("shipout", function()
if not pfile then
pfile = newpdf.open(tex.jobname .. '.pdf')
end
local voff = node.new'kern'
voff.kern = tex.voffset + pdf.variable.vorigin
voff.next = token.scan_list()
@ -25,7 +28,7 @@ token.luacmd("shipout", function()
pfile:indirect(page, string.format([[<</Type/Page/Parent %i 0 R/Contents %i 0 R/MediaBox[0 %i %i %i]/Resources%s%s>>]], parent, content, -math.ceil(list.depth/65781.76), math.ceil(list.width/65781.76), math.ceil(list.height/65781.76), resources, annots))
token.put_next(token.create'immediateassignment', token.create'global', token.create'deadcycles', token.create(0x30), token.create'relax')
token.scan_token()
end, 'protected')
end, 'force', 'protected')
local infodir = ""
local creationdate = os.date("D:%Y%m%d%H%M%S%z"):gsub("+0000$", "Z"):gsub("%d%d$", "'%0")
local function write_infodir(p)
@ -48,6 +51,9 @@ local function write_infodir(p)
return p:indirect(nil, string.format("<<%s%s>>", infodir, additional))
end
callback.register("stop_run", function()
if not pfile then
return
end
for fid, id in pairs(fontdirs) do
local f = font.getfont(fid)
local psname = f.psname or f.fullname

View File

@ -91,9 +91,23 @@
\pdfAlloc{count}{minorversion}{7}
\pdfAlloc{count}{compresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored
\pdfAlloc{count}{objcompresslevel}{0} % see above
\directlua{
lua.prepared_code[\csstring#lua.prepared_code+1] = tex.toks[0] .. "end"
\the\toks0
\texAlloc{count}{bodydirection}{0}
\texAlloc{count}{pagedirection}{0}
\etoksapp0{
function tex.getbodydir() return tex.bodydirection end
function tex.getpagedir() return tex.pagedirection end
function tex.setbodydir(i) tex.bodydirection = i end
function tex.setpagedir(i) tex.pagedirection = i end
local dir_regs = require 'luametalatex-dir-registers'
dir_regs 'textdir'
dir_regs 'bodydir'
dir_regs 'pagedir'
end
}
\directlua{
lua.prepared_code[\csstring#lua.prepared_code+1] = tex.toks[0]
\the\toks0
}
\endgroup

View File

@ -0,0 +1,44 @@
-- local names = {}
local setters = {
}
local getters = {
}
local value_values = token.values'value'
for i=0,#value_values do
value_values[value_values[i]] = i
end
function tex.gettextdir() return tex.textdirection end
function tex.getlinedir() return tex.linedirection end
function tex.getmathdir() return tex.mathdirection end
function tex.getpardir() return tex.pardirection end
-- local integer_code = value_values.none
local integer_code = value_values.integer
local functions = lua.get_functions_table()
local lua_call_cmd = token.command_id'lua_call'
local function set_xdir(id, scanning)
-- local name = names[id]
if scanning then
return integer_code, getters[id]()
-- return integer_code, tex[name .. 'ection']
end
local value
if token.scan_keyword'tlt' then
value = 0
elseif token.scan_keyword'trt' then
value = 1
else
value = token.scan_int()
end
setters[id](value)
-- tex["set" .. name](value)
end
return function(name)
local getter = tex["get" .. name]
local setter = tex["set" .. name]
assert(getter and setter, "direction parameter undefined")
local idx = token.luacmd(name, set_xdir, "protected", "global", "value")
-- names[idx] = name
getters[idx] = getter
setters[idx] = setter
return idx
end

View File

@ -3,15 +3,50 @@ local functions = lua.getfunctionstable()
-- 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 = 0
local predefined_luafunctions = status.ini_version and 65535 -- 1<<16 - 1 -- We start with 1<<16
local function new_luafunction(name)
predefined_luafunctions = predefined_luafunctions + 1
return predefined_luafunctions
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_expandable_call_cmd = token.command_id'lua_expandable_call'
function token.luacmd(name, func, ...)
local idx = new_luafunction(name)
set_lua(name, idx, ...)
local idx
local tok = token.create(name)
local cmd = tok.command
if cmd == lua_value_cmd then
idx = tok.mode
elseif cmd == lua_call_cmd then
idx = tok.mode
elseif cmd == lua_expandable_call_cmd then
idx = tok.mode
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
@ -154,13 +189,12 @@ token.luacmd("write", function(_, immediate) -- \write
end
end, "protected")
local lua_call_cmd = token.command_id'lua_call'
token.luacmd("immediate", function() -- \immediate
local next_tok = token.scan_token()
if next_tok.command ~= lua_call_cmd then
return token.put_next(next_tok)
end
local function_id = next_tok.index
local function_id = next_tok.mode
functions[function_id](function_id, 'immediate')
end, "protected")
-- functions[43] = function() -- \pdfvariable
@ -169,15 +203,18 @@ end, "protected")
-- end
if status.ini_version then
function fixupluafunctions()
tex.setcount("global", "e@alloc@luafunction@count", predefined_luafunctions)
return predefined_luafunctions
end
else
function fixupluafunctions(i)
predefined_luafunctions = i
end
local prepared_code = lua.bytecode[1]
prepared_code()
lua.bytecode[1] = nil
function fixupluafunctions()
new_luafunction = luatexbase.new_luafunction
fixupluafunctions = nil
end
-- function fixupluafunctions()
-- new_luafunction = luatexbase.new_luafunction
-- fixupluafunctions = nil
-- end
end
require'luametalatex-back-pdf'

View File

@ -30,6 +30,7 @@ kpse.init_prog("LUATEX", 400, "nexthi", nil)
status.init_kpse = 1
require'luametalatex-init-config'
status.safer_option = 0
status.shell_escape = 0
local read_tfm = require'luametalatex-font-tfm'
local read_vf = require'luametalatex-font-vf'
font.read_tfm = read_tfm
@ -58,10 +59,6 @@ callback.register('define_font', function(name, size)
end
return id
end)
-- callback.register('terminal_input', function(prompt)
-- print('Input expected: ', prompt)
-- return 'AAA'
-- end)
callback.register('find_log_file', function(name) return name end)
-- callback.register('find_read_file', function(i, name) return kpse.find_file(name, 'tex', true) end)
callback.register('find_data_file', function(name, ...) return kpse.find_file(name, 'tex', true) end)
@ -88,16 +85,17 @@ callback.register('show_error_message', function()
texio.write_nl(status.lasterrorstring)
end)
callback.register('pre_dump', function()
lua.prepared_code[1] = string.format("fixupluafunctions(%i)", fixupluafunctions())
lua.bytecode[1] = assert(load(table.concat(lua.prepared_code, ' ')))
end)
function texconfig.init()
lua.bytecode[2]()
if not status.ini_version then
lua.bytecode[2]()
lua.bytecode[2] = nil
end
end
if status.ini_version then
lua.prepared_code = {}
lua.prepared_code = {false}
local code = package.searchers[2]('luametalatex-firstcode')
if type(code) == "string" then error(string.format("Initialization code not found %s", code)) end
lua.bytecode[2] = code

View File

@ -1,40 +1,14 @@
% Thomas Esser, 1998. public domain.
%
\ifx\pdfoutput\undefined \else
\ifx\pdfoutput\relax \else
%
% We're building the latex format with the pdfetex engine (started 2004).
\input pdftexconfig
\pdfoutput=0
%
% pdfTeX related primitives are no longer hidden by default
% (started 2005). Uncomment and recreate the format files by running
% "fmtutil --all" resp. "fmtutil-sys --all" to revert to the old
% (2004) behaviour.
% \input pdftex-dvi.tex
%
\fi
\fi
%
% the usual format initialization.
\scrollmode
\luabytecode2
\begingroup
\catcode`\{=1
\catcode`\}=2
\def\x{\everyjob{\luabytecode2}}
\expandafter\endgroup\x
\let\savedversionofeTeXversion\eTeXversion
\let\savedversionofdump\dump
\let\dump\relax
\let\eTeXversion\relax
\global\chardef\eTeXversion=2
\global\def\eTeXrevision{.2}
\endgroup
% \let\savedversionofdump\dump
% \let\dump\relax
\input latex.ltx
\let\eTeXversion\savedversionofeTeXversion
% \input luametalatex-baseregisters
\let\dump\savedversionofdump
\let\savedversionofdump\undefined
\directlua{fixupluafunctions()}%
\everyjob\expandafter{\the\everyjob\directlua{fixupluafunctions()}}%
\directlua{fixupluafunctions()}%
\dump
\endinput