% \iffalse % % Package `localloc' to use with LaTeX 2e/2.09 and plain-TeX % Copyright (C) 1991,1994,1995 Bernd Raichle. All rights reserved. % % % Copying of this file is authorized only if either % (1) you make absolutely no changes to your copy, including name, or % (2) if you do make changes, you name it something other than % localloc.dtx, localloc.doc, localloc.tex, or localloc.sty. % This restriction helps ensure that all styles developed here % remain identical. % % Error reports in case of UNCHANGED versions please to: % Bernd Raichle % Stettener Str. 73 % D-73732 Esslingen % Federal Republic of Germany % Email: raichle@Informatik.Uni-Stuttgart.DE % % % ========== INSTALLATION GUIDE: ========== % % The complete distribution consists of a set of files, which are % packed and documented in _one_ `docstrip archive file' called % `localloc.dtx' (the file you are currently reading). This archive % file can be unpacked to create the necessary files containing the % macros, documentation, etc. % % To unpack the archive file you need: % % * `localloc.dtx' (it is the file you are currently reading) % % * `docstrip.tex' version 2.x or newer % (You can find this file in the LaTeX 2e release.) % % Then run `localloc.dtx' through plainTeX or LaTeX to unpack the % archive file: % % tex localloc.dtx % or % latex localloc.dtx % % This will create a set of file which contain the macro code or % code to produce the documentation of the `localloc' package. % % --------------- start of docstrip archive file ------------------ % \fi % % \CheckSum{369} % % \iffalse %<*install> \def\batchfile{localloc.dtx} \input docstrip.tex \preamble This is a file of the `localloc' package reimplementing plain-TeX's and LaTeX's basic allocation macros to allow local allocation of registers. -- Copyright (C) 1991-1995 Bernd Raichle. All rights reserved -- This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. IMPORTANT NOTICE: Copying of this file is authorized only if either (1) you make absolutely no changes to your copy, including name, or (2) if you do make changes, you name it something other than localloc.dtx, localloc.doc, localloc.tex, or localloc.sty. For error reports see original source file `localloc.dtx'. \endpreamble %\generateFile{localloc.ins}{t}{\from{localloc.dtx}{install}} \generateFile{localloc.sty}{t}{\from{localloc.dtx}{package}} \generateFile{localloc.drv}{t}{\from{localloc.dtx}{driver}} \generateFile{localtst.tex}{t}{\from{localloc.dtx}{test}} \Msg{***********************************************************} \Msg{*} \Msg{* To finish the installation you have to move the following} \Msg{* file into a directory searched by TeX:} \Msg{*} \Msg{* \space\space localloc.sty} \Msg{*} \Msg{* To produce the documentation of this archive file run the} \Msg{* file `localloc.drv' through LaTeX 2e:} \Msg{*} \Msg{* \space\space latex localloc.drv} \Msg{*} \Msg{* Happy TeXing} \Msg{***********************************************************} \relax\endinput % % \fi % % \changes{v1.1b}{95/09/24}{Released after a long sleep in my % archives; prefixed some tokens with \cs{lcllc@}.} % \changes{v1.1a}{94/10/16}{English documentation; added support for % \LaTeXe; added self unpacking archive code.} % \changes{v1.0b}{91/09/06}{Error in \cs{newinsert}: consecutive calls % return the same insertion register number.} % \changes{v1.0a}{91/09/04}{All macros in {plain.tex} replaced.} % % \DoNotIndex{\fileversion,\filedate,\docdate,\filename} % \DoNotIndex{\begingroup,\endgroup,\def,\relax} % \DoNotIndex{\ifnum,\ifcase,\else,\fi} % \DoNotIndex{\expandafter,\the} % \DoNotIndex{\@ne,\m@ne,\next} % % % \newcommand{\PiCTeX}{\protect\pPiCTeX} % \newcommand{\pPiCTeX}{\relax % P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC\kern-.11em\TeX} % % % \title{An Enhanced Implementation of the Allocation Macros in \LaTeXe, % \LaTeX~2.09, and plain-\TeX} % \date{\filedate~(\fileversion)} % \author{Bernd Raichle\\ % Stettener Str.~73\\ % D-73732 Esslingen, FRG\\ % Email: {\tt raichle@Informatik.Uni-Stuttgart.DE}} % % \maketitle % % \begin{abstract} % This style option reimplements the allocation command macros % provided by plain-\TeX\ and adds macros to allow allocation % of local registers inside groups. % \end{abstract} % %^^A \tableofcontents % % \section{Introduction} % % \subsection{Restrictions of {\tt plain.tex}'s Register Allocation Macros} % % In {\tt plain.tex}, Donald E.\ Knuth writes about the macros for % register allocation~\cite[lines 149ff]{plain.tex-3.14159}: % \begin{quote} % When a register is used only temporarily, it need not be % allocated; grouping can be used, making the value previously in % the register return after the close of the group. The main use % of these macros is for registers that are defined by one macro % and used by others, possibly at different nesting levels. All % such registers should be defined through these macros; otherwise % conflicts may occur, especially when two or more more macro % packages are being used at once. % \end{quote} % Additional remarks can be read in the TeXbook~\cite[p.~346]{DEK91}: % \begin{quote} % {\it Allocation of registers.\/} The second major part of the % {\tt plain.tex} file provides a foundation on which systems of % independently developed macros can coexist peacefully without % interfering in their usage of registers. The idea is that macro % writers should abide by the macro conventions following ground % rules: [\ldots] % (4)~Furthermore, it's possible to use any register in a group, if % you ensure that \TeX's grouping mechanism will restore the % register when you're done with the group, and if you are certain % that other macros will not make global assignments to that % register when you need it. \ % (5)~But when a register is used by several macros, or over long % spans of time, it should be allocated by \verb+\newcount+, % \verb+\newdimen+, \verb+\newbox+, etc. \ (6)~Similar remarks apply % [\ldots] % to insertions (which require \verb+\box+, \verb+\count+, % \verb+\dimen+, and \verb+\skip+ registers all having the same % number). % \end{quote} % % This means, that within plain-\TeX\ and all formats based on % plain-\TeX\ a user can not allocate a register for temporary use % using the given mechanisms. Nonetheless there is often the need % for a allocated register which is only used within a rather small % piece of document text and should be set free for reuse in the rest % of the formatting run: % % If a macro~\verb+\macroa+ needs a register which should never be % destroyed by another macro~\verb+\macrob+ which is called by % \verb+\macroa+, you either have to know about the realisation of % \verb+\macrob+ or you have to allocate a new register. % % The name of this newly allocated register is only known to the % macro package in which macro~\verb+\macroa+ resides. If you have % a lot of macros which needs registers by their own it is possible % that all of the 256~registers of one type will be allocated. In % most cases it would be possible to share some of these registers by % more than one macro because the register is only needed within (an % environment delimited by) a group. To share registers---if they are % used only locally---it will be necessary to provide a mechanism to % allocate registers locally. Unfortunately {\tt plain.tex} and all % derived formats, like \LaTeX, misses this mechanism leading to the % problem that some macro packages cannot be combined. % % In the following example it is necessary to call two macros % |\macroa| and |macrob| in the same group (e.g.\ because |\macroa| % performs special actions at the begin and |\macrob| at the end of % an environment). Further you do not have any knowledge about the % use of scratch register in |\macroa|, |\macrob| or the text in the % argument specified by the user. Therefore it is impossible to use % a scratch register to save the current value of |\hsize|; we have % to allocate a new register to save it. %\begin{verbatim} % \newdimen\savedhsize %\end{verbatim} %\begin{verbatim} % \def\callAandB#1{\begingroup % \savedhsize=\hsize % \hsize=0.8\hsize \macroa % #1\relax % \hsize=\savedhsize \macrob % \endgroup} %\end{verbatim} % If there will be a mechanism, e.g. by a macro |\lnewdimen|, to % allocate a local register it is possible to use this local register % inside the group without worrying about possible dependencies % between the macros and the user specified text. Additionally after % leaving the group, the dimen register will be free to be used by % other macros. %\begin{verbatim} % \def\callAandB#1{\begingroup % \lnewdimen\savedhsize \savedhsize=\hsize % \hsize=0.8\hsize \macroa % #1\relax % \hsize=\savedhsize \macrob % \endgroup} %\end{verbatim} % % % \subsection{Local Register Allocation Macros} % % \DescribeMacro{\newcount} % \DescribeMacro{\newdimen} % \DescribeMacro{\newskip} % \DescribeMacro{\newbox} % {\let\newinsert=\relax \DescribeMacro{\newinsert}}^^A % When using this reimplementation of the allocation macros, the {\tt % plain.tex} macros |\newcount|, |\newdimen|, |\newskip|, and % |\newbox| will have a changed behaviour in two aspects: % \begin{itemize} % \item Do not assume that registers which are allocated consecutively % have consecutive register numbers. In general you should not % make any assumption about the order of register numbers. % \item It is possible that a register was locally allocated and used % in the past. After leaving the group the register is set to free % and the old value---normally zero---is restored. Nonetheless % you should not assume that a newly allocated register is % initialised with the value zero. % \end{itemize} % % {\let\newmuskip=\relax \DescribeMacro{\newmuskip}} % {\let\newtoks=\relax \DescribeMacro{\newtoks}}^^A % The behaviour of the macros |\newmuskip| and |\newtoks| are not % changed because they are not used for insertions. Nonetheless this % can be changed in a future version. % % \DescribeMacro{\lnewcount} % \DescribeMacro{\lnewdimen} % \DescribeMacro{\lnewskip} % \DescribeMacro{\lnewmuskip} % \DescribeMacro{\lnewbox} % \DescribeMacro{\lnewtoks} % |\lnewcount|, |\lnewdimen|, |\lnewskip|, |\lnewmuskip|, |\lnewbox|, % and |\lnewtoks| are the set of new macros to allocate registers % within the scope of the current group. At the end of the current % group the allocated register is freed. % % As with their global counterparts you should not assume that the % registers are allocated in a consecutive order---neither increasing % nor decreasing---or that the allocated register is initialised with % zero. % % % \subsection{Usage Examples} % % \subsubsection{\LaTeX's Picture Environment} % % \LaTeX's picture environment uses the box register |\@picbox| and % the dimen register |\@picht| to save the contents of a picture and % the user specified height of this picture at the beginning of the % environment. These two registers are set at the beginning and used % at the end of the |picture| environment. Because the two registers % are used nowhere else, it is possible to share them by only % allocating them within the environment. % % This is the simplified code for the |\begin{picture}| and % |\end{picture}| commands; the macros |\begin| and |\end| start and % end a new group: %\begin{verbatim} %\newbox\@picbox %\newdimen\@picht %\end{verbatim} %\begin{verbatim} %\def\picture(#1,#2){% % \@picht = #2\unitlength % save picture height % \setbox\@picbox = \hbox to #1\unitlength\bgroup % \ignorespaces} %\end{verbatim} %\begin{verbatim} %\def\endpicture{% % \hss % \egroup % close picture box % \ht\@picbox = \@picht % set box height to save picture height % \dp\@picbox = 0pt % set box depth to 0pt % \mbox{\box\@picbox}} % output this box %\end{verbatim} % % Using the new local allocation macros the code changes is simple: % Move the |\newbox| and |\newdimen| command within the |\picture| % macro definition and rename them to |\lnewbox| and |\lnewdimen|: %\begin{verbatim} % %\newbox\@picbox % %\newdimen\@picht %\end{verbatim} %\begin{verbatim} %\def\picture(#1,#2){% % \lnewbox\@picbox % \lnewdimen\@picht % \@picht = #2\unitlength % save picture height % \setbox\@picbox = \hbox to #1\unitlength\bgroup % \ignorespaces} %\end{verbatim} % % Additionally we can use a property of the usage pattern of these % two registers: % Within a nested use of the |picture| environment---you can use % subpictures within a picture---these registers are allocated for % each nesting level. This is not really necessary because the box % and the dimen register is always used in a group and is never % changed globally. % It is possible to add tests to avoid a (local) reallocation of % these registers: %\begin{verbatim} %\let\@picbox=\relax % mark register as not yet allocated %\let\@picht =\relax % mark register as not yet allocated %\end{verbatim} %\begin{verbatim} %\def\picture(#1,#2){% % \ifx\@picbox\relax \lnewbox\@picbox \fi % \ifx\@picht\relax \lnewdimen\@picht \fi % \@picht = #2\unitlength % save picture height % \setbox\@picbox = \hbox to #1\unitlength\bgroup % \ignorespaces} %\end{verbatim} % % % \subsubsection{\LaTeX's {\tt\protect\bslash multiput} Macro} % % Another example of registers which are used only in one rarely % used macro, are the count register |\@multicnt| and the two dimen % registers |\@xdim| and |\@ydim| for the |\multiput| command. To % change it according to the scheme above you have to insert an % additional grouping. % % In \LaTeXe\ these three rarely used registers and some more are % shared with the |\bezier| command, whose definition has to be % changed accordingly. This shows the need---and advantage---of a % better allocation scheme. % % \subsubsection{\PiCTeX} % % The macro package \PiCTeX\ uses a lot of dimen registers. A subset % of these registers are only used within a picture or within a set % of drawing and parameter setting commands. % % As an example the dimen registers |\totalarclength| is only used in % a very restrictic set of commands, i.e., it can be allocated within % the scope of the higher level commands or within \PiCTeX's % |\beginpicture| \ldots\ |\endpicture| environment. % % % \StopEventually{^^A % \begin{thebibliography}{0} % \bibitem{DEK91} Donald E.\ Knuth, % {\it The \TeX{}book}, % Addison-Wesley Publ., Reading, Mass., Juni 1991. % \bibitem{plain.tex-3.14159} File {\tt plain.tex}, % version 3.14159, % March 1995. % \end{thebibliography} % } % % % % \section{Implementation} % % % \subsection{Prolog, \LaTeXe\ Package Declarations, etc.} % % The very first thing we do is to ensure that this file is not % read in twice. To this end we check whether the macro % |\lnewcount| is defined. If so, we just stop reading this file. % \begin{macrocode} %<+package>\expandafter\ifx\csname lnewcount\endcsname\relax %<+package>\else \expandafter\endinput \fi % \end{macrocode} % % For the sake of \LaTeXe\ users declarations for this package are % included. The additional group hack is needed to prevent the % definition of |\ProvidesPackage| as |\relax| if it is undefined. % \begin{macrocode} %<+package|test>\begingroup\expandafter\expandafter\expandafter\endgroup %<+package|test>\expandafter\ifx\csname ProvidesPackage\endcsname\relax %<+package|test>\else \NeedsTeXFormat{LaTeX2e} %<+package> \ProvidesPackage{localloc}% %<+test> \ProvidesFile{localtst.tex}% %<*!package&!test> \ProvidesFile{localloc.dtx}% % [1995/09/24 v1.1b % Additional LaTeX Kernel Macros (local allocation)] %<+package|test>\fi % \end{macrocode} % % \begin{macrocode} %<*package> % \end{macrocode} % % To allow the use of this file within a plain-\TeX\ job, we have % to change the category code of the `at' character~{\tt @}. % \begin{macrocode} \expandafter\chardef\csname lcllc@at\endcsname=\catcode`\@ \catcode`\@=11 % \makeatletter % \end{macrocode} % % % \subsection{Accessing the {\tt muskip} registers} % % Beside the well-known \TeX\ registers, like |\count| or |\box|, % there is another set of registers which are used only in few % macros. The |\muskip| registers are normally used in math mode % only and the coercion of the value in a |\muskip| register to an % integer (|\count|), dimension (|\dimen|), or glue (|\glue|) % produces an error. % % The unit of a |\muskip| value is~$1$\,mu---there are $18$\,mu in % $1$\,em of the current font in {\em math family~2}. If you % assign a value to a |\muskip| register, this value is represented % in the unit~mu, not in~pt. The dimension of the |\muskip| value % is computed, if this value is used by |\mskip| or |\mkern|. % % To use a |\muskip| register as a replacement for a |\count| % register, it is necessary to do assignments, additions, and other % operations in units of~mu. If you want to coerce an % integer to a |\muskip| register, you have to get the value with % |\the| and add the keyword~|mu| while scanning the number. To get % the integer value of a |\muskip| register, you can use the % following macro~|\lcllc@cnvmutocnt|. % % \begin{macro}{\lcllc@cnvmutocnt} % The macro |\lcllc@cnvmutocnt| ist called with a |\muskip| register % or a value in~|mu| units as its argument. It will expand to the % integer value. To get the value of a register, we first expand % the value of this register to a list of tokens with \TeX's |\the| % primitive. % Example: if the register has the value~$3.4$\,mu, the expansion of % |\the| produces the tokens $\mbox{\tt 3}_{12} \mbox{\tt .}_{12} % \mbox{\tt 4}_{12} \mbox{\tt m}_{12} \mbox{\tt u}_{12}$. % \begin{macrocode} \def\lcllc@cnvmutocnt#1{\expandafter\lcllc@delmukey\the#1} % \end{macrocode} % % After we have expanded the value of the register, it is necessary % to strip of the unit keyword~|mu| and the fraction of the value. % To do this, we have to use tokens with {\em category code}~12 to % match the expansion string produced by~|\the|. % \begin{macrocode} \begingroup \catcode`\M=12 \catcode`\U=12 \catcode`\.=12 \lowercase{\endgroup \def\lcllc@delmukey#1.#2MU{#1}} % \end{macrocode} % \end{macro} % % % \subsection{Allocation registers} % % \subsubsection{Registers defined in {\tt plain.tex}} % % Plain-\TeX's allocation macros use a fixed set of |count| % registers containing a set of numbers with the highest allocated % register number. To make the following macro code more readable, % alias names for these |count| registers are defined. % \begin{macrocode} \countdef\count@ptr = 10 \countdef\dimen@ptr = 11 \countdef\skip@ptr = 12 \countdef\muskip@ptr = 13 \countdef\box@ptr = 14 \countdef\toks@ptr = 15 \countdef\read@ptr = 16 \countdef\write@ptr = 17 \countdef\mathfam@ptr = 18 % \end{macrocode} % {\tt plain.tex} for \TeX~3 introduces a new allocation command % needing an additional allocation count register. To simplify the % code of this package with older versions of {\tt plain.tex}, a % dummy count register is allocated and used. % \begin{macrocode} \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname newlanguage\endcsname\relax \csname newcount\endcsname\language@ptr \else \countdef\language@ptr = 19 \fi % \end{macrocode} % % The allocation command for insertion uses another register, which % is already aliased as |\insc@unt|. %\begin{verbatim} %\countdef\insc@unt = 20 % = 19 in older versions of `plain.tex' %\end{verbatim} % % % \subsubsection{Additional Registers} % % For the new local allocation macros additional registers are % needed containing the boundaries for all types of locally % allocated registers. Whereas all globally allocated registers % are located in the lower region of the register numbers (with the % exception of the set of registers needed for an insertion), % locally allocated registers are taken from the higher region of % the register numbers---from top towards the bottom. % % To avoid using six additional count registers we use |\muskip| % registers to save the current lower boundary of the allocatable % register region. These boundaries are initialised either % with~$256$ or the actual boundary of the insertion allocation % register. % \begin{macrocode} \newmuskip\count@limit \count@limit = \the\insc@unt mu \newmuskip\dimen@limit \dimen@limit = \the\insc@unt mu \newmuskip\skip@limit \skip@limit = \the\insc@unt mu \newmuskip\box@limit \box@limit = \the\insc@unt mu \newmuskip\muskip@limit \muskip@limit = 256mu \newmuskip\toks@limit \toks@limit = 256mu % \end{macrocode} % % To simplify the code of the following allocation macros and to % save macro space, two additional |\muskip| registers are % allocated and initialised with the constants $16$ and~$256$. % \begin{macrocode} \newmuskip\cclvi@mu \cclvi@mu = 256mu \newmuskip\xvi@mu \xvi@mu = 16mu % \end{macrocode} % % % \subsection{Allocation Macros for the ``End User''} % % \subsubsection{Global Allocation Macros} % % \begin{macro}{\newcount} \begin{macro}{\newdimen} % \begin{macro}{\newskip} \begin{macro}{\newmuskip} % \begin{macro}{\newbox} \begin{macro}{\newtoks} % \begin{macro}{\newread} \begin{macro}{\newwrite} % \begin{macro}{\newfam} \begin{macro}{\newlanguage} % We have to replace the original macros in {\tt plain.tex} by new % ones to allow locally allocated registers. Otherwise it will be % possible that the two regions, the lower one with globally % allocated registers and the higher one with locally allocated % registers, will overlap resulting in a double use of the same % register. % % With the new macros it will be unnecessary to un-outer the {\tt % plain.tex} macros, because the local allocation macros have to be % non outer. Nonetheless we want to use this package in % conjunction with \LaTeX\ and therefore we have to define some of % them as non outer. % % The top level macros use the low level macro |\alloc@| which has % the following parameters: % The boundaries of the lower and the higher region, the type of % the allocated register, a flag if we have to check on overlapping % with insertion registers, the \TeX\ primitive to be used to % define this register, and the user given control sequence. % \begin{macrocode} %\outer \def\newcount {\alloc@\count@ptr \count@limit \count 1\countdef } %\outer \def\newdimen {\alloc@\dimen@ptr \dimen@limit \dimen 1\dimendef } %\outer \def\newskip {\alloc@\skip@ptr \skip@limit \skip 1\skipdef } % \outer \def\newmuskip {\alloc@\muskip@ptr \muskip@limit\muskip 0\muskipdef} %\outer \def\newbox {\alloc@\box@ptr \box@limit \box 1\chardef } % \outer \def\newtoks {\alloc@\toks@ptr \toks@limit \toks 0\toksdef } % \outer \def\newread {\alloc@\read@ptr \xvi@mu \read 0\chardef } %\outer \def\newwrite {\alloc@\write@ptr \xvi@mu \write 0\chardef } %\outer \def\newfam {\alloc@\mathfam@ptr\xvi@mu \fam 0\chardef } % \outer \def\newlanguage{\alloc@\lang@ptr \cclvi@mu \language0\chardef } % \end{macrocode} % \end{macro}\end{macro}\end{macro}\end{macro}\end{macro} % \end{macro}\end{macro}\end{macro}\end{macro}\end{macro} % % |\newinsert| needs additional code because this macro has to % allocate a set of |\box|, |\count|, |\dimen|, and |\skip| % registers with the restriction that all registers have to have % the same number. |\newinsert| is redefined at the end of this % file. % % % \subsubsection{Local Allocation Macros} % % % \begin{macro}{\lnewcount} \begin{macro}{\lnewdimen} % \begin{macro}{\lnewskip} \begin{macro}{\lnewmuskip} % \begin{macro}{\lnewbox} \begin{macro}{\lnewtoks} % There is an equivalent set of macros to allocate registers % locally. Instead of using the low level macro |\alloc@| it uses % the macro |\lalloc@| with the same set of parameters. % \begin{macrocode} \def\lnewcount {\lalloc@\count@ptr \count@limit \count 1\countdef } \def\lnewdimen {\lalloc@\dimen@ptr \dimen@limit \dimen 1\dimendef } \def\lnewskip {\lalloc@\skip@ptr \skip@limit \skip 1\skipdef } \def\lnewmuskip{\lalloc@\muskip@ptr\muskip@limit\muskip 0\muskipdef} \def\lnewbox {\lalloc@\box@ptr \box@limit \box 1\chardef } \def\lnewtoks {\lalloc@\toks@ptr \toks@limit \toks 0\toksdef } % \end{macrocode} % \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro} % % Local allocation macros for |\read|, |\write| streams, math % |\fam|, |language| numbers, or insertions are possible but not % very useful because of the global nature of these resources. % % % \subsection{Low Level Allocation Macros} % % The allocation scheme used by the macros in {\tt plain.tex} is % simple: % \begin{itemize} % \item all allocations are global, % \item register, math family, language, input/output stream % numbers are allocated using the lowest possible number, i.e., % it is done from lower number to higher numbers, % \item the set of insertion registers (|box|, |count|, |skip|, and % |dimen|), which have to have the same register number, are % allocated beginning from~$255$ to lower numbers. % \end{itemize} % % Contrary to this simple scheme this package uses numbers for % locally allocated registers from top to bottom interfering with % the original insertion register allocation scheme {\it and\/} the % simple test for a register number overflow. % % \begin{macro}{\lcllc@insnums} % Insertion registers are now allocated in a non-monotonous order % using the lowest possible number (because the allocation of the % needed set of registers is done in a global way). To allow the % checking of overlapping of globally or locally allocated % registers with the registers used for insertions, the insertion % register numbers are saved as a list in |\lcllc@insnums|. % Each entry in this list is saved as \mbox{\tt\string\do$\langle % n\rangle$.}; the list is initialised as empty. % \begin{macrocode} \def\lcllc@insnums{} % \end{macrocode} % \end{macro} % % \begin{macro}{\lcllc@checkins} % Whenever a new |box|, |count|, |skip|, or |dimen| register is % allocated it has to be checked first, if the next possible % free register is already allocated for an insertion. % % To detect a collision between a possibly free register number and % the set of insertion registers, the macro |\lcllc@checkins| is % called with the register number to be tested in % |\allocationnumber|. The argument of this macro has to be either % $1$ or~$-1$ and is used to get the next register number to be % tested against the insertion number list if an additional % iteration is needed. The result is a register number in % |\allocationnumber| which is not used for an insertion. (Note: % Nonetheless it can be an out-of-region register number of an % already used register!) % \begin{macrocode} \def\lcllc@checkins#1{% \begingroup % \end{macrocode} % After opening a new group, the macro |\do| is defined to read the % next insertion number delimited by a simple dot. It then tests % this number against the current |\allocationnumber| and if the % register numbers are equal, |\allocationnumber| is advanced by the % given argument (which is $1$ or~$-1$). % % To avoid a global change of |\allocationnumber|, a group hack % with expansion is used: If the list |\lcllc@insnums| is expanded % with this definition of |\do|, the result is empty if the % register number is not used for an insertion. Otherwise it % expands to the |\advance| command followed by an additional % |lcllc@checkins| (which has to be protected by |\noexpand|) to % start another iteration with the changed |\allocationnumber|. % \begin{macrocode} \def\do##1.{% \ifnum##1=\allocationnumber \advance\allocationnumber#1\relax \noexpand\lcllc@checkins{#1}% \fi}% % \end{macrocode} % The following expanded definition text of |\x| contains code to % close the group and the expansion of |\lcllc@insnums|, which is % either empty or contains the change of |\allocationnumber| and an % iterative call of |\lcllc@checkins|. After the definition is % completed, the code is executed which closes the group. % \begin{macrocode} \edef\x{\endgroup \lcllc@insnums}% \x} % \end{macrocode} % \end{macro} % % % \begin{macro}{\alloc@} % |\alloc@| is the low level macro for global allocation, which is % called with six arguments. The macro itself only uses the first % four argument: The two boundaries, the item type to be allocated, % and a flag if this item is propably used for an insertion. The % remaining two arguments, the \TeX\ primitive and the control % sequence to assign the allocated number is used by % |\lcllc@def|. % \begin{macrocode} \def\alloc@#1#2#3#4{% % \end{macrocode} % In the first step we assign the boundary of the lower region for % this item type to |\allocationnumber| and increment it by one. % \begin{macrocode} \allocationnumber#1% \advance\allocationnumber\@ne % \end{macrocode} % If this item type is used by insertion, we have to check for % collision with the |\lcllc@checkins| macro. After the execution of % this macro, |\allocationnumber| contains the next free number to % be used for allocation. This number is assigned globally to the % register containing the boundary. % \begin{macrocode} \ifnum#4=\@ne \lcllc@checkins\@ne \fi \global#1\allocationnumber % \end{macrocode} % We now have found an unused register. Nonetheless it is possible % that the register number is either not in the range of existing % register number or it is used for a locally allocated register. % |\ch@ck| is used to test these things. % \begin{macrocode} \ch@ck#1#2#3% % \end{macrocode} % At the end the \meta{control sequence} is defined using the % found |\allocationnumber|. % \begin{macrocode} \lcllc@def\global{}#3} % \end{macrocode} % \end{macro} % % % \begin{macro}{\lalloc@} % |\lalloc@| is the low level macro for local allocation. The % definition of this macro a copy of |\alloc@| with some small % changes. % \begin{macrocode} \def\lalloc@#1#2#3#4{% % \end{macrocode} % In the first step we assign the boundary of the {\it higher\/} % region and {\it decrement\/} it by one. Because the higher % boundary is saved in a |\muskip| register, we have to use % |\lcllc@cnvmutocnt| to get the boundary value. % \begin{macrocode} \allocationnumber\lcllc@cnvmutocnt#2% \advance\allocationnumber\m@ne % \end{macrocode} % The check for insertion number collisions is called with~$-1$ to % decrement the register number to get the next free register % number. The |\allocationnumber| is then assigned {\it locally\/} % to the |\muskip| register containing the boundary. % \begin{macrocode} \ifnum#4=\@ne \lcllc@checkins\m@ne \fi #2\the\allocationnumber mu % % \end{macrocode} % The check for an already used globally allocated register or a % range underflow is needed, too. % \begin{macrocode} \ch@ck#1#2#3% % \end{macrocode} % At the end the \meta{control sequence} is defined using the % found |\allocationnumber|. % \begin{macrocode} \lcllc@def\relax{(local)}#3} % \end{macrocode} % \end{macro} % % % \begin{macro}{\ch@ck} % The test macro |\ch@ck| for a collision of the globally and % locally allocated registers from {\tt plain.tex} has to be % changed because the higher boundary is given as a |\muskip| value % instead of a normal integer. % \begin{macrocode} \def\ch@ck#1#2#3{% \ifnum#1<\lcllc@cnvmutocnt#2\relax \else \errmessage{No room for a new #3}% % \allocationnumber\m@ne \fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\lcllc@def} % |\lcllc@def| is used to assign the found |\allocationnumber| % to the \meta{control sequence} using the \TeX\ primitive. % Additionally an entry is written to the {\tt log} file. % \begin{macrocode} \def\lcllc@def#1#2#3#4#5{% #1#4#5=\allocationnumber \wlog{\string#5#2=\string#3\the\allocationnumber}} % \end{macrocode} % \end{macro} % % % \subsubsection{Low Level Insertion Allocation Macros} % % Insertions need a set of registers with the same register number. % To find a new register number when allocating an insertion, we % have to get the maximum of all boundaries used for an insertion. % % \begin{macro}{\lcllc@getmax} % |\lcllc@getmax| is used to assign |\allocationnumber| to the % maximum of |\allocationnumber| and its argument. % \begin{macrocode} \def\lcllc@getmax#1{% \ifnum#1<\allocationnumber \else \allocationnumber#1\advance\allocationnumber\@ne \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\newinsert} % |\newinsert| globally allocates a set of registers used for an % insertion. % \begin{macrocode} \outer\def\newinsert{% % \end{macrocode} % First we have to find the maximum of all globally allocated % register number used for an insertion. We start % by setting |\allocationnumber| to~$-1$\,\ldots % \begin{macrocode} \allocationnumber\m@ne % \end{macrocode} % \ldots\,and get the maxmimum of the boundaries for |count|, % |dimen|, |skip|, and |box| registers. % \begin{macrocode} \lcllc@getmax\count@ptr \lcllc@getmax\dimen@ptr \lcllc@getmax\skip@ptr \lcllc@getmax\box@ptr % \end{macrocode} % Then we have to check if this |\allocationnumber| is already used % for another insertion. % \changes{v1.0b}{91/09/06}{\cs{lcllc@checkins} inserted} % \begin{macrocode} \lcllc@checkins\@ne % \end{macrocode} % At last we have to check if this |\allocationnumber| is used for % one of the locally allocated registers. % \begin{macrocode} \ch@ck\allocationnumber\count@limit\count \ch@ck\allocationnumber\dimen@limit\dimen \ch@ck\allocationnumber\skip@limit\skip \ch@ck\allocationnumber\box@limit\box % \end{macrocode} % The found register number for insertions is then (globally) % inserted into the list of insertion numbers. % \begin{macrocode} \begingroup \let\do\relax \xdef\lcllc@insnums{\do\the\allocationnumber.\lcllc@insnums}% \endgroup % \end{macrocode} % At the end the \meta{control sequence} is defined using the % found |\allocationnumber|. % \begin{macrocode} \lcllc@def\global{}\insert\chardef} % \end{macrocode} % \end{macro} % % The register |\insc@unt| which is used to contain the boundary % number for insertion registers in the original {\tt plain.tex} % macro is not used anymore. % % % Finally, the category code of the `at' character~{\tt @} is reset % to its original value. % \begin{macrocode} \catcode`\@=\lcllc@at % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % \iffalse %<*driver> \NeedsTeXFormat{LaTeX2e} \documentclass[a4paper]{ltxdoc} \GetFileInfo{localloc.dtx} \begin{document} \DocInput{\filename} \end{document} % % \fi % % \iffalse % % \section{Test File} % % A first version of a test file which can be used for plain-TeX, % \LaTeX~2.09, and \LaTeXe. The result shows the allocated register % numbers. You should notice that the insertions and global box % registers are not contiguously allocated but interfere. Further % from one to the next line there is a new global register number % greater than the former one. Whereas the local register numbers % are set to zero when leaving a group and they are recycled in the % next lines. % % \begin{macrocode} %<*test> % This test file can be used with plain-TeX & LaTeX 2.09/2e. % \edef\FORMAT{% \expandafter\ifx\csname documentstyle\endcsname\relax 0% \else\expandafter\ifx\csname documentclass\endcsname\relax 1\else 2\fi\fi} \immediate\write16{=====>>> You are using % \ifcase\FORMAT plainTeX\or LaTeX 2.09\or LaTeX 2e\else ??\fi} \ifcase\FORMAT \input localloc.sty\relax \or \documentstyle[localloc]{article}\begin{document}\or \documentclass{article}\usepackage{localloc}\begin{document}\fi \tracingstats=1 % some macros \def\Message#1{\immediate\write16{#1}} \def\RegVal#1{\the\csname test#1\endcsname} \def\ShowSet#1{\if l#1local\else global\fi: \RegVal{i#1} \RegVal{ii#1}/\RegVal{iii#1} \RegVal{iv#1}} \def\ShowAll#1{\Message{#1 -- \ShowSet{g} -- \ShowSet{l}}} \def\ShowIns{\Message{Insertions: \the\testinsi, \the\testinsii, \the\testinsiii}} % initialise \chardef\testig=0 \chardef\testil=0 \chardef\testiig=0 \chardef\testiil=0 \chardef\testiiig=0 \chardef\testiiil=0 \chardef\testivg=0 \chardef\testivl=0 \chardef\testinsii=0 \chardef\testinsiii=0 % allocate an insertion/set of registers \newinsert\testinsi % make sure that a collision boxes/insertions occurs {\count0=\testinsi \advance\count0 -2 \loop\csname newbox\endcsname\testig \ifnum\testig<\count0\repeat} % \newbox\testig \lnewbox\testil \ShowAll{Level 0} \begingroup \lnewbox\testiil \newbox\testiig \ShowAll{Level 1} \begingroup \newbox\testivg \lnewbox\testivl \ShowAll{Level 2}\ShowIns \endgroup \lnewbox\testiiil \newbox\testiiig \ShowAll{Level 1b} \csname newinsert\endcsname\testinsii \ShowIns \begingroup \newbox\testivg \lnewbox\testivl \ShowAll{Level 2} \endgroup \ShowAll{Level 1b} \endgroup \newinsert\testinsiii \ShowAll{Level 0}\ShowIns \begingroup \lnewbox\testiil \newbox\testiig \lnewbox\testiiil \newbox\testiiig \ShowAll{Level 1} \begingroup \newbox\testivg \lnewbox\testivl \newbox\testvg \lnewbox\testvl \ShowAll{Level 2}\ShowIns \endgroup \ShowAll{Level 1} \endgroup \ShowAll{Level 0} \end{document} % % \end{macrocode} % % \fi % % \Finale % %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% % \endinput