% \iffalse meta-comment
%
%% File: l3alloc.dtx Copyright (C) 1990-2012,2014 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
%%
%%    http://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 released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX3 Project.
%%
%% -----------------------------------------------------------------------
%
%<*driver>
\documentclass[full]{l3doc}
\GetIdInfo$Id: l3alloc.dtx 5363 2014-08-24 19:57:56Z joseph $
  {L3 Register allocation}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3alloc} package\\ Register allocation^^A
%   \thanks{This file describes v\ExplFileVersion,
%      last revised \ExplFileDate.}^^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 \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
%  Note that this module is only used for generating an \pkg{expl3}-based
%  format. Under \LaTeX{}, the \pkg{etex} package is used for allocation
%  management.
%
%  This module provides the basic mechanism for allocating \TeX{}'s
%  registers. While designing this we have to take into account the
%  following characteristics:
%  \begin{itemize}
%    \item |\box255| is reserved for use in the output routine, so it
%      should not be allocated otherwise.
%    \item \TeX{} can load up $256$ hyphenation patterns (registers
%      \tn{language} $0$ to $255$),
%    \item \TeX{} can load no more than $16$ math families,
%    \item \TeX{} supports no more than $16$ I/O streams for reading
%      (\tn{read}) and $16$ I/O streams for writing (\tn{write}),
%    \item \TeX{} supports no more than $256$ inserts.
%    \item The other registers (\tn{count}, \tn{dimen}, \tn{skip},
%      \tn{muskip}, \tn{box}, and \tn{toks}) range from $0$ to $32\,767$
%      ($65\,535$ for \LuaTeX{}), but registers numbered above $255$ are
%      accessed somewhat less efficiently (except in \LuaTeX{}, where access
%      is \enquote[flat}).
%    \item Registers could be allocated both globally and locally; the
%      use of registers could also be global or local. Here we
%      provide support for globally allocated registers for both
%      global and local use.
%  \end{itemize}
%  We also need to allow for some bookkeeping: we need to know which
%  register was allocated last and which registers can not be
%  allocated by the standard mechanisms.
%
% \section{Internal functions}
%
% Register-based allocation is a low-level process, and is therefore
% only to be used as part of kernel code.
%
% \begin{function}[updated = 2012-11-09]{\__alloc_new:nnnN}
%   \begin{syntax}
%     \cs{__alloc_new:nnnN} \Arg{type} \Arg{min} \Arg{max} \meta{function}
%   \end{syntax}
%   Shorthand for allocating new registers. Defines \cs{\meta{type}_new:N} as
%   and allocator function of the specified \meta{type}, indexed up from
%   \meta{min} to a \meta{max}, and with assignment carried out by
%   the \meta{function}. This process will create two token lists,
%   \cs{g_\meta{type}_allocation_tl} and \cs{c_\meta{type}_allocation_max_tl},
%   to store the current and maximum allocation numbers, respectively.
% \end{function}
%
%  \begin{function}[updated = 2011-09-05]{\__alloc_setup_type:nnn}
%    \begin{syntax}
%      \cs{__alloc_setup_type:nnn} \Arg{type} \Arg{min} \Arg{max}
%    \end{syntax}
%    Sets up the storage needed for the administration of registers of
%    \Arg{type}, which will start allocating at \meta{min} and will issue
%    an error if there is an attempt to allocate past the \meta{max}.
%  \end{function}
%
%  \begin{function}{\__alloc_reg:nNN}
%    \begin{syntax}
%      \cs{__alloc_reg:nNN} \Arg{type} \meta{function} \meta{register}
%    \end{syntax}
%    Preforms the allocation for a new \meta{register} of \meta{type},
%    using the allocator \meta{function} (which will be either a
%    primitive \tn{\ldots def} or \tn{chardef}).
%  \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3alloc} implementation}
%
%    \begin{macrocode}
%<*initex>
%    \end{macrocode}
%
%    \begin{macrocode}
%<@@=alloc>
%    \end{macrocode}
%
% \begin{macro}[int]{\@@_new:nnnN}
%   Shorthand for defining new register types and their allocators: creates
%   the appropriate variables and the allocator function itself.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_new:nnnN #1#2#3#4
  {
    \@@_setup_type:nnn {#1} {#2} {#3}
    \cs_new_protected:cpn { #1 _new:N } ##1 { \@@_reg:nNN {#1} #4 ##1 }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int]{\@@_setup_type:nnn}
%   For each type of register we need to \enquote{counters} that hold the
%   last allocated global register, plus a constant for the maximum
%   allocation.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_setup_type:nnn #1#2#3
  {
    \tl_new:c   { g__ #1 _allocation_tl }
    \tl_gset:cx { g__ #1 _allocation_tl } { \int_eval:n {#2} }
    \tl_const:cx { c__ #1 _allocation_max_tl } { \int_eval:n {#3} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\int_eval:n}
%   For bootstrapping purposes, a definition of \cs{int_eval:n} is needed
%   in terms of primitives. This is replaced in \pkg{l3int} with a clearer
%   one.
%    \begin{macrocode}
\cs_new:Npn \int_eval:n #1 { \tex_number:D \etex_numexpr:D #1 \scan_stop: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {\box_new:N, \dim_new:N, \int_new:N, \muskip_new:N \skip_new:N}
%   To get everything to work correctly for inserts, some register types
%   need to have their allocators set up \enquote{early}. It therefore
%   makes sense to collect most of them together here.
%    \begin{macrocode}
\luatex_if_engine:TF
  { \@@_new:nnnN { box } \c_zero \c_max_register_int \tex_chardef:D }
  { \@@_new:nnnN { box } \c_zero \c_max_register_int \tex_mathchardef:D }
\@@_new:nnnN { dim }     \c_zero \c_max_register_int \tex_dimendef:D
\@@_new:nnnN { int }    { 11 }   \c_max_register_int \tex_countdef:D
\@@_new:nnnN { muskip } \c_zero  \c_max_register_int \tex_muskipdef:D
\@@_new:nnnN { skip }   \c_zero  \c_max_register_int \tex_skipdef:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\insert_new:N}
%   For inserts, there is a need to reserve space in various other registers.
%   First, the basic allocation is done.
%    \begin{macrocode}
\@@_new:nnnN { insert } { 221 } { 254 } \tex_chardef:D
%    \end{macrocode}
%   Reserve a gap in the \texttt{box}, \texttt{dim}, \texttt{int} and
%   \texttt{skip} lists. (An inline token list mapping would read better here,
%   but this does not work until \texttt{int} allocation is available!) Note
%   that \texttt{box255} is reserved by \TeX{} itself (\LuaTeX{} does make
%   this alterable, but that doesn't really do much for us so we ignore
%   that!)
%    \begin{macrocode}
\tl_const:Nn \c__box_allocation_reserve_begin_tl  { 221 }
\tl_const:Nn \c__box_allocation_reserve_end_tl    { 255 }
\tl_const:Nn \c__dim_allocation_reserve_begin_tl  { 221 }
\tl_const:Nn \c__dim_allocation_reserve_end_tl    { 254 }
\tl_const:Nn \c__int_allocation_reserve_begin_tl  { 221 }
\tl_const:Nn \c__int_allocation_reserve_end_tl    { 254 }
\tl_const:Nn \c__skip_allocation_reserve_begin_tl { 221 }
\tl_const:Nn \c__skip_allocation_reserve_end_tl   { 254 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int]{\@@_reg:nNN}
%   This internal macro performs the actual allocation.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_reg:nNN #1#2#3
  {
    \__chk_if_free_cs:N #3
    \int_compare:nNnTF
      { \tl_use:c { g__ #1 _allocation_tl } }
      > { \tl_use:c { c__ #1 _allocation_max_tl } }
      { \__msg_kernel_fatal:nnx { kernel } { out-of-registers } {#1} }
      {
        \tex_global:D #2 #3 \tl_use:c { g__ #1 _allocation_tl } \scan_stop:
        \iow_log:x
          {
            \token_to_str:N #3 ~=~ #1 ~register~
            \tl_use:c { g__ #1 _allocation_tl }
          }
        \@@_next:n {#1}
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_next:n}
%   Set up the next allocation by adding one to the current number, and if
%   necessary skipping over a reserved block.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_next:n #1
  {
    \tl_gset:cx { g__ #1 _allocation_tl }
      {
        \int_eval:n
          {
            \tl_if_exist:cTF { c__ #1 _allocation_reserve_begin_tl }
              {
                \int_compare:nNnTF
                  { \tl_use:c { g__ #1 _allocation_tl } + \c_one }
                  =
                  { \tl_use:c { c__ #1 _allocation_reserve_begin_tl } }
                  { \tl_use:c { c__ #1 _allocation_reserve_end_tl } }
                  { \tl_use:c { g__ #1 _allocation_tl } }
              }
              { \tl_use:c { g__ #1 _allocation_tl } }
            + \c_one
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</initex>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
