% \iffalse Hi Emacs! This is -*-LaTeX-*- source ! \fi
\ifx\begin\undefined\else
\documentstyle[newdoc]{article}\MakePercentIgnore
\fi
% \title{The {\tt forvir.tex} virtual font generator}
% \author{David Kastrup}
% \CodelineIndex
% \EnableCrossrefs
% \begin{document}
% \maketitle
% \MakeShortVerb{\"}
% \begin{abstract}
% This is {\tt forvir.tex}, a foreign language virtual font generation
% package. Its purpose is to read in a suitable definition of foreign
% language virtual font and ligature requirements, and produce based
% on that information a bunch of {\tt vpl}-files from the
% corresponding {\tt pl}-files of the original fonts.  It must be read
% before processing your language definition file.  It requires plain
% \TeX{} to be preread (though hyphenation patterns and exceptions
% need not be loaded) or as a format, and should never produce a
% dvi-file.
%
%  The {\tt pl}-files can be derived by the utility {\tt pltotf}, and
%  the resulting files have to be converted into virtual
%  fonts and {\tt tfm}-files by~{\tt vptovf}.
%
%  These property list files resemble lisp code, and by proper
%  redefinition of "\catcode"\/s, \TeX{} is capable of scanning and
%  writing them at reasonable speed.
% \end{abstract}
% \tableofcontents
%
% \section{Implementation}
%
% We will make use of several special control sequences. For this
% reason we make the `"@"' character a~letter.
%    \begin{macrocode}
\catcode`\@=11
%    \end{macrocode}
% Since this is supposed to be the main file to be loaded, we do not
% care to save catcodes. In order to parse the lisp-like expressions
% of {\tt pl}-files, we make `"("' start a~control sequence, so that
% the first element of a list (which starts immediately after the
% opening parenthesis) will be interpreted as a~control word. We
% sometimes assemble a~control word by "\csname"\dots"\endcsname" and
% generate part of it by~"\string", so `"("' can become part of
% a~command name as well. This is because "\string" will produce
% "\escapechar" in the first character position, which we set to~`"("'
% in order to be able to write, say, `"\noexpand\LIG"' and get
% `"(LIG"'.
%
% Some other times, when we are parsing a~nested expression, we will
% make `"("' an opening brace. And sometimes we will have to output
% parens as well. 
%
% Since we can easily use real braces and backslashes in our file here
% when that functionality is desired, we will make `"("' a~letter
% while reading this file. Then we can use it in~"\write", and in
% command names.
%    \begin{macrocode}
\catcode`\(=11
%    \end{macrocode}
% \def\MakePrivateLetters{\makeatletter\catcode`\(11 }
% \begin{macro}{\vplfile}
% \begin{macro}{\vplwrite}
% What else do we need? A file to write our new virtual font
% information to:
%    \begin{macrocode}
\newwrite\vplfile
\def\vplwrite{\immediate\write\vplfile}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\font@}
% We need a~font to temporarily modify the values of "1ex" and "1em"
% depending on the font we are currently working with. We use a text
% font guaranteed to be present:
%    \begin{macrocode}
\let\font@=\nullfont
%    \end{macrocode}
% \end{macro}
% \subsection{Syntactical definitions}
% \begin{macro}{\lispdef}
%    Most of the time, we will syntactically have to interpret
%    lisp-like expressions. Those start with an opening brace, the
%    function name, and then the arguments followed by a~closing
%    brace.  We will want to convert this into a \TeX-like call.
%    Mostly, an opening brace will be our escape character, and
%    a~closing one will be an end-group character. We assume this
%    holds.
%
%    Now the real challenge is that we might have to pass some
%    parameters which are {\em not\/} included in the lisp-style
%    argument. These parameters {\em must\/} be single tokens, or the
%    whole scheme presented here will break. We write, for example,
%\begin{verbatim}
%\lispdef#1#2\xxx#3{...}
%\end{verbatim}
%   and mean that the macro "\xxx" gets passed two tokens in
%   \TeX-style, and one in Lisp-style. We need not even specify "#3"
%   here, the token will be converted to \TeX-style regardless of
%   whether it is actually included in the argument list. This is
%   because the conversion really consists only of tacking on
%   an~opening brace. This also means that the lisp-style argument
%   gets scanned only when really used, meaning that "\catcode"
%   changes can take effect when used in~"\lispdef" without
%   an~argument.
% \begin{macro}{\acclispdef}
%    We use
%    a~word called "\acclispdef" to accumulate the \TeX~parameters in
%    its first argument, starting with none. Th second argument is
%    an~`amendment' explained later.
%    \begin{macrocode}
\def\lispdef{\acclispdef{}{}}
%    \end{macrocode}
% \begin{macro}{\addhash}
% \begin{macro}{\endlispdef}
%    Now our first argument will be the accumulated list, our second
%    either a~hash mark, or the token we want to define. In the first
%    case, we call~"\addhash", in the second case~"\endlispdef".
%    \begin{macrocode}
\def\acclispdef#1#2#3{\ifx###3\expandafter\addhash \else
     \expandafter\endlispdef\fi #3{#1}{#2}}
%    \end{macrocode}
%    The first argument here will be the hash mark (I~really wanted to
%    error-check this by making the first argument "##", but for some
%    reason, \TeX{} does not allow this inside of parameter
%    lists). The fourth one will be the corresponding number, so this is
%    easy.
%    \begin{macrocode}
\def\addhash#1#2#3#4{\acclispdef{#2#1#4}{#3}}
%    \end{macrocode}
% \begin{macro}{\endlispdefii}
%    "\endlispdef" will just fix up a~proper macro name, and
%    call~"\endlispdefii".
%    \begin{macrocode}
\def\endlispdef#1{\expandafter\endlispdefii
        \csname lf@\string#1\endcsname #1}
%    \end{macrocode}
%    Now we are getting into {\em very\/} deep water. We want to
%    define our control sequence to call up the second control
%    sequence. We want it to take the \TeX{} arguments, and pass them
%    to our second one. We want to insert an opening brace after the
%    call to the second control sequence and the \TeX{} argument
%    tokens, this we can do by an appropriate "\iffalse" around
%    a~closing brace. It has to be reached by a~sequence
%    of~"\expandafter"s in order to be expanded before argument
%    recognition.
%
%    Are we having fun yet?
%    \begin{macrocode}
\def\endlispdefii#1#2#3#4{%
      \edef#2#3{#4\noexpand\expandafter
                \noexpand#1%
                \xpspread#3\end\end
                \noexpand\expandafter
                {\noexpand\iffalse}\noexpand\fi}%
      \def#1#3}
%    \end{macrocode}
% \begin{macro}{\xpspread}
%    "\xpspread" is supposed to insert appropriate "\expandafter"s
%    around the argument list, and stops when "\end\end" appears in
%    its argument list. Including "\end" as a~defined limiter
%    is an~instance of defensive programming. We could just use no
%    delimiter, and take the first non-hash token as such, but
%    undelimited parameters are unbraced, space-skipped, etc. Although
%    in the current version of "\endlispdefii" this would work, it
%    would not be so very modification-safe.
%
%    "\xpspread" gets {\em two\/} arguments, because at the time of
%    the macro call of~"\xpspread" (when executing the~"\edef") the
%    "#3" will have been replaced as an~"\endlispdefii" parameter with
%    a~string consisting of hash marks and numbers. Only when those
%    are contributed to the "\edef" are they converted into the final
%    parameter form by~\TeX.
%    \begin{macrocode}
\def\xpspread#1#2{\ifx#1\end \else
       \noexpand\expandafter ###2%
       \expandafter\xpspread\fi}
%    \end{macrocode}
%    Now "###2" will, after argument substitution, become
%    something like "#1", which the "\edef" will interpret
%    accordingly. When the definition is called later, this will be
%    replaced by a~single \TeX-like token, and it will have
%    an~"\expandafter" tacked on in front of it.
%
%    Imagine what fun I~had in debugging this. Wizards might enjoy
%    watching these macros in action via~"\tracingall".
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\lispdelimdef}
% \begin{macro}{\lisptackend}
% \begin{macro}{\lisptackendii}
% Sometimes we want to parse a~lisp expression which is unwrapped,
% without braces, and delimited by~"\end". We do this with
%    \begin{macrocode}
\def\lispdelimdef{\acclispdef{}%
       {\noexpand\expandafter\noexpand\lisptackend}}
