% \iffalse
%% File: l3alloc.dtx Copyright (C) 1990-2006,2009 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 ``expl3 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 LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver>
\RequirePackage{l3names}
%</driver>
%\fi
\GetIdInfo$Id: l3alloc.dtx 2063 2010-10-03 08:26:49Z mittelba $
       {L3 Experimental register allocation}%
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{\filename.\filenameext}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3alloc} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Allocating registers and the like}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
% \begin{documentation}
%
% \section{Allocating registers and the like}
%
%    Note that this module is only used for generating an pkg{expl3}-based
%    format. Under \LaTeXe, the |etex.sty| 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
%      |\tex_language:D| 0-255),
%    \item \TeX\ can load no more than 16 math families,
%    \item \TeX\ supports no more than 16 io-streams for reading
%      (|\tex_read:D|) and 16 io-streams for writing (|\tex_write:D|),
%    \item \TeX\ supports no more than 256 inserts, Omega supports more.
%    \item The other registers (|\tex_count:D|, |\tex_dimen:D|,
%      |\tex_skip:D|, |\tex_muskip:D|, |\tex_box:D|, and |\tex_toks:D|
%      range from 0 to 32768, but registers numbered above 255 are
%      accessed somewhat less efficiently.
%    \item Registers could be allocated both globally and locally; the
%      use of registers could also be globaly or locally. Here we
%      provide support for globally allocated registers for both
%      gloabl and local use and for locally allocated registers for
%      local use only.
%    \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{Functions}
%
%
% \begin{function}{\alloc_new:nnnN}
% \begin{syntax}
% "\alloc_new:nnnN" \Arg{type} \Arg{min} \Arg{max} <alloc_cmd>
% \end{syntax}
% Shorthand for allocating new registers. Defines \cs{<type>_new:N} and
% \cs{<type>_new_local:N} allocators of the specified <type>, indexed up from
% <min> for global registers and down from <max> for local registers, with
% registers assigned using the function <alloc_cmd>.
%
% Internally uses "\alloc_setup_type:nnn" and "\alloc_reg:NnNN"
% defined below in case you want finer-grained control.
% \end{function}
%
%
%  \begin{function}{\alloc_setup_type:nnn}
%    \begin{syntax}
%      "\alloc_setup_type:nnn" \Arg{type} \Arg{g_start_num} \Arg{l_start_num}
%    \end{syntax}
%    Sets up the storage needed for the administration of registers of
%    type <type>.\\
%    <type> should be a token list in braces, it can be one of
%    "int", "dimen", "skip", "muskip", "box", "toks", "ior", "iow",
%    "pattern", or "ins".\\
%    <g_start_num> is the number of the first non-allocated global
%    register, it will be incremented by 1 when the allocation is done.
%    <l_start_num> is the number of the first non-allocated local
%    register, it will be decremented by 1 when the allocation is done.
%  \end{function}
%
%  \begin{function}{\alloc_reg:NnNN}
%    \begin{syntax}
%    "\alloc_reg:NnNN" "g"$\big/$"l" <type> <alloc_cmd> <cs>
%    \end{syntax}
%    Performs the allocation of a register of type <type> to control
%    sequence <cs>, using the command <alloc_cmd>. The "g" or "l"
%    indicates whether the allocation should be global or local.
%    This macro is the basic building block for the definition of the
%    "\"<type>"_new:N" commands
%  \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3alloc} implementation}
%
% \subsection{Internal functions}
%
% \begin{function}{ \alloc_next:Nn }
% \begin{syntax}
% "\alloc_next:Nn" "l"/"g" \Arg{type}
% \end{syntax}
% These functions find the next free register for the specified type.
% \end{function}
%
% \subsection{Module code}
%
%    \begin{macrocode}
%<*initex>
%    \end{macrocode}
%
%  \begin{macro}{\alloc_setup_type:nnn}
%    For each type of register we need to `counters' that hold the
%    last allocated global or local register. We also need a sequence
%    to store the `exceptions'.
%    \begin{macrocode}
\cs_new_nopar:Npn \alloc_setup_type:nnn #1#2#3 {
  \seq_new:c {g_#1_allocation_seq}
  \tl_new:cn {g_#1_allocation_tl } {#2}
  \tl_new:cn {l_#1_allocation_tl } {#3}
}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\alloc_next:Nn}
% This routine finds the next free register. For globally allocated
% registers we first increment the counter that keeps track of them;
% for local registers, decrement.
%    \begin{macrocode}
\cs_new_nopar:Npn \alloc_next:Nn #1#2 {
  \tl_set:cx {#1_#2_allocation_tl}
    {
      \int_eval:n
        {
          \tl_use:c {#1_#2_allocation_tl}
          \if:w #1 g + \else: - \fi: 1
        }
    }
%    \end{macrocode}
% Then we need to check whether we have run out of registers.
%    \begin{macrocode}
  \int_compare:nNnTF
    { \tl_use:c{g_#2_allocation_tl} } = { \tl_use:c{l_#2_allocation_tl} }
    {
      \iow_term:x {
        We~ ran~ out~ of~
        \if:w #1 g \scan_stop: global~ \else: local~ \fi:
        'l#2!'~ registers!
      }
    }
%    \end{macrocode}
% We also need to check whether the value of the counter already
% occurs in the list of already allocated registers.
%    \begin{macrocode}
    {
      \seq_if_in:cxTF {g_#2_allocation_seq} {\tl_use:c{#1_#2_allocation_tl}}
        {
          \iow_log:x{ \tl_use:c{#1_#2_allocation_tl}~already~allocated. }
          \alloc_next:Nn #1 {#2}
        }
%    \end{macrocode}
% By now the |.._allocation_tl| counter will contain the number of
% the register we will assign a control sequence for.
%    \begin{macrocode}
        { \iow_log:x{\tl_use:c{#1_#2_allocation_tl}~free.} }
    }
}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\alloc_reg:NnNN}
%  This internal macro performs the actual allocation. Its first
%  argument is either `|g|' for a globally allocated register or `|l|'
%  for a locally allocated register. The second argument is the
%  type of register to allocate, the third argument is the command
%  to use and the fourth argument is the control sequence that is to
%  be defined to point to the register.
%    \begin{macrocode}
\cs_new_nopar:Npn \alloc_reg:NnNN #1#2#3#4 {
  \chk_if_free_cs:N #4
  \if:w #1 g
    \exp_after:wN \pref_global:D
  \fi:
  #3 #4 \tl_use:c{#1_ #2 _allocation_tl}
  %%\cs_record_meaning:N#1
  \iow_log:x{
    \token_to_str:N#4~=~#2~register~\tl_use:c{#1_#2_allocation_tl}
  }
  \alloc_next:Nn #1 {#2}
 }
%    \end{macrocode}
%  \end{macro}
%
%
% \begin{macro}{\alloc_new:nnnN}
% Shorthand for defining new register types and their allocators:
%    \begin{macrocode}
\cs_new:Npn \alloc_new:nnnN #1#2#3#4 {
  \alloc_setup_type:nnn {#1} {#2} {#3}
  \cs_new_nopar:cpn {#1_new:N} ##1 {
    \alloc_reg:NnNN g {#1} #4 ##1
  }
  \cs_new_nopar:cpn {#1_new_local:N} ##1 {
    \alloc_reg:NnNN l {#1} #4 ##1
  }
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</initex>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
% \PrintIndex
%
% \endinput
