New approach to backend registers

This commit is contained in:
Marcel Krüger 2020-06-28 04:52:06 +02:00
parent c9fb95eff3
commit f12fa8a2e6
9 changed files with 163 additions and 138 deletions

View File

@ -143,10 +143,9 @@ callback.register("stop_run", function()
texio.write_nl(string.format("Transcript written on %s.\n", status.log_name)) texio.write_nl(string.format("Transcript written on %s.\n", status.log_name))
end, "Finish PDF file") end, "Finish PDF file")
token.luacmd("pdfvariable", function() token.luacmd("pdfvariable", function()
for n, t in pairs(pdf.variable_tokens) do for _, n in ipairs(pdf.variable_names) do
if token.scan_keyword(n) then if token.scan_keyword(n) then
token.put_next(t) return token.put_next(token.create('pdfvariable ' .. n))
return
end end
end end
-- The following error message gobbles the next word as a side effect. -- The following error message gobbles the next word as a side effect.

View File

@ -0,0 +1,99 @@
local value_values = token.values'value'
for i=0,#value_values do
value_values[value_values[i]] = i
end
local count_code = value_values.integer
local dimen_code = value_values.dimension
local set_local = require'luametalatex-local'
local texmeta = getmetatable(tex)
local texmetaoldindex = texmeta.__index
local texmetaoldnewindex = texmeta.__newindex
local tex_variables = {}
function texmeta.__index(t, k)
return tex_variables[k] or texmetaoldindex(t, k)
end
function texmeta.__newindex(t, k, v)
if tex_variables[k] then
return set_local(tex_variables, k, v)
else
return texmetaoldnewindex(t, k, v)
end
end
local function tex_variable(value, scanner, name, default)
token.luacmd(name, function(_, scanning)
if scanning == 'value' then
return value, tex_variables[name]
else
token.scan_keyword'='
return set_local(tex_variables, name, scanner(), scanning == 'global')
end
end, 'global', 'protected', 'value')
tex_variables[name] = default
end
local real_pdf_variables, pdf_variable_names = {}, {'pageresources'}
local pdf_toks = {}
local pdf_variables = setmetatable(pdf.variable, {
__index = function(_, k)
local v = real_pdf_variables[k]
if v then return v end
v = pdf_toks[k]
if v then
return tex.toks[v]
end
end,
__newindex = function(_, k, v)
if real_pdf_variables[k] then
return set_local(real_pdf_variables, k, v)
end
local toks = pdf_toks[k]
if toks then
tex.toks[toks] = v
end
end,
})
pdf.variable_names = pdf_variable_names
local function pdf_variable(value, scanner, name, default)
pdf_variable_names[#pdf_variable_names+1] = name
token.luacmd('pdfvariable ' .. name, function(_, scanning)
if scanning == 'value' then
return value, real_pdf_variables[name]
else
token.scan_keyword'='
return set_local(real_pdf_variables, name, scanner(), scanning == 'global')
end
end, 'global', 'protected', 'value')
real_pdf_variables[name] = default
end
tex_variable(count_code, token.scan_int, 'suppressfontnotfounderror', 0)
tex_variable(count_code, token.scan_int, 'outputmode', 1) -- The "traditional" default would be 0,
-- but we do not actually support that.
tex_variable(dimen_code, token.scan_dimen, 'pageheight', tex.sp'297mm')
tex_variable(dimen_code, token.scan_dimen, 'pagewidth', tex.sp'210mm')
tex_variable(count_code, token.scan_int, 'bodydirection', 0)
tex_variable(count_code, token.scan_int, 'pagedirection', 0)
pdf_variable(dimen_code, token.scan_dimen, 'horigin', tex.sp'1in')
pdf_variable(dimen_code, token.scan_dimen, 'vorigin', tex.sp'1in')
pdf_variable(dimen_code, token.scan_dimen, 'linkmargin', tex.sp'0pt')
pdf_variable(count_code, token.scan_int, 'majorversion', 1)
pdf_variable(count_code, token.scan_int, 'minorversion', 7)
pdf_variable(count_code, token.scan_int, 'compresslevel', 0)
pdf_variable(count_code, token.scan_int, 'objcompresslevel', 0) -- 0 is actually the only supported value right now, so this is basically ignored
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'

View File

@ -1,124 +0,0 @@
\begingroup
\catcode`\^^^^fffe=11
\catcode`\@=11
\toks0{%
do
local function frozen(s)
local t = token.create(s)
return t
% print(t, token.new(t.mode, t.command), t.mode, t.command, t.data, t.cmdchrcs)
% return token.new(t.mode, t.command)
end
local dimen_cmd = token.command_id'register_dimen'
local count_cmd = token.command_id'register_int'
local toks_cmd = token.command_id'register_toks'
local tex_params = {}
local texmeta = getmetatable(tex)
local texmetaoldindex = texmeta.__index
local texmetaoldnewindex = texmeta.__newindex
function texmeta.__index(t, k)
local v = tex_params[k]
if v then
if v.command == count_cmd then
return tex.count[v.index]
elseif v.command == dimen_cmd then
return tex.dimen[v.index]
elseif v.command == toks_cmd then
return tex.toks[v.index]
end
else
return texmetaoldindex(t, k)
end
end
function texmeta.__newindex(t, k, v)
local p = tex_params[k]
if p then
if p.command == count_cmd then
tex.count[p.index] = v
elseif p.command == dimen_cmd then
tex.dimen[p.index] = v
elseif p.command == toks_cmd then
tex.toks[p.index] = v
end
else
return texmetaoldnewindex(t, k, v)
end
end
local pdf_params = {}
pdf.variable_tokens = pdf_params
setmetatable(pdf.variable, {
__index = function(t, k)
local v = pdf_params[k]
if v then
if v.command == count_cmd then
return tex.count[v.index]
elseif v.command == dimen_cmd then
return tex.dimen[v.index]
elseif v.command == toks_cmd then
return tex.toks[v.index]
end
end
end,
__newindex = function(t, k, v)
local p = pdf_params[k]
if p then
if p.command == count_cmd then
tex.count[p.index] = v
elseif p.command == dimen_cmd then
tex.dimen[p.index] = v
elseif p.command == toks_cmd then
tex.toks[p.index] = v
end
else
return rawset(t, k, v)
end
end,
})
}
\def\InternalAlloc#1#2#3#4#5{%
\csname new#3\endcsname#1%
\global#1=#5\relax
\etoksapp0{#2_params["\luaescapestring{#4}"] = frozen"\luaescapestring{\csstring#1}"}
}
\def\internalAlloc#1#2#3{%
\expandafter\InternalAlloc\csname ^^^^fffe#3@#1\endcsname{#1}{#2}{#3}%
}
\def\texAlloc#1#2{%
\expandafter\InternalAlloc\csname #2\endcsname{tex}{#1}{#2}%
}
\def\pdfAlloc{%
\internalAlloc{pdf}%
}
\texAlloc{count}{suppressfontnotfounderror}{0}
\texAlloc{count}{outputmode}{1} % The "traditional" default would be 0,
% but we do not actually support that.
\texAlloc{dimen}{pageheight}{297mm}
\texAlloc{dimen}{pagewidth}{210mm}
\pdfAlloc{dimen}{horigin}{1in}
\pdfAlloc{dimen}{vorigin}{1in}
\pdfAlloc{dimen}{linkmargin}{0pt}
\pdfAlloc{count}{majorversion}{1}
\pdfAlloc{count}{minorversion}{7}
\pdfAlloc{count}{compresslevel}{0}
\pdfAlloc{count}{objcompresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored
\pdfAlloc{toks}{pageresources}{{}}
\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

@ -11,16 +11,13 @@ function tex.gettextdir() return tex.textdirection end
function tex.getlinedir() return tex.linedirection end function tex.getlinedir() return tex.linedirection end
function tex.getmathdir() return tex.mathdirection end function tex.getmathdir() return tex.mathdirection end
function tex.getpardir() return tex.pardirection end function tex.getpardir() return tex.pardirection end
-- local integer_code = value_values.none
local integer_code = value_values.integer 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 function set_xdir(id, scanning)
-- local name = names[id] if scanning == 'value' then
if scanning then print(scanning)
return integer_code, getters[id]() return integer_code, getters[id]()
-- return integer_code, tex[name .. 'ection']
end end
-- local global = scanning == 'global'
local value local value
if token.scan_keyword'tlt' then if token.scan_keyword'tlt' then
value = 0 value = 0
@ -30,7 +27,6 @@ local function set_xdir(id, scanning)
value = token.scan_int() value = token.scan_int()
end end
setters[id](value) setters[id](value)
-- tex["set" .. name](value)
end end
return function(name) return function(name)
local getter = tex["get" .. name] local getter = tex["get" .. name]

View File

@ -12,7 +12,7 @@ local set_lua = token.set_lua
-- probably doesn't store the function in the array part of the Lua table. -- probably doesn't store the function in the array part of the Lua table.
-- Let's reconsider if this ever becomes a problem. -- Let's reconsider if this ever becomes a problem.
-- local new_luafunction = luatexbase.new_luafunction -- local new_luafunction = luatexbase.new_luafunction
local predefined_luafunctions = status.ini_version and 65535 -- 1<<16 - 1 -- We start with 1<<16 local predefined_luafunctions = status.ini_version and 65536 -- 1<<16 -- We start with 1<<16 + 1 (1<<16=65536 is reserved for luametalatex-local)
local function new_luafunction(name) local function new_luafunction(name)
if predefined_luafunctions then if predefined_luafunctions then
predefined_luafunctions = predefined_luafunctions + 1 predefined_luafunctions = predefined_luafunctions + 1
@ -221,6 +221,7 @@ else
-- fixupluafunctions = nil -- fixupluafunctions = nil
-- end -- end
end end
require'luametalatex-baseregisters'
require'luametalatex-back-pdf' require'luametalatex-back-pdf'
require'luametalatex-node-luaotfload' require'luametalatex-node-luaotfload'

53
luametalatex-local.lua Normal file
View File

@ -0,0 +1,53 @@
-- Implement support for local variables.
local stack = {}
local restore_func = 65536 -- Reserved in firstcode
lua.get_functions_table()[restore_func] = function()
local level = assert(stack[tex.currentgrouplevel], 'Out of sync')
stack[tex.currentgrouplevel] = nil
for t,entries in next, level do
for k,v in next, entries do
t[k] = v
end
end
end
local lua_call = token.command_id'lua_call'
local restore_toks = {token.create'atendofgroup', token.new(restore_func, lua_call)}
local put_next = token.put_next
local runtoks = tex.runtoks
local function put_restore_toks()
put_next(restore_toks)
end
return function(t, k, v, global)
local l = tex.currentgrouplevel
if global then
for i=1,l do
local level = stack[i]
if level then
local saved = level[t]
if saved then
saved[k] = nil
end
end
end
elseif l > 0 then
local level = stack[l]
if not level then
level = {}
runtoks(put_restore_toks)
stack[l] = level
end
local saved = level[t]
if not saved then
saved = {}
level[t] = saved
end
saved[k] = saved[k] or t[k]
end
t[k] = v
end

View File

@ -1,5 +1,6 @@
\directlua{unhook_expl()} \directlua{unhook_expl()}
\input luametalatex-baseregisters % See baseregisters for list of toks pdfvariables
\expandafter\newtoks\csname pdfvariable \space pageresources\endcsname
\ifx\@tfor\undefined \ifx\@tfor\undefined
\def\@tfor#1\do#2{} \def\@tfor#1\do#2{}
\fi \fi

View File

@ -1,4 +1,4 @@
local mode = 6 local mode = 0
-- Control how much escaping is done... the mode is a bitset: -- Control how much escaping is done... the mode is a bitset:
-- Bit 0: Disable auto-detection of pre-escaped input -- Bit 0: Disable auto-detection of pre-escaped input
-- Bit 1: Convert UTF-8 input to UTF-16 -- Bit 1: Convert UTF-8 input to UTF-16

View File

@ -17,5 +17,5 @@
\endgroup \endgroup
\input load-unicode-data.tex \input load-unicode-data.tex
\input etex.src \input etex.src
\input luametalatex-baseregisters \expandafter\newtoks\csname pdfvariable \space pageresources\endcsname
\dump \dump