From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/localloc/localloc.dtx | 1026 ++++++++++++++++++++++++++++ 1 file changed, 1026 insertions(+) create mode 100644 macros/latex/contrib/localloc/localloc.dtx (limited to 'macros/latex/contrib/localloc/localloc.dtx') diff --git a/macros/latex/contrib/localloc/localloc.dtx b/macros/latex/contrib/localloc/localloc.dtx new file mode 100644 index 0000000000..ad770b5d85 --- /dev/null +++ b/macros/latex/contrib/localloc/localloc.dtx @@ -0,0 +1,1026 @@ +% \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 -- cgit v1.2.3