diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx | 309 |
1 files changed, 215 insertions, 94 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index b8f00b1187e..ca266626585 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2020-09-06} +% \date{Released 2020-09-24} % % \maketitle % @@ -120,9 +120,15 @@ % 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. +% \begin{function}{ltx.utils} +% Most public interfaces provided by the module are stored within the +% |ltx.utils| table. +% \end{function} +% +% \begin{function}[deprecated = 2021-12-31]{l3kernel} +% For compatibility reasons, there are also some deprecated interfaces provided +% in the |l3kernel| table. These do not return their result as Lua values but +% instead print them to \TeX. % \end{function} % % \begin{function}{l3kernel.charcat} @@ -143,8 +149,9 @@ % for user input. % \end{function} % -% \begin{function}{l3kernel.filedump} +% \begin{function}{ltx.utils.filedump, l3kernel.filedump} % \begin{syntax} +% \meta{dump}| = ltx.utils.filedump(|\meta{file}|,|\meta{offset}|,|\meta{length}|)| \\ % |l3kernel.filedump(|\meta{file}|,|\meta{offset}|,|\meta{length}|)| % \end{syntax} % Returns the uppercase hexadecimal representation of the content of the @@ -154,8 +161,9 @@ % is read starting at the \meta{offset}. % \end{function} % -% \begin{function}{l3kernel.filemdfivesum} +% \begin{function}{ltx.utils.filemd5sum, l3kernel.filemdfivesum} % \begin{syntax} +% \meta{hash}| = ltx.utils.filemd5sum(|\meta{file}|)| \\ % |l3kernel.filemdfivesum(|\meta{file}|)| % \end{syntax} % Returns the MD5 sum of the file contents read as bytes; note that @@ -164,8 +172,9 @@ % nothing is returned with \emph{no error raised}. % \end{function} % -% \begin{function}{l3kernel.filemoddate} +% \begin{function}{ltx.utils.filemoddate, l3kernel.filemoddate} % \begin{syntax} +% \meta{date}| = ltx.utils.filemoddate(|\meta{file}|)| \\ % |l3kernel.filemoddate(|\meta{file}|)| % \end{syntax} % Returns the date/time of last modification of the \meta{file} in the @@ -179,8 +188,9 @@ % not found, nothing is returned with \emph{no error raised}. % \end{function} % -% \begin{function}{l3kernel.filesize} +% \begin{function}{ltx.utils.filesize, l3kernel.filesize} % \begin{syntax} +% |size = ltx.utils.filesize(|\meta{file}|)| \\ % |l3kernel.filesize(|\meta{file}|)| % \end{syntax} % Returns the size of the \meta{file} in bytes. If the \meta{file} is not @@ -313,11 +323,17 @@ % \pkg{pdftexcmds} package. % % \begin{macro}{l3kernel} +% \begin{macro}{ltx.utils} % Create a table for the kernel's own use. % \begin{macrocode} l3kernel = l3kernel or { } +local l3kernel = l3kernel +ltx = ltx or {utils={}} +ltx.utils = ltx.utils or { } +local ltxutils = ltx.utils % \end{macrocode} % \end{macro} +% \end{macro} % % Local copies of global tables. % \begin{macrocode} @@ -331,7 +347,6 @@ local string = string local tex = tex local texio = texio local tonumber = tonumber -local unicode = unicode % \end{macrocode} % % Local copies of standard functions. @@ -342,23 +357,33 @@ 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 os_exec = os.execute 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 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 true_tok = token.create'prg_return_true:' +local false_tok = token.create'prg_return_false:' % \end{macrocode} % -% Newer Con\TeX{}t releases replace the |unicode| library by |utf| and -% since Lua 5.3 we can even use the Lua standard |utf8| library. % \begin{macrocode} -local utf8_char = (utf8 and utf8.char) or (utf and utf.char) or unicode.utf8.char -% \end{macrocode} +local function deprecated(table, name, func) + table[name] = function(...) + write_nl(format("Calling deprecated Lua function %s", name)) + table[name] = func + return func(...) + end +end +% \end{macrocode % % Deal with Con\TeX{}t: doesn't use |kpse| library. % \begin{macrocode} @@ -371,20 +396,20 @@ local kpse_find = (resolvers and resolvers.findfile) or kpse.find_file % 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))) + return (gsub(str, ".", + function (ch) return format("%02X", byte(ch)) end)) end % \end{macrocode} % \end{macro} % % \begin{macro}{l3kernel.charcat} % Creating arbitrary chars using |tex.cprint|. +% The alternative approach using |token.put_next(token.create(...))| +% would be about 10\% slower. % \begin{macrocode} -local charcat -function charcat(charcode, catcode) +deprecated(l3kernel, 'charcat', function(charcode, catcode) cprint(catcode, utf8_char(charcode)) -end -l3kernel.charcat = charcat +end) % \end{macrocode} % \end{macro} % @@ -392,9 +417,10 @@ l3kernel.charcat = charcat % Simple timing set up: give the result from the system clock in scaled % seconds. % \begin{macrocode} -local base_time = 0 +local os_clock = os.clock +local base_clock_time = 0 local function elapsedtime() - local val = (os_clock() - base_time) * 65536 + 0.5 + local val = (os_clock() - base_clock_time) * 65536 + 0.5 if val > 2147483647 then val = 2147483647 end @@ -402,36 +428,56 @@ local function elapsedtime() end l3kernel.elapsedtime = elapsedtime local function resettimer() - base_time = os_clock() + base_clock_time = os_clock() end l3kernel.resettimer = resettimer % \end{macrocode} % \end{macro} % +% \begin{macro}{ltx.utils.filedump} % \begin{macro}{l3kernel.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 file then - local length = tonumber(length) or lfs_attr(file,"size") - local offset = tonumber(offset) or 0 - local f = open(file,"rb") - if f then - if offset > 0 then - f:seek("set",offset) - end - local data = f:read(length) - escapehex(data) - f:close() - end + 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 -l3kernel.filedump = filedump +ltxutils.filedump = filedump +deprecated(l3kernel, "filedump", function(name, offset, length) + local dump = filedump(name, tonumber(offset), tonumber(length)) + if dump then + write(dump) + end +end) % \end{macrocode} % \end{macro} +% \end{macro} % +% \begin{macro}{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} % \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 @@ -439,94 +485,129 @@ l3kernel.filedump = filedump % \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 +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 -l3kernel.filemdfivesum = filemdfivesum +ltxutils.filemd5sum = filemd5sum +deprecated(l3kernel, "filemdfivesum", function(name) + local hash = filemd5sum(name) + if hash then + write(hash) + end +end) % \end{macrocode} % \end{macro} +% \end{macro} % +% \begin{macro}{ltx.utils.filemoddate} % \begin{macro}{l3kernel.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 function filemoddate(name) - local file = kpse_find(name, "tex", true) - if file then +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 date then - local d = os_date("*t", date) - if d.sec >= 60 then - d.sec = 59 + 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 - 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 + elseif d.yday ~= u.yday then + if d.yday > u.yday then + off = off + 1440 + else + off = off - 1440 end - local timezone - if off == 0 then - timezone = "Z" + end + local timezone + if off == 0 then + timezone = "Z" + else + if off < 0 then + timezone = "-" + off = -off else - local hours = floor(off / 60) - local mins = abs(off - hours * 60) - timezone = format("%+03d", hours) - .. "'" .. format("%02d", mins) .. "'" + timezone = "+" 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) + 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 -l3kernel.filemoddate = filemoddate +ltxutils.filemoddate = filemoddate +deprecated(l3kernel, "filemoddate", function(name) + local hash = filemoddate(name) + if hash then + write(hash) + end +end) % \end{macrocode} % \end{macro} +% \end{macro} % +% \begin{macro}{ltx.utils.filesize} % \begin{macro}{l3kernel.filesize} % A simple disk lookup. % \begin{macrocode} local function filesize(name) - local file = kpse_find(name, "tex", true) + local file = kpse_find(name, "tex", true) if file then local size = lfs_attr(file, "size") if size then - write(size) + return size end end end -l3kernel.filesize = filesize +ltxutils.filesize = filesize +deprecated(l3kernel, "filesize", function(name) + local size = filesize(name) + if size then + write(size) + end +end) % \end{macrocode} % \end{macro} +% \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) +deprecated(l3kernel, "strcmp", function (A, B) if A == B then write("0") elseif A < B then @@ -534,15 +615,15 @@ local function strcmp(A, B) else write("1") end -end -l3kernel.strcmp = strcmp +end) % \end{macrocode} % \end{macro} % % \begin{macro}{l3kernel.shellescape} % Replicating the \pdfTeX{} log interaction for shell escape. % \begin{macrocode} -local function shellescape(cmd) +local os_exec = os.execute +deprecated(l3kernel, "shellescape", function(cmd) local status,msg = os_exec(cmd) if status == nil then write_nl("log","runsystem(" .. cmd .. ")...(" .. msg .. ")\n") @@ -551,8 +632,48 @@ local function shellescape(cmd) else write_nl("log","runsystem(" .. cmd .. ")...failed " .. (msg or "") .. "\n") end +end) +% \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 token_create = token.create + local set_lua = token.set_lua + local undefined_cs = token.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 -l3kernel.shellescape = shellescape % \end{macrocode} % \end{macro} % |