From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/luatex/generic/luatexbase/README.md | 7 + macros/luatex/generic/luatexbase/luatexbase.dtx | 860 ++++++++++++++++++++++++ macros/luatex/generic/luatexbase/luatexbase.ins | 19 + macros/luatex/generic/luatexbase/luatexbase.pdf | Bin 0 -> 263467 bytes 4 files changed, 886 insertions(+) create mode 100644 macros/luatex/generic/luatexbase/README.md create mode 100644 macros/luatex/generic/luatexbase/luatexbase.dtx create mode 100644 macros/luatex/generic/luatexbase/luatexbase.ins create mode 100644 macros/luatex/generic/luatexbase/luatexbase.pdf (limited to 'macros/luatex/generic/luatexbase') diff --git a/macros/luatex/generic/luatexbase/README.md b/macros/luatex/generic/luatexbase/README.md new file mode 100644 index 0000000000..bbcb8d4654 --- /dev/null +++ b/macros/luatex/generic/luatexbase/README.md @@ -0,0 +1,7 @@ +The LaTeX kernel (LaTeX2e 2015/10/01 onward) builds in support for +LuaTeX functionality, also available as `ltluatex.tex` for users for +users of plain TeX and those with older LaTeX kernel implementations. +This support is based on ideas taken from the original `luatexbase` +package, but there are interface differences. This 'stub' package +provides a compatibility layer to allow existing packages to upgrade +smoothly to the new support structure. diff --git a/macros/luatex/generic/luatexbase/luatexbase.dtx b/macros/luatex/generic/luatexbase/luatexbase.dtx new file mode 100644 index 0000000000..a00e9481d1 --- /dev/null +++ b/macros/luatex/generic/luatexbase/luatexbase.dtx @@ -0,0 +1,860 @@ +% \iffalse meta-comment +% +% Copyright (C) 2009-2013 by Élie Roux +% Copyright (C) 2010, 2011 by Manuel Pégourié-Gonnard +% Copyright (C) 2015 David Carlisle and Joseph Wright +% +% 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: +% +% http://www.latex-project.org/lppl.txt +% +%\ifx\BeginCatcodeRegime\undefined\else\expandafter\endinput\fi +% +%\ifx +% \ProvidesPackage\undefined\begingroup\def\ProvidesPackage +% \ProvidesFile\undefined\begingroup\def\ProvidesFile +% #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} +%\fi +%\ProvidesPackage{luatexbase} +%\ProvidesPackage{luatexbase-compat} +%\ProvidesPackage{luatexbase-modutils} +%\ProvidesPackage{luatexbase-loader} +%\ProvidesPackage{luatexbase-regs} +%\ProvidesPackage{luatexbase-attr} +%\ProvidesPackage{luatexbase-cctb} +%\ProvidesPackage{luatexbase-mcb} +%<*driver> +\ProvidesFile{luatexbase.dtx} +% +%<*tex,sty> +[2015/10/04 v1.3 +% +% luatexbase interface to LuaTeX +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +% luatexbase interface to LuaTeX (legacy subpackage) +%<*tex,sty> +] +% +%<*driver> +\documentclass{ltxdoc} +\GetFileInfo{luatexbase.dtx} +\begin{document} +\title{\filename\\(Lua\TeX{}-specific support, luatexbase interface)} +\author{David Carlisle and Joseph Wright\footnote{Significant portions + of the code here are adapted/simplified from the packages \textsf{luatex} and + \textsf{luatexbase} written by Heiko Oberdiek, \'{E}lie Roux, + Manuel P\'{e}gouri\'{e}-Gonnar and Philipp Gesang.}} +\date{\filedate} +\maketitle +\setcounter{tocdepth}{2} +\tableofcontents +\DocInput{\filename} +\end{document} +% +% \fi +% +% \section{Overview} +% +% Lua\TeX{} adds a number of engine-specific functions to \TeX{}. Support +% for those is now available for this area in the \LaTeX{} kernel and as +% an equivalent stand-alone file |ltluatex.tex| for plain users. The +% functionality there is derived from the earlier \textsf{luatex} +% and \textsf{luatexbase} packages by Heiko Oberdiek, \'{E}lie Roux, +% Manuel P\'{e}gouri\'{e}-Gonnar and Philipp Gesang. However, the +% interfaces are not all identical. +% +% The interfaces defined in this package are closely modelled on the original +% \textsf{luatexbase} package, and provide a compatibility layer between +% the new kernel-level support and existing code using \textsf{luatexbase}. +% +% \section{The \textsf{luatexbase} package interface} +% +% \subsection +% [Catcode tables] +% {Catcode tables\footnote{This +% interface was previously defined in the \textsf{luatexbase-cctbl} +% sub-package.}} +% +% \subsubsection{\TeX} +% +% +% \noindent +% \DescribeMacro{\CatcodeTableIniTeX} +% \DescribeMacro{\CatcodeTableString} +% \DescribeMacro{\CatcodeTableLaTeX} +% \DescribeMacro{\CatcodeTableLaTeXAtLetter} +% \DescribeMacro{\CatcodeTableOther} +% \DescribeMacro{\CatcodeTableExpl} +% \TeX\ access to predefined catcode tables. +% +% The first four tables are aliases giving alternative names for some +% catcodetables that are defined in the \textsf{ltluatex} core. +% +% |\CatcodeTableOther| is like |\CatcodeTableString| except that +% the catcode of space is $12$ (other). +% +% |\CatcodeTableExpl| is similar to the environment set by the +% \textsf{expl3} command |\ExplSyntaxOn| note that this only affects +% catcode settings, not for example |\endlinechar|. +% +% One difference between this implementation and the tables defined +% in the earlier \textsf{luatexbase} package is that these tables are +% defined to match the settings used by \LaTeX\ over the full Unicode +% range (as set in the file \textsf{unicode-letters.def}). +% +% \noindent +% \DescribeMacro{\SetCatcodeRange} +% An alias for |\@setrangecatcode| which is defined in the +% \textsf{ctablestack} package imported into this version of +% \textsf{luatexbase}. (The order of arguments is the +% same despite the variation in the naming). This is useful for +% setting up a new catcode table and assigns a given catcode to a +% range of characters. +% +% \noindent +% \DescribeMacro{\BeginCatcodeRegime} +% \DescribeMacro{\EndCatcodeRegime} +% A simple wrapper around |\@pushcatcodetable| providing a slightly +% different interface. The usage is:\\% +% \verb|\BeginCatcodeRegime|\meta{catcode table}\\ +% \verb| |\meta{code}\\ +% \verb|\EndCatcodeRegime| +% +% \noindent +% \DescribeMacro{\PushCatcodeTableNumStack} +% \DescribeMacro{\PopCatcodeTableNumStack} +% These are defined to be aliases for |\@pushcatcodetable| and +% |\@popcatcodetable| although the actual implementation is quite different +% to the older packages, the use of the commands should match. +% +% \noindent +% \DescribeMacro{\newluatexcatcodetable} +% \DescribeMacro{\setluatexcatcodetable} +% Aliases for the \textsf{ltluatex} functions +% dropping |luatex| from the name to match the convention of not +% using |luatex|-prefixed names for the Lua\TeX\ primitives. +% +% \subsubsection{Lua} +% +% The standard way to access catcode table numbers from Lua in +% \textsf{ltluatex} is the |registernumber| function. This +% package provides a |catcodetables| table with a metatable +% that accesses this function and is extended with aliases for the +% predefined tables so you can use |catcodetables.expl| as an +% alternative to |catcodetables.CatcodeTableExpl|, both being +% equivalent to\\ +% |registernumber('CatcodeTableExpl')|. +% +% +% \subsection +% [Lua Callbacks] +% {Lua Callbacks\footnote{This +% interface was previously defined in the \textsf{luatexbase-mcb} +% sub-package.}} +% +% The |luatexbase| table is extended with some additional Lua +% functions to provide the interfaces provided by the previous +% implementation. +% +% +% \noindent +% \DescribeMacro{priority\_in\_callback}\meta{name}\meta{description}\\% +% As in the earlier interfaces the function +% is provided to return a number indicating the position of a +% specified function in a callback list. However it is usually used +% just as a boolean test that the function is registered with the +% callback. Kernel-level support does not directly expose the priority numbers, +% however the function here is defined to return the number of the specified +% function in the list returned by |luatexbase.callback_descriptions|. +% +% +% \noindent +% \DescribeMacro{is\_active\_callback}\meta{name}\meta{description}\\% +% This boolean function was defined in the development sources +% of the previous implementation. Here it is defined as an alias for +% the function |in_callback| provided by \textsf{ltluatex}. +% Given a callback and a description string, it returns true if a +% callback function with that description is currently registered. +% +% \noindent +% \DescribeMacro{reset\_callback}\meta{name}\meta{make\_false}\\ +% This function unregisters all functions registered for the callback +% \meta{name}. If \meta{make\_false} is true, the callback is then set +% to false (rather than nil). Unlike the earlier implementation +% This version does call |remove_from_callback| on each function in +% the callback list for \meta{name}, and each removal will be recorded +% in the log. +% +% \noindent +% \DescribeMacro{remove\_from\_callback}\meta{name}\meta{description}\\% +% This function is unchanged from the kernel-level implementation. +% It is backward compatible with the previous \textsf{luatexbase} +% package but enhanced as it returns the removed callback and its +% description. +% Together with the |callback_descriptions| function this allows much +% finer control over the order of functions in a callback list as the +% functions can be removed then re-added to the list in any desired order. +% +% \noindent +% \DescribeMacro{add\_to\_callback}\meta{name}\meta{function}\meta{description}\meta{priority}\\% +% This function is defined as a wrapper around the kernel-level +% implementation, which does not have the fourth \meta{priority} +% argument. +% +% If multiple callbacks are registered to a callback of type +% \textsf{exclusive} then \textsf{ltluatex} raises an error, but +% here it is allowed if \texttt{priority} is $1$, in which case the +% \verb|reset_callback| is first called to remove the existing +% callback. +% +% In general the \texttt{priority} argument is implemented by +% temporarily removing some callbacks from the list and replacing +% them after having added the new callback. +% +% \noindent +% \DescribeMacro{create\_callback}\meta{name}\meta{type}\meta{default}\\% +% This function is unchanged from kernel-level +% implementation, the only change is a change of terminology for the +% types of callback, the type |first| is now classified as |exclusive| +% and the kernel code raises an error if multiple callback functions +% are registered. The previous \textsf{luatexbase} implementation +% allowed multiple functions to be registered, but only activated the +% first in the list. +% +% \subsection +% [Module declaration] +% {Module declaration\footnote{This +% interface was previously defined in the \textsf{luatexbase-modutils} +% sub-package.}} +% +% \subsubsection{\TeX} +% +% \noindent +% \DescribeMacro{\RequireLuaModule}\meta{file}\oarg{info}\\ +% This command is provided as a wrapper around +% |\directlua{require(|\meta{file}|}|, and executes the Lua code in +% the specified file. +% The optional argument is accepted but ignored. +% +% Current versions of Lua\TeX\ all use the |kpse| \TeX\ path searching +% library with the |require| function, so the more complicated +% definition used in earlier implementations is no +% longer needed. +% +% \subsubsection{Lua} +% +% \noindent +% \DescribeMacro{provides\_module}\meta{info}\\ +% The \textsf{luatexbase} version of |provides_module| returns a list of log +% and error functions so that it is usually called as:\\ +% |local err, warning, info, log = luatexbase.provides_module({name=..| +% +% The returned functions are all instances of the functions provided by +% the kernel: |module_error|, +% |module_warning| and |module_info|, They all use their first argument +% as a format string fo rany later arguments. +% +% \DescribeMacro{errwarinf}\meta{name}\\ +% Returns four error and warning functions associated with \meta{name} +% mostly a helper function for \verb|provides\_module|, but can be called +% separately. +% +% \subsection +% [Lua Attributes] +% {Lua Attributes and Whatsits\footnote{This +% interface was previously defined in the \textsf{luatexbase-attr} +% sub-package.}} +% +% +% \subsubsection{\TeX} +% +% \noindent +% \DescribeMacro{\newluatexattribute} +% \DescribeMacro{\setluatexattribute} +% \DescribeMacro{\unsetluatexattribute} +% As for catcode tables, aliases for the attribute allocation functions are +% provided with |luatex| in the names. +% +% +% \subsubsection{Lua} +% The lua code in this section is concerned with an experimental +% whatsit handling suite of functions in the original package. +% This is not fully documented here and is guraded by the +% \textsf{docstrip} guard \verb|whatsit| so it may optionally be +% included or excluded from the sources when the package is built. +% +% \subsection{Prefixed names for lua\TeX\ primitives} +% \noindent +% \DescribeMacro{\luatexattributedef} +% \DescribeMacro{\luatexcatcodetable} +% \DescribeMacro{\luatexluaescapestring} +% \DescribeMacro{\luatexlatelua} +% \DescribeMacro{\luatexoutputbox} +% \DescribeMacro{\luatexscantextokens} +% Aliases for commonly ued lua\TeX\ primitives that existing packages +% using \textsf{luatexbase} use with prefixed names. +% +% If additional primtives are required it is recommended that the +% code is updated to use unprefixed names. To ensure that the code +% works with the original \textsf{luatexbase} package on older formats +% you may use the lua function \texttt{tex.enableprimitives} to enable +% some or all primitives to be available with unprefixed names. +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{\textsf{luatexbase} interface} +% +% \begin{macrocode} +%<*emu> +\edef\emuatcatcode{\the\catcode`\@} +\catcode`\@=11 +% \end{macrocode} +% +% Load |ctablestack|. +% \begin{macrocode} +\ifx\@setrangecatcode\@undefined + \ifx\RequirePackage\@undefined + \input{ctablestack.sty}% + \else + \RequirePackage{ctablestack} + \fi +\fi +% \end{macrocode} +% +% Simple require wrapper as we now assume |require| implicitly uses the +% |kpathsea| search library. +% \begin{macrocode} +\def\RequireLuaModule#1{\directlua{require("#1")}\@gobbleoptarg} +% \end{macrocode} +% +% In \LaTeX\ (or plain macro package that has defined |\@ifnextchar|) +% use |\@ifnextchar| otherwise use a simple alternative, in practice this +% will never be followed by a brace group, so full version of |\@ifnextchar| +% not needed. +% \begin{macrocode} +\ifdefined\@ifnextchar +\def\@gobbleoptarg{\@ifnextchar[\@gobble@optarg{}}% +\else +\long\def\@gobbleoptarg#1{\ifx[#1\expandafter\@gobble@optarg\fi#1}% +\fi +% \end{macrocode} +% +% \begin{macrocode} +\def\@gobble@optarg[#1]{} +% \end{macrocode} +% +% Extended catcode table support. Use the names from the previous +% \textsf{luatexbase} and \textsf{luatex} packages. +% \begin{macrocode} +\let\CatcodeTableIniTeX\catcodetable@initex +\let\CatcodeTableString\catcodetable@string +\let\CatcodeTableLaTeX\catcodetable@latex +\let\CatcodeTableLaTeXAtLetter\catcodetable@atletter +% \end{macrocode} +% +% Additional tables declared in the previous interface. +% \begin{macrocode} +\newcatcodetable\CatcodeTableOther +\@setcatcodetable\CatcodeTableOther{% + \catcodetable\CatcodeTableString + \catcode32 12 } +% \end{macrocode} +% +% \begin{macrocode} +\newcatcodetable\CatcodeTableExpl +\@setcatcodetable\CatcodeTableExpl{% + \catcodetable\CatcodeTableLaTeX + \catcode126 10 % tilde is a space char + \catcode32 9 % space is ignored + \catcode9 9 % tab also ignored + \catcode95 11 % underscore letter + \catcode58 11 % colon letter +} +% \end{macrocode} +% +% Top level access to catcodetable stack. +% \begin{macrocode} +\def\BeginCatcodeRegime#1{% + \@pushcatcodetable + \catcodetable#1\relax} +% \end{macrocode} +% +% \begin{macrocode} +\def\EndCatcodeRegime{% + \@popcatcodetable} +% \end{macrocode} +% +% The implementation of the stack is completely +% different, but usage should match. +% \begin{macrocode} +\let\PushCatcodeTableNumStack\@pushcatcodetable +\let\PopCatcodeTableNumStack\@popcatcodetable +% \end{macrocode} +% +% A simple copy. +% \begin{macrocode} +\let\SetCatcodeRange\@setrangecatcode +% \end{macrocode} +% +% Another copy. +% \begin{macrocode} +\let\setcatcodetable\@setcatcodetable +% \end{macrocode} +% +% \subsubsection{Additional lua code} +% \begin{macrocode} +\directlua{ +% \end{macrocode} +% +% Remove all registered callbacks, then disable. +% Set to false if optional second argument is |true|. +% \begin{macrocode} +function luatexbase.reset_callback(name,make_false) + for _,v in pairs(luatexbase.callback_descriptions(name)) + do + luatexbase.remove_from_callback(name,v) + end + if make_false == true then + luatexbase.disable_callback(name) + end +end +% \end{macrocode} +% +% Allow exclusive callbacks to be over-written if priority argument is +% 1 to match the ``first'' semantics of the original package. +% \changes{v1.1}{2015/10/02}{Fully handle priority argument} +% +% First save the kernel function. +% \begin{macrocode} +luatexbase.base_add_to_callback=luatexbase.add_to_callback +% \end{macrocode} +% +% Implement the priority argument by taking off existing callbacks +% that have higher priority than the new one, adding the new one, +% Then putting the saved callbacks back. +% \begin{macrocode} +function luatexbase.add_to_callback(name,fun,description,priority) +% \end{macrocode} +%^^A texio.write_nl('\string\n HERE: adding ' .. +%^^A description .. +%^^A ' to ' .. +%^^A name .. +%^^A ' with priority ' .. +%^^A (priority or '@@@')) +%^^A texio.write_nl('Original list') +%^^A for k,v in pairs(luatexbase.callback_descriptions(name)) do +%^^A texio.write_nl(' ' .. k .. ': ' .. v) +%^^A end +% \begin{macrocode} + local priority= priority + if priority==nil then + priority=\string#luatexbase.callback_descriptions(name)+1 + end + if(luatexbase.callbacktypes[name] == 3 and + priority == 1 and + \string#luatexbase.callback_descriptions(name)==1) then + luatexbase.module_warning("luatexbase", + "resetting exclusive callback: " .. name) + luatexbase.reset_callback(name) + end + local saved_callback={},ff,dd + for k,v in pairs(luatexbase.callback_descriptions(name)) do + if k >= priority then + ff,dd= luatexbase.remove_from_callback(name, v) + saved_callback[k]={ff,dd} + end + end + luatexbase.base_add_to_callback(name,fun,description) + for k,v in pairs(saved_callback) do + luatexbase.base_add_to_callback(name,v[1],v[2]) + end +% \end{macrocode} +%^^A texio.write_nl('New list') +%^^A for k,v in pairs(luatexbase.callback_descriptions(name)) do +%^^A texio.write_nl(' ' .. k .. ': ' .. v) +%^^A end +% \begin{macrocode} + return +end +% \end{macrocode} +% +% Emulate the catcodetables table. +% Explicitly fill the table rather than rely on the metatable call to +% |registernumber| as that is unreliable on old Lua\TeX{}. +% \begin{macrocode} +luatexbase.catcodetables=setmetatable( + {['latex-package'] = \number\CatcodeTableLaTeXAtLetter, + ini = \number\CatcodeTableIniTeX, + string = \number\CatcodeTableString, + other = \number\CatcodeTableOther, + latex = \number\CatcodeTableLaTeX, + expl = \number\CatcodeTableExpl, + expl3 = \number\CatcodeTableExpl}, + { __index = function(t,key) + return luatexbase.registernumber(key) or nil + end} +)} +% \end{macrocode} +% +% On old Lua\TeX{} workaround hashtable issues. +% Allocate in \TeX{}, and also directly add to |luatexbase.catcodetables|. +% \begin{macrocode} +\ifnum\luatexversion<80 % +\def\newcatcodetable#1{% + \e@alloc\catcodetable\chardef + \e@alloc@ccodetable@count\m@ne{"8000}#1% + \initcatcodetable\allocationnumber + {\escapechar=\m@ne + \directlua{luatexbase.catcodetables['\string#1']=% + \the\allocationnumber}}% +} +\fi +% \end{macrocode} +% +% \begin{macrocode} +\directlua{ +% \end{macrocode} +% +% |priority_in_callback| returns position in the callback list. +% Not provided by default by the kernel as usually it is just used +% as a boolean test, for which |in_callback| is provided. +% \begin{macrocode} +function luatexbase.priority_in_callback (name,description) + for i,v in ipairs(luatexbase.callback_descriptions(name)) + do + if v == description then + return i + end + end + return false +end +% \end{macrocode} +% +% The (unreleased) version~0.7 of \textsf{luatexbase} provided this +% boolean test under a different name, so we provide an alias here. +% \begin{macrocode} +luatexbase.is_active_callback = luatexbase.in_callback +% \end{macrocode} +% +% \textsf{ltluatex} implementation of |provides_module| does not return +% print functions so define modified version here. +% \changes{v1.3}{2015/10/03}{Use the first argument as a format string for +% later arguments} +% \begin{macrocode} +luatexbase.base_provides_module=luatexbase.provides_module +function luatexbase.errwarinf(name) + return + function(s,...) return luatexbase.module_error(name, s:format(...)) end, + function(s,...) return luatexbase.module_warning(name, s:format(...)) end, + function(s,...) return luatexbase.module_info(name, s:format(...)) end, + function(s,...) return luatexbase.module_info(name, s:format(...)) end +end +function luatexbase.provides_module(info) + luatexbase.base_provides_module(info) + return luatexbase.errwarinf(info.name) +end +} +% \end{macrocode} +% +% Same for attribute table as catcode tables. In old Lua\TeX{}, add to the +% |luatexbase.attributes| table directly. +% \begin{macrocode} +\ifnum\luatexversion<80 % +\def\newattribute#1{% + \e@alloc\attribute\attributedef + \e@alloc@attribute@count\m@ne\e@alloc@top#1% + {\escapechar=\m@ne + \directlua{luatexbase.attributes['\string#1']=% + \the\allocationnumber}}% +} +\fi +% \end{macrocode} +% +% Define a safe percent command for plain \TeX. +% \begin{macrocode} +\ifx\@percentchar\@undefined + {\catcode`\%=12 \gdef\@percentchar{%}} +\fi +% \end{macrocode} +% \changes{v1.2a}{2015/10/03}{Add missing local definitions for whatsit code} +% +% \begin{macrocode} +%<*whatsit> +\directlua{% +% \end{macrocode} +% +% \begin{macrocode} +local copynode = node.copy +local newnode = node.new +local nodesubtype = node.subtype +local nodetype = node.id +local stringformat = string.format +local tableunpack = unpack or table.unpack +local texiowrite_nl = texio.write_nl +local texiowrite = texio.write +local whatsit_t = nodetype"whatsit" +local user_defined_t = nodesubtype"user_defined" +local unassociated = "__unassociated" +local user_whatsits = { __unassociated = { } } +local whatsit_ids = { } +local anonymous_whatsits = 0 +local anonymous_prefix = "anon" +% \end{macrocode} +% +% User whatsit allocation is split into two functions: +% \verb|new_user_whatsit_id| registers a new id (an integer) +% and returns it. This is a wrapper around \verb|new_whatsit| +% but with the extra \texttt{package} argument, and recording +% the mapping in lua tables +% +% If no name given, generate a name from a counter. +% +% \begin{macrocode} +local new_user_whatsit_id = function (name, package) + if name then + if not package then + package = unassociated + end + else % anonymous + anonymous_whatsits = anonymous_whatsits + 1 + warning("defining anonymous user whatsit no. \@percentchar + d", anonymous_whatsits) + package = unassociated + name = anonymous_prefix .. tostring(anonymous_whatsits) + end + + local whatsitdata = user_whatsits[package] + if not whatsitdata then + whatsitdata = { } + user_whatsits[package] = whatsitdata + end + + local id = whatsitdata[name] + if id then %- warning + warning("replacing whatsit \@percentchar s:\@percentchar + s (\@percentchar d)", package, name, id) + else %- new id + id=luatexbase.new_whatsit(name) + whatsitdata[name] = id + whatsit_ids[id] = { name, package } + end + return id +end +luatexbase.new_user_whatsit_id = new_user_whatsit_id +% \end{macrocode} +% +% \verb|new_user_whatsit| first registers a new id and then also +% creates the corresponding whatsit node of subtype “user-defined”. +% Return a nullary function that delivers copies of the whatsit. +% +% Alternatively, the first argument can be a whatsit node that +% will then be used as prototype. +% +% \begin{macrocode} +local new_user_whatsit = function (req, package) + local id, whatsit + if type(req) == "string" then + id = new_user_whatsit_id(req, package) + whatsit = newnode(whatsit_t, user_defined_t) + whatsit.user_id = id + elseif req.id == whatsit_t and req.subtype == user_defined_t then + id = req.user_id + whatsit = copynode(req) + if not whatsit_ids[id] then + warning("whatsit id \@percentchar d unregistered; " + .. "inconsistencies may arise", id) + end + end + return function () return copynode(whatsit) end, id +end +luatexbase.new_user_whatsit = new_user_whatsit +% \end{macrocode} +% +% If one knows the name of a user whatsit, its corresponding id +% can be retrieved by means of \verb|get_user_whatsit_id|. +% +% \begin{macrocode} +local get_user_whatsit_id = function (name, package) + if not package then + package = unassociated + end + return user_whatsits[package][name] +end +luatexbase.get_user_whatsit_id = get_user_whatsit_id +% \end{macrocode} +% +% The inverse lookup is also possible via \verb|get_user_whatsit_name|. +% \begin{macrocode} +local get_user_whatsit_name = function (asked) + local id + if type(asked) == "number" then + id = asked + elseif type(asked) == "function" then + %- node generator + local n = asked() + id = n.user_id + else %- node + id = asked.user_id + end + local metadata = whatsit_ids[id] + if not metadata then % unknown + warning("whatsit id \@percentchar d unregistered; + inconsistencies may arise", id) + return "", "" + end + return tableunpack(metadata) +end +luatexbase.get_user_whatsit_name = get_user_whatsit_name +% \end{macrocode} +% A function that outputs the +% current allocation status to the terminal. +% +% \begin{macrocode} +local dump_registered_whatsits = function (asked_package) + local whatsit_list = { } + if asked_package then + local whatsitdata = user_whatsits[asked_package] + if not whatsitdata then + error("(no user whatsits registered for package + \@percentchar s)", asked_package) + return + end + texiowrite_nl("(user whatsit allocation stats for " .. + asked_package) + for name, id in next, whatsitdata do + whatsit_list[\string#whatsit_list+1] = + stringformat("(\@percentchar s:\@percentchar + s \@percentchar d)", asked_package, name, id) + end + else + texiowrite_nl("(user whatsit allocation stats") + texiowrite_nl(stringformat(" ((total \@percentchar d)\string\n + (anonymous \@percentchar d))", + current_whatsit, anonymous_whatsits)) + for package, whatsitdata in next, user_whatsits do + for name, id in next, whatsitdata do + whatsit_list[\string#whatsit_list+1] = + stringformat("(\@percentchar s:\@percentchar + s \@percentchar d)", package, name, id) + end + end + end + texiowrite_nl" (" + local first = true + for i=1, \string#whatsit_list do + if first then + first = false + else % indent + texiowrite_nl" " + end + texiowrite(whatsit_list[i]) + end + texiowrite"))\string\n" +end +luatexbase.dump_registered_whatsits = dump_registered_whatsits +% \end{macrocode} +% Lastly, we define a couple synonyms for convenience. +% \begin{macrocode} +luatexbase.newattribute = new_attribute +luatexbase.newuserwhatsit = new_user_whatsit +luatexbase.newuserwhatsitid = new_user_whatsit_id +luatexbase.getuserwhatsitid = get_user_whatsit_id +luatexbase.getuserwhatsitname = get_user_whatsit_name +luatexbase.dumpregisteredwhatsits = dump_registered_whatsits +% \end{macrocode} +% +% \begin{macrocode} +} +% +% \end{macrocode} +% +% Resolve name clashes and prefixed name issues. +% +% Top level \textsf{luatexbase} macros +% \begin{macrocode} +\let\newluatexattribute\newattribute +\let\setluatexattribute\setattribute +\let\unsetluatexattribute\unsetattribute +\let\newluatexcatcodetable\newcatcodetable +\let\setluatexcatcodetable\setcatcodetable +% \end{macrocode} +% +% Internal \textsf{luatexbase} macros +% \begin{macrocode} +\let\luatexbase@directlua\directlua +\let\luatexbase@ensure@primitive\@gobble +% \end{macrocode} +% +% Lua\TeX\ primitives +% \begin{macrocode} +\let\luatexattribute\attribute +\let\luatexattributedef\attributedef +\let\luatexcatcodetable\catcodetable +\let\luatexluaescapestring\luaescapestring +\let\luatexlatelua\latelua +\let\luatexoutputbox\outputbox +\let\luatexscantextokens\scantextokens +% \end{macrocode} +% +% Reset catcode of |@|. +% \begin{macrocode} +\catcode`\@=\emuatcatcode\relax +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Legacy \textsf{luatexbase} sub-packages} +% +% The original \textsf{luatexbase} was comprised of seven sub packages +% that could in principle be loaded separately. Here we define them all +% with the same code that just loads the main package, they are +% distinguished just by the |\ProvidesPackage| specified above at the start +% of the file. +% \begin{macrocode} +%<*emu-cmp,emu-mod,emu-loa,emu-reg,emu-att,emu-cct,emu-mcb> +% \end{macrocode} +% +% \begin{macrocode} +\ifx\RequirePackage\undefined + \input{luatexbase.sty}% +\else + \RequirePackage{luatexbase} +\fi +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \subsection{Legacy Lua code} +% +% \changes{v1.2}{2015/10/03}{Provide \texttt{luatexbase.loader.lua}} +% +% The original \textsf{luatexbase} included a file |luatexbase.loader.lua| +% that could be loaded independently of the rest of the package. This really +% doesn't need to do anything! +% \begin{macrocode} +%<*emu-lua> +% \end{macrocode} +% +% \begin{macrocode} +luatexbase = luatexbase or { } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \Finale diff --git a/macros/luatex/generic/luatexbase/luatexbase.ins b/macros/luatex/generic/luatexbase/luatexbase.ins new file mode 100644 index 0000000000..9730a75331 --- /dev/null +++ b/macros/luatex/generic/luatexbase/luatexbase.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\nopreamble +\nopostamble + +\askforoverwritefalse + +\generate{\file{luatexbase.sty}{\from{luatexbase.dtx}{sty,emu,whatsit}}} +\generate{\file{luatexbase-compat.sty}{\from{luatexbase.dtx}{sty,emu-cmp}}} +\generate{\file{luatexbase-modutils.sty}{\from{luatexbase.dtx}{sty,emu-mod}}} +\generate{\file{luatexbase-loader.sty}{\from{luatexbase.dtx}{sty,emu-loa}}} +\generate{\file{luatexbase-regs.sty}{\from{luatexbase.dtx}{sty,emu-reg}}} +\generate{\file{luatexbase-attr.sty}{\from{luatexbase.dtx}{sty,emu-att}}} +\generate{\file{luatexbase-cctb.sty}{\from{luatexbase.dtx}{sty,emu-cct}}} +\generate{\file{luatexbase-mcb.sty}{\from{luatexbase.dtx}{sty,emu-mcb}}} + +\generate{\file{luatexbase.loader.lua}{\from{luatexbase.dtx}{emu-lua}}} + +\endbatchfile diff --git a/macros/luatex/generic/luatexbase/luatexbase.pdf b/macros/luatex/generic/luatexbase/luatexbase.pdf new file mode 100644 index 0000000000..71626c1873 Binary files /dev/null and b/macros/luatex/generic/luatexbase/luatexbase.pdf differ -- cgit v1.2.3