| 1 | % \begin{meta-comment} |
| 2 | % |
| 3 | % $Id: doafter.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $ |
| 4 | % |
| 5 | % Insert tokens to be read after a group has been processed |
| 6 | % |
| 7 | % (c) 1996 Peter Schmitt and Mark Wooding |
| 8 | % |
| 9 | % \end{meta-comment} |
| 10 | % |
| 11 | % \begin{meta-comment} <general public licence> |
| 12 | %% |
| 13 | %% doafter package -- insert a token really after a group |
| 14 | %% Copyright (c) 1996 Peter Schmitt and Mark Wooding |
| 15 | %<*package> |
| 16 | %% |
| 17 | %% This program is free software; you can redistribute it and/or modify |
| 18 | %% it under the terms of the GNU General Public License as published by |
| 19 | %% the Free Software Foundation; either version 2 of the License, or |
| 20 | %% (at your option) any later version. |
| 21 | %% |
| 22 | %% This program is distributed in the hope that it will be useful, |
| 23 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 24 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 25 | %% GNU General Public License for more details. |
| 26 | %% |
| 27 | %% You should have received a copy of the GNU General Public License |
| 28 | %% along with this program; if not, write to the Free Software |
| 29 | %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 30 | %</package> |
| 31 | %% |
| 32 | % \end{meta-comment} |
| 33 | % |
| 34 | % \begin{meta-comment} <Package preamble> |
| 35 | %<+latex2e>\NeedsTeXFormat{LaTeX2e} |
| 36 | %<+latex2e>\ProvidesPackage{doafter} |
| 37 | %<+latex2e> [1996/05/08 1.2 Aftergroup hacking (PS/MDW)] |
| 38 | % \end{meta-comment} |
| 39 | % |
| 40 | % \CheckSum{259} |
| 41 | %\iffalse |
| 42 | %<*package> |
| 43 | %\fi |
| 44 | %% \CharacterTable |
| 45 | %% {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 |
| 46 | %% 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 |
| 47 | %% Digits \0\1\2\3\4\5\6\7\8\9 |
| 48 | %% Exclamation \! Double quote \" Hash (number) \# |
| 49 | %% Dollar \$ Percent \% Ampersand \& |
| 50 | %% Acute accent \' Left paren \( Right paren \) |
| 51 | %% Asterisk \* Plus \+ Comma \, |
| 52 | %% Minus \- Point \. Solidus \/ |
| 53 | %% Colon \: Semicolon \; Less than \< |
| 54 | %% Equals \= Greater than \> Question mark \? |
| 55 | %% Commercial at \@ Left bracket \[ Backslash \\ |
| 56 | %% Right bracket \] Circumflex \^ Underscore \_ |
| 57 | %% Grave accent \` Left brace \{ Vertical bar \| |
| 58 | %% Right brace \} Tilde \~} |
| 59 | %% |
| 60 | %\iffalse |
| 61 | %</package> |
| 62 | %\fi |
| 63 | % |
| 64 | % \begin{meta-comment} <driver> |
| 65 | % |
| 66 | %<*driver> |
| 67 | \input{mdwtools} |
| 68 | \describespackage{doafter} |
| 69 | \author{Peter Schmitt\thanks{% |
| 70 | Peter came up with the basic implementation after I posed the problem |
| 71 | in the \texttt{comp.text.tex} newsgroup. I fixed some really piddly little |
| 72 | things, to improve it a bit, wrote the documentation, and turned the code |
| 73 | into a nice \package{doc}ced package. Then Peter gave me an updated |
| 74 | version, and I upgraded this from memory. Then he gave me some more tweaks |
| 75 | which I haven't incorporated.} |
| 76 | \and Mark Wooding} |
| 77 | \def\author#1{} |
| 78 | \mdwdoc |
| 79 | %</driver> |
| 80 | % |
| 81 | % \end{meta-comment} |
| 82 | % |
| 83 | % \section{Description} |
| 84 | % |
| 85 | % \subsection{What it's all about} |
| 86 | % |
| 87 | % \DescribeMacro{\doafter} |
| 88 | % It's common for the \TeX\ primitive |\aftergroup| to be used to `tidy up' |
| 89 | % after a group. For example, \LaTeX's colour handling uses this to insert |
| 90 | % appropriate |\special|s when the scope of a colour change ends. This |
| 91 | % causes several problems, though; for example, extra grouping must be added |
| 92 | % within boxes to ensure that the |\special|s don't `leak' out of their box |
| 93 | % and appear in odd places in the document. \LaTeX\ usually solves this |
| 94 | % problem by reading the box contents as an argument, although this isn't |
| 95 | % particularly desirable. The |\doafter| macro provided here will solve the |
| 96 | % problem in a different way, by allowing a macro to regain control after |
| 97 | % all the |\aftergroup| things have been processed. |
| 98 | % |
| 99 | % The macro works like this: |
| 100 | % \begin{grammar} |
| 101 | % <doafter-cmd> ::= \[[ |
| 102 | % "\\doafter" <token> <group> |
| 103 | % \]] |
| 104 | % \end{grammar} |
| 105 | % The \<token> can be any token you like, except an explicit braces, since |
| 106 | % it's read as an undelimited macro argument. The \<group> is a normal |
| 107 | % \TeX\ group, surrounded by either implicit or explicit braces, or by |
| 108 | % |\begingroup| and |\endgroup| tokens. Once the final closing token of the |
| 109 | % \<group> is read, and any tokens saved up by |\aftergroup| have been |
| 110 | % processed, the \<token> is inserted and processed. Under normal |
| 111 | % circumstances, this will be a macro. |
| 112 | % |
| 113 | % There are some subtle problems with the current implementation, which you |
| 114 | % may need to be aware of: |
| 115 | % |
| 116 | % \begin{itemize} |
| 117 | % |
| 118 | % \item Since we're inserting things after all the |\aftergroup| tokens, |
| 119 | % those tokens might read something they're not expecting if they try |
| 120 | % to look ahead at the text after the group (e.g., with |\futurelet|). |
| 121 | % This is obviously totally unavoidable. |
| 122 | % |
| 123 | % \item Implicit braces (like |\bgroup| and |\egroup|) inserted using |
| 124 | % |\aftergroup| may be turned into \emph{explicit} $|{|_1$ and $|}|_2$ |
| 125 | % characters within a |\doafter| group. This can cause probems under |
| 126 | % very specialised circumstances. The names |\bgroup| and |\egroup| |
| 127 | % are treated specially, and they will work normally (remaining as |
| 128 | % implicit braces). This should minimise problems caused by this |
| 129 | % slight difference. (This only applies to the last |\aftergroup| |
| 130 | % token in a group.) |
| 131 | % |
| 132 | % \item To handle the |\aftergroup| tokens properly, |\doafter| has to insert |
| 133 | % some |\aftergroup| tokens of its own. It will then process the |
| 134 | % other tokens some more, and set them up to be read again. This does |
| 135 | % mean that after the group ends, some assignments and other `stomach |
| 136 | % operations' will be performed, which may cause problems in |
| 137 | % alignments and similar places. |
| 138 | % |
| 139 | % \end{itemize} |
| 140 | % |
| 141 | % |
| 142 | % \subsection{Package options} |
| 143 | % |
| 144 | % There are a fair few \textsf{docstrip} options provided by this packge: |
| 145 | % |
| 146 | % \begin{description} |
| 147 | % \item [driver] extracts the documentation driver. This isn't usually |
| 148 | % necessary. |
| 149 | % \item [package] extracts the code as a standalone package, formatted for |
| 150 | % either \LaTeXe\ or Plain~\TeX. |
| 151 | % \item [latex2e] inserts extra identification code for a \LaTeXe\ package. |
| 152 | % \item [plain] inserts some extra code for a Plain \TeX\ package. |
| 153 | % \item [macro] just extracts the raw code, for inclusion in another package. |
| 154 | % \item [test] extracts some code for testing the current implementation. |
| 155 | % \end{description} |
| 156 | % |
| 157 | % |
| 158 | % \implementation |
| 159 | % |
| 160 | % \section{Implementation} |
| 161 | % |
| 162 | % \subsection{The main macro} |
| 163 | % |
| 164 | % We start outputting code here. If this is a Plain~\TeX\ package, we must |
| 165 | % make \lit{@} into a letter. |
| 166 | % |
| 167 | % \begin{macrocode} |
| 168 | %<*macro|package> |
| 169 | %<+plain>\catcode`\@=11 |
| 170 | % \end{macrocode} |
| 171 | % |
| 172 | % \begin{macro}{\doafter} |
| 173 | % |
| 174 | % The idea is to say \syntax{"\\doafter" <token> <group>} and expect the |
| 175 | % \synt{token} to be processed after the group has finished its stuff, |
| 176 | % even if it contains |\aftergroup| things. My eternal gratitude goes to |
| 177 | % Peter Schmitt, who came up with most of the solution implemented here; |
| 178 | % I've just tidied up some very minor niggles and things later. |
| 179 | % |
| 180 | % Let's start with some preamble. I'll save the (hopefully) primitive |
| 181 | % |\aftergroup| in a different token. |
| 182 | % |
| 183 | % \begin{macrocode} |
| 184 | \let\@@aftergroup\aftergroup |
| 185 | % \end{macrocode} |
| 186 | % |
| 187 | % Now to define the `user' interface. It takes a normal undelimited |
| 188 | % argument, although this must be a single token; otherwise eveything will |
| 189 | % go wrong. It assumes that the token following is some kind of group |
| 190 | % opening thing (an explicit or implicit character with catcode~1, or |
| 191 | % a |\begingroup| token). To make this work, I'll save the token, |
| 192 | % together with an |\@@aftergroup| (to save an |\expandafter| later) in |
| 193 | % a temporary macro which no-one will mind me using, and then look ahead at |
| 194 | % the beginning-group token. |
| 195 | % |
| 196 | % \begin{macrocode} |
| 197 | \def\doafter#1{% |
| 198 | \def\@tempa{\@@aftergroup#1}% |
| 199 | \afterassignment\doafter@i\let\@let@token% |
| 200 | } |
| 201 | % \end{macrocode} |
| 202 | % |
| 203 | % I now have the token in |\@let@token|, so I'll put that in. I'll then |
| 204 | % make |\aftergroup| do my thing rather than the normal thing, and queue |
| 205 | % the tokens |\@prepare@after| and the |\doafter| argument for later use. |
| 206 | % |
| 207 | % \begin{macrocode} |
| 208 | \def\doafter@i{% |
| 209 | \@let@token% |
| 210 | \let\aftergroup\@my@aftergroup% |
| 211 | \@@aftergroup\@prepare@after\@tempa% |
| 212 | } |
| 213 | % \end{macrocode} |
| 214 | % |
| 215 | % \end{macro} |
| 216 | % |
| 217 | % \begin{macro}{\@my@aftergroup} |
| 218 | % |
| 219 | % Now the cleverness begins. We keep two macros (Peter's original used |
| 220 | % count registers) which keep counts of the numbers of |\aftergroup|s, |
| 221 | % both locally and globally. Let's call the local counter~$n$ and the |
| 222 | % global one $N$. Every time we get a call to our |\aftergroup| hack, |
| 223 | % we set~$n := n+1$ and~$N := n$, and leave the token given to us for later |
| 224 | % processing. When we actually process an |\aftergroup| token properly, |
| 225 | % set~$N := N-1$ to indicate that it's been handled; when they're all done, |
| 226 | % we'll have $N=n$, which is exactly what we'd have if there weren't any |
| 227 | % to begin with. |
| 228 | % |
| 229 | % \begin{macrocode} |
| 230 | \def\ag@cnt@local{0 } |
| 231 | \let\ag@cnt@global\ag@cnt@local |
| 232 | % \end{macrocode} |
| 233 | % |
| 234 | % Now we come to the definition of my version of |\aftergroup|. I'll just |
| 235 | % add the token |\@after@token| before every |\aftergroup| token I find. |
| 236 | % This means there's two calls to |\aftergroup| for every one the user makes, |
| 237 | % but these things aren't all that common, so it's OK really. I'll also |
| 238 | % bump the local counter, and synchronise them. |
| 239 | % |
| 240 | % \begin{macrocode} |
| 241 | \def\@my@aftergroup{% |
| 242 | \begingroup% |
| 243 | \count@\ag@cnt@local% |
| 244 | \advance\count@\@ne% |
| 245 | \xdef\ag@cnt@global{\the\count@\space}% |
| 246 | \endgroup% |
| 247 | \let\ag@cnt@local\ag@cnt@global% |
| 248 | \@@aftergroup\@after@token\@@aftergroup% |
| 249 | } |
| 250 | % \end{macrocode} |
| 251 | % |
| 252 | % \end{macro} |
| 253 | % |
| 254 | % Now what does |\@after@token| we inserted above actually do? Well, this |
| 255 | % is more exciting. There are actually two different variants of the |
| 256 | % macro, which are used at different times. |
| 257 | % |
| 258 | % \begin{macro}{\@after@token} |
| 259 | % |
| 260 | % The default |\@after@token| starts a group, which will `catch' |
| 261 | % |\aftergroup| tokens which I throw at it. I put the two counters into |
| 262 | % some scratch count registers. (There's a slight problem here: Plain \TeX\ |
| 263 | % only gives us one. For the sake of evilness I'll use |\clubpenalty| as the |
| 264 | % other one. Eeeek.) I then redefine |\@after@token| to the second |
| 265 | % variant, and execute it. The |\@start@after@group| macro starts the |
| 266 | % group, because this code is shared with |\@prepare@after| below. |
| 267 | % |
| 268 | % \begin{macrocode} |
| 269 | \def\@after@token{% |
| 270 | \@start@after@group% |
| 271 | \@after@token% |
| 272 | } |
| 273 | \def\@start@after@group{% |
| 274 | \begingroup% |
| 275 | \count@\ag@cnt@global% |
| 276 | \clubpenalty\ag@cnt@local% |
| 277 | \let\@after@token\@after@token@i% |
| 278 | } |
| 279 | % \end{macrocode} |
| 280 | % |
| 281 | % \end{macro} |
| 282 | % |
| 283 | % \begin{macro}{\@after@token@i} |
| 284 | % |
| 285 | % I have $|\count@| = N$ and $|\@tempcnta| = n$. I'll decrement~$N$, |
| 286 | % and if I have $N = n$, I know that this is the last token to do, so I |
| 287 | % must insert an |\@after@all| after the token. This will close the group, |
| 288 | % and maybe insert the original |\doafter| token if appropriate. |
| 289 | % |
| 290 | % \begin{macrocode} |
| 291 | \def\@after@token@i{% |
| 292 | \advance\count@\m@ne% |
| 293 | \ifnum\count@=\clubpenalty% |
| 294 | \global\let\ag@cnt@global\ag@cnt@local% |
| 295 | \expandafter\@after@aftertoken\expandafter\@after@all% |
| 296 | \else% |
| 297 | \expandafter\@@aftergroup% |
| 298 | \fi% |
| 299 | } |
| 300 | % \end{macrocode} |
| 301 | % |
| 302 | % Finally, establish a default meaning for |\@after@all|. |
| 303 | % |
| 304 | % \begin{macrocode} |
| 305 | \let\@after@all\endgroup |
| 306 | % \end{macrocode} |
| 307 | % |
| 308 | % \end{macro} |
| 309 | % |
| 310 | % \begin{macro}{\@prepare@after} |
| 311 | % |
| 312 | % If this group is handled by |\doafter|, then the first |\aftergroup| token |
| 313 | % isn't |\@after@token|; it's |\@prepare@after|. |
| 314 | % |
| 315 | % There are some extra cases to deal with: |
| 316 | % \begin{itemize} |
| 317 | % \item If $N=n$ then there were no |\aftergroup| tokens, so we have an easy |
| 318 | % job. I'll just let the token do its stuff directly. |
| 319 | % \item Otherwise, $N>n$, and there are |\aftergroup| tokens. I'll open |
| 320 | % the group, and let |\@after@token| do all the handling. |
| 321 | % \end{itemize} |
| 322 | % |
| 323 | % \begin{macrocode} |
| 324 | \def\@prepare@after{% |
| 325 | \ifx\ag@cnt@local\ag@cnt@global\else% |
| 326 | \expandafter\@prepare@after@i% |
| 327 | \fi% |
| 328 | } |
| 329 | \def\@prepare@after@i#1{% |
| 330 | \@start@after@group% |
| 331 | \def\@after@all{\@@aftergroup#1\endgroup}% |
| 332 | } |
| 333 | % \end{macrocode} |
| 334 | % |
| 335 | % \end{macro} |
| 336 | % |
| 337 | % \begin{macro}{\@after@aftertoken} |
| 338 | % |
| 339 | % This is where all the difficulty lies. The next token in the stream is |
| 340 | % an |\aftergroup| one, which could be more or less anything. We have an |
| 341 | % argument, which is some code to do \emph{after} the token has been |
| 342 | % |\aftergroup|ed. |
| 343 | % |
| 344 | % If the token is anything other than a brace (i.e., an explicit character |
| 345 | % of category~1 or~2) then I have no problem; I can scoop up the token with |
| 346 | % an undelimited macro argument. But the only way I can decide if this token |
| 347 | % is a brace (nondestructively) is with |\futurelet|, which makes the token |
| 348 | % implicit, so I can't decide whether it's really dangerous. |
| 349 | % |
| 350 | % There is a possible way of doing this\footnote{Due to Peter Schmitt, |
| 351 | % again.} which relates to nobbling the offending token with |\string| and |
| 352 | % sifting through the results. The problem here involves scooping up all the |
| 353 | % tokens of a |\string|ed control sequence, which may turn out to be |
| 354 | % `|\csname\endcsname|' or something equally horrid. |
| 355 | % |
| 356 | % The solution I've used is much simpler: I'll change |\bgroup| and |\egroup| |
| 357 | % to stop them from being implicit braces before comparing. |
| 358 | % |
| 359 | % \begin{macrocode} |
| 360 | \def\@after@aftertoken#1{% |
| 361 | \let\bgroup\relax\let\egroup\relax% |
| 362 | \toks@{#1}% |
| 363 | \futurelet\@let@token\@after@aftertoken@i% |
| 364 | } |
| 365 | \def\@after@aftertoken@i{% |
| 366 | \ifcat\noexpand\@let@token{% |
| 367 | \@@aftergroup{% |
| 368 | \else\ifcat\noexpand\@let@token}% |
| 369 | \@@aftergroup}% |
| 370 | \else% |
| 371 | \def\@tempa##1{\@@aftergroup##1\the\toks@}% |
| 372 | \expandafter\expandafter\expandafter\@tempa% |
| 373 | \fi\fi% |
| 374 | } |
| 375 | % \end{macrocode} |
| 376 | % |
| 377 | % \end{macro} |
| 378 | % |
| 379 | % |
| 380 | % Phew! |
| 381 | % |
| 382 | % \begin{macrocode} |
| 383 | %<+plain>\catcode`\@=12 |
| 384 | %</macro|package> |
| 385 | % \end{macrocode} |
| 386 | % |
| 387 | % \subsection{Test code} |
| 388 | % |
| 389 | % The following code gives |\doafter| a bit of a testing. It's based on |
| 390 | % the test suite I gave to comp.text.tex, although it's been improved a |
| 391 | % little since then. |
| 392 | % |
| 393 | % The first thing to do is define a control sequence with an \lit{@} sign |
| 394 | % in its name, so we can test catcode changes. This also hides an |
| 395 | % |\aftergroup| within a macro, making life more difficult for prospective |
| 396 | % implementations. |
| 397 | % |
| 398 | % \begin{macrocode} |
| 399 | %<*test> |
| 400 | \catcode`\@=11 |
| 401 | \def\at@name{\aftergroup\saynine} |
| 402 | \def\saynine{\say{ix}} |
| 403 | \catcode`\@=12 |
| 404 | % \end{macrocode} |
| 405 | % |
| 406 | % Now define a command to write a string to the terminal. The name will |
| 407 | % probably be familiar to REXX hackers. |
| 408 | % |
| 409 | % \begin{macrocode} |
| 410 | \def\say{\immediate\write16} |
| 411 | % \end{macrocode} |
| 412 | % |
| 413 | % Test one: This is really easy; it just tests that the thing works at all. |
| 414 | % If your implementation fails this, it's time for a major rethink. |
| 415 | % |
| 416 | % \begin{macrocode} |
| 417 | \say{Test one... (1--2)} |
| 418 | \def\saytwo{\say{ii}} |
| 419 | \doafter\saytwo{\say{i}} |
| 420 | % \end{macrocode} |
| 421 | % |
| 422 | % Test two: Does |\aftergroup| work? |
| 423 | % |
| 424 | % \begin{macrocode} |
| 425 | \say{Test two... (1--4)} |
| 426 | \def\saythree{\say{iii}} |
| 427 | \def\sayfour{\say{iv}} |
| 428 | \doafter\sayfour{\say{i}\aftergroup\saythree\say{ii}} |
| 429 | % \end{macrocode} |
| 430 | % |
| 431 | % Test three: Test braces and |\iffalse| working as they should. Several |
| 432 | % proposed solutions based on |\write|ing the group to a file get upset by |
| 433 | % this test, although I forgot to include it in the torture test. It also |
| 434 | % tests whether literal braces can be |\aftergroup|ed properly. (Added a new |
| 435 | % test here, making sure that |\bgroup| is left as an implicit token.) |
| 436 | % |
| 437 | % \begin{macrocode} |
| 438 | \say{Test three... (1--4, `\string\bgroup', 5)} |
| 439 | \def\sayfive{\say{v}} |
| 440 | \doafter\sayfive{% |
| 441 | \say{i}% |
| 442 | \aftergroup\say% |
| 443 | \aftergroup{% |
| 444 | \aftergroup\romannumeral\aftergroup3% |
| 445 | \aftergroup}% |
| 446 | \iffalse}\fi% |
| 447 | \aftergroup\def% |
| 448 | \aftergroup\sayfouretc% |
| 449 | \aftergroup{% |
| 450 | \aftergroup\say% |
| 451 | \aftergroup{% |
| 452 | \aftergroup i% |
| 453 | \aftergroup v% |
| 454 | \aftergroup}% |
| 455 | \aftergroup\say% |
| 456 | \aftergroup{% |
| 457 | \aftergroup\string% |
| 458 | \aftergroup\bgroup% |
| 459 | \aftergroup}% |
| 460 | \aftergroup}% |
| 461 | \aftergroup\sayfouretc% |
| 462 | \say{ii}% |
| 463 | } |
| 464 | % \end{macrocode} |
| 465 | % |
| 466 | % Test four: Make sure the implementation isn't leaking things. This just |
| 467 | % makes sure that |\aftergroup| is its normal reasonable self. |
| 468 | % |
| 469 | % \begin{macrocode} |
| 470 | \say{Test four... (1--3)} |
| 471 | {\say{i}\aftergroup\saythree\say{ii}} |
| 472 | % \end{macrocode} |
| 473 | % |
| 474 | % Test five: Nesting, aftergroup, catcodes, grouping. This is the `torture' |
| 475 | % test I gave to comp.text.tex, slightly corrected (oops) and amended. It |
| 476 | % ensures that nested groups and |\doafter|s work properly (the latter is |
| 477 | % actually more likely than might be imagined). |
| 478 | % |
| 479 | % \begin{macrocode} |
| 480 | \say{Test five... (1--14)} |
| 481 | \def\sayten{\say{x}} |
| 482 | \def\saythirteen{\say{xiii}} |
| 483 | \def\sayfourteen{\say{xiv}} |
| 484 | \doafter\sayfourteen\begingroup% |
| 485 | \say{i}% |
| 486 | {\say{ii}\aftergroup\sayfour\say{iii}}% |
| 487 | \def\saynum{\say{viii}}% |
| 488 | \doafter\sayten{% |
| 489 | \say{v}% |
| 490 | \def\saynum{\say{vii}}% |
| 491 | \catcode`\@=11% |
| 492 | \aftergroup\saynum% |
| 493 | \say{vi}% |
| 494 | \at@name% |
| 495 | \saynum% |
| 496 | }% |
| 497 | \say{xi}% |
| 498 | \aftergroup\saythirteen% |
| 499 | \say{xii}% |
| 500 | \endgroup |
| 501 | \end |
| 502 | %</test> |
| 503 | % \end{macrocode} |
| 504 | % |
| 505 | % That's it. All present and correct. |
| 506 | % |
| 507 | % \Finale |
| 508 | % |
| 509 | \endinput |