diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/l3kernel/l3luatex.dtx |
Initial commit
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3luatex.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3luatex.dtx | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/macros/latex/contrib/l3kernel/l3luatex.dtx b/macros/latex/contrib/l3kernel/l3luatex.dtx new file mode 100644 index 0000000000..9557fc8a08 --- /dev/null +++ b/macros/latex/contrib/l3kernel/l3luatex.dtx @@ -0,0 +1,539 @@ +% \iffalse meta-comment +% +%% File: l3luatex.dtx +% +% Copyright (C) 2010-2019 The LaTeX3 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} package: \LuaTeX-specific functions^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released 2019-08-25} +% +% \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} +% +% \section{Lua interfaces} +% +% As well as interfaces for \TeX{}, there are a small number of Lua functions +% provided here. +% +% \begin{function}{l3kernel} +% All public interfaces provided by the module are stored within the +% |l3kernel| table. +% \end{function} +% +% \begin{function}{l3kernel.charcat} +% \begin{syntax} +% |l3kernel.charcat(|\meta{charcode}, \meta{catcode}|)| +% \end{syntax} +% Constructs a character of \meta{charcode} and \meta{catcode} and returns +% the result to \TeX{}. +% \end{function} +% +% \begin{function}{l3kernel.elapsedtime} +% \begin{syntax} +% |l3kernel.elapsedtime()| +% \end{syntax} +% Returns the CPU time in \meta{scaled seconds} since the start of the +% \TeX{} run or since |l3kernel.resettimer| was issued. This only +% measures the time used by the CPU, not the real time, e.g., waiting +% for user input. +% \end{function} +% +% \begin{function}{l3kernel.filemdfivesum} +% \begin{syntax} +% |l3kernel.filemdfivesum(|\meta{file}|)| +% \end{syntax} +% Returns the of 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}{l3kernel.filemoddate} +% \begin{syntax} +% |l3kernel.filemoddate(|\meta{file}|)| +% \end{syntax} +% Returns the of 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}{l3kernel.filesize} +% \begin{syntax} +% |l3kernel.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} +% +% \begin{function}{l3kernel.resettimer} +% \begin{syntax} +% |l3kernel.resettimer()| +% \end{syntax} +% Resets the timer used by |l3kernel.elapsetime|. +% \end{function} +% +% \begin{function}{l3kernel.strcmp} +% \begin{syntax} +% |l3kernel.strcmp(|\meta{str one}, \meta{str two}|)| +% \end{syntax} +% Compares the two strings and returns |0| to \TeX{} +% if the two are identical. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3luatex} implementation} +% +% \begin{macrocode} +%<*initex|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. 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} +\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} } } +\sys_if_engine_luatex:F + { + \clist_map_inline:nn + { + \lua_escape:n , \lua_escape:e , + \lua_now:n , \lua_now:e + } + { + \cs_set:Npn #1 ##1 + { + \__kernel_msg_expandable_error:nnn + { kernel } { luatex-required } { #1 } + } + } + \clist_map_inline:nn + { \lua_shipout_e:n , \lua_shipout:n } + { + \cs_set_protected:Npn #1 ##1 + { + \__kernel_msg_error:nnn + { kernel } { luatex-required } { #1 } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\__kernel_msg_new:nnnn { kernel } { luatex-required } + { LuaTeX~engine~not~in~use!~Ignoring~#1. } + { + The~feature~you~are~using~is~only~available~ + with~the~LuaTeX~engine.~LaTeX3~ignored~'#1'. + } +% \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}{l3kernel} +% Create a table for the kernel's own use. +% \begin{macrocode} +l3kernel = l3kernel or { } +% \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 unicode = unicode +% \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 md5_sum = md5.sum +local open = io.open +local os_clock = os.clock +local os_date = os.date +local setcatcode = tex.setcatcode +local sprint = tex.sprint +local write = tex.write +% \end{macrocode} +% +% Newer Con\TeX{}t releases replace the |unicode| library by |utf|. +% \begin{macrocode} +local utf8_char = (utf and utf.char) or unicode.utf8.char +% \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) + write((gsub(str, ".", + function (ch) return format("%02X", byte(ch)) end))) +end +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.charcat} +% Creating arbitrary chars needs a category code table. As set up here, +% one may have been assigned earlier (see \pkg{l3bootstrap}) or a hard-coded +% one is used. The latter is intended for format mode and should be adjusted +% to match an eventual allocator. +% \begin{macrocode} +local charcat_table = l3kernel.charcat_table or 1 +local function charcat(charcode, catcode) + setcatcode(charcat_table, charcode, catcode) + sprint(charcat_table, utf8_char(charcode)) +end +l3kernel.charcat = charcat +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.elapsedtime, l3kernel.resettimer} +% Simple timing set up: give the result from the system clock in scaled +% seconds. +% \begin{macrocode} +local base_time = 0 +local function elapsedtime() + local val = (os_clock() - base_time) * 65536 + 0.5 + if val > 2147483647 then + val = 2147483647 + end + write(format("%d",floor(val))) +end +l3kernel.elapsedtime = elapsedtime +local function resettimer() + base_time = os_clock() +end +l3kernel.resettimer = resettimer +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.filemdfivesum} +% 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 filemdfivesum(name) + local file = kpse_find(name, "tex", true) + if file then + local f = open(file, "rb") + if f then + local data = f:read("*a") + escapehex(md5_sum(data)) + f:close() + end + end +end +l3kernel.filemdfivesum = filemdfivesum +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.filemoddate} +% See procedure \texttt{makepdftime} in \texttt{utils.c} of +% \pdfTeX{}. +% \begin{macrocode} +local function filemoddate(name) + local file = kpse_find(name, "tex", true) + if file then + local date = lfs_attr(file, "modification") + if date then + local d = os_date("*t", date) + if d.sec >= 60 then + d.sec = 59 + end + 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 + local hours = floor(off / 60) + local mins = abs(off - hours * 60) + timezone = format("%+03d", hours) + .. "'" .. format("%02d", mins) .. "'" + end + write("D:" + .. format("%04d", d.year) + .. format("%02d", d.month) + .. format("%02d", d.day) + .. format("%02d", d.hour) + .. format("%02d", d.min) + .. format("%02d", d.sec) + .. timezone) + end + end +end +l3kernel.filemoddate = filemoddate +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.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 + write(size) + end + end +end +l3kernel.filesize = filesize +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{l3kernel.strcmp} +% String comparison which gives the same results as \pdfTeX{}'s +% \tn{pdfstrcmp}, although the ordering should likely not be relied upon! +% \begin{macrocode} +local function strcmp(A, B) + if A == B then + write("0") + elseif A < B then + write("-1") + else + write("1") + end +end +l3kernel.strcmp = strcmp +% \end{macrocode} +% \end{macro} +% +% \subsection{Generic \Lua{} and font support} +% +% \begin{macrocode} +%<*initex> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=alloc> +% \end{macrocode} +% +% A small amount of generic code is used by almost all \LuaTeX{} material so +% needs to be loaded by the format. +% \begin{macrocode} +attribute_count_name = "g_@@_attribute_int" +bytecode_count_name = "g_@@_bytecode_int" +chunkname_count_name = "g_@@_chunkname_int" +whatsit_count_name = "g_@@_whatsit_int" +require("ltluatex") +% \end{macrocode} +% +% With the above available the font loader code used by plain \TeX{} and +% \LaTeXe{} when used with \LuaTeX{} can be loaded here. This is thus being +% treated more-or-less as part of the engine itself. +% \begin{macrocode} +require("luaotfload-main") +local _void = luaotfload.main() +% \end{macrocode} +% \begin{macrocode} +%</initex> +% \end{macrocode} +% +% \begin{macrocode} +%</lua> +% \end{macrocode} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +%\end{implementation} +% +%\PrintIndex |