summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3luatex.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3luatex.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3luatex.dtx750
1 files changed, 0 insertions, 750 deletions
diff --git a/macros/latex/contrib/l3kernel/l3luatex.dtx b/macros/latex/contrib/l3kernel/l3luatex.dtx
deleted file mode 100644
index 3d177f6345..0000000000
--- a/macros/latex/contrib/l3kernel/l3luatex.dtx
+++ /dev/null
@@ -1,750 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3luatex.dtx
-%
-% Copyright (C) 2010-2024 The LaTeX Project
-%
-% It may be distributed and/or modified under the conditions of the
-% LaTeX Project Public License (LPPL), either version 1.3c of this
-% license or (at your option) any later version. The latest version
-% of this license is in the file
-%
-% https://www.latex-project.org/lppl.txt
-%
-% This file is part of the "l3kernel bundle" (The Work in LPPL)
-% and all files in that bundle must be distributed together.
-%
-% -----------------------------------------------------------------------
-%
-% The development version of the bundle can be found at
-%
-% https://github.com/latex3/latex3
-%
-% for those people who are interested.
-%
-%<*driver>
-\documentclass[full,kernel]{l3doc}
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-% The \pkg{l3luatex} module\\ \LuaTeX-specific functions^^A
-% }
-%
-% \author{^^A
-% The \LaTeX{} Project\thanks
-% {^^A
-% E-mail:
-% \href{mailto:latex-team@latex-project.org}
-% {latex-team@latex-project.org}^^A
-% }^^A
-% }
-%
-% \date{Released 2024-03-14}
-%
-% \maketitle
-%
-% \begin{documentation}
-%
-% The \LuaTeX{} engine provides access to the \Lua{} programming language,
-% and with it access to the \enquote{internals} of \TeX{}. In order to use
-% this within the framework provided here, a family of functions is
-% available. When used with \pdfTeX{}, \pTeX{}, \upTeX{} or \XeTeX{} these raise an
-% error: use \cs{sys_if_engine_luatex:T} to avoid this. Details on using
-% \Lua{} with the \LuaTeX{} engine are given in the \LuaTeX{} manual.
-%
-% \section{Breaking out to \Lua{}}
-%
-% \begin{function}[EXP, added = 2018-06-18]{\lua_now:n, \lua_now:e}
-% \begin{syntax}
-% \cs{lua_now:n} \Arg{token list}
-% \end{syntax}
-% The \meta{token list} is first tokenized by \TeX{}, which includes
-% converting line ends to spaces in the usual \TeX{} manner and which
-% respects currently-applicable \TeX{} category codes. The resulting
-% \meta{\Lua{} input} is passed to the \Lua{} interpreter for processing.
-% Each \cs{lua_now:n} block is treated by \Lua{} as a separate chunk.
-% The \Lua{} interpreter executes the \meta{\Lua{} input} immediately,
-% and in an expandable manner.
-% \begin{texnote}
-% \cs{lua_now:e} is a macro wrapper around \tn{directlua}: when
-% \LuaTeX{} is in use two expansions are required to yield the
-% result of the \Lua{} code.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[added = 2018-06-18]{\lua_shipout_e:n, \lua_shipout:n}
-% \begin{syntax}
-% \cs{lua_shipout:n} \Arg{token list}
-% \end{syntax}
-% The \meta{token list} is first tokenized by \TeX{}, which includes
-% converting line ends to spaces in the usual \TeX{} manner and which
-% respects currently-applicable \TeX{} category codes. The resulting
-% \meta{\Lua{} input} is passed to the \Lua{} interpreter when the
-% current page is finalised (\emph{i.e.}~at shipout). Each
-% \cs{lua_shipout:n} block is treated by \Lua{} as a separate chunk.
-% The \Lua{} interpreter will execute the \meta{\Lua{} input} during the
-% page-building routine: no \TeX{} expansion of the \meta{\Lua{} input}
-% will occur at this stage.
-%
-% In the case of the \cs{lua_shipout_e:n} version the input is fully
-% expanded by \TeX{} in an \texttt{e}-type manner during the shipout
-% operation.
-% \begin{texnote}
-% At a \TeX{} level, the \meta{\Lua{} input} is stored as a
-% \enquote{whatsit}.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[EXP, added = 2015-06-29]{\lua_escape:n, \lua_escape:e}
-% \begin{syntax}
-% \cs{lua_escape:n} \Arg{token list}
-% \end{syntax}
-% Converts the \meta{token list} such that it can safely be passed to
-% \Lua{}: embedded backslashes, double and single quotes, and newlines
-% and carriage returns are escaped. This is done by prepending an extra
-% token consisting of a backslash with category code~$12$, and for the line
-% endings, converting them to |\n| and |\r|, respectively.
-% \begin{texnote}
-% \cs{lua_escape:e} is a macro wrapper around \tn{luaescapestring}:
-% when \LuaTeX{} is in use two expansions are required to yield the
-% result of the \Lua{} code.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[added = 2022-05-14]{\lua_load_module:n}
-% \begin{syntax}
-% \cs{lua_load_module:n} \Arg{Lua module name}
-% \end{syntax}
-% Loads a Lua module into the Lua interpreter.
-%
-% \cs{lua_now:n} passes its \Arg{token list} argument to the Lua interpreter
-% as a single line, with characters interpreted under the current catcode
-% regime. These two facts mean that \cs{lua_now:n} rarely behaves as expected
-% for larger pieces of code. Therefore, package authors should \textbf{not}
-% write significant amounts of Lua code in the arguments to \cs{lua_now:n}.
-% Instead, it is strongly recommended that they write the majorty of their Lua
-% code in a separate file, and then load it using \cs{lua_load_module:n}.
-% \begin{texnote}
-% This is a wrapper around the Lua call |require '|\meta{module}|'|.
-% \end{texnote}
-% \end{function}
-%
-% \section{Lua interfaces}
-%
-% As well as interfaces for \TeX{}, there are a small number of Lua functions
-% provided here.
-%
-% \begin{function}{ltx.utils}
-% Most public interfaces provided by the module are stored within the
-% |ltx.utils| table.
-% \end{function}
-%
-% \begin{function}{ltx.utils.filedump}
-% \begin{syntax}
-% \meta{dump}| = ltx.utils.filedump(|\meta{file}|,|\meta{offset}|,|\meta{length}|)| \\
-% \end{syntax}
-% Returns the uppercase hexadecimal representation of the content of the
-% \meta{file} read as bytes. If the \meta{length} is given, only this part
-% of the file is returned; similarly, one may specify the \meta{offset} from
-% the start of the file. If the \meta{length} is not given, the entire file
-% is read starting at the \meta{offset}.
-% \end{function}
-%
-% \begin{function}{ltx.utils.filemd5sum}
-% \begin{syntax}
-% \meta{hash}| = ltx.utils.filemd5sum(|\meta{file}|)| \\
-% \end{syntax}
-% Returns the MD5 sum of the file contents read as bytes; note that
-% the result will depend on the nature of the line endings used in the file,
-% in contrast to normal \TeX{} behaviour. If the \meta{file} is not found,
-% nothing is returned with \emph{no error raised}.
-% \end{function}
-%
-% \begin{function}{ltx.utils.filemoddate}
-% \begin{syntax}
-% \meta{date}| = ltx.utils.filemoddate(|\meta{file}|)| \\
-% \end{syntax}
-% Returns the date/time of last modification of the \meta{file} in the
-% format
-% \begin{quote}
-% |D:|\meta{year}\meta{month}\meta{day}\meta{hour}\meta{minute}^^A
-% \meta{second}\meta{offset}
-% \end{quote}
-% where the latter may be |Z| (UTC) or
-% \meta{plus-minus}\meta{hours}|'|\meta{minutes}|'|. If the \meta{file} is
-% not found, nothing is returned with \emph{no error raised}.
-% \end{function}
-%
-% \begin{function}{ltx.utils.filesize}
-% \begin{syntax}
-% |size = ltx.utils.filesize(|\meta{file}|)| \\
-% \end{syntax}
-% Returns the size of the \meta{file} in bytes. If the \meta{file} is not
-% found, nothing is returned with \emph{no error raised}.
-% \end{function}
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3luatex} implementation}
-%
-% \begin{macrocode}
-%<*package>
-% \end{macrocode}
-%
-% \subsection{Breaking out to \Lua{}}
-%
-% \begin{macrocode}
-%<*tex>
-% \end{macrocode}
-%
-% \begin{macrocode}
-%<@@=lua>
-% \end{macrocode}
-%
-% \begin{macro}[EXP]{\@@_escape:n, \@@_now:n, \@@_shipout:n}
-% Copies of primitives.
-% \begin{macrocode}
-\cs_new_eq:NN \@@_escape:n \tex_luaescapestring:D
-\cs_new_eq:NN \@@_now:n \tex_directlua:D
-\cs_new_eq:NN \@@_shipout:n \tex_latelua:D
-% \end{macrocode}
-% \end{macro}
-%
-% These functions are set up in \pkg{l3str} for bootstrapping: we want to
-% replace them with a \enquote{proper} version at this stage, so clean up.
-% \begin{macrocode}
-\cs_undefine:N \lua_escape:e
-\cs_undefine:N \lua_now:e
-% \end{macrocode}
-%
-% \begin{macro}[EXP]{\lua_now:n, \lua_now:e}
-% \begin{macro}{\lua_shipout_e:n, \lua_shipout:n}
-% \begin{macro}[EXP]{\lua_escape:n, \lua_escape:e}
-% Wrappers around the primitives.
-% \begin{macrocode}
-\cs_new:Npn \lua_now:e #1 { \@@_now:n {#1} }
-\cs_new:Npn \lua_now:n #1 { \lua_now:e { \exp_not:n {#1} } }
-\cs_new_protected:Npn \lua_shipout_e:n #1 { \@@_shipout:n {#1} }
-\cs_new_protected:Npn \lua_shipout:n #1
- { \lua_shipout_e:n { \exp_not:n {#1} } }
-\cs_new:Npn \lua_escape:e #1 { \@@_escape:n {#1} }
-\cs_new:Npn \lua_escape:n #1 { \lua_escape:e { \exp_not:n {#1} } }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\lua_load_module:n}
-% Wrapper around |require'|\meta{module}|'|.
-% \begin{macrocode}
-\str_new:N \l_@@_err_msg_str
-\cs_new_protected:Npn \lua_load_module:n #1
- {
- \bool_if:nF { \@@_load_module_p:n { #1 } }
- {
- \msg_error:nnnV
- { luatex } { module-not-found } { #1 } \l_@@_err_msg_str
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% As with engines other than \LuaTeX{}
-% these have to be macros, we give them the same status in all cases.
-% When \LuaTeX{} is not in use, simply give an error message/
-% \begin{macrocode}
-\sys_if_engine_luatex:F
- {
- \clist_map_inline:nn
- {
- \lua_escape:n , \lua_escape:e ,
- \lua_now:n , \lua_now:e
- }
- {
- \cs_gset:Npn #1 ##1
- {
- \msg_expandable_error:nnn
- { luatex } { luatex-required } { #1 }
- }
- }
- \clist_map_inline:nn
- { \lua_shipout_e:n , \lua_shipout:n, \lua_load_module:n }
- {
- \cs_gset_protected:Npn #1 ##1
- {
- \msg_error:nnn
- { luatex } { luatex-required } { #1 }
- }
- }
- }
-% \end{macrocode}
-% \subsection{Messages}
-%
-% \begin{macrocode}
-\msg_new:nnnn { luatex } { luatex-required }
- { LuaTeX~engine~not~in~use!~Ignoring~#1. }
- {
- The~feature~you~are~using~is~only~available~
- with~the~LuaTeX~engine.~LaTeX3~ignored~'#1'.
- }
-
-\msg_new:nnnn { luatex } { module-not-found }
- { Lua~module~`#1'~not~found. }
- {
- The~file~`#1.lua'~could~not~be~found.~Please~ensure~
- that~the~file~was~properly~installed~and~that~the~
- filename~database~is~current. \\ \\
- The~Lua~loader~provided~this~additional~information: \\
- #2
- }
-
-\prop_gput:Nnn \g_msg_module_name_prop { luatex } { LaTeX }
-\prop_gput:Nnn \g_msg_module_type_prop { luatex } { }
-% \end{macrocode}
-%
-% \begin{macrocode}
-%</tex>
-% \end{macrocode}
-%
-% \subsection{\Lua{} functions for internal use}
-%
-% \begin{macrocode}
-%<*lua>
-% \end{macrocode}
-%
-% Most of the emulation of \pdfTeX{} here is based heavily on Heiko Oberdiek's
-% \pkg{pdftexcmds} package.
-%
-% \begin{macro}{ltx.utils}
-% Create a table for the kernel's own use.
-% \begin{macrocode}
-ltx = ltx or {utils={}}
-ltx.utils = ltx.utils or { }
-local ltxutils = ltx.utils
-% \end{macrocode}
-% \end{macro}
-%
-% Local copies of global tables.
-% \begin{macrocode}
-local io = io
-local kpse = kpse
-local lfs = lfs
-local math = math
-local md5 = md5
-local os = os
-local string = string
-local tex = tex
-local texio = texio
-local tonumber = tonumber
-% \end{macrocode}
-%
-% Local copies of standard functions.
-% \begin{macrocode}
-local abs = math.abs
-local byte = string.byte
-local floor = math.floor
-local format = string.format
-local gsub = string.gsub
-local lfs_attr = lfs.attributes
-local open = io.open
-local os_date = os.date
-local setcatcode = tex.setcatcode
-local sprint = tex.sprint
-local cprint = tex.cprint
-local write = tex.write
-local write_nl = texio.write_nl
-local utf8_char = utf8.char
-local package_loaded = package.loaded
-local package_searchers = package.searchers
-local table_concat = table.concat
-
-local scan_int = token.scan_int or token.scan_integer
-local scan_string = token.scan_string
-local scan_keyword = token.scan_keyword
-local put_next = token.put_next
-local token_create = token.create
-local token_new = token.new
-local set_macro = token.set_macro
-% \end{macrocode}
-%
-% Since token.create only returns useful values after the tokens
-% has been added to TeX's hash table, we define a variant which
-% defines it first if necessary.
-% \begin{macrocode}
-local token_create_safe
-do
- local is_defined = token.is_defined
- local set_char = token.set_char
- local runtoks = tex.runtoks
- local let_token = token_create'let'
-
- function token_create_safe(s)
- local orig_token = token_create(s)
- if is_defined(s, true) then
- return orig_token
- end
- set_char(s, 0)
- local new_token = token_create(s)
- runtoks(function()
- put_next(let_token, new_token, orig_token)
- end)
- return new_token
- end
-end
-
-local true_tok = token_create_safe'prg_return_true:'
-local false_tok = token_create_safe'prg_return_false:'
-% \end{macrocode}
-% In Con\TeX{}t lmtx \texttt{token.command_id} does not exist,
-% but it can easily be emulated with Con\TeX{}t's \texttt{tokens.commands}.
-% \begin{macrocode}
-local command_id = token.command_id
-if not command_id and tokens and tokens.commands then
- local id_map = tokens.commands
- function command_id(name)
- return id_map[name]
- end
-end
-% \end{macrocode}
-%
-% Deal with Con\TeX{}t: doesn't use |kpse| library.
-% \begin{macrocode}
-local kpse_find = (resolvers and resolvers.findfile) or kpse.find_file
-% \end{macrocode}
-%
-% \begin{macro}[int]{escapehex}
-% An internal auxiliary to convert a string to the matching hex escape.
-% This works on a byte basis: extension to handled UTF-8 input is
-% covered in \pkg{pdftexcmds} but is not currently required here.
-% \begin{macrocode}
-local function escapehex(str)
- return (gsub(str, ".",
- function (ch) return format("%02X", byte(ch)) end))
-end
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{ltx.utils.filedump}
-% Similar comments here to the next function: read the file in binary mode
-% to avoid any line-end weirdness.
-% \begin{macrocode}
-local function filedump(name,offset,length)
- local file = kpse_find(name,"tex",true)
- if not file then return end
- local f = open(file,"rb")
- if not f then return end
- if offset and offset > 0 then
- f:seek("set", offset)
- end
- local data = f:read(length or 'a')
- f:close()
- return escapehex(data)
-end
-ltxutils.filedump = filedump
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[int]{md5.HEX}
-% Hash a string and return the hash in uppercase hexadecimal format.
-% In some engines, this is build-in. For traditional \LuaTeX{}, the conversion
-% to hexadecimal has to be done by us.
-% \begin{macrocode}
-local md5_HEX = md5.HEX
-if not md5_HEX then
- local md5_sum = md5.sum
- function md5_HEX(data)
- return escapehex(md5_sum(data))
- end
- md5.HEX = md5_HEX
-end
-% \end{macrocode}
-% \end{macro}
-% \begin{macro}{ltx.utils.filemd5sum}
-% Read an entire file and hash it: the hash function itself is a built-in.
-% As Lua is byte-based there is no work needed here in terms of UTF-8
-% (see \pkg{pdftexcmds} and how it handles strings that have passed through
-% \LuaTeX{}). The file is read in binary mode so that no line ending
-% normalisation occurs.
-% \begin{macrocode}
-local function filemd5sum(name)
- local file = kpse_find(name, "tex", true) if not file then return end
- local f = open(file, "rb") if not f then return end
-
- local data = f:read("*a")
- f:close()
- return md5_HEX(data)
-end
-ltxutils.filemd5sum = filemd5sum
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{ltx.utils.filemoddate}
-% There are two cases: If the C standard library is C99 compliant,
-% we can use |%z| to get the timezone in almost the right format.
-% We only have to add primes and replace a zero or missing offset
-% with |Z|.
-%
-% Of course this would be boring, so Windows does things differently.
-% There we have to manually calculate the offset.
-% See procedure \texttt{makepdftime} in \texttt{utils.c} of
-% \pdfTeX{}.
-% \begin{macrocode}
-local filemoddate
-if os_date'%z':match'^[+-]%d%d%d%d$' then
- local pattern = lpeg.Cs(16 *
- (lpeg.Cg(lpeg.S'+-' * '0000' * lpeg.Cc'Z')
- + 3 * lpeg.Cc"'" * 2 * lpeg.Cc"'"
- + lpeg.Cc'Z')
- * -1)
- function filemoddate(name)
- local file = kpse_find(name, "tex", true)
- if not file then return end
- local date = lfs_attr(file, "modification")
- if not date then return end
- return pattern:match(os_date("D:%Y%m%d%H%M%S%z", date))
- end
-else
- local function filemoddate(name)
- local file = kpse_find(name, "tex", true)
- if not file then return end
- local date = lfs_attr(file, "modification")
- if not date then return end
- local d = os_date("*t", date)
- local u = os_date("!*t", date)
- local off = 60 * (d.hour - u.hour) + d.min - u.min
- if d.year ~= u.year then
- if d.year > u.year then
- off = off + 1440
- else
- off = off - 1440
- end
- elseif d.yday ~= u.yday then
- if d.yday > u.yday then
- off = off + 1440
- else
- off = off - 1440
- end
- end
- local timezone
- if off == 0 then
- timezone = "Z"
- else
- if off < 0 then
- timezone = "-"
- off = -off
- else
- timezone = "+"
- end
- timezone = format("%s%02d'%02d'", timezone, hours // 60, hours % 60)
- end
- return format("D:%04d%02d%02d%02d%02d%02d%s",
- d.year, d.month, d.day, d.hour, d.min, d.sec, timezone)
- end
-end
-ltxutils.filemoddate = filemoddate
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{ltx.utils.filesize}
-% A simple disk lookup.
-% \begin{macrocode}
-local function filesize(name)
- local file = kpse_find(name, "tex", true)
- if file then
- local size = lfs_attr(file, "size")
- if size then
- return size
- end
- end
-end
-ltxutils.filesize = filesize
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[int]{luadef}
-% An internal function for defining control sequences form Lua which behave
-% like primitives. This acts as a wrapper around |token.set_lua| which accepts
-% a function instead of an index into the functions table.
-% \begin{macrocode}
-local luacmd do
- local set_lua = token.set_lua
- local undefined_cs = command_id'undefined_cs'
-
- if not context and not luatexbase then require'ltluatex' end
- if luatexbase then
- local new_luafunction = luatexbase.new_luafunction
- local functions = lua.get_functions_table()
- function luacmd(name, func, ...)
- local id
- local tok = token_create(name)
- if tok.command == undefined_cs then
- id = new_luafunction(name)
- set_lua(name, id, ...)
- else
- id = tok.index or tok.mode
- end
- functions[id] = func
- end
- elseif context then
- local register = context.functions.register
- local functions = context.functions.known
- function luacmd(name, func, ...)
- local tok = token_create(name)
- if tok.command == undefined_cs then
- token.set_lua(name, register(func), ...)
- else
- functions[tok.index or tok.mode] = func
- end
- end
- end
-end
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[int]{try_require}
-% Loads a Lua module. This function loads the module similarly to the standard
-% Lua global function |require|, with a few differences. On success,
-% |try_require| returns |true, module|. If the module cannot be found, it
-% returns |false, err_msg|. If the module is found, but something goes wrong
-% when loading it, the function throws an error.
-% \begin{macrocode}
-local function try_require(name)
- if package_loaded[name] then
- return true, package_loaded[name]
- end
-
- local failure_details = {}
- for _, searcher in ipairs(package_searchers) do
- local loader, data = searcher(name)
- if type(loader) == 'function' then
- package_loaded[name] = loader(name, data) or true
- return true, package_loaded[name]
- elseif type(loader) == 'string' then
- failure_details[#failure_details + 1] = loader
- end
- end
-
- return false, table_concat(failure_details, '\n')
-end
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_load_module_p:n}
-% Check to see if we can load a module using |require|. If we
-% can load the module, then we load it immediately. Otherwise, we save the
-% error message in |\l_@@_err_msg_str|.
-% \begin{macrocode}
-local char_given = command_id'char_given'
-local c_true_bool = token_create(1, char_given)
-local c_false_bool = token_create(0, char_given)
-local c_str_cctab = token_create('c_str_cctab').mode
-
-luacmd('@@_load_module_p:n', function()
- local success, result = try_require(scan_string())
- if success then
- set_macro(c_str_cctab, 'l_@@_err_msg_str', '')
- put_next(c_true_bool)
- else
- set_macro(c_str_cctab, 'l_@@_err_msg_str', result)
- put_next(c_false_bool)
- end
-end)
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Preserving iniTeX Lua data for runs}
-%
-% \begin{macrocode}
-%<@@=lua>
-% \end{macrocode}
-%
-% The Lua state is not dumped when a forat is written, therefore any Lua
-% variables filled doing format building need to be restored in order to
-% be accessible during normal runs.
-%
-% We provide some kernel-internal helpers for this. They will only be available if
-% \texttt{luatexbase} is available. This is not a big restriction though, because
-% Con\TeX{}t (which does not use \texttt{luatexbase}) does not load \pkg{expl3}
-% in the format.
-%
-% \begin{macrocode}
-local register_luadata, get_luadata
-
-if luatexbase then
- local register = token_create'@expl@luadata@bytecode'.index
- if status.ini_version then
-% \end{macrocode}
-%
-% \begin{macro}[int]{register_luadata}
-% \texttt{register_luadata} is only available during format generation.
-% It accept a string which uniquely identifies the data object and has to be
-% provided to retrieve it later. Additionally it accepts a function which is
-% called in the \texttt{pre_dump} callback and which has to return a string that
-% evaluates to a valid Lua object to be preserved.
-% \begin{macrocode}
- local luadata, luadata_order = {}, {}
-
- function register_luadata(name, func)
- if luadata[name] then
- error(format("LaTeX error: data name %q already in use", name))
- end
- luadata[name] = func
- luadata_order[#luadata_order + 1] = func and name
- end
-% \end{macrocode}
-% \end{macro}
-%
-% The actual work is done in \texttt{pre_dump}. The \texttt{luadata_order} is used
-% to ensure that the order is consistent over multiple runs.
-% \begin{macrocode}
- luatexbase.add_to_callback("pre_dump", function()
- if next(luadata) then
- local str = "return {"
- for i=1, #luadata_order do
- local name = luadata_order[i]
- str = format('%s[%q]=%s,', str, name, luadata[name]())
- end
- lua.bytecode[register] = assert(load(str .. "}"))
- end
- end, "ltx.luadata")
- else
-% \end{macrocode}
-%
-% \begin{macro}[int]{get_luadata}
-% \texttt{get_luadata} is only available if data should be restored.
-% It accept the identifier which was used when the data object was registered and
-% returns the associated object. Every object can only be retrieved once.
-% \begin{macrocode}
- local luadata = lua.bytecode[register]
- if luadata then
- lua.bytecode[register] = nil
- luadata = luadata()
- end
- function get_luadata(name)
- if not luadata then return end
- local data = luadata[name]
- luadata[name] = nil
- return data
- end
- end
-end
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macrocode}
-%</lua>
-% \end{macrocode}
-%
-% \begin{macrocode}
-%</package>
-% \end{macrocode}
-%
-%\end{implementation}
-%
-%\PrintIndex