% \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|package> \RequirePackage{l3names} % %\fi \GetIdInfo$Id: l3alloc.dtx 1362 2009-05-28 20:19:21Z joseph $ {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} % % \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} % % 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_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 .\\ % should be a token list in braces, it can be one of % "int", "dimen", "skip", "muskip", "box", "toks", "ior", "iow", % "pattern", or "ins".\\ % is the number of the first non-allocated global % register, it will be incremented by 1 when the allocation is done. % 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" % \end{syntax} % Performs the allocation of a register of type to control % sequence , using the command . 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 % "\""_new:N" commands % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3alloc} implementation} % % \subsection{Internal functions} % % \begin{function}{ \alloc_next_g:n | % \alloc_next_l:n } % \begin{syntax} % "\alloc_next_g:n" \Arg{type} % \end{syntax} % These functions find the next free register for the specified type. % \end{function} % % \subsection{Module code} % % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \package_check_loaded_expl: % %<*initex|package> % \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{ \num_new:c {g_ #1 _allocation_num} \num_new:c {l_ #1 _allocation_num} \seq_new:c {g_ #1 _allocation_seq} \num_set:cn {g_ #1 _allocation_num}{#2} \num_set:cn {l_ #1 _allocation_num}{#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\alloc_next_g:n} % \begin{macro}{\alloc_next_l:n} % These routines find the next free register. For globally allocated % registers we first increment the counter that keeps track of them. % \begin{macrocode} \cs_new_nopar:Npn \alloc_next_g:n #1 { \num_gincr:c {g_ #1 _allocation_num} % \end{macrocode} % Then we need to check whether we have run out of registers. % \begin{macrocode} \intexpr_compare:nTF { \num_use:c{g_ #1 _allocation_num} = \num_use:c{l_ #1 _allocation_num} } {\iow_term:x{We~ ran~ out~ of~ registers~ of~ type~ g_#1!}} { % \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:cxT {g_ #1 _allocation_seq} {\num_use:c{g_ #1 _allocation_num}} % \end{macrocode} % If it does, we find the next value. % \begin{macrocode} { \iow_term:x{\num_use:c{g_ #1 _allocation_num}~already~allocated!} \alloc_next_g:n {#1} } } % \end{macrocode} % By now the |.._allocation_num| counter will contain the number of % the register we will assign a control seuence for. % \begin{macrocode} } % \end{macrocode} % For the locally allocated registers we have a similar function. % \begin{macrocode} \cs_new_nopar:Npn \alloc_next_l:n #1 { \num_gdecr:c {l_ #1 _allocation_num} % \end{macrocode} % (Will: should that be "\num_decr" (no "g") ?!) % \begin{macrocode} \intexpr_compare:nTF { \num_use:c{g_ #1 _allocation_num} = \num_use:c{l_ #1 _allocation_num} } {\iow_term:x{We~ ran~ out~ of~ registers~ of~ type~ l_#1!}} { \seq_if_in:cxTF {g_ #1 _allocation_seq} {\num_use:c{l_ #1 _allocation_num}} { \iow_term:x{\num_use:c{l_ #1 _allocation_num}~already~allocated!} \alloc_next_l:n {#1} } { \iow_term:x{\num_use:c{l_ #1 _allocation_num}~free!} } } } % \end{macrocode} % \end{macro} % \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{ % \end{macrocode} % It first checks that the control sequence that is to denote the % register does not already exist. % \begin{macrocode} \chk_if_free_cs:N #4 % \end{macrocode} % Next, it decides whether a prefix is needed for the allocation % command; % \begin{macrocode} \if:w #1 g \exp_after:wN \pref_global:D \fi: % \end{macrocode} % And finally the actual allocation takes place. % \begin{macrocode} #3 #4 \num_use:c{#1_ #2 _allocation_num} %%\cs_record_meaning:N#1 % \end{macrocode} % All that's left to do is write a message in the log file. % \begin{macrocode} \iow_log:x{ \token_to_str:N#4=#2~register~\num_use:c{#1_ #2 _allocation_num}} % \end{macrocode} % Finally, it calls |\alloc_next_|\meta{\texttt{\textup g}/\texttt{\textup l}} to find the next free register % number. % \begin{macrocode} \use:c{alloc_next_#1:n} {#2} } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % % \end{implementation} % \PrintIndex % % \endinput