% \iffalse meta-comment % %% File: l3alloc.dtx % % Copyright (C) 1990-2012,2014-2020 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} % % \fi % % \title{^^A % The \pkg{l3alloc} package\\ Register allocation^^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 2020-06-18} % % \maketitle % % \begin{documentation} % % This module provides the basic mechanism for allocating \TeX{}'s % registers when operating in format mode. When loaded as a package on % an existing format, the mechanisms from the latter are used. % % The approach used here is informed by the mechanisms used in plain % \TeX{}/\LaTeX{} but noting that newer engines provide us much more % flexibility. In addition to this, we do not need allocators for all % register types: for example \texttt{toks} are not used by \LaTeX3 whilst % reads/writes are handled using a pool and thus do not need a classical % allocator. % % In classical (non-\LuaTeX{}) engines, there are various restriction on % registers, for example |\box255| is hard-coded as the output box and % inserts have to be allocated below this (not in the extended pool). Rather % than worry about this, allocations for the registers affected (\TeX{} % |box|, |count|, |dimen| and |skip| types) are simply made only from the % extended pool. (There is a performance impact in engines other than % \LuaTeX{} but the free use of registers in \pkg{expl3} means that code % cannot be sure of obtaining a low-numbered register in any case.) % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3alloc} implementation} % % \begin{macrocode} %<*initex> % \end{macrocode} % % \begin{macrocode} %<@@=alloc> % \end{macrocode} % % \begin{variable} % { % \g_@@_int_int , % \g_@@_dim_int , % \g_@@_muskip_int , % \g_@@_int_int , % \g_@@_box_int % } % The core register tracking is done using the same raw \TeX{} count % registers as reserved by plain \TeX{} and \LaTeXe{}, as there may be the % odd piece of generic code that needs to work by number. However, as not % all of our variables work the same way, some of the older registers are % simply ignored. For the same reason, there is no special status for the % low-numbers registers other than counts. To avoid having to worry about % inserts and reflecting the register availability in \eTeX{}, the lower % register space is unused here (though is available for hard-coded % use). % \begin{macrocode} \tex_countdef:D \g_@@_int_int = 10 ~ \tex_countdef:D \g_@@_dim_int = 11 ~ \tex_countdef:D \g_@@_skip_int = 12 ~ \tex_countdef:D \g_@@_muskip_int = 13 ~ \tex_countdef:D \g_@@_box_int = 14 ~ \g_@@_int_int = 255 ~ \g_@@_dim_int = 255 ~ \g_@@_skip_int = 255 ~ \g_@@_muskip_int = 0 ~ \g_@@_box_int = 255 ~ % \end{macrocode} % \end{variable} % % \begin{variable} % { % \g_@@_attribute_int , % \g_@@_bytecode_int , % \g_@@_chunkname_int , % \g_@@_whatsit_int % } % To allow \LuaTeX{} to load |ltluatex.lua| for generic \Lua{} support, a % small number of counts have to be correctly named at the \TeX{} level. % At present there are no \pkg{expl3} allocators for these concepts so the % names and numbers of the tracking variables may change. % \begin{macrocode} \tex_ifdefined:D \tex_luatexversion:D \tex_global:D \tex_countdef:D \g_@@_attribute_int = 21 ~ \tex_global:D \tex_countdef:D \g_@@_bytecode_int = 22 ~ \tex_global:D \tex_countdef:D \g_@@_chunkname_int = 23 ~ \tex_global:D \tex_countdef:D \g_@@_whatsit_int = 24 ~ \tex_fi:D % \end{macrocode} % \end{variable} % % \begin{macro} % {\box_new:N, \dim_new:N, \int_new:N, \muskip_new:N \skip_new:N} % Each of the public allocators is a wrapper around the one internal % function needed here. % \begin{macrocode} \cs_new_protected:Npx \box_new:N #1 { \exp_not:N \@@_reg:nNnN { box } \cs_if_exist:NTF \tex_luatexversion:D { \tex_chardef:D } { \cs_if_exist:NTF \tex_omathchardef:D { \tex_omathchardef:D } { \tex_mathchardef:D } } \c_max_register_int #1 } \cs_new_protected:Npn \dim_new:N #1 { \@@_reg:nNnN { dim } \tex_dimendef:D \c_max_register_int #1 } \cs_new_protected:Npn \int_new:N #1 { \@@_reg:nNnN { int } \tex_countdef:D \c_max_register_int #1 } \cs_new_protected:Npn \muskip_new:N #1 { \@@_reg:nNnN { muskip } \tex_muskipdef:D \c_max_register_int #1 } \cs_new_protected:Npn \skip_new:N #1 { \@@_reg:nNnN { skip } \tex_skipdef:D \c_max_register_int #1 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_reg:nNNN} % The allocator itself is modelled somewhat on \LaTeXe{}'s \tn{e@alloc}, % though there is no need to set \tn{allocationnumber}. % \begin{macrocode} \cs_new_protected:Npn \@@_reg:nNnN #1#2#3#4 { \__kernel_chk_if_free_cs:N #4 \int_compare:nNnTF { \int_use:c { g_@@_ #1 _int } } < {#3} { \int_gincr:c { g_@@_ #1 _int } \tex_global:D #2 #4 \int_use:c { g_@@_ #1 _int } \iow_log:x { \token_to_str:N #4 ~=~ #1 ~register~ \int_use:c { g_@@_ #1 _int } } } { \__kernel_msg_fatal:nnx { kernel } { out-of-registers } {#1} } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex