diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:53:06 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:53:06 +0000 |
commit | 1f4499ce04e16a3dae7c287b445576361cc20769 (patch) | |
tree | ad95653c87d8135183eddbd885d1645f9dc5b547 /Master/texmf-dist/source/latex/expl3/l3seq.dtx | |
parent | 4206a1600d2e36ae7c46f99a3c58ae98112ee1ad (diff) |
trunk/Master/texmf-dist/source/latex/expl3
git-svn-id: svn://tug.org/texlive/trunk@270 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3seq.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3seq.dtx | 622 |
1 files changed, 622 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3seq.dtx b/Master/texmf-dist/source/latex/expl3/l3seq.dtx new file mode 100644 index 00000000000..f3da69642ef --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3seq.dtx @@ -0,0 +1,622 @@ +% \iffalse +%% File: l3seq.dtx Copyright (C) 1990-1998 LaTeX3 project +% +%<*dtx> + \ProvidesFile{l3seq.dtx} +%</dtx> +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{l3seq} +%<driver> \ProvidesFile{l3seq.drv} +% \fi +% \ProvidesFile{l3seq.dtx} + [1998/04/20 v1.0d L3 Experimental Token List Pointers] +% +% \iffalse +%<*driver> +\documentclass{l3doc} + +\begin{document} +\DocInput{l3seq.dtx} +\end{document} +%</driver> +% \fi +% +% +% \GetFileInfo{l3seq.dtx} +% \title{The \textsf{l3seq} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% Sequences} +% \author{\Team} +% \date{\filedate} +% \maketitle +% +% +% +% \section{Sequence} +% +% \LaTeX3 implements a data type called `sequences'. These are special +% token lists that can be accessed via special function on the `left'. +% Appending tokens is possible at both ends. Appended token lists can be +% accessed only as a union. The token lists that form the individual +% items of a sequence might contain any tokens except two internal +% functions that are used to structure sequences (see section internal +% functions below). It is also possible to map functions on such +% sequences so that they are executed for every item on the sequence. +% +% All functions that return items from a sequence in some <tlp> assume +% that the <tlp> is local. See remarks below if you need a global +% returned value. +% +% The defined functions are not orthogonal in the sense that every +% possible variation possible is actually available. If you need a new +% variant use the expansion functions described in the package +% \texttt{l3expan} to build it. +% +% Adding items to the left of a sequence can currently be done with +% either something like "\seq_put_left:Nn" or with a ``stack'' function +% like "\seq_push:Nn" which has the same effect. Maybe one should +% therefore remove the ``left'' functions totally. +% +% \subsection{Functions} +% +% \begin{function}{% +% \seq_new:N | +% \seq_new:O | +% \seq_new:c | +% } +% \begin{syntax} +% "\seq_new:N" <sequence> +% \end{syntax} +% Defines <sequence> to be a variable of type sequences. +% \end{function} +% +% \begin{function}{% +% \seq_clear:N | +% \seq_clear:c | +% \seq_gclear:N | +% \seq_gclear:c | +% } +% \begin{syntax} +% "\seq_clear:N" <sequence> +% \end{syntax} +% These functions locally or globally clear <sequence>. +% \end{function} +% +% \begin{function}{% +% \seq_put_left:Nn | +% \seq_put_left:No | +% \seq_put_left:Nx | +% \seq_put_left:cn | +% \seq_put_right:Nn | +% \seq_put_right:No | +% \seq_put_right:Nx | +% } +% \begin{syntax} +% "\seq_put_left:Nn" <sequence> <token list> +% \end{syntax} +% Locally appends <token list> as a single item to the left +% or right of <sequence>. <token list> might get expanded before +% appending. +% \end{function} +% +% \begin{function}{% +% \seq_gput_left:Nn | +% \seq_gput_right:Nn | +% \seq_gput_right:No | +% \seq_gput_right:cn | +% \seq_gput_right:co | +% \seq_gput_right:cc | +% } +% \begin{syntax} +% "\seq_gput_left:Nn" <sequence> <token list> +% \end{syntax} +% Globally appends <token list> as a single item to the left +% or right of <sequence>. +% \end{function} +% +% \begin{function}{% +% \seq_get:NN | +% \seq_get:cN | +% } +% \begin{syntax} +% "\seq_get:NN" <sequence> <tlp> +% \end{syntax} +% Functions that locally assign the left-most item of <sequence> to the +% token list pointer <tlp>. Item is not removed from <sequence>! If you +% need a global return value you need to code something like this: +% \begin{quote} +% "\seq_get:NN" <sequence> "\l_tmpa_tlp" \\ +% "\tlp_gset_eq:NN" <global tlp> "\l_tmpa_tlp" +% \end{quote} +% But if this kind of construction is used often enough a separate +% function should be provided. +% \end{function} +% +% \begin{function}{% +% \seq_gconcat:NNN | +% \seq_gconcat:ccc | +% } +% \begin{syntax} +% "\seq_gconcat:NNN" <seq1> <seq2> <seq3> +% \end{syntax} +% Function that conatenates <seq2> and <seq3> and globally assigns the +% result to <seq1>. +% \end{function} +% +% \begin{function}{\seq_map:NN} +% \begin{syntax} +% "\seq_map:NN" <sequences> <function> +% \end{syntax} +% This function applies <function> (which must be a function with one +% argument) to every item of <sequence>. <function> is not executed +% within a sub-group so that side effects can be achieved locally. The +% operation is not expandable which means that it can't be used within +% write operations etc. +% +% In the current implementation the next functions are more efficient and +% should be preferred. +% \end{function} +% +% \begin{function}{\seq_map_inline:Nn | +% \seq_map_inline:cn +% } +% \begin{syntax} +% "\seq_map_inline:Nn" <sequence> "{" <inline function> "}" +% \end{syntax} +% Applies <inline function> (which should be the direct coding for a +% function with one argument (i.e.\ use "##1" as the place holder for +% this argument)) to every item of <sequence>. <inline function> is not +% executed within a sub-group so that side effects can be achieved locally. +% The operation is not expandable which means that it can't be used +% within write operations etc. +% \end{function} +% +% \subsection{Predicates and conditionals} +% +% \begin{function}{\seq_empty_p:N} +% \begin{syntax} +% "\seq_empty_p:N" <sequence> +% \end{syntax} +% This predicate returns `true' if <sequence> is `empty' i.e., doesn't +% contain any tokens. +% \end{function} +% +% \begin{function}{% +% \seq_empty:NTF | +% \seq_empty:cTF | +% \seq_empty:NF | +% \seq_empty:cF | +% } +% \begin{syntax} +% "\seq_empty:NTF" <sequence> "{" <true code> "}{" <false code> "}" +% \end{syntax} +% Set of conditionals that test whether or not a particular <sequence> +% is empty and if so executes either <true code> or <false code>. +% \end{function} +% +% \begin{function}{% +% \seq_if_in:NnTF | +% \seq_if_in:cnTF | +% \seq_if_in:coTF | +% } +% \begin{syntax} +% "\seq_if_in:NnTF" <sequ> "{" <item> "}{" <true code> "}{" <false code> "}" +% \end{syntax} +% Function that tests if <item> is in <sequ>. Depending on the result +% either <true code> or <false code> is executed. +% \end{function} +% +% \subsection{Internal functions} +% +% \begin{function}{\seq_empty_err:N} +% \begin{syntax} +% "\seq_empty_err:N" <sequence> +% \end{syntax} +% Signals an \LaTeX3 error if <sequence> is empty. +% \end{function} +% +% \begin{function}{\seq_pop_aux:nnNN} +% \begin{syntax} +% "\seq_pop_aux:nnNN" <assign1> <assign2> <sequence> <tlp> +% \end{syntax} +% Function that assigns the left-most item of <sequence> to <tlp> using +% <assign1> and assigns the tail to <sequence> using <assign2>. This +% function could be used to implement a global return function. +% \end{function} +% +% \begin{function}{% +% \seq_get_aux:w | +% \seq_pop_aux:w | +% \seq_put_aux:Nnn | +% \seq_put_aux:w | +% } +% Functions used to implement put and get operations. They are not for +% meant for direct use. +% \end{function} +% +% \begin{function}{% +% \seq_elt:w | +% \seq_elt_end: } +% Functions (usually used as constants) that separates items within a +% sequence. They might get special meaning during mapping operations and +% are not supposed to show up as tokens within an item appended to a +% sequence. +% \end{function} +% +% +% \section {Implementation} +% +% We start by ensuring that the required packages are loaded. +% \begin{macrocode} +%<package&!check>\RequirePackage{l3toks} +%<package&!check>\RequirePackage{l3quark} +%<package&check>\RequirePackage{l3chk} +%<package>\RequirePackage{l3expan} +%<*package> +% \end{macrocode} +% +% A sequence is a control sequence whose top-level expansion is of the +% form `|\seq_elt:w| \m{text$\sb1$} |\seq_elt_end:| \ldots{} +% |\seq_elt:w| \zv{text$\sb{n}$} \ldots'. We use explicit delimiters +% instead of braces around \m{text} to allow efficient searching for +% an item in the sequence. +% +% \begin{macro}{\seq_elt:w} +% \begin{macro}{\seq_elt_end:} +% We allocate the delimiters and make them noops as default. +% \begin{macrocode} +\let_new:NN \seq_elt:w \use_noop: +\let_new:NN \seq_elt_end: \use_noop: +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\seq_new:N} +% \begin{macro}{\seq_new:O} +% \begin{macro}{\seq_new:c} +% Sequences are implemented using token lists. +% \begin{macrocode} +\def_new:Npn \seq_new:N #1{\tlp_new:Nn #1{}} +\def_new:Npn \seq_new:c {\exp_args:Nc \seq_new:N} +\def_new:Npn \seq_new:O {\exp_args:No \seq_new:N} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_clear:N} +% \begin{macro}{\seq_clear:c} +% \begin{macro}{\seq_gclear:N} +% \begin{macro}{\seq_gclear:c} +% Clearing a sequence is the same as clearing a token list. +% \begin{macrocode} +\let_new:NN \seq_clear:N \tlp_clear:N +\let_new:NN \seq_clear:c \tlp_clear:c +\let_new:NN \seq_gclear:N \tlp_gclear:N +\let_new:NN \seq_gclear:c \tlp_gclear:c +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_clear_new:N} +% \begin{macro}{\seq_clear_new:c} +% \begin{macro}{\seq_gclear_new:N} +% \begin{macro}{\seq_gclear_new:c} +% Clearing a sequence is the same as clearing a token list. +% \begin{macrocode} +\let_new:NN \seq_clear_new:N \tlp_clear_new:N +\let_new:NN \seq_clear_new:c \tlp_clear_new:c +\let_new:NN \seq_gclear_new:N \tlp_gclear_new:N +\let_new:NN \seq_gclear_new:c \tlp_gclear_new:c +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_empty_p:N} +% A predicate which evaluates to |\c_true| iff the sequence is empty. +% \begin{macrocode} +\let_new:NN \seq_empty_p:N \tlp_empty_p:N +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\seq_empty:NTF} +% \begin{macro}{\seq_empty:cTF} +% \begin{macro}{\seq_empty:NF} +% \begin{macro}{\seq_empty:cF} +% |\seq_empty:NTF|\m{seq}\m{true~case}\m{false~case} will check +% whether the \m{seq} is empty and then select one of the other +% arguments. |seq_empty:cTF| turns its first argument into a +% control sequence to get the name of the sequence. +% \begin{macrocode} +\def_new:Npn \seq_empty:NTF #1{ + \if_meaning:NN#1\c_empty_tlp + \exp_after:NN\use_choice_i:nn + \else: \exp_after:NN\use_choice_ii:nn \fi:} +\def_new:Npn \seq_empty:cTF {\exp_args:Nc\seq_empty:NTF} +% \end{macrocode} +% A variant of this, is only to do something if the sequence is +% {\em not} empty. +% \begin{macrocode} +\def_new:Npn \seq_empty:NF #1{ + \if_meaning:NN#1\c_empty_tlp \exp_after:NN\use_none:n + \else: \exp_after:NN\use:n \fi:} +\def_new:Npn \seq_empty:cF {\exp_args:Nc\seq_empty:NF} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\seq_empty_err:N} +% Signals an error if the sequence is empty. +% \begin{macrocode} +\def_new:Npn \seq_empty_err:N #1{\if_meaning:NN#1\c_empty_tlp +% \end{macrocode} +% As I said before, I don't think we need to provide checks for this +% kind of error, since it is a severe internal macro package error +% that can not be produced by the user directly. Can it? So the +% next line of code should be probably removed. +% \begin{macrocode} + \tlp_clear:N \l_testa_tlp % catch prefixes + \err_latex_bug:n{Empty~sequence~`\token_to_string:N#1'}\fi:} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\seq_get:NN} +% \begin{macro}{\seq_get:cN} +% |\seq_get:NN |\zz{sequence}\zz{cmd} defines \zz{cmd} to be the +% left_most element of \zz{sequence}. +% \begin{macrocode} +\def_new:Npn \seq_get:NN #1{ + \seq_empty_err:N #1 + \exp_after:NN\seq_get_aux:w #1\q_stop} +\def_new:Npn \seq_get_aux:w \seq_elt:w #1\seq_elt_end: + #2\q_stop #3{\tlp_set:Nn #3{#1}} +\def_new:Npn \seq_get:cN {\exp_args:Nc \seq_get:NN} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_pop_aux:nnNN} +% |\seq_pop_aux:nnNN| \zz{def$\sb1$} \zz{def$\sb2$} \zz{sequence} +% \zz{cmd} assigns the left_most element of \zz{sequence} to +% \zz{cmd} using \zz{def$\sb2$}, and assigns the tail of +% \zz{sequence} to \zz{sequence} using \zz{def$\sb1$}. +% \begin{macrocode} +\def_new:Npn \seq_pop_aux:nnNN #1#2#3{ + \seq_empty_err:N #3 + \exp_after:NN\seq_pop_aux:w #3\q_stop #1#2#3} +\def_new:Npn \seq_pop_aux:w \seq_elt:w #1\seq_elt_end: + #2\q_stop #3#4#5#6{#3#5{#2}#4#6{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\seq_put_aux:Nnn} +% |\seq_put_aux:Nnn| \zz{sequence} \zv{left} \zv{right} adds the +% elements specified by \zv{left} to the left of \zz{sequence}, and +% those specified by \zv{right} to the right. +% \begin{macrocode} +\def_new:Npn \seq_put_aux:Nnn #1{ + \exp_after:NN\seq_put_aux:w #1\q_stop #1} +\def_new:Npn \seq_put_aux:w #1\q_stop #2#3#4{\tlp_set:Nn #2{#3#1#4}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\seq_put_left:Nn} +% \begin{macro}{\seq_put_left:No} +% \begin{macro}{\seq_put_left:Nx} +% \begin{macro}{\seq_put_left:cn} +% \begin{macro}{\seq_put_right:Nn} +% \begin{macro}{\seq_put_right:No} +% \begin{macro}{\seq_put_right:Nx} +% Here are the usual operations for adding to the left and right. +% \begin{macrocode} +\def_new:Npn \seq_put_left:Nn #1#2{ +% \end{macrocode} +% We can't put in a |\use_noop:| instead of |{}| since this argument is +% passed literally (and we would end up with many |\use_noop:|s inside +% the sequences. +% \begin{macrocode} + \seq_put_aux:Nnn #1{\seq_elt:w #2\seq_elt_end:}{}} +\def_new:Npn \seq_put_left:cn {\exp_args:Nc\seq_put_left:Nn} +\def_new:Npn \seq_put_left:No {\exp_args:NNo\seq_put_left:Nn} +\def_new:Npn \seq_put_left:Nx {\exp_args:Nnx\seq_put_left:Nn} +\def_new:Npn \seq_put_right:Nn #1#2{ + \seq_put_aux:Nnn #1{}{\seq_elt:w #2\seq_elt_end:}} +\def_new:Npn \seq_put_right:No {\exp_args:Nno\seq_put_right:Nn} +\def_new:Npn \seq_put_right:Nx {\exp_args:Nnx\seq_put_right:Nn} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_gput_left:Nn} +% \begin{macro}{\seq_gput_right:Nn} +% \begin{macro}{\seq_gput_right:No} +% \begin{macro}{\seq_gput_right:cn} +% \begin{macro}{\seq_gput_right:co} +% \begin{macro}{\seq_gput_right:cc} +% An here the global variants. +% \begin{macrocode} +\def_new:Npn \seq_gput_left:Nn { +%<*check> + \pref_global_chk: +%</check> +%<_check> \pref_global:D + \seq_put_left:Nn} +\def_new:Npn \seq_gput_right:Nn { +%<*check> + \pref_global_chk: +%</check> +%<_check> \pref_global:D + \seq_put_right:Nn} +\def_new:Npn \seq_gput_right:No {\exp_args:NNo \seq_gput_right:Nn} +\def_new:Npn \seq_gput_right:cn {\exp_args:Nc \seq_gput_right:Nn} +\def_new:Npn \seq_gput_right:co {\exp_args:Nco \seq_gput_right:Nn} +\def_new:Npn \seq_gput_right:cc {\exp_args:Ncc \seq_gput_right:Nn} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_map:NN} +% |\seq_map:NN| \zz{sequence} \zz{cmd} applies \zz{cmd} to each +% element of \zz{sequence}, from left to right. Since we don't have +% braces, this implementation is not very efficient. It might be +% better to say that \zz{cmd} must be a function with one argument +% that is delimited by |\seq_elt_end:|. +% \begin{macrocode} +\def_new:Npn \seq_map:NN #1#2{ + \def:Npn \seq_elt:w ##1\seq_elt_end: {#2{##1}}#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\seq_map_inline:Nn} +% \begin{macro}{\seq_map_inline:cn} +% When no braces are used, this version of mapping seems more +% natural. +% \begin{macrocode} +\def_new:Npn \seq_map_inline:Nn #1#2{ + \gdef:Npn \seq_elt:w ##1\seq_elt_end: {#2}#1} +\def_new:Npn \seq_map_inline:cn{\exp_args:Nc\seq_map_inline:Nn} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_gconcat:NNN} +% \begin{macro}{\seq_gconcat:ccc} +% |\seq_gconcat:NNN| \m{seq~1} \m{seq~2} \m{seq~3} will globally +% assign \m{seq~1} the concatenation of \m{seq~2} and \m{seq~3}. +% \begin{macrocode} +\def_new:Npn \seq_gconcat:NNN #1#2#3{ + \l_tmpa_toks \exp_after:NN{#2} + \l_tmpb_toks \exp_after:NN{#3} + \gdef:Npx #1{\toks_use:N \l_tmpa_toks \toks_use:N \l_tmpb_toks}} +\def_new:Npn \seq_gconcat:ccc{\exp_args:Nccc\seq_gconcat:NNN} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\seq_if_in:NnTF} +% \begin{macro}{\seq_if_in:cnTF} +% \begin{macro}{\seq_if_in:coTF} +% |\seq_if_in:NnTF| \m{seq}\m{item} \m{true~case} \m{false~case} +% will check whether \m{item} is in \m{seq} and then either execute +% the \m{true~case} or the \m{false~case}. \m{true~case} and +% \m{false~case} may contain incomplete |\if_char_code:w| +% statements. +% \begin{macrocode} +\def_new:Npn \seq_if_in:NnTF #1#2{ + \def:Npn\tmp:w + ##1\seq_elt:w #2\seq_elt_end: ##2##3\q_stop{ +% \end{macrocode} +% Note that |##2| contains exactly one token which we can compare +% with |\q_no_value|. +% \begin{macrocode} + \if_meaning:NN\q_no_value##2 + \exp_after:NN\use_choice_ii:nn + \else: + \exp_after:NN\use_choice_i:nn + \fi: + } + \exp_after:NN + \tmp:w #1\seq_elt:w + #2\seq_elt_end: \q_no_value \q_stop} +\def_new:Npn \seq_if_in:coTF {\exp_args:Nco \seq_if_in:NnTF} +\def_new:Npn \seq_if_in:cnTF {\exp_args:Nc \seq_if_in:NnTF} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% \subsection{Stack operations} +% +% We build stacks from sequences, but here we put the +% specific functions together. +% +% +% \begin{macro}{\seq_push:Nn} +% \begin{macro}{\seq_push:No} +% \begin{macro}{\seq_push:cn} +% \begin{macro}{\seq_pop:NN} +% \begin{macro}{\seq_pop:cN} +% Since sequences can be used as stacks, we ought to have both +% `push' and `pop'. In most cases they are nothing more then new +% names for old functions. +% \begin{macrocode} +\let_new:NN \seq_push:Nn \seq_put_left:Nn +\let_new:NN \seq_push:No \seq_put_left:No +\let_new:NN \seq_push:cn \seq_put_left:cn +\def_new:Npn \seq_pop:NN {\seq_pop_aux:nnNN \tlp_set:Nn \tlp_set:Nn} +\def_new:Npn \seq_pop:cN {\exp_args:Nc \seq_pop:NN} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\seq_gpush:Nn} +% \begin{macro}{\seq_gpush:No} +% \begin{macro}{\seq_gpush:cn} +% \begin{macro}{\seq_gpop:NN} +% \begin{macro}{\seq_gpop:cN} +% I don't agree with Denys that one needs only local stacks, +% actually I believe that one will probably need the functions +% here more often. In case of |\seq_gpop:NN| the value is +% nevertheless returned locally. +% \begin{macrocode} +\let_new:NN \seq_gpush:Nn \seq_gput_left:Nn +\def_new:Npn \seq_gpush:No {\exp_args:NNo \seq_gpush:Nn} +\def_new:Npn \seq_gpush:cn {\exp_args:Nc \seq_gpush:Nn} +\def_new:Npn \seq_gpop:NN {\seq_pop_aux:nnNN \tlp_gset:Nn \tlp_set:Nn} +\def_new:Npn \seq_gpop:cN {\exp_args:Nc \seq_gpop:NN} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\seq_top:NN} +% \begin{macro}{\seq_top:cN} +% Looking at the top element of the stack without removing it is +% done with this operation. +% \begin{macrocode} +\let_new:NN \seq_top:NN \seq_get:NN +\let_new:NN \seq_top:cN \seq_get:cN +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% Show token usage: +% \begin{macrocode} +%</package> +%<*showmemory> +%\showMemUsage +%</showmemory> +% \end{macrocode} +% +% +% + |