%    \end{macrocode}
% Oh that was the reason for the ``amendment'' above!
%    \begin{macrocode}
\def\lisptackend#1#{\lisptackendii{#1}}
\def\lisptackendii#1#2{#1#2\end}
%    \end{macrocode}
%    How does this work? The "\noexpand"s are just for the sake of the
%    "\edef", and the "\expandafter" gets our brace expansion done.
%    This brace is used as an~argument delimiter for "\lisptackend"
%    (the tokens before cannot be braces) which has the main task of
%    wrapping up all up to the opening brace into braces again.
%    Afterwards, "\lisptackendii" unwraps both bracings, and tacks
%    the~"\end"~on.
% \end{macro}
% \end{macro}
% \end{macro}
% \subsection{Numeric conversions}
% In our source we have numbers represented in a special notation:
% a~letter followed by a representation of the value. We have
% \begin{description}
%    \item[D] followed by a decimal number.
%    \item[R] followed by a decimal fraction representing a~fixed
%             point number with 20~bits of decimals, usually in units
%             of the design size.
%    \item[O] followed by an octal number.
%    \item[H] followed by a~hexadecimal number.
%    \item[C] followed by a~character. This must be a~`harmless'
%             character, not a paren or the like. The standard tools
%             generate this number property only for letters and
%             digits, which is "\catcode"-safe.
%    \item[BOUNDARY] followed by nothing can appear in some properties
%                    as a number substitute. We convert this into the
%                    numerical value 256.
% \end{description}
% We want to have a unique representation of all those characters,
% which we can employ just as a number. And in case of real numbers,
% we want to preserve the full precision until we know what we will do
% with the number. So we will choose a~decimal representation, and
% we'll keep the strings in case of the `R' and `D' properties.
%
% \begin{macro}{\deccode}
% \begin{macro}{\deccodeii}
%    Ok, here we go. "\deccode" expands into a~decimal representation
%    of its argument. And `expansion' means that this works entirely
%    in~\TeX's mouth, i.e., in an~"\edef". We echo the tokens without
%    braces, then set up "\end" as a delimiter at the right of them,
%    and call "\deccodedelim" which will do the rest.  "BOUNDARY" gets
%    converted to~256, by the~way.
%    \begin{macrocode}
\def\deccode#1{\deccodedelim#1\end}
\def\deccodedelim#1{\csname gc@#1\endcsname}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\numconvert}
%    "\deccodeii" works by getting the next character, forming a
%    control sequence with the name "\gc@" followed by the appropriate
%    letter, and calling that. "gc" was probably an abbreviation for
%    `get converted', but I forgot.
%
%    Most conversions are done by "\numconvert", which works by
%    inserting an appropriate character and using the "\number"
%    primitive. Note how additional spaces before the number are
%    stripped by using "#2" as undelimited argument in~between. Note
%    also that the space after "#3" is swallowed by "\number".
%    \begin{macrocode}
\def\numconvert#1 #2#3\end{\number#1#2#3 }
\def\gc@O{\numconvert'}
\def\gc@H{\numconvert"}
\def\gc@C{\numconvert`}
%    \end{macrocode}
% \end{macro}
% Decimal and real conversions should just keep the value. We use two
% parameters here so that the first one is an undelimited parameter
% which will strip any leading spaces. For better syntax checking,
% however, we include one literal space as a~requirement.
%    \begin{macrocode}
\expandafter\def\expandafter\gc@D\space #1#2\end{#1#2}  \let\gc@R\gc@D
%    \end{macrocode}
% The last possibility is simply `"BOUNDARY"'. This is simple, if not
% droll.
%    \begin{macrocode}
\def\gc@B OUNDARY\end{256}
%    \end{macrocode}
% Ok, here is an extension: We want to be able to use an internally
% allocated number. We do this with `"N"' followed by the
% control sequence name (no escape character).
%    \begin{macrocode}
\expandafter\def\expandafter\gc@N \space #1#2\end{%
    \number\csname#1#2\endcsname}
%    \end{macrocode}
% \subsection{Printing dimensions}
%
% \begin{macro}{\aftergroupdimen}
% \begin{macro}{\contribute}
%    "\aftergroupdimen" will convert a dimensional value into a~real
%    representation, which will be gathered by "\aftergroup", complete
%    with "R" prefix. Of course, you will have to enclose the call by
%    "\begingroup \endgroup" and appropriate "\aftergroup"s telling
%    what to do with the string.
%
%    To put a whole string after the group (delimited
%    by "\end") we use "\contribute".
%    \begin{macrocode}
\def\contribute#1{%
        \ifx#1\end \let\next\relax \else \aftergroup#1%
        \let\next\contribute \fi\next}
%    \end{macrocode}
%    Ok, here we go with "\aftergroupdimen". `"R "' is first.
%    \begin{macrocode}
\def\aftergroupdimen#1{%
        \aftergroup R\expandafter\aftergroup\space
%    \end{macrocode}
%    Next we produce the sign, and assign the absolute value of the
%    dimension to "\dimen@i".
%    \begin{macrocode}
        \dimen@i #1\relax
        \ifdim\dimen@i<\z@
                \dimen@i -\dimen@i
                \aftergroup -%
        \fi
%    \end{macrocode}
%    Ok, now we can output the leading decimal digits. We get this by
%    putting them into "\dimen@". Oh, by the way, we output our value
%    relative to the dimension "\unit".
%    \begin{macrocode}
        \dimen@\dimen@i\divide\dimen@\unit
        \expandafter\contribute\number\dimen@\end
%    \end{macrocode}
%    Output a decimal point.
%    \begin{macrocode}
        \aftergroup.%
%    \end{macrocode}
%    Ok, now to the decimal fraction. Since our real variables have
%    20~fractional bits, we can safely represent them using 20~digits,
%    after which additional digits can not possibly have any influence
%    on the number representation. Of course, this is overkill, but
%    better safe than sorry. We use "\count@" as our loop variable.
%    \begin{macrocode}
        \count@ 20
        \loop
%    \end{macrocode}
%    First we put into "\dimen@i" the remainder of the last division
%    which produced the last digit in "\dimen@".
%    \begin{macrocode}
                \multiply\dimen@\unit
                \advance\dimen@i-\dimen@
%    \end{macrocode}
%    In case that the remainder is zero, we stop the procedure by
%    clearing our counter (so we don't really get 20~digits when they
%    would all be trivially zero).
%    \begin{macrocode}
                \ifdim\dimen@i=\z@ \count@\z@ \fi
%    \end{macrocode}
%    Ok, here comes the loop part. We multiply the remainder in
%    "\dimen@", which is now smaller than "\unit" by 10, and divide to
%    get the next digit of the expansion.
%    \begin{macrocode}
        \ifnum\count@>\z@
                \multiply\dimen@i 10
                \dimen@ \dimen@i
                \divide\dimen@ \unit
%    \end{macrocode}
%    Now we just contribute it and loop.
%    \begin{macrocode}
                \expandafter\aftergroup\number\dimen@
                \advance\count@\m@ne
        \repeat}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \subsection{Various property behaviours}
% \begin{macro}{\echodef}
% \begin{macro}{\echodo}
% \begin{macro}{\endecho}
%    "\echodef"\meta{name} defines the lisp `call' "("\meta{name}
%    simply as echoing itself along with its argument. This is used
%    for properties which are passed on without looking at them.
%
%    First we define "\echodef" as defining a control sequence
%    executing "\echodo" with itself as start of~argument.
%    \begin{macrocode}
\def\echodef#1{\def#1{\echodo#1}}
%    \end{macrocode}
%    Then we define "\echodo" to scan in a group, and put the lisp
%    call triggering it at the head of the token list. In order not to
%    interpret comments, allow them to have nested parentheses, and be
%    structured in lines, we have to adjust a~few "\catcode"s.
%    \begin{macrocode}
\lispdef\echodo{\begingroup
        \catcode`\(\@ne
        \catcode`\^^M12
        \endecho}
%    \end{macrocode}
%    And this is ended by calling "\endecho" which will write the
%    token list together with a closing `")"'. The opening one will
%    appear automagically because we will later adjust "\escapechar"
%    to `"("' instead of `"\"'.
%    \begin{macrocode}
\def\endecho#1{\endgroup\vplwrite{\noexpand#1)}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\getdef}
% \begin{macro}{\dogetdef}
%    "\getdef"\meta{name} will not echo, but put the scanned tokens in
%    the special global variable "\@v("\meta{name}.
%
%    We let this work by calling "\dogetdef" with the name of the control
%    sequence to be assigned. A~suitable "\gdef" is generated.
%    \begin{macrocode}
\def\getdef#1{\def#1{\dogetdef#1}}
\lispdef#1\dogetdef{\expandafter\gdef
           \csname @v\string#1\endcsname}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\defgetnumeric}
% \begin{macro}{\getnumeric}
%    "\defgetnumeric"\meta{name} is used to define a~lisp call which
%    will get and echo a numeric value. The echo will be ``as is'',
%    but the value will be converted into a decimal representation and
%    put into "\@v("\meta{name}.
%    \begin{macrocode}
\def\defgetnumeric#1{\def#1{\getnumeric#1}}
%    \end{macrocode}
%    We call "\endgetnumeric" with our token and with the string in
%    question as argument. Again, we will do an open brace by letting
%    the closing one disappear.
%    \begin{macrocode}
\lispdef#1\getnumeric#2{%
        \vplwrite{\noexpand#1#2)}%
        \expandafter\xdef\csname @v\string#1\endcsname
            {\deccode{#2}}}
%    \end{macrocode}
%    The way we did that you can use "\afterassignment" before calling
%    "\getnumeric", and it will be triggered just after the final
%    assignment.
% \end{macro}
% \end{macro}
% \begin{macro}{\deffontdimen}
% \begin{macro}{\getfontdimen}
%    We use this to directly enter into the
%    appropriate fontdimensions of our
%    scratch font "\font@". The fontdimens will be echoed as well.
%
%    We do this only to properly set up the values of~"1em"
%    and~"1ex". The other font dimensions are either just echoed or
%    got by "\getnumeric".
%
%    Syntax is "\deffontdimen"\meta{digit}\meta{name}
%
%    \begin{macrocode}
\def\deffontdimen#1#2{\def#2{\getfontdimen#1#2}}
%    \end{macrocode}
%    "\getfontdimen" is called with the digit, the name, and the
%    dimensional value.
%    \begin{macrocode}
\lispdef#1#2\getfontdimen#3{%
      \vplwrite{\noexpand#2#3)}%
      \fontdimen#1\font@ \deccode{#3}\unit}
%    \end{macrocode}
%    And what value did we assign to our font dimension? Why, the
%    numeric multiplied by our "\unit", the design size. \TeX{} will
%    do this multiplication reasonably nice by itself (it truncates
%    the numeric to 16 fractional bits, but that can be tolerated. The
%    results of the multiplication are pretty accurate).
% \end{macro}
% \end{macro}
% \begin{macro}{\ignoredo}
%    Sometimes we want a property to quietly disappear. Such
%    properties we "\let" to "\ignoredo".
%    \begin{macrocode}
\lispdef\ignoredo#1{}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\enterlist}
% \begin{macro}{\cparen}
%    "\enterlist"\meta{name} will enter the given list (printing its
%    name), scan it executing its internals, and exit afterwards. If
%    you want to do more after exiting the list, use "\aftergroup"
%    after "\enterlist"\meta{name}.
%
%    Most probably you will want a closing paren printed, and
%    "\aftergroup\cparen" will do the trick.
%    \begin{macrocode}
\def\enterlist#1{\vplwrite{\noexpand#1}\bgroup}
\def\cparen{\vplwrite{)}}
%    \end{macrocode}
%    Note that the "\bgroup" in "\enterlist" will be matched by the
%    closing~`")"' of the property.
% \end{macro}
% \end{macro}
% \section{The different Properties}
% \begin{macro}{\unit}
% \begin{macro}{\DESIGNSIZE}
% \begin{macro}{\endDESIGNSIZE}
%    We store the designsize in the dimension variable "\unit", which
%    we will first declare.
%    \begin{macrocode}
\newdimen\unit
%    \end{macrocode}
%    And of course, "\unit" will be set with
%    \begin{macrocode}
\def\DESIGNSIZE{\afterassignment\endDESIGNSIZE\getnumeric\DESIGNSIZE}
\def\endDESIGNSIZE{\unit \@v(DESIGNSIZE\p@}
%    \end{macrocode}
%    "\p@" is \TeX's shorthand for "pt", and of course the incredible
%    "\@v(DESIGNSIZE" contains a~decimal representation of the design
%    size.
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\CHECKSUM}
%    We save the checksum for later reference in our "(MAPFONT"
%    property.
%    \begin{macrocode}
\getdef\CHECKSUM
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\COMMENT}
%    We simply echo comments.
%    \begin{macrocode}
\echodef\COMMENT
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\CODINGSCHEME}
% \begin{macro}{\FAMILY}
% \begin{macro}{\FACE}
% \begin{macro}{\HEADER}
%    We do the same with a number of other operations of a~more or
%    less harmless nature.
%    \begin{macrocode}
\echodef\CODINGSCHEME
\echodef\FAMILY
\echodef\FACE
\echodef\HEADER
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\SEVENBITSAFEFLAG}
%    The "(SEVENBITSAFEFLAG" we let disappear silently: we would not
%    want a~warning just because we utilize upper character codes.
%    \begin{macrocode}
\let\SEVENBITSAFEFLAG=\ignoredo
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\BOUNDARYCHAR}
% This we simply echo.
%    \begin{macrocode}
\echodef\BOUNDARYCHAR
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\CHARACTER}
% Just for now\dots
%    \begin{macrocode}
\echodef\CHARACTER
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\FONTDIMEN}
% Just enter it.
%    \begin{macrocode}
\def\FONTDIMEN{\enterlist\FONTDIMEN\aftergroup\cparen}
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
\defgetnumeric\SLANT
\deffontdimen5\XHEIGHT
\deffontdimen6\QUAD
\echodef\SPACE
\echodef\STRETCH
\echodef\SHRINK
\echodef\EXTRASPACE
\defgetnumeric\CHARWD
\defgetnumeric\CHARHT
\defgetnumeric\CHARDP
\defgetnumeric\CHARIC
%    \end{macrocode}
% \subsection{Dealing with the Ligature Table}
%    The ligature table will present us with a~lot of~problems making
%    it desirable to read it in whole before starting any processing.
%    In order to do this fast (not having to rescan everything
%    whenever we enter a new word) we convert this into an internal
%    representation using just one giant "\edef". Since our input
%    contains a~lot of closing braces (and we need them to stay
%    closing braces of some sort, or the "\edef" will never end), we
%    will have to fake a lot of open ones, since we use `"("' not as
%    an open brace, but as an escape character. Unfortunately, it is
%    not much use defining a macro for a fake open brace, because it
%    will in most cases be easier to fake them directly instead of
%    wondering how often to expand the macro for it to work.
% \begin{macro}{\LIGTABLE}
%    Ligature tables are processed pretty simply.
%    \begin{macrocode}
\lispdef\LIGTABLE{\vplwrite{\noexpand\LIGTABLE}%
%    \end{macrocode}
%    That was almost all needed to be done. Let's go:
%    \begin{macrocode}
        \begingroup \afterassignment\endLIGTABLE
        \edef\ligtable}
%    \end{macrocode}
%    After the "\edef" has finished, "\endLIGTABLE" will
%    be~called, which is really just the start. Note that this "\edef"
%    will accumulate the whole ligature table.
%
%    A~slight ugliness remains to be told:
%    The~single properties of the "LIGTABLE" are usually (when
%    "tftopl" has generated the file) separated by
%    newlines, which are equivalent to spaces. These spaces will creep
%    into our ligature table, and there is not much we can do
%    about~it. We cannot use "\ignorespaces" since it is not
%    expandable, we cannot use a~macro taking an undelimited argument
%    (thus stripping spaces) because that macro would fail after the
%    last property. We {\em could}, however, set the "\catcode" of
%    newline to `ignore', but if ligature tables were to be formatted
%    differently, we might get burned if a~newline were to indicate
%    a~syntactically necessary space. When we are finally executing
%    our ligature tables, the spaces will be executed, doing nothing
%    (because we are in vertical mode at the time). We tolerate that.
% \end{macro}
% Now we define the things we want to have our expressions expand to.
% \begin{macro}{\ligtable}
%    We will read in our ligature table and store it in a~reasonably
%    compact form as a~macro called~"\ligtable". This macro will
%    contain entries of the following sort:
%    \begin{description}
%    \item["\bslash dolabel"\meta{dec. code}\meta{text code}] is the entry
%        for a~"(LABEL" directive. The~\meta{dec. code} is the label
%        code converted into decimal (for a unique representation),
%        the~\meta{text code} is the label code in its original text
%        representation which we will employ when writing the ligature
%        table for better readability.
%    \item["\bslash dolig"\meta{ligtype}\meta{dec. code}\meta{text code}%
%        \meta{contents}] represents a~kern or ligature node, where
%        \meta{ligtype} is a control sequence like "\KRN" or~"\LIG",
%        the codes are as above, and the \meta{contents} are the
%        concluding element of the instruction.
%    \item["\bslash dostop"] represents the "(STOP" instruction.
%    \item["\bslash doinsert\{"\meta{insertion matter}"\}"] will be put into the
%        list for material that has to be surrounded by appropriate
%        "(SKIP" instructions as to not influence the behaviour of
%        ligature code encountered before. This will be introduced
%        only by the first pass.
%    \end{description}
% \end{macro}
% \begin{macro}{\LABEL}
%    Labels will be entered as a~macro called "\dolabel" with two
%    arguments. The first is the decimal representation of the label,
%    the second one the original of the~source.
%    \begin{macrocode}
\lispdef\LABEL#1{\dolabel{\deccode{#1}}{#1}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\STOP}
% \begin{macro}{\gobble}
%    We treat "(STOP" next because it is so easy to~do. Almost. We
%    have to discard the (empty) argument.
%    \begin{macrocode}
\lispdef\STOP#1{\dostop}
\def\gobble#1{}
%    \end{macrocode}
%    We will certainly need this definition of~"\gobble" a~few more
%    times.
% \end{macro}
% \end{macro}
% \begin{macro}{\ligdef}
%    We use "\ligdef" to define all ligature and kern commands. It
%    will call "\getlig" with a repetition of its~argument.
%    \begin{macrocode}
\def\ligdef#1{\def#1{\getlig#1}}
\ligdef\LIG
\expandafter\ligdef\csname /LIG\endcsname
\expandafter\ligdef\csname /LIG>\endcsname
\expandafter\ligdef\csname LIG/\endcsname
\expandafter\ligdef\csname LIG/>\endcsname
\expandafter\ligdef\csname /LIG/\endcsname
\expandafter\ligdef\csname /LIG/>\endcsname
\expandafter\ligdef\csname /LIG/>>\endcsname
\ligdef\KRN
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\getlig}
%    What will "\getlig" have to do? Take the command code, the
%    relevant character code (two blank-ended words) and the action
%    (in case of ligatures, a character code, in case of a~kern,
%    a~dimension), and form a~proper "\dolig" command with decimal
%    code, original code and rest.
%    \begin{macrocode}
\lispdelimdef#1\getlig#2 #3#4 #5#6\end{%
     \dolig#1{\deccode{#2 #3#4}}{#2 #3#4}{#5#6}}
%    \end{macrocode}
% \end{macro}
% \subsubsection{The parsing passes on the Ligature Table}
% Basically we do a~number of passes on the ligature table in order to
% properly work in all the changes to it. All of these passes with the
% exception of the output pass work inside of an "\edef", that means
% \TeX's mouth. They cannot perform any assignments or do any actual
% actions due to that, but only macro expansions. We will see,
% however, that this can accomplish a~lot.
%
% The reason we use only one "\edef" here to build up a whole large
% table, instead of adding bit for~bit by separate "\edef"s is that
% this would use up time growing quadratically with the size of the
% generated list, whereas the single "\edef" uses time only linearly
% proportional to the size of the list---a~difference not to be
% sneezed~at!
%
% The output pass does not build any tables any more, so it is pretty
% much linear in time as well, although it is not buried in
% an~"\edef", does assignments, and calls the counting pass.
%
% Before further ramblings, here are our passes:
% \begin{description}
%     \item[Reading the table in]
%     This performs just a~translation into a more or less compact
%     macro form, and directly uses the ligature table information
%     from the file as input. `"("' is an escape character, `")"'~is a
%     closing brace (the latter is necessary to let the closing brace
%     of the "(LIGTABLE" instruction end our~"\edef"). Due to that,
%     a~lot of unmatched open braces have to be produced by our
%     macros. This is taken care of by the "\lispdef"~macros.
%     \item[Pass~I]
%     Here we handle `mimicking', where a~new character will behave
%     like another one when encountered as the right of a~kern
%     instruction, and `substitutions', where a~label instruction can
%     be modified by adding additional code or additional labels,
%     perhaps with own code, and so on. Labels occuring before
%     insertions are moved behind the insertions, and insertions
%     itself can again contain mimics or substitutions.
%     \item[Pass~II]
%     This is the output pass, which writes the modified ligature
%     table to the ".vpl"~file. Apart from writing out the separate
%     commands, it will have to handle insertions by putting skip
%     commands around them. It intermittently preparses insertions in
%     counting mode for that reason. Furthermore, all active
%     substitutions encountered during this pass are disabled for the
%     remaining substitution pass.
%     \item[Counting pass]
%     This simply advances "\stepcount" for every ligature or kern
%     step encountered.
%     \item[Remaining substitutions pass]
%     This does all the substitutions not already done. It has to do
%     them properly, utilizing both of the main passes in order to get
%     everything necessary done.
% \end{description}
%
% \begin{macro}{\doperhaps}
%    Ok, here follow the pass constructs. "\doperhaps" will look at
%    its argument, and if it is not the same as "\relax" (as all
%    undefined "\csname"\dots"\endcsname" constructs are) it is
%    expanded, else it is discarded.
%    \begin{macrocode}
\def\doperhaps#1{\ifx#1\relax\else\expandafter#1\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pisetup}
% \begin{macro}{\pidef}
% \begin{macro}{\pidefii}
% \begin{macro}{\pilet}
%    During pass~I, several macros will have a reassigned behaviour.
%    We define a pass~I behaviour using "\pidef". It will define
%    a~macro with the appropriate behaviour, and will put
%    a~"\let"-assignment of this macro to the original one into the
%    token register~"\pisetup".
%    \begin{macrocode}
\newtoks\pisetup       \pisetup{}
\def\pidef#1{%
    \expandafter\pidefii
    \expandafter#1\csname pi\string#1\endcsname}
\def\pidefii#1#2{%
           \pisetup\expandafter{\the\pisetup\let#1#2}%
           \def#2}
%    \end{macrocode}
%    "\pilet" can be used, too.
%    \begin{macrocode}
\def\pilet#1=#2{\pisetup\expandafter{\the\pisetup\let#1#2}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\piisetup}
% \begin{macro}{\piidef}
% \begin{macro}{\piidefii}
%    This is just as above, only for the output pass (pass~II).
%    \begin{macrocode}
\newtoks\piisetup      \piisetup{}
\def\piidef#1{%
    \expandafter\piidefii
    \expandafter#1\csname pii\string#1\endcsname}
\def\piidefii#1#2{%
           \piisetup\expandafter{\the\piisetup\let#1#2}%
           \def#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\cntsetup}
% \begin{macro}{\cntdef}
% \begin{macro}{\cntdefii}
%    When inserting material, we sometime have to know how much we
%    have to insert, in~order to be able to put an appropriate skip
%    around the inserted material. We do this not really in a~separate
%    pass, but in piecewise partial passes (this is elaborated later).
%
%    However, all the same technique applies.
%    \begin{macrocode}
\newtoks\cntsetup      \cntsetup{}
\def\cntdef#1{%
    \expandafter\cntdefii
    \expandafter#1\csname cnt\string#1\endcsname}
\def\cntdefii#1#2{%
           \cntsetup\expandafter{\the\cntsetup\let#1#2}%
           \def#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\stepcount}
%    Before we forget it: The counter for this is called "\stepcount".
%    \begin{macrocode}
\newcount\stepcount
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\ifskipneeded}
% \begin{macro}{\skipneededtrue}
% \begin{macro}{\skipneededfalse}
%    Oh, and another thing we might forget later on: the conditional
%    indicating whether there have been any ligature or kern steps in
%    the current program, making it necessary to include a~`"SKIP"'
%    command when doing insertions.
%    \begin{macrocode}
\newif\ifskipneeded
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\dostop}
%    Now we start to define all this little words embedded into our
%    ligature table. We start with "\dostop". As long as we are not in
%    any special passes, we want it to expand to itself, or rather,
%    not to~expand at~all, like~"\relax".
%    \begin{macrocode}
\let\dostop=\relax
%    \end{macrocode}
%    This behaviour needs no change whatsoever in pass~I.
%    Unfortunately, however, we will have to switch back and forth
%    between pass~I settings and pass~II settings in one and the same
%    group, and so every pass~II definition must be offset by one for
%    pass~I.
%    \begin{macrocode}
\pilet\dostop=\relax
%    \end{macrocode}
%
%    In pass~II, the output pass, we have a~slight complication: we
%    want to write a~stop command only if there is any unfinished
%    ligature program remaining. It~is if the macro "\ifskipneeded",
%    indicating a~necessary skip if we were to insert any matter, is
%    true.
%
%    Strictly speaking, this can only happen when we are flushing code
%    substitutions which were not handled in the normal ligature
%    table, but that we'll explain later.
%    \begin{macrocode}
\piidef\dostop{\ifskipneeded
        \vplwrite{(STOP)}%
        \skipneededfalse \fi}
%    \end{macrocode}
%    A~stop command simply does not count in skip distances. So we
%    do nothing in the count~pass.
%    \begin{macrocode}
\cntdef\dostop{}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\doinsert}
% \begin{macro}{\complexinsert}
%    Now insertions are hairy matter. The way we do substitutes, an
%    insertion is {\em guaranteed\/} to contain some ligature or kern
%    step at its end. Thus the label rearrangement business in pass~I
%    will work properly without intervention even inside of
%    insertions.
%
%    This makes it possible to let insertions stay passive in pass~I
%    by~default. Note, however, that the {\em contents\/} of
%    an~insertion are expanded, thus properly handling mimics and
%    other~stuff.
%    \begin{macrocode}
\let\doinsert=\relax
\pilet\doinsert=\relax
%    \end{macrocode}
%    In pass~II, insertions are complicated. When no active code has
%    been done before (there cannot be any labels without code before
%    an insertion, because they would have been moved to after the
%    insertion), the insertion can be simply dropped~in. Otherwise
%    matters are more complex.
%    \begin{macrocode}
\piidef\doinsert{%
      \ifskipneeded \expandafter\complexinsert
      \else \expandafter\unbrace \fi}
%    \end{macrocode}
%    Ok, the complex way is to first count the amount of inserted
%    material, write an appropriate `"SKIP"' command to skip over it,
%    and then just do the insertion. Unfortunately, we have to skip
%    not only this insertion, but {\em all\/} up to the next ligature
%    or kern step. Here we go. The undelimited argument is needed for
%    unbracing, by~the~way.
%    \begin{macrocode}
\def\complexinsert#1#2\dolig{\begingroup\the\cntsetup
         \skipcount\z@ #1#2%
         \vplwrite
                {\noexpand\SKIP D\number\skipcount)}%
         \endgroup \skipneededfalse #1#2\dolig}
%    \end{macrocode}
%    Of course, when counting through, insertion material is treated
%    like any other material. To avoid grouping, however, we have to
%    unbrace it.
%    \begin{macrocode}
\cntdef\doinsert#1{#1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\dolig}
%    We define a~non-expanding behaviour by default for~"\dolig". And
%    this behaviour will have to extend to its first argument.
%    \begin{macrocode}
\def\dolig{\noexpand\dolig\noexpand}
%    \end{macrocode}
%    A~ligature mode needs to be treated special only if it is a~kern.
%    In that case we check for the presence of "mimic" prefixes which
%    will cause another character to kern just like the given one.
%    This needs to know the code to mimic, and if there is no~mimic
%    code there, we will have to gobble this argument.
%    \begin{macrocode}
\pidef\dolig#1#2#3#4{\ifx#1\KRN
      \expandafter\doperhaps
      \csname @m#2\endcsname\gobble{#4}\fi
%    \end{macrocode}
%    We have to deal with another case: in order to be able to
%    properly remove spurious labels in the remaining substitutions
%    pass, we use the special ligature code "\dolig\end\end\end\end",
%    which will have to disappear, and be replaced by a~stop command.
%    \begin{macrocode}
      \ifx#1\end \dostop \else
           \noexpand\dolig\noexpand#1{#2}{#3}{#4}\fi}
\piidef\dolig#1#2#3#4{%
      \vplwrite{\noexpand#1#3 #4)}%
      \skipneededtrue}
\cntdef\dolig#1#2#3#4{\advance\stepcount\@ne}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\COPYKRN}
% \begin{macro}{\addtomimic}
%     How to set up such a~"\mimic" behaviour? With "(COPYKRN"\dots")"
%     which gets two arguments, the first being the code to treat, the
%     second that it should be likened to. Both will be in the list
%     number format. First we package this into a complete argument.
%    \begin{macrocode}
\lispdelimdef\COPYKRN #1 #2#3 #4#5\end{%
    \expandafter\addtomimic
    \csname m@\deccode{#4#5}\endcsname{#1 #2#3}}
%    \end{macrocode}
%    This was just a little preparation of the arguments. Now we~go.
%    \begin{macrocode}
\def\addtomimic#1#2{%
       \edef#1\gobble##1{\doperhaps#1\gobble{##1}%
%    \end{macrocode}
%    Whoa, what will that do? Nothing if "#1" was yet undefined, and
%    it will echo "#1" with "##1" (that is, the string "#1", not the
%    argument) at exact the locations we need, if it was already
%    defined.
%    \begin{macrocode}
          \domimic{\deccode{#2}}{#2}{##1}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\domimic}
%    And what do we have to do with a~mimic call encountered in
%    pass~I? Easy as pie. Note that this can call further mimics into
%    action. Note also that the arguments are readily prepared.
%    \begin{macrocode}
\let\domimic=\relax
\pidef\domimic{\dolig\KRN}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\dolabel}
%    And what do we have to do with labels? For labels we might have
%    substitutes, code to be used instead. And such substitutes must
%    not come {\em after\/} any labels without intervening ligature ot
%    kern commands. So what we do is basically the following: if we
%    have a~substitute, we replace our label by it. If we haven't, we
%    inactivate further expansion, move our label directly before the
%    next ligature or kern command, and work on possibly intervening
%    labels probably to be substituted.
%    \begin{macrocode}
\let\dolabel=\relax
\pidef\dolabel#1#2{\expandafter
      \doperhaps\csname @s#1\endcsname
      \domovelabel{\noexpand\dolabel{#1}{#2}}}
\piidef\dolabel#1#2{%
      \vplwrite{\noexpand\LABEL #2)}%
      \expandafter\let\csname @s#1\endcsname \empty}
\cntdef\dolabel#1#2{}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\domovelabel}
%    This will move the label, as told above. The default behaviour of
%    "\domovelabel" is just to echo its argument (without braces). And
%    the code for "\domovelabel" on pass~I will
%    move our label to the front of the next "\dolig".
%    \begin{macrocode}
\def\unbrace#1{#1}
\let\domovelabel=\unbrace
\pidef\domovelabel#1#2\dolig#3{%
       #2\ifx#3\end \else#1\fi \dolig#3}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\prefixes}
% \begin{macro}{\registerprefix}
%     This here registers a~possible prefix in "\prefixes", a token
%     register. It also puts a~label representation into "\next".
%    \begin{macrocode}
\newtoks\prefixes
\prefixes{}

\def\registerprefix#1#2{%
     \edef\next{\noexpand\dolabel{\deccode{#2}}{#2}}%
     \ifx#1\relax
          \prefixes\expandafter\expandafter\expandafter{%
                \expandafter\the\expandafter\prefixes
                \expandafter#1\expandafter\domovelabel
                \expandafter{\next}\dolig\end\end\end\end}%
     \fi}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\COPYLIG}
% \begin{macro}{\sameas}
%    Now a substitute will replace a~label, and be called with the~label
%    as its argument, wrapped in a~"\domovelabel". One possible
%    substitute, for example, can be done with
%    "\SameLigaturesAs"\meta{no1}\meta{no2} which gets two list
%    numbers as its argument, and places a~label for~\meta{no1} before
%    that of~\meta{no2}.
%
%    We first fix up the arguments a~bit.
%    \begin{macrocode}
\lispdelimdef\COPYLIG #1 #2#3 #4#5\end{%
     \expandafter\sameas
     \csname @s\deccode{#4#5}\endcsname{#1 #2#3}}
%    \end{macrocode}
%    This gets increasingly hairy. Remember that an already defined
%    prefix will dismantle the "\domovelabel", while if none is
%    defined, at this stage the "\domovelabel" will dismantle itself.
%    This is all necessary because when the prefix is finally used, it
%    will really {\em have\/} to dismantle an active "\domovelabel".
%
%    We again use the trick of passing "##1" as first parameter
%    (literally speaking, it is `"#1"') in order to keep things ready
%    till we really need the parameter.
%    \begin{macrocode}
\def\sameas#1#2{%
     \registerprefix#1{#2}%
     \edef#1\domovelabel##1{%
          \doperhaps#1%
          \domovelabel{\next##1}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\AMENDLIG}
% \begin{macro}{\sameplus}
%    If you thought that the last lines were hairy, well here for
%    something even nicer: "AMENDLIG" gets three arguments,
%    and the third one is additional ligature code which will be used
%    together with the ligature code copied from the second argument
%    as a~ligature table for the first one.
%
%    First, again, argument massaging.
%    \begin{macrocode}
\lispdelimdef\AMENDLIG #1 #2#3 #4#5 #6#7 {%
     \expandafter\sameplus
     \csname @s\deccode{#4#5 #6#7}\endcsname{#1 #2#3}}
%    \end{macrocode}
%    Well, strictly speaking this is not so much different from the
%    above, only that we now form an insertion instead of the label.
%    But I~strongly suggest that you ponder the actions initiated
%    depending on whether "\doperhaps" finds an expandable macro or
%    not. And note that the `point of interest', where a~label would
%    be placed, or where the next substitute command builder will
%    insert something, moves nicely around with "##1" to magically be
%    where it is needed.
%    \begin{macrocode}
\def\sameplus#1#2#3#4\end{%
     \registerprefix#1{#2}%
     \edef#1\domovelabel##1{%
           \doperhaps#1%
           \domovelabel{\doinsert{\next#3#4}##1}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\ADDLIG}
% \begin{macro}{\prefprog}
%    Well, here is the last substitute mangler: a prefix is an
%    additional piece of ligature (additional to the original one,
%    that is) which will be executed before the other (original)
%    steps. The implementation should now appear straightforward (if
%    you understood the last few chunks).
%    \begin{macrocode}
\lispdelimdef\ADDLIG#1 #2#3 {%
    \expandafter\prefprog
    \csname @s\deccode{#1 #2#3}\endcsname{#1 #2#3}}
\def\prefprog#1#2#3#4\end{%
     \registerprefix#1{#2}%
     \edef#1\domovelabel##1{%
         \doperhaps#1%
         \domovelabel{\doinsert{##1#3#4}}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\endLIGTABLE}
%    Ok, now we are ready for doing the pass~I constructs. Don't worry
%    about us fouling up the various "\do" commands: they will be
%    restored on return from the group.
%    \begin{macrocode}
\def\endLIGTABLE{%
    \the\pisetup \edef\ligtable{\ligtable}%
%    \end{macrocode}
%    This was the entire pass~I? A~single simple "\edef"? Well in that
%    case we better move to pass~II:
%    \begin{macrocode}
    \the\piisetup
%    \end{macrocode}
%    And now we just go for it:
%    \begin{macrocode}
    \ligtable
%    \end{macrocode}
%    Ok, now we still might have prefixes not used. We handle them
%    here:
%    \begin{macrocode}
    \the\pisetup
    \edef\ligtable{\expandafter\empty\the\prefixes}
    \the\piisetup \ligtable
%    \end{macrocode}
%    That should about have rounded up our ligature table. We should
%    be able to close the matter now.
%    \begin{macrocode}
    \cparen\endgroup}
%    \end{macrocode}
% \end{macro}
% \subsection{Accents}
% Accents are accessed as special control sequences. They
% consist of a box, with the width being the horizontal shift
% needed for a character of height~0,
% the height similar, the depth being the overhang of the accent
% (its height minus the xheight of its font).
% The second element of an accent is a font selecting control sequence.
% If called, it will return a map number, and will allocate one
% if necessary.
% The third element is "\chardef"ed to the character code of the accent.
% \begin{macro}{\newaccent}
%    These will be temporarily assigned to "\accentbox", "\accentfont"
%    and "\accentchar". We use "\next" here to temporarily hide the
%    outerness of~"\newbox".
%
%    \begin{macrocode}
\let\@tempa\newbox
\let\newbox\relax
\lispdef\NEWACCENT#1{%
              \newbox\next%
              \expandafter\xdef\csname#1\endcsname
                  {{\number\next}\relax{0}}}
\let\newbox\@tempa
\let\@tempa\relax
\def\get@ccent#1#2#3{%
        \chardef\accentbox#1%
        \def\accentfont{#2}%
        \chardef\accentchar#3\relax}
\def\getaccent#1{\get@ccent#1}

\def\convertit#1{%
\begingroup
\font@
\immediate\openout\vplfile=#1.vpl
\def\do##1{\catcode`##112 }\dospecials
\catcode`\/11
\catcode`\>11 % This is for /LIG> commands and the like
\escapechar`(
\catcode`\)\tw@
\catcode`\(\z@
\newlinechar`\^^M
\catcode`\ 10
%    \end{macrocode}
%    We do not want to have carriage returns to have any effect, so we
%    change their category to `ignore'. This will {\em still\/} strip
%    spaces ("\catcode 10") at the start of line. And at the end
%    of~line, spaces are stripped anyhow at a~very early stage by the
%    line reading routines of~\TeX{} (long before "\catcode"s
%    are considered).
%    \begin{macrocode}
     \catcode`\^^M10
\vplwrite{\noexpand\VTITLE Accent replacement of #1)}%
\input #1.pl
\vplwrite{\noexpand\MAPFONT D 0 \noexpand\FONTNAME #1)%
        \noexpand\FONTCHECKSUM \@v(CHECKSUM ))}%
\immediate\closeout\vplfile
\endgroup}
\catcode`\@=12
\catcode`\(=12
%    \end{macrocode}
% \end{macro}
% \PrintIndex
% \end{document}
