% \iffalse
%
% $Id: MagmaTeX.dtx,v 1.24 2002/10/04 02:25:02 don Exp $
%
% Copyright © 2002 by Don Taylor «don@maths.usyd.edu.au»
%
%% This file provides LaTeX and plain TeX versions of the MagmaTeX macros
%% that support literate Magma scripts. They are based on the plain TeX
%% macros (lambdaTeX) written for Haskell by Patryk Zadarnowski.
%% The original copyright notice for lambdaTeX is reproduced below.
%%
%% Copyright © 2000 Patryk Zadarnowski «pat@jantar.org»
%%
%% Redistribution  and  use  in  source  and  binary  forms,  with  or  without
%% modification, are permitted provided  that the following conditions are met:
%% (1) Redistributions of  source code must retain the  above copyright notice,
%% this list  of conditions and the following  disclaimer.  (2) Redistributions
%% in  binary form  must reproduce  the above  copyright notice,  this  list of
%% conditions and  the following disclaimer  in the documentation  and/or other
%% materials provided  with the distribution.  (3)  The name of  any author may
%% not  be used  to  endorse or  promote  products derived  from this  software
%% without their specific prior written permission.
%%
%% THIS SOFTWARE IS  PROVIDED ``AS IS'' AND ANY  EXPRESS OR IMPLIED WARRANTIES,
%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
%% FITNESS FOR  A PARTICULAR  PURPOSE, ARE DISCLAIMED.   IN NO EVENT  SHALL THE
%% AUTHORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
%% OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT  NOT LIMITED  TO,  PROCUREMENT OF
%% SUBSTITUTE  GOODS OR SERVICES;  LOSS OF  USE, DATA  OR PROFITS;  OR BUSINESS
%% INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
%% CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
%% ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
%% POSSIBILITY OF SUCH DAMAGE.
%% ********************************************************************
%%
% \fi
%
% \CheckSum{3097}
%% \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         \~}
%
% \iffalse
% Copyright © 2002 by Don Taylor «don@maths.usyd.edu.au»
%
%    \begin{macrocode}
%<magma>\NeedsTeXFormat{LaTeX2e}[1996/12/01]
%<plain>\def\filename{MagmaTeX.tex}
%<plain>\def\fileversion{$Revision: 1.24 $ - $Date: 2002/10/04 02:25:02 $}
%    \end{macrocode}
%
%    Announce the package and its version.
%
%    \begin{macrocode}
%<magma>\ProvidesPackage{MagmaTeX}
%<*driver>
\ProvidesFile{magmatex.drv}
%</driver>
%<*magma|driver>
           [2002/10/04 v1.24
%</magma|driver>
%<magma>   LaTeX package for literate Magma]
%    \end{macrocode}
%
%    This bit of code contains the documentation driver file for \TeX{}
%    and \LaTeXe{}, i.e., the file that will produce the documentation
%    you are currently reading. It can be extracted from this file by the
%    \textsc{docstrip} program.
%    \begin{macrocode}
%<*driver>
]
\documentclass[a4paper]{ltxdoc}
\GetFileInfo{magmatex.drv}
\setcounter{StandardModuleDepth}{1}
\RecordChanges
\newcommand{\Magma}{{\normalfont\scshape Magma}}
\begin{document}
\providecommand{\Lenv}[1]{\textsf{#1}}
\providecommand{\Lpkg}[1]{\texttt{#1}}
\DocInput{MagmaTeX.dtx}
\PrintChanges
\end{document}
%</driver>
%    \end{macrocode}
% \fi
%
% \changes{v1.18}{2002/09/03}{Removed rogue spaces from \cs{ifx} constructions}
%
% \title{Literate programming with \Magma-\TeX
% \thanks{This file has version number \fileversion,
%         last revised \filedate.}}
% \author{Don Taylor}
% \date{Printed: \today}
%
% \maketitle
%
% \begin{abstract}
%    This document describes the \Magma-\TeX{} package.  It is a
%    collection of \LaTeXe{} macros for processing literate \Magma\
%    scripts. The macros are derived from the plain \TeX{} macros
%    (\texttt{lambdaTeX}) written for literate Haskell by
%    Patryk Zadarnowski.
% \end{abstract}
%
% \section{Introduction}
%
%    A ``literate programming'' style encourages good documentation by
%    integrating program code with comments in such a way that the comments
%    become the primary focus. The file can be processed with a typesetting
%    system such as \TeX{} or \LaTeXe{} to produce printable output and the
%    code can be extracted and passed to the relevant compiler or interpreter.
%    Even better, in some cases, the file itself can be passed to the compiler
%    or interpreter.
%
%    Literate programming has its origins in Donald Knuth's \texttt{WEB} and
%    \texttt{CWEB} systems for Pascal and C programming respectively.
%    Auxiliary programs \texttt{tangle} and \texttt{weave} extract the code
%    and typeset the documentation using (plain) \TeX.
%
%    Following Knuth, a ``literate comment'' convention was developed by
%    Richard Bird and Philip Wadler for the functional programming languages
%    Orwell and Haskell.  In this style a line in which |>| is the first
%    character is treated as part of the program; all other lines are
%    treated as comments.  Several Haskell interpreters (such as Hugs98)
%    can read ``literate'' scripts, discarding all lines except those
%    beginning with |>|. The \texttt{lambdaTeX} macros, written by Patryk
%    Zadarnowski, typeset a literate script directly, without resorting to
%    any preprocessing.
%
%    The macros defined in this file are based on \texttt{lambdaTeX} and
%    provide the proper syntax highlighting for the \Magma\ programming
%    language.  Currently [September, 2002], the \Magma\ system does not
%    support the direct loading of literate scripts and so a preprocessor
%    is needed to extract the program code from the script. The executable code
%    is recovered by taking only those lines beginning with |>|, and deleting
%    the first two characters of each of those lines.  The Python program
%    \texttt{magmacode.py} provided with this distribution does precisely this.
%
%    \section{Typesetting \Magma\ code}
%    The author of a literate \Magma\ script that is to be typeset with
%    \Magma-\TeX{} does not need to learn very many new macros. In fact, it
%    is enough to preface each line of executable code with |>| and ensure
%    that each block of code ends with a blank line.
%
%    \DescribeMacro>
%    When \Magma-\TeX\ encounters the |>| character it enters a ``|magma|
%    mode''.  This is implemented as a lexical analyser that recognizes
%    \Magma\ lexemes and typesets them with appropriate syntax highlighting.
%
%    \DescribeMacro\magmanames
%    All \Magma\ keywords are recognized by \Magma-\TeX{} but function names
%    and intrinsics defined in the \Magma\ code will not be known to the lexical
%    analyser. To remedy this, a comma separated list of strings that should be
%    typeset as function, intrinsics or variables can be supplied to \Magma-\TeX
%    via the |\magmanames| macro. To indicate a variable, prefix its name in the
%    list with the |!| character.  To indicate an intrinsic, prefix its name with
%    the \verb=|= character. All other names in the list are assumed to refer to
%    functions.  For example,
%    \begin{center}
%       \verb=\magmanames{myfunction,|myIntrinsic,!MyVariable}=
%    \end{center}
%
%    By default, any single letter lexeme is assumed to be a variable.  Any
%    lexeme of more than one letter beginning with an upper case letter or
%    with \texttt{p} followed by an upper case letter is assumed to be an
%    intrinsic; all other identifier lexemes are assumed to be variables.
%    This covers most cases and it should not be necessary to have a long
%    list of identifiers in |\magmanames|.
%
%    \DescribeMacro"
%    The \Magma-\TeX\ macros support an |inline| \Magma\ mode for including code
%    fragments within the documentation comments.  This is done by putting the code
%    fragment between a pair of double quote characters |"| (for example,
%    |"Z := Integers();"|).  Within the |inline| mode newlines are treated as simple
%    whitespace and \Magma\ comments are illegal.   Because the quote character
%    terminates the mode, strings cannot appear in this mode.
%
%    \DescribeMacro\mmleftskip
%    \DescribeMacro\mmrightskip
%    \DescribeMacro\beforemm
%    \DescribeMacro\aftermm
%    \DescribeMacro\everymm
%    As mentioned above, |magma| mode is entered by the |>| character and
%    exits when it encounters a blank line.  (Actually, if it encounters a
%    line not beginning with |>| the mode will exit but the first character
%    of the line will be lost.) The text is typeset as a separate paragraph,
%    indented by |\mmleftskip| on the left and |\mmrightskip| on the right.
%    The |\beforemm| macro is inserted before the fragment of code and
%    |\aftermm| is inserted after it. The |>| character itself is not
%    displayed. In both |magma| and |inline| mode, the |\everymm| macro is
%    inserted immediately after entering |Magma| mode.
%
%    \DescribeMacro<
%    The character |<| has also been made active and its effect is to
%    typeset any text between |<| and |>| in italic. The meanings of |<| and
%    |>| are restored within math formulas.
%
%    By convention, the style of comment is indicated by the file extension,
%    with \texttt{.m} indicating a usual \Magma\ file and \texttt{.lm}
%    indicating a literate \Magma\ file. Using this style, a typical
%    \Magma{} intrinsic would appear in the file as
%
%    \begin{verbatim}
%     > intrinsic SimpleReflections ( C::AlgMatElt ) -> []
%     > {The simple reflection matrices for a given Cartan matrix}
%     >   n := Ncols( C );
%     >   rho := [ Id(M) : k in [1..n] ] where M is Parent(C);
%     >   for k := 1 to n do
%     >   for i := 1 to n do        // only column `k` needs changing
%     >      rho[k][i,k] := rho[k][i,k] - C[i,k];
%     >   end for;
%     >   end for;
%     >   return rho;
%     >  end intrinsic;
%    \end{verbatim}
%
% \subsection{Limitations}
%  This section is an edited version of the Limitations and Quirks sections
%  of the \texttt{lambdaTeX} file.
%
%   \begin{enumerate}
%   \item No support for strings in |inline| mode.
%   \item Function names must be marked as such explicitly.
%   \item Names beginning with an upper case letter are assumed to be intrinsics.
%   \item $<$ or $>$ as the first character in math mode doesn't work.
%   \item Code lines don't wrap. (But perhaps this is the correct behaviour.)
%   \end{enumerate}
%
%   \Magma-\TeX\ reserves |<|, |>| and |"| as active characters but
%   restores the meaning of |<| and |>| in math mode. However, this
%   doesn't work as well as expected. When \TeX{} sees the \$
%   character, it reads the following character to see if it is
%   another \$ beginning a math display. If that character is active,
%   it attempts to expand it.  So, you must write |$ >$| rather than |$>$|.
%
%   \DescribeMacro\lt
%   \DescribeMacro\gt
%   To make amends for this, the macros |\lt| and |\gt| are provided to
%   complement |\le| and |\ge| already in \TeX{} and \LaTeXe.
%   Fortunately, one rarely needs to write a relational operator as the first
%   character in a formula and, of course, |$a>b$| works as expected.
%
%   When parsing |//|-style comments, the lexical analyser temporarily switches
%   out of |magma| mode, so that the normal document fonts can take effect.
%   In order to avoid strange behaviour (due to category code changes), the
%   character immediately following |//| should be a space.
%
%   Font selection the \PlainTeX{} version is somewhat limited. There is
%   just one size provided for all text set in |magma| and |inline| mode, namely 10pt.
%   In the \LaTeXe{} version things are slightly better because the font
%   changing commands pick up the size of the document font.  This
%   fits in well with the standard 10pt, 11pt and 12pt options of many class
%   files and also works with the \Lpkg{slides} class and \Lpkg{foiltex}. On
%   other hand, font selection in math mode needs further work.  Currently, low
%   level \TeX{} commands (viz. |\mathchar|) are  used in both the \PlainTeX{} and
%   \LaTeXe{} versions.
%
%  \section{The \Lpkg{code} environment}
%
%  \DescribeEnv{code}
%    In addition to including executable code in the file it is often
%    useful to provide examples of \Magma\ input illustrating a particular
%    construction or algorithm.  For cases like this we provide the
%    \texttt{code} environment. This environment simply prints the code
%    verbatim without any attempt to recognize the \Magma\ tokens. Any
%    syntax highlighting must be given explicitly.  Code marked up in this
%    way is not intended to be extracted and passed to \Magma. On the other
%    hand it is a useful environment in which to set out the higher level
%    aspects of algorithms in pseudo-code.
%
% \section{Package options}
%  \changes{v1.19}{2002/09/04}{Added the the \texttt{linenumbers} package option}
%  \DescribeEnv{linenumbers}
%    This is the only option provided for this package.  When in force, all
%    code lines will be numbered at the left hand margin.  It would be fairly
%    easy to extend this to provide index entries for all occurrences of functions,
%    intrinsics and variables, modelled on the \Lpkg{doc} package.
%
%
% \DescribeMacro\LineNumbers
% \DescribeMacro\NoLineNumbers
%    When the \texttt{linenumbers} option is used, two additional macros become
%    available: \cmd{\LineNumbers} and \cmd{\NoLineNumbers}.  These turn line
%    numbering of \Magma{} code on and off.  To reset the actual line number to
%    a chosen value, use the standard \LaTeXe{} \cmd{\setcounter} command with
%    the counter \texttt{MagmaLineNo}.  For example, |\setcounter{MagmaLineNo}{0}|.
% \StopEventually{}
%
% \section{The {\normalfont\scshape docstrip} modules}
%
% The following can be passed to the \textsc{docstrip} program to selectively
% generate the external files:
% \begin{center}
% \begin{tabular}{ll}
%   magma   & produce the \Lpkg{MagmaTeX} package for \LaTeXe\\
%   code    & produce the \Lenv{code} environment\\
%   plain   & produce the \texttt{MagmaTeX.tex} file for \PlainTeX\\
%   driver  & produce a documentation driver file \\
% \end{tabular}
% \end{center}
%
% The default behaviour of the installation file should be to include the
% \Lenv{code} environment in the \Lpkg{MagmaTeX} package.  Do this by
% passing |{magma,code}| to \textsc{docstrip}.
%
% \section{Implementation}
%
% In \PlainTeX{} we need to provide our own mechanism to lock
% out multiple loading of the macro file.  We also store the existing
% catcode of `@', then change its catcode so that it can be used
% in `private' \TeX{} control sequences.  The original catcode
% is restored at the end of the package.
%
%    \begin{macrocode}
%<*plain>
\expandafter\ifx\csname\filename\endcsname\fileversion
  \message{[already loaded]}\endinput\fi
\expandafter\ifx\csname\filename\endcsname\relax % file not yet loaded
  \else\message{Discrepancy in `\filename' file versions:
     version \csname\filename\endcsname\space already loaded.
     Now loading}\fi
\expandafter\xdef\csname\filename\endcsname{%
  \catcode`\noexpand\@=\the\catcode`\@
  \expandafter
    \gdef\expandafter\noexpand\csname\filename\endcsname{\fileversion}}
\catcode `\@=11
%</plain>
%    \end{macrocode}
%
% \begin{macro}{\everymm}
% \begin{macro}{\beforemm}
% \begin{macro}{\beforemm}
%  The macro |\beforemm| will be expanded just before entering
%  |magma| mode, |\everymm| will be expanded just after entering
%  |magma| mode and |\aftermm| will be expanded on leaving |magma|
%  mode.
%    \begin{macrocode}
%<*magma|plain>
\def\everymm{}
\def\beforemm{\vskip 6pt plus3pt minus1pt}
\def\aftermm{\vskip 4pt plus3pt minus1pt}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \section{Line numbers}
% \begin{macro}{linenumbers}
% Sometimes it might be useful to number all the code lines in the printed
% documentation.  To handle this (in \LaTeXe{} only) we provide the
% \texttt{linenumbers} option.  This is the only option provided by
% by this package.
% \end{macro}
%
% \begin{macro}{\mm@ndx}
% Line numbers are handled by invoking the macro \cmd{\mm@ndx} at the
% beginning of each code line (see \cmd{\mm@outputline}).  In \PlainTeX,
% and when the \texttt{linenumbers} option is not present, this has no
% effect.
%    \begin{macrocode}
\let\mm@ndx=\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c@MagmaLineNo}
% \begin{macro}{\LineNumbers}
% \begin{macro}{\NoLineNumbers}
% In \LaTeXe{}, the \texttt{linenumbers} option sets \cmd{mm@ndx}
% to \cmd{\mm@CodeLineNo}, which advances the counter \cmd{\c@MagmaLineNo}
% and then typesets the resulting number.
%
%    \begin{macrocode}
%<*magma>
\newif\ifmm@numbered \mm@numberedfalse
\newcount\c@MagmaLineNo \c@MagmaLineNo\z@
\def\mm@CodeLineNo{\global\advance\c@MagmaLineNo\@ne
  \rlap{\quad\llap{\reset@font\scriptsize\arabic{MagmaLineNo}}}}
\def\LineNumbers{\let\mm@ndx\mm@CodeLineNo}
\def\NoLineNumbers{\let\mm@ndx=\relax}
\DeclareOption{linenumbers}{\LineNumbers}
\ProcessOptions
%</magma>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Fonts}
%    \begin{macrocode}
%<*plain>
%    \end{macrocode}
%
% For the \PlainTeX{} version, the fonts needed for syntax
% highlighting are loaded with explicit |\font| commands. The
% font families are \texttt{phv} and \texttt{pcr}, where the \texttt{p}
% means PostScript, \texttt{hv} means Helvetica and \texttt{cr} means
% Courier.
%
%    \begin{macrocode}
\font\mm@keyface=phvb at 10pt    % bold                keywords
\font\mm@funface=phvr at 10pt    % normal              functions
\font\mm@varface=phvro at 10pt   % oblique             variables
\font\mm@intrface=phvrc at 10pt  % caps and small caps intrinsics
\font\mm@boolface=phvrrn at 10pt % narrow              boolean operators
\font\mm@relface=phvbo at 10pt   % bold oblique        relations
\font\mm@consface=phvbo at 10pt  % bold oblique        constructors
\font\mm@numface=phvr at 10pt    % normal              numbers
\font\mm@strface=pcrr at 10pt    % normal              strings
\font\mm@symface=phvr at 10pt    % normal              symbols
\font\mm@ssymface=phvr at 7pt    % normal              sub/super scripts
\font\mm@sssymface=phvr at 5pt   % normal
%    \end{macrocode}
% We turn off all hyphenation in these fonts.  [It is not clear that
% the last two fonts above are ever used.]
%    \begin{macrocode}
\hyphenchar\mm@keyface=-1
\hyphenchar\mm@funface=-1
\hyphenchar\mm@varface=-1
\hyphenchar\mm@intrface=-1
\hyphenchar\mm@relface=-1
\hyphenchar\mm@symface=-1
\hyphenchar\mm@numface=-1
\hyphenchar\mm@strface=-1
\hyphenchar\mm@ssymface=-1
\hyphenchar\mm@sssymface=-1
%</plain>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*magma>
%    \end{macrocode}
%
% \changes{v1.3}{2002/08/15}{Added NFSS font handling}
% For the \LaTeXe{} version we tap into the NFSS.  We use the
% same names as above, but now the control sequences will not be
% direct references to fonts.  Instead they will be font changing
% macros.
%
% \changes{v1.15}{2002/08/29}{Changed the font mechanism so that Magma
%     superscripts are set in a small size}
%
% \begin{macro}{\mm@sz}
% \begin{macro}{\mm@ssz}
%  The first thing to do is to get the size of the main document font.
%  Perhaps this should use \cmd{\AtBeginDocument}, but this simple
%  approach should take care of most cases.
%    \begin{macrocode}
\newdimen\mm@sz
\mm@sz=\f@size pt
\newdimen\mm@ssz
\mm@ssz=0.8\mm@sz
\def\mm@size{\mm@sz}%
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
\DeclareFontFamily{OT1}{mmphv}{\hyphenchar\font=-1}
%
\DeclareFontShape{OT1}{mmphv}{m}{n}{ <-> s * [0.91] phvr}{}
\DeclareFontShape{OT1}{mmphv}{b}{n}{ <-> s * [0.91] phvb}{}
\DeclareFontShape{OT1}{mmphv}{m}{sl}{<-> s * [0.91] phvro}{}
\DeclareFontShape{OT1}{mmphv}{m}{sc}{<-> s * [0.91] phvrc}{}
\DeclareFontShape{OT1}{mmphv}{m}{c}{ <-> s * [0.91] phvrrn}{}
\DeclareFontShape{OT1}{mmphv}{b}{sl}{<-> s * [0.91] phvbo}{}
%
\DeclareFontFamily{OT1}{mmpcr}{\hyphenchar\font=-1}
\DeclareFontShape{OT1}{mmpcr}{m}{n}{<-> pcrr}{}
%
\DeclareFixedFont{\mm@symface}{OT1}{mmphv}{m}{n}{\mm@sz}
\DeclareMathSizes{\mm@ssz}{}{}{}
%
\def\mm@keyface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{b}{n}}%
\def\mm@funface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{m}{n}}%
\def\mm@varface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{m}{sl}}%
\def\mm@intrface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{m}{sc}}%
\def\mm@boolface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{m}{c}}%
\def\mm@relface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{b}{sl}}%
\def\mm@consface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{b}{sl}}%
\def\mm@numface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmphv}{m}{n}}%
\def\mm@strface{\fontsize{\mm@size}\z@ \usefont{OT1}{mmpcr}{m}{n}}%
%</magma>
%    \end{macrocode}
%
% \begin{macro}{\mmleftskip}
% \begin{macro}{\mmrightskip}
% \begin{macro}{\mmcommentskip}
% \begin{macro}{\mmwordspace}
% \begin{macro}{\mmspacewidth}
% \begin{macro}{\mmtabwidth}
% We need to set some defaults for a number of skip
% dimensions.  All of these can be overridden by the user.
% Some of this could be done a lot better.  For example,
% rather than a fixed space corresponding to a tab character
% the package should move to the next tab stop. Also, the
% way the lexical analyser emits tokens short-circuits \TeX's
% internal spacing mechanisms.  Perhaps it would be possible to create
% a custom version of math mode with the spacing we need.  This
% may allow better breaking of long code lines. (But do we really
% want that?)
% \changes{v1.20}{2002/09/05}{Removed \cs{mm@beforerel} and \cs{mm@afterrel}}
%    \begin{macrocode}
\newdimen\mmleftskip    \mmleftskip=30pt
\newdimen\mmrightskip   \mmrightskip=10pt
\newdimen\mmcommentskip \mmcommentskip=1em
\newdimen\mmwordspace
\newdimen\mmspacewidth
\newdimen\mmtabwidth
%
\setbox0=\hbox{N}
\mmwordspace=.5\wd0
\mmspacewidth=\wd0
\mmtabwidth=8\wd0
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\Magma}
%  Since literate scripts will often refer to \Magma, we provide a
%  convenient macro for this purpose.
%    \begin{macrocode}
\def\Magma{{\mm@intrface Magma}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Keywords, functions, intrinsics and variables}
%
% \begin{macro}{\typeset}
% Each lexeme produced by the lexical analyser is turned into a
% control sequence consisting of the lexeme bracketed by |<| and |>|.
% If this control sequence is defined, then its expansion used to
% typeset the lexeme. The |\typeset| macro is used to define the
% special formatting of a specific lexeme.
%    \begin{macrocode}
\def\typeset#1#2{\expandafter\def\csname<#1>\endcsname{#2}}
%    \end{macrocode}
% \end{macro}
%
% The \Magma\ keywords were obtained from the files |res.t| and
% |semi_res.t| used by the lexical analyser of \Magma\ itself.
% The following keywords are reserved in \Magma\, as is the
% underscore character |_|.  (But note that \Magma\ accepts |_|
% within the name of a variable.)
%    \begin{macrocode}
\typeset{assert}{{\mm@keyface assert}}
\typeset{assigned}{{\mm@keyface assigned}}
\typeset{break}{{\mm@keyface break}}
\typeset{by}{{\mm@keyface by}}
\typeset{case}{{\mm@keyface case}}
\typeset{clear}{{\mm@keyface clear}}
\typeset{continue}{{\mm@keyface continue}}
\typeset{declare}{{\mm@keyface declare}}
\typeset{default}{{\mm@keyface default}}
\typeset{delete}{{\mm@keyface delete}}
\typeset{div}{{\mm@keyface div}}
\typeset{do}{{\mm@keyface do}}
\typeset{elif}{{\mm@keyface elif}}
\typeset{else}{{\mm@keyface else}}
\typeset{end}{{\mm@keyface end}}
\typeset{error}{{\mm@keyface error}}
\typeset{exists}{{\mm@keyface exists}}
\typeset{exit}{{\mm@keyface exit}}
\typeset{for}{{\mm@keyface for}}
\typeset{forall}{{\mm@keyface forall}}
\typeset{forward}{{\mm@keyface forward}}
\typeset{fprintf}{{\mm@keyface fprintf}}
\typeset{freeze}{{\mm@keyface freeze}}
\typeset{function}{{\mm@keyface function}}
\typeset{if}{{\mm@keyface if}}
\typeset{iload}{{\mm@keyface iload}}
\typeset{import}{{\mm@keyface import}}
\typeset{intrinsic}{{\mm@keyface intrinsic}}
\typeset{is}{{\mm@keyface is}}
\typeset{local}{{\mm@keyface local}}
\typeset{load}{{\mm@keyface load}}
\typeset{mod}{{\mm@keyface mod}}
\typeset{print}{{\mm@keyface print}}
\typeset{printf}{{\mm@keyface printf}}
\typeset{procedure}{{\mm@keyface procedure}}
\typeset{quit}{{\mm@keyface quit}}
\typeset{read}{{\mm@keyface read}}
\typeset{readi}{{\mm@keyface readi}}
\typeset{repeat}{{\mm@keyface repeat}}
\typeset{require}{{\mm@keyface require}}
\typeset{requirege}{{\mm@keyface requirege}}
\typeset{requirerange}{{\mm@keyface requirerange}}
\typeset{restore}{{\mm@keyface restore}}
\typeset{return}{{\mm@keyface return}}
\typeset{save}{{\mm@keyface save}}
\typeset{select}{{\mm@keyface select}}
\typeset{then}{{\mm@keyface then}}
\typeset{time}{{\mm@keyface time}}
\typeset{to}{{\mm@keyface to}}
\typeset{until}{{\mm@keyface until}}
\typeset{vprint}{{\mm@keyface vprint}}
\typeset{vprintf}{{\mm@keyface vprintf}}
\typeset{vtime}{{\mm@keyface vtime}}
\typeset{when}{{\mm@keyface when}}
\typeset{where}{{\mm@keyface where}}
\typeset{while}{{\mm@keyface while}}
%    \end{macrocode}
%
% The following \Magma\ reserved word behaves more like a
% constructor and so will be set with the constructor
% typeface.
%    \begin{macrocode}
\typeset{random}{{\mm@consface random}}
%    \end{macrocode}
%
% \changes{v1.23}{2002/09/09}{Added italic correction for relations}
% The \Magma\ keywords for relations are also reserved.
%    \begin{macrocode}
\typeset{adj}{{\mm@relface adj\/}}
\typeset{and}{{\mm@relface and\/}}
\typeset{cat}{{\mm@relface cat\/}}
\typeset{cmpeq}{{\mm@relface cmpeq\/}}
\typeset{cmpne}{{\mm@relface cmpne\/}}
\typeset{diff}{{\mm@relface diff\/}}
\typeset{eq}{{\mm@relface eq\/}}
\typeset{ge}{{\mm@relface ge\/}}
\typeset{gt}{{\mm@relface gt\/}}
\typeset{in}{{\mm@relface in\/}}
\typeset{join}{{\mm@relface join\/}}
\typeset{le}{{\mm@relface le\/}}
\typeset{lt}{{\mm@relface lt\/}}
\typeset{meet}{{\mm@relface meet\/}}
\typeset{ne}{{\mm@relface ne\/}}
\typeset{not}{{\mm@relface not\/}}
\typeset{notadj}{{\mm@relface notadj\/}}
\typeset{notin}{{\mm@relface notin\/}}
\typeset{notsubset}{{\mm@relface notsubset\/}}
\typeset{or}{{\mm@relface or\/}}
\typeset{sdiff}{{\mm@relface sdiff\/}}
\typeset{subset}{{\mm@relface subset\/}}
\typeset{xor}{{\mm@relface xor\/}}
%    \end{macrocode}
%
% In addition to reserved words, \Magma\ has the following
% semi-reserved words, used as constructors.
%
%    \begin{macrocode}
\typeset{car}{{\mm@consface car}}
\typeset{comp}{{\mm@consface comp}}
\typeset{cop}{{\mm@consface cop}}
\typeset{elt}{{\mm@consface elt}}
\typeset{ext}{{\mm@consface ext}}
\typeset{frac}{{\mm@consface frac}}
\typeset{func}{{\mm@consface func}}
\typeset{hom}{{\mm@consface hom}}
\typeset{ideal}{{\mm@consface ideal}}
\typeset{iso}{{\mm@consface iso}}
\typeset{lideal}{{\mm@consface lideal}}
\typeset{loc}{{\mm@consface loc}}
\typeset{map}{{\mm@consface map}}
\typeset{ncl}{{\mm@consface ncl}}
\typeset{pmap}{{\mm@consface pmap}}
\typeset{proc}{{\mm@consface proc}}
\typeset{quo}{{\mm@consface quo}}
\typeset{rec}{{\mm@consface rec}}
\typeset{recformat}{{\mm@consface recformat}}
\typeset{rep}{{\mm@consface rep}}
\typeset{rideal}{{\mm@consface rideal}}
\typeset{sub}{{\mm@consface sub}}
%    \end{macrocode}
%
% \Magma\ boolean values:
%    \begin{macrocode}
\typeset{true}{{\mm@boolface true}}
\typeset{false}{{\mm@boolface false}}
%    \end{macrocode}
%
% As an extra frill, an identifier given as the string name of
% a greek letter will be typeset as a symbol rather than as a word.
%    \begin{macrocode}
\typeset{alpha}{$\alpha_{\mm@sub}$}
\typeset{beta}{$\beta_{\mm@sub}$}
\typeset{gamma}{$\gamma_{\mm@sub}$}
\typeset{delta}{$\delta_{\mm@sub}$}
\typeset{epsilon}{$\epsilon_{\mm@sub}$}
\typeset{zeta}{$\zeta_{\mm@sub}$}
\typeset{eta}{$\eta_{\mm@sub}$}
\typeset{theta}{$\theta_{\mm@sub}$}
\typeset{iota}{$\iota_{\mm@sub}$}
\typeset{kappa}{$\kappa_{\mm@sub}$}
\typeset{lambda}{$\lambda_{\mm@sub}$}
\typeset{mu}{$\mu_{\mm@sub}$}
\typeset{nu}{$\nu_{\mm@sub}$}
\typeset{xi}{$\xi_{\mm@sub}$}
\typeset{pi}{$\pi_{\mm@sub}$}
\typeset{rho}{$\rho_{\mm@sub}$}
\typeset{sigma}{$\sigma_{\mm@sub}$}
\typeset{tau}{$\tau_{\mm@sub}$}
\typeset{upsilon}{$\upsilon_{\mm@sub}$}
\typeset{phi}{$\phi_{\mm@sub}$}
\typeset{chi}{$\chi_{\mm@sub}$}
\typeset{psi}{$\psi_{\mm@sub}$}
\typeset{omega}{$\omega_{\mm@sub}$}
%    \end{macrocode}
%
%  In \PlainTeX{} the control sequence \cmd{\mit} changes to family 1.
%  In \LaTeXe{} it is defined in major class files such as \Lpkg{article},
%  \Lpkg{slides}, and \Lpkg{foils} (in \Lpkg{fltfonts.def}).  To avoid
%  a potential problem if it is not defined, we give a provisional
%  definition.
%
%    \begin{macrocode}
%<magma>\providecommand{\mit}{\@fontswitch\relax\mathnormal}
\typeset{Alpha}{$\mit A_{\mm@sub}$}
\typeset{Beta}{$\mit B_{\mm@sub}$}
\typeset{Gamma}{$\Gamma_{\mm@sub}$}
\typeset{Delta}{$\Delta_{\mm@sub}$}
\typeset{Epsilon}{$\mit E_{\mm@sub}$}
\typeset{Zeta}{$\mit Z_{\mm@sub}$}
\typeset{Eta}{$\mit H_{\mm@sub}$}
\typeset{Theta}{$\Theta_{\mm@sub}$}
\typeset{Iota}{$\mit I_{\mm@sub}$}
\typeset{Kappa}{$\mit K_{\mm@sub}$}
\typeset{Lambda}{$\Lambda_{\mm@sub}$}
\typeset{Mu}{$\mit M_{\mm@sub}$}
\typeset{Nu}{$\mit N_{\mm@sub}$}
\typeset{Xi}{$\Xi_{\mm@sub}$}
\typeset{Pi}{$\mit\Pi_{\mm@sub}$}
\typeset{Rho}{$\mit P_{\mm@sub}$}
\typeset{Sigma}{$\Sigma_{\mm@sub}$}
\typeset{Tau}{$\mit T_{\mm@sub}$}
\typeset{Upsilon}{$\Upsilon_{\mm@sub}$}
\typeset{Phi}{$\Phi_{\mm@sub}$}
\typeset{Chi}{$\mit X_{\mm@sub}$}
\typeset{Psi}{$\Psi_{\mm@sub}$}
\typeset{Omega}{$\Omega_{\mm@sub}$}
%    \end{macrocode}
%
% The same treatment is applied to a few other mathematical symbols.
%    \begin{macrocode}
\typeset{aleph}{$\aleph_{\mm@sub}$}
\typeset{infinity}{$\infty_{\mm@sub}$}
\typeset{nabla}{$\nabla_{\mm@sub}$}
%    \end{macrocode}
%
% Here are some more \Magma\ lexemes that we choose to typeset
% using \TeX\ symbols.
%    \begin{macrocode}
\typeset{::}{${}\mathrel{::}{}$}
\typeset{..}{${}\ldotp\ldotp{}$}
\typeset{<-}{${}\leftarrow{}$}
\typeset{->}{${}\rightarrow{}$}
\typeset{:->}{${}\mapsto{}$}
\typeset{=>}{${}\Rightarrow{}$}
\typeset{;}{{\kern.1em\mm@funface ;}}
\typeset{,}{{\mm@funface,\kern.15em\relax}}
%    \end{macrocode}
%
% \begin{macro}{\magmanames}
%  \Magma\ syntax does not distinguish between functions, intrinsics and variables,
%  but we would like to typeset each kind of name differently. Therefore, we
%  define a |\magmanames| macro that accepts a comma-separated list of names.
%  To indicate a variable, prefix its name in the list with the |!| character.
%  To indicate an intrinsic, prefix its name with the \verb=|= character.
%  All other names in the list are assumed to refer to functions.
%    \begin{macrocode}
\def\magmanames(#1){\def\mm@tok{}\mm@funbegin#1\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@funbegin}
% \begin{macro}{\mm@varcollect}
% \begin{macro}{\mm@intrcollect}
% The collection process is carried out by a small finite state
% machine with states |\mm@funbegin|, |\mm@varcollect|, and
% |\mm@intrcollect|.  It can be seen that the code accepts space
% and tab characters as well as commas as list separators.
%
%    \begin{macrocode}
\def\mm@funbegin#1{%
 \ifx#1\relax
  \let\next=\relax
 \else\ifx#1,
  \let\next=\mm@funbegin
 \else\ifnum`#1=9
  \let\next=\mm@funbegin
 \else\ifnum`#1=32
  \let\next=\mm@funbegin
 \else\if#1!
  \def\mm@tok{}%
  \let\next=\mm@varcollect
 \else\if#1|
  \def\mm@tok{}%
  \let\next=\mm@intrcollect
 \else
  \def\mm@tok{#1}%
  \let\next=\mm@funcollect
 \fi\fi\fi\fi\fi\fi
 \next}
%    \end{macrocode}
% Functions and procedures
%    \begin{macrocode}
\def\mm@funcollect#1{%
 \ifx#1\relax
  \typeset{\mm@tok}{{\mm@funface\mm@tok$_{\mm@sub}$}}%
  \let\next=\relax
 \else\ifx#1,
  \typeset{\mm@tok}{{\mm@funface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=9
  \typeset{\mm@tok}{{\mm@funface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=32
  \typeset{\mm@tok}{{\mm@funface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else
  \xdef\mm@tok{\mm@tok#1}%
  \let\next=\mm@funcollect
 \fi\fi\fi\fi
 \next}
%    \end{macrocode}
% Variables
%    \begin{macrocode}
\def\mm@varcollect#1{%
 \ifx#1\relax
  \typeset{\mm@tok}{{\mm@varface\mm@tok$_{\mm@sub}$}}%
  \let\next=\relax
 \else\ifx#1,
  \typeset{\mm@tok}{{\mm@varface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=9
  \typeset{\mm@tok}{{\mm@varface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=32
  \typeset{\mm@tok}{{\mm@varface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else
  \xdef\mm@tok{\mm@tok#1}%
  \let\next=\mm@varcollect
 \fi\fi\fi\fi
 \next}
%    \end{macrocode}
% Intrinsics
%    \begin{macrocode}
\def\mm@intrcollect#1{%
 \ifx#1\relax
  \typeset{\mm@tok}{{\mm@intrface\mm@tok$_{\mm@sub}$}}%
  \let\next=\relax
 \else\ifx#1,
  \typeset{\mm@tok}{{\mm@intrface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=9
  \typeset{\mm@tok}{{\mm@intrface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else\ifnum`#1=32
  \typeset{\mm@tok}{{\mm@intrface\mm@tok$_{\mm@sub}$}}%
  \let\next=\mm@funbegin
 \else
  \xdef\mm@tok{\mm@tok#1}%
  \let\next=\mm@intrcollect
 \fi\fi\fi\fi
 \next}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsection{Lexical modes}
%
% The bulk of the code in the following sections implements a lexical
% analyser and token recognizer for the \Magma\ syntax.  The lexical
% analyser reads the input stream character by character and builds
% a lexeme via a finite state machine.
%
% After this package loads, the characters |>| and |"| will be active
% and they provide the entry points to the finite state machine. Thus
% the finite state machine can operate in several modes:
% \begin{center}
% \begin{tabular}{ll}
%   |magma|   & executable \Magma\ code\\
%   |inline|  & \Magma\ code appearing within a paragraph\\
%   |comment| & |//|-style comment text
% \end{tabular}
% \end{center}
%
% |Inline| mode is used to typeset a short fragment of \Magma\ code
% in the middle of a paragraph, for example when referring to a variable defined
% within the program. The mode is entered by the |"| character. The finite state
% machine exits when it encounters another |"| character. Newlines are treated
% as whitespace, \Magma\ comments are illegal, and strings cannot be used.
%
% |Magma| mode is used to process literate scripts. The mode is entered by
% the |>| character and exits when it encounters a line not beginning with |>|.
% The |>| character itself is not displayed.
%
% The text is typeset as a separate paragraph, indented by |\mmleftskip| on the
% left and |\mmrightskip| on the right. The |\beforemm| macro is inserted before
% the fragment of code and |\aftermm| is inserted after it.
% In both modes, the |\everymm| macro is inserted immediately after entering
% the mode.
%
% The |comment| mode is entered when |//| is encountered in |magma| mode. Thus
% it is actually a sub-mode of the |magma| mode. Fonts revert to the main
% document fonts.
%
% \begin{macro}{\ifmm@high}
% \begin{macro}{\ifmm@keephigh}
% \Magma\ uses |^| to indicate an exponent and we intend to set exponents as
% superscripts.  Thus we shall set |\ifmm@high| to |true| when we encounter
% a circumflex and it will remain |true| until we complete the exponent. Normally
% the exponent will be complete when we encounter a punctuation character or
% a symbol and there are no open brackets.  However, this does not apply to a
% full stop and in this case we need to continue building the exponent.  This
% is why we need |\ifmm@keephigh|.
%    \begin{macrocode}
\newif\ifmm@high
\newif\ifmm@keephigh
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifmm@inline}
% \begin{macro}{\ifmm@intr}
% \begin{macro}{\@intrinsic}
% \begin{macro}{\@end}
%  The lexical analyser needs to retain some state information.
%  When the |inline| mode is entered, the control sequence |\ifmm@inline|
% is set |true|. %
% In \Magma\ an intrinsic must have a documentation comment (enclosed in
% braces) immediately following its signature.  This use of braces needs
% to be distinguished from their use as set delimiters.  We do this via
% the flag |\ifmm@intr| by setting it to |true| when the |intrinsic| keyword
% is encountered provided it is not preceded by the keyword |end|.
%    \begin{macrocode}
\newif\ifmm@inline
\newif\ifmm@intr
\def\@intrinsic{intrinsic}
\def\@end{end}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\mm@brackets}
% When processing code that will be set as an exponent we need to
% recognize expressions with balanced brackets, braces and parentheses.
% To do this we keep track of the number of open brackets, braces and
% parentheses in |\mm@brackets|.
%    \begin{macrocode}
\newcount\mm@brackets
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@space}
% \begin{macro}{\mm@indent}
% The current lexeme will be kerned by |\mm@space| and
% |\mm@indent| will hold the amount of space at the left of
% the current line.
%    \begin{macrocode}
\newdimen\mm@space
\newdimen\mm@indent
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\mm@i}
% \begin{macro}{\mm@ii}
% The current line will be built in |\mm@i| and |\mm@ii| will
% hold a partially constructed superscript.  The box |\voidb@x|
% remains permanently void and is used to reset the other two
% boxes.
%    \begin{macrocode}
\newbox\voidb@x
\newbox\mm@i
\newbox\mm@ii
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\mm@preparemagma}
% At this stage we are able to code the entry points to the
% various modes of the finite state machine. The |magma| and
% |inline| modes will use |\mm@preparemagma| to reset the
% category codes of many letters and the math codes of many symbols.
%
%    \begin{macrocode}
\def\mm@preparemagma{% Do not allow any blank lines in this definition
 \catcode9=12\catcode13=12\catcode32=12
 \catcode33=12\catcode34=12\catcode35=12\catcode36=12
 \catcode37=12\catcode38=12\catcode39=12\catcode40=12
 \catcode41=12\catcode42=12\catcode43=12\catcode44=12
 \catcode45=12\catcode46=12\catcode47=12\catcode58=12
 \catcode59=12\catcode60=12\catcode61=12\catcode62=12
 \catcode63=12\catcode64=12\catcode91=12\catcode92=12
 \catcode93=12\catcode94=12\catcode95=12\catcode96=12
 \catcode123=12\catcode124=12\catcode125=12\catcode126=12
%    \end{macrocode}
%
% This section sets up symbols in \PlainTeX{} style.  More
% work needs to be done for the \LaTeXe{} version --- possibly
% using |\DeclareMathSymbol| commands following something like
% |\DeclareSymbolFont{mm@symface}{OT1}{mmphv}{m}{sl}|
%
%    \begin{macrocode}
\textfont15=\mm@symface
%<plain> \scriptfont15=\mm@ssymface
%<plain> \scriptscriptfont15=\mm@sssymface
%    \end{macrocode}
%
%  In the |\mathcode|s for \Magma\ symbols, the |F| in the
%  second digit position means that the character will
%  be taken from font 15 defined above. A 0 as the first digit
%  means that the character is `ordinary'.
%
%    \begin{macrocode}
 \mathcode"21="3F21 % !
 % quote "
 \mathcode"23="0F23 % #
 \mathcode"24="0F24 % $
 \mathcode"25="0F25 % %
 \mathcode"26="0F26 % &
 \mathcode"27="0027 % '
 \mathcode"28="0028 % (
 \mathcode"29="0029 % )
 \mathcode"2A="0203 % *
 \mathcode"2B="002B % +
 \mathcode"2C="0F2C % ,
 \mathcode"2D="0200 % -
 \mathcode"2E="013A % .
 \mathcode"2F="002F % /
%    \end{macrocode}
% Digits are omitted.
%    \begin{macrocode}
 \mathcode"3A="003A % :
 \mathcode"3B="0F3B % ;
 \mathcode"3C="013C % < ( \langle is "0268 )
 \mathcode"3D="003D % =
 \mathcode"3E="013E % > ( \rangle is "0269 )
 \mathcode"3F="0F3F % ?
 \mathcode"40="0F40 % @
%    \end{macrocode}
% Upper case letters omitted.
%    \begin{macrocode}
 \mathcode"5B="005B % [
 \mathcode"5C="026E % \
 \mathcode"5D="005D % ]
 \mathcode"5E="0F5E % ^
 \mathcode"5F="0F5F % _
 \mathcode"60="0F12 % `
%    \end{macrocode}
% Lower case letters omitted.
%    \begin{macrocode}
 \mathcode"7B="0266 % {
 \mathcode"7C="026A % |
 \mathcode"7D="0267 % }
 \mathcode"7E="0218 % ~ (large)
%    \end{macrocode}
% We need to initialize our state and ensure that the control
% sequence \cmd{\mm@tok} begins with empty content;  this is
% where the string form of each lexeme is accumulated.
%    \begin{macrocode}
 \mm@intrfalse
 \mm@highfalse
 \mm@brackets=0
 \def\mm@tok{}%
%    \end{macrocode}
%
% The previous lexeme will be held in |\mm@last| and text to be set as a
% subscript will be accumulated in |\mm@sub|.  These control sequences
% are initialized in \cmd{\mm@afteremit}, which also sets the interword
% space to 0pt.
%    \begin{macrocode}
 \mm@afteremit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@beginInline}
% \begin{macro}{\mm@endInline}
% This is the entry point to the |inline| mode.  It simply begins
% a group, calls |\mm@preparemagma| and then enters the |\mm@lex@state|.
%    \begin{macrocode}
\def\mm@beginInline{%
  \begingroup
  \mm@inlinetrue
  \leavevmode
  \everymm
  \mm@preparemagma\mm@lex@state}
\let\mm@endInline=\endgroup
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\mm@beginMagma}
% The |magma| mode is entered in almost the same way except that
% there are a few more things to initialize.
%    \begin{macrocode}
\def\mm@beginMagma{%
  \beforemm
  \begingroup
  \mm@inlinefalse
  \everymm
  \offinterlineskip
  \def\mm@parskip{}%
  \mm@preparemagma
  \global\mm@indent=\mmleftskip
  \mm@code@state}
%    \end{macrocode}
% \end{macro}
%
% The entry point for the italic mode (not really necessary) can
% be found at the end of the file.
%
% \subsection{Lexeme formatting}
%
% Whenever the finite state machine finds a lexeme it passes it to
% one of the formatting macro |\mm@emitxxx|.  The primary role of
% a formatting macro is to put the lexeme into box 255 together with
% the appropriate font change.
%
% \begin{macro}{\mm@emitvar}
% Trailing digits on a variable name will be set as a subscript
% unless they immediately follow a full stop.  In the current
% implementation, lower case greek letters followed by digits will
% be set correctly, but upper case greek letters followed by digits will
% be identified as intrinsics therefore they will be set as such even
% though an upper case greek letter without trailing digits will be set
% as the greek symbol.  This could be changed by setting trailing
% digits of intrinsics as subscripts as is the case for the names of
% variables.
%
%    \begin{macrocode}
\def\mm@emitvar{%
 \if\csname<\mm@tok>\endcsname\relax
   \setbox255=\hbox{{\mm@varface\mm@tok\/$_{\mm@sub}$}}%
 \else
   \setbox255=\hbox{\csname<\mm@tok>\endcsname}%
 \fi
%    \end{macrocode}
%  Whenever we encounter the literal `|intrinsic|' not immediately
%  preceded by `|end|', we set |\mm@intrtrue|.
%    \begin{macrocode}
 \ifx\mm@tok\@intrinsic\ifx\mm@last\@end\else\mm@intrtrue\fi\fi
 \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitintr}
% Intrinsics are treated similarly, except that trailing digits
% are not set as subscripts unless the intrinsic has been
% declared via |\magmanames|.
%    \begin{macrocode}
\def\mm@emitintr{%
 \if\csname<\mm@tok>\endcsname\relax
  \setbox255=\hbox{{\mm@intrface\mm@tok}}%
 \else
  \setbox255=\hbox{\csname<\mm@tok>\endcsname}%
 \fi
 \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitsym}
%  Symbols are set in math mode.
%    \begin{macrocode}
\def\mm@emitsym{%
 \if\csname<\mm@tok>\endcsname\relax
  \setbox255=\hbox{${}\mm@tok{}$}%
 \else
  \setbox255=\hbox{\csname<\mm@tok>\endcsname}%
 \fi
 \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitnum}
% Numbers have their own face.
%    \begin{macrocode}
\def\mm@emitnum{%
 \setbox255=\hbox{{\mm@numface\mm@tok}}%
 \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitchr}
%  This is where literal names are typeset.  They are surrounded by
%  single quotes.
%    \begin{macrocode}
\def\mm@emitchr{%
 \if\csname<\mm@tok>\endcsname\relax
  \setbox255=\hbox{{\mm@funface`\mm@tok'}}%
 \else
  \setbox255=\hbox{{\mm@funface`\csname<\mm@tok>\endcsname'}}%
 \fi
 \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitstr}
%  This is where strings are typeset.  There are three types of
%  string: quoted literals delimited by |"|, documentation comments
%  for intrinsics delimited by |{| and |}|, and multiline comments
%  delimited by |/*| and |*/|.
%    \begin{macrocode}
\def\mm@emitstr#1#2{%
  \setbox255=\hbox{#1{\mm@strface\mm@tok}#2}%
  \mm@emit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emitslashes}
% \begin{macro}{\mm@preparecomment}
% \begin{macro}{\mm@emitcomment}
% C++ style comments start with |//| and continue to the end of the line.
% When a pair of slashes is recognized, the lexeme is sent here for
% typesetting.
%    \begin{macrocode}
\def\mm@emitslashes{%
 \setbox255=\hbox{\hskip\mmcommentskip/\kern-1.5pt/\mm@tok}\mm@emit}
%    \end{macrocode}
%
% The text of the comment is set in the document font. To
% do this we temporarily leave |magma| mode and collect all
% the text up to the end of the line.  The lexical analyser does
% this by first calling |\mm@preparecomment| to change the
% category code of the newline character and then moving to the
% \textsc{comment} state.
%
%    \begin{macrocode}
\def\mm@preparecomment{%
 \mm@emitslashes
 \endgroup
 \begingroup
 \catcode13=12}
%    \end{macrocode}
%
% The |\mm@emitcomment| macro has the task of returning
% to |magma| mode.
%
%    \begin{macrocode}
\def\mm@emitcomment#1{%
 \setbox255=\hbox{#1}%
 \def\mm@tok{}%
 \mm@emit
 \endgroup
 \begingroup
 \mm@inlinefalse
 \everymm
 \offinterlineskip
 \def\mm@parskip{}%
 \mm@preparemagma
 \mm@newline@state}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\mm@emitsup}
% Text following a circumflex is accumulated in the box |\mm@ii|.
% The following macro is only used to deal with the case of a minus
% sign immediately following a circumflex.
%    \begin{macrocode}
\def\mm@emitsup{%
  \global\setbox\mm@ii=\hbox{$\mm@tok$}%
  \mm@afteremit}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@emit}
% On the whole, the previous macros put a single lexeme into |box255| surrounded
% by font changes and other decoration.  The |\mm@emit| macro builds up a
% line that will later be output by |\mm@outputline|.  If we are still
% accumulating material for a superscript, |box255| is appended to
% |\mm@ii|, otherwise it is appended to |\mm@i|.
%    \begin{macrocode}
\def\mm@emit{%
  \ifmm@high
    \global\setbox\mm@ii=\hbox{\unhbox\mm@ii\kern\mm@space\unhbox255}%
    \ifnum\mm@brackets>0\relax\else\mm@highfalse\fi
    \ifmm@keephigh\mm@hightrue\fi
  \fi
  \ifmm@high\relax
  \else\ifmm@inline
     \ifhbox\mm@ii$\mskip1.5mu{}^{\box\mm@ii}$\fi
     \kern\mm@space\box255%
   \else
     \global\setbox\mm@i=\hbox{\unhbox\mm@i\ifhbox\mm@ii
          $\mskip1.5mu{}^{\box\mm@ii}$\fi\kern\mm@space\unhbox255}%
   \fi
   \global\setbox\mm@ii=\box\voidb@x
  \fi
  \mm@afteremit}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\mm@afterermit}
%  This is where we reset the macros that accumulate lexemes etc.
%  It is the only place where \cmd{\mm@last} is set.
%    \begin{macrocode}
\def\mm@afteremit{%
%<magma>  \ifmm@high\else\def\mm@size{\mm@sz}\fi
  \mm@keephighfalse
  \edef\mm@last{\mm@tok}\def\mm@tok{}\def\mm@sub{}\mm@space=0pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@outputline}
%  The size of box |\mm@i| is checked to see whether it is in the
%  bounds set for |magma| code. If not, an error message is issued.
%  In any event, the box is put on \TeX's vertical list and the
%  indentation level is reset to its initial value.
%    \begin{macrocode}
\def\mm@outputline{%
 \ifhbox\mm@i
  \dimen255=\hsize
  \advance\dimen255 by -\mmrightskip
  \advance\dimen255 by -\mm@indent
  \ifdim\wd\mm@i>\dimen255
   \dimen255=-\dimen255 \advance\dimen255 by \wd\mm@i
   \count255=\inputlineno \advance\count255 by -1
   \immediate\write16{}%
   \immediate\write16{%
    Overfull \hbox (\the\dimen255
    \space too wide) in Magma code at line \the\count255}%
   \global\setbox\mm@i=\hbox{\unhbox\mm@i\vrule width\overfullrule}%
  \fi
  \mm@parskip
  \hbox{\mm@ndx\strut\kern\mm@indent\unhbox\mm@i}%
  \global\mm@indent=\mmleftskip
 \fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Magma category codes}
%
% In the next section we shall implement a relatively complete lexical analyser for
% \Magma. To make our job simpler, we collect all ASCII characters into
% the following eleven equivalence classes:
%
% \begin{verse}
%    \begin{tabular}{rl}
%   0.& SP -- space\\
%   1.& LC -- lowercase letters\\
%   2.& UC -- uppercase letters\\
%   3.& DI -- digits\\
%   4.& SY -- symbols\\
%   5.& PU -- punctuation\\
%   6.& AP -- apostrophe\\
%   7.& QT -- double quotation mark\\
%   8.& NL -- newline\\
%   9.& LB -- left brace\\
%  10.& CX -- circumflex
%    \end{tabular}
% \end{verse}
%
%    \begin{macrocode}
\chardef\mm@SP=0
\chardef\mm@LC=1
\chardef\mm@UC=2
\chardef\mm@DI=3
\chardef\mm@SY=4
\chardef\mm@PU=5
\chardef\mm@AP=6
\chardef\mm@QT=7
\chardef\mm@NL=8
\chardef\mm@LB=9
\chardef\mm@CX=10
%
\newcount\mm@delim
%    \end{macrocode}
%
% \begin{macro}{\mm@cc}
% \begin{macro}{\mm@getcc}
% The macro |\mm@getcc#1| computes the \Magma\ category code of its argument
% and stores it in the counter variable |\mm@cc|.
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
\newcount\mm@cc
\def\mm@getcc#1{%
  \mm@cc=`#1
  \ifnum\mm@cc<65 %%% NUL - @
    \ifnum\mm@cc<32 %%% NUL - US
     \ifnum\mm@cc=9
       \mm@cc=\mm@SP
     \else\ifnum\mm@cc=13
       \mm@cc=\mm@NL
     \else
       \mm@cc=-1
     \fi\fi
    \else %%% SP - @
     \ifnum\mm@cc<48 %%% SP - /
       \ifnum\mm@cc=32 %%% SP
         \mm@cc=\mm@SP
       \else\ifnum\mm@cc=34 %%% "
         \mm@cc=\mm@QT
       \else\ifnum\mm@cc=39 %%% '
         \mm@cc=\mm@AP
       \else\ifnum\mm@cc=40 %%% (
         \advance\mm@brackets by 1
         \mm@cc=\mm@PU
       \else\ifnum\mm@cc=41 %%% )
         \advance\mm@brackets by -1
         \mm@cc=\mm@PU
       \else\ifnum\mm@cc=44 %%% ,
         \mm@cc=\mm@PU
       \else                %%% . ! # $ % & * + - /
         \mm@cc=\mm@SY
       \fi\fi\fi\fi\fi\fi
     \else %%% 0 - @
       \ifnum\mm@cc<58 %%% 0 - 9
     \mm@cc=\mm@DI
       \else\ifnum\mm@cc=59 %%% ;
         \mm@cc=\mm@PU
       \else                %%% : < = > ?
         \mm@cc=\mm@SY
       \fi\fi
     \fi
    \fi
  \else %%% A - DEL
    \ifnum\mm@cc<97 %%% A - `
      \ifnum\mm@cc<91 %%% A - Z
        \mm@cc=\mm@UC
      \else\ifnum\mm@cc=91 %%% [
        \advance\mm@brackets by 1
        \mm@cc=\mm@PU
      \else\ifnum\mm@cc=92 %%% \
        \mm@cc=\mm@SY
      \else\ifnum\mm@cc=93 %%% ]
        \advance\mm@brackets by -1
        \mm@cc=\mm@PU
      \else\ifnum\mm@cc=94 %%% ^
        \mm@cc=\mm@CX
      \else\ifnum\mm@cc=95 %%% _
        \mm@cc=\mm@LC
      \else                %%% `
        \mm@cc=\mm@PU
      \fi\fi\fi\fi\fi\fi
    \else %%% a - DEL
      \ifnum\mm@cc<123 %%% a - z
        \mm@cc=\mm@LC
      \else\ifnum\mm@cc=123 %%% {
        \advance\mm@brackets by 1
        \mm@cc=\mm@LB
      \else\ifnum\mm@cc=124 %%% |
        \mm@cc=\mm@SY
      \else\ifnum\mm@cc=125 %%% }
        \advance\mm@brackets by -1
        \mm@cc=\mm@PU
      \else\ifnum\mm@cc=126 %%% ~
        \mm@cc=\mm@SY
      \else
        \mm@cc=-1
      \fi\fi\fi\fi\fi
    \fi
  \fi}
%    \end{macrocode}
%
% \begin{macro}{\mm@setbrackets}
% We keep track of the number of open backets in the counter |\mm@brackets|.
% This information is needed when we are scanning lexemes following a circumflex.
% The resulting expression will be typeset as a superscript.
%    \begin{macrocode}
\def\mm@setbrackets#1{%
  \ifnum`#1=40            %%% (
    \advance\mm@brackets by 1
  \else\ifnum`#1=41       %%% )
    \advance\mm@brackets by -1
  \else\ifnum`#1=91       %%% [
    \advance\mm@brackets by 1
  \else\ifnum`#1=93       %%% ]
    \advance\mm@brackets by -1
  \else\ifnum`#1=123      %%% {
    \advance\mm@brackets by 1
  \else\ifnum`#1=125      %%% }
    \advance\mm@brackets by -1
  \fi\fi\fi\fi\fi\fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{The lexical analyser}
%
% \DescribeMacro\mm@tok
% The lexical analyser is implemented as a finite state machine. Each state
% \textsc{xxx} is represented by a macro of the form |\mm@xxx@state|.
% Transitions are determined by the next character from the input stream.
% The current lexeme is constructed in the control sequence |\mm@tok|.
% The transition chosen is the value of |\next|.
%
% The full stop ( |.| ) plays a special role.  It can appear between a
% variable name and an index, it can appear as a decimal point in a number,
% and it can be part of the lexeme |..| indicating a range.
%
% \begin{macro}{\mm@LBaction}
% \begin{macro}{\mm@QTaction}
% \begin{macro}{\mm@NLaction}
% \begin{macro}{\mm@PUaction}
% \begin{macro}{\mm@SYaction}
%  In many cases a character triggers identical action in almost
%  all states.  In order to make the code more maintainable we would
%  like to define the action in only one place.  So far this has
%  only been attempted for a left brace, a double quote, a newline,
%  all punctuation characters, and symbols in some states. In fact
%  the goal has not been achieved because not all states have exactly
%  the same action.
%    \begin{macrocode}
\def\mm@LBaction#1{%
  \ifmm@high \mm@setbrackets#1\fi
  \ifmm@intr \let\next=\mm@doc@state
  \else
    \def\mm@tok{#1}%
    \mm@emitsym
    \let\next=\mm@lex@state
  \fi}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\mm@QTaction{%
  \ifmm@inline
    \mm@endInline
    \let\next=\relax
  \else
    \def\mm@tok{}%
    \let\next=\mm@str@state
  \fi}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\mm@NLaction{%
  \ifmm@inline
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
  \else
    \let\next=\mm@newline@state
  \fi}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\mm@PUaction#1{%
  \ifmm@high\mm@setbrackets{#1}\fi
  \def\mm@tok{#1}%
  \mm@emitsym
  \let\next=\mm@lex@state}
%
\def\mm@SYaction#1{%
  \ifx#1.%
    \mm@keephightrue
    \mm@emitvar
    \mm@keephightrue
    \def\mm@tok{#1}%
    \let\next=\mm@sym@state
  \else
    \mm@emitvar
    \def\mm@tok{#1}%
    \ifx#1/\let\next=\mm@slash@state\else\let\next=\mm@sym@state\fi
  \fi}
%    \end{macrocode}
%\end{macro}
%\end{macro}
%\end{macro}
%\end{macro}
%\end{macro}
%
% \begin{macro}{\mm@code@state}
% In |magma| mode this is the entry point to the finite state machine.
% The machine remains in this state until a character that is not white
% space is encountered.
%
%    \begin{macrocode}
\def\mm@code@state#1{%
 \mm@getcc#1%
 \def\mm@tok{#1}%
 \ifcase\mm@cc                     % SP - space
    \ifnum`#1=9\global\advance\mm@indent by \mmtabwidth
    \else\global\advance\mm@indent by \mmspacewidth\fi
    \let\next=\mm@code@state
   \or                             % LC - lowercase letters
    \ifx#1p%
     \let\next=\mm@p@state
    \else
     \let\next=\mm@var@state
    \fi
   \or \let\next=\mm@init@state    % UC - uppercase letters
   \or \let\next=\mm@dec@state     % DI - digits
   \or                             % SY - symbols
    \ifx#1/%
     \let\next=\mm@slash@state
    \else
     \let\next=\mm@sym@state
    \fi
   \or                             % PU - punctuation
    \mm@emitsym
    \let\next=\mm@lex@state
   \or                             % AP - apostrophe
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or \let\next=\mm@str@state     % QT - double quotation mark
   \or \let\next=\mm@newline@state % NL - newline
   \or                             % LB - left brace
    \ifmm@intr
     \let\next=\mm@doc@state
    \else
     \mm@emitsym
     \let\next=\mm@lex@state
    \fi
   \or \let\next=\mm@circumflex@state % CX - circumflex
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@newline@state}
%  This state is entered whenever a newline character is recognized.
%  It emits the text gathered so far (via |\mm@outputline|).  If the
%  next character is |>| it returns to the \textsc{code} state.
%  If it doesn't find |>|, it exits the mode.  It should check to see
%  that the next character is blank or newline and issue a warning if
%  this is not the case.
%    \begin{macrocode}
\def\mm@newline@state#1{%
 \mm@outputline
 \ifx#1>%
  \mm@space=0pt
  \let\next=\mm@code@state
 \else
  \par
  \endgroup
  \aftermm
  \par\noindent\ignorespaces
  \let\next=\relax
 \fi
 \next}
%    \end{macrocode}
%\end{macro}
%
% \begin{macro}{\mm@lex@state}
% This is the entry point into the machine for the |inline| mode.
% This is the state that eats spaces while looking for the start
% of a new lexeme.
%    \begin{macrocode}
\def\mm@lex@state#1{%
 \mm@getcc#1%
 \def\mm@tok{#1}%
 \ifcase\mm@cc                      % SP - space
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or                              % LC - lowercase letters
    \ifx#1p\let\next=\mm@p@state
    \else  \let\next=\mm@var@state
    \fi
   \or \let\next=\mm@init@state     % UC - uppercase letters
   \or \let\next=\mm@dec@state      % DI - digits
   \or                              % SY - symbols
    \ifx#1/\let\next=\mm@slash@state
    \else  \let\next=\mm@sym@state
    \fi
   \or \mm@PUaction{#1}%            % PU - punctuation
   \or                              % AP - apostrophe
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or \mm@QTaction                 % QT - double quotation mark
   \or \mm@NLaction                 % NL - newline
   \or \mm@LBaction{#1}%            % LB - left brace
   \or \let\next=\mm@circumflex@state % CX - circumflex
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@var@state}
% In this state the machine is constructing a lexeme that will be
% set as a variable identifier unless overridden by a |\typeset|
% declaration.
%    \begin{macrocode}
\def\mm@var@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitvar
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \edef\mm@tok{\mm@tok\mm@sub#1}%
    \def\mm@sub{}%
    \let\next=\mm@var@state
   \or  % UC - uppercase letters
    \edef\mm@tok{\mm@tok\mm@sub#1}%
    \def\mm@sub{}%
    \let\next=\mm@var@state
   \or  % DI - digits
    \edef\mm@sub{\mm@sub#1}%
    \let\next=\mm@var@state
   \or \mm@SYaction{#1}% SY - symbols
   \or  % PU - punctuation
     \mm@emitvar
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitvar
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitvar
    \mm@QTaction
   \or  % NL - newline
    \mm@emitvar
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitvar
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitvar
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@p@state}
% This state is entered whenever a lowercase |p| is encountered
% as the first character of a lexeme. If the next character is an
% uppercase letter, then the lexeme being constructed will
% set as an intrinsic identifier unless overridden by a |\typeset|
% declaration.
%    \begin{macrocode}
\def\mm@p@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitvar
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@var@state
   \or  % UC - uppercase letters
    \mm@emitvar
    \def\mm@tok{#1}%
    \let\next=\mm@intr@state
   \or  % DI - digits
    \edef\mm@sub{\mm@sub#1}%
    \let\next=\mm@var@state
   \or  \mm@SYaction{#1}% SY - symbols
   \or  % PU - punctuation
     \mm@emitvar
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitvar
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitvar
    \mm@QTaction
   \or  % NL - newline
    \mm@emitvar
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitvar
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitvar
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@intr@state}
% In this state the machine is constructing a lexeme that will be
% set as an intrinsic identifier unless overridden by a |\typeset|
% declaration.
%    \begin{macrocode}
\def\mm@intr@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitintr
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@intr@state
   \or  % UC - uppercase letters
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@intr@state
   \or  % DI - digits
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@intr@state
   \or  % SY - symbols
     \ifx#1.%
       \mm@keephightrue
       \mm@emitintr
       \mm@keephightrue
       \def\mm@tok{#1}%
       \let\next=\mm@sym@state
     \else
       \mm@emitintr
       \def\mm@tok{#1}%
       \ifx#1/\let\next=\mm@slash@state\else\let\next=\mm@sym@state\fi
     \fi
   \or  % PU - punctuation
     \mm@emitintr
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitintr
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitintr
    \mm@QTaction
   \or  % NL - newline
    \mm@emitintr
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitintr
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitintr
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@init@state}
% This state is entered whenever an uppercase letter is encountered
% as the first character of a lexeme. The lexeme being constructed will
% be set as an intrinsic identifier unless overridden by a |\typeset|
% declaration or unless it has length 1.
%    \begin{macrocode}
\def\mm@init@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
     % SP - space
     \mm@emitvar
     \mm@space=\mmwordspace
     \let\next=\mm@lex@state
   \or  % LC - lowercase letters
     \edef\mm@tok{\mm@tok#1}%
     \let\next=\mm@intr@state
   \or  % UC - uppercase letters
     \edef\mm@tok{\mm@tok#1}%
     \let\next=\mm@intr@state
   \or  % DI - digits
     \edef\mm@sub{\mm@sub#1}%
     \let\next=\mm@var@state
   \or \mm@SYaction{#1}% SY - symbols
   \or  % PU - punctuation
     \mm@emitvar
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitvar
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitvar
    \mm@QTaction
   \or  % NL - newline
    \mm@emitvar
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitvar
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitvar
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@sym@state}
% In this state the machine is constructing a lexeme that will be
% set as a symbol unless overridden by a |\typeset| declaration.
%    \begin{macrocode}
\def\mm@sym@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitsym
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \mm@emitsym
    \def\mm@tok{#1}%
    \ifx#1p%
     \let\next=\mm@p@state
    \else
     \let\next=\mm@var@state
    \fi
   \or  % UC - uppercase letters
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@init@state
   \or  % DI - digits
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@dec@state
   \or  % SY - symbols
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@sym@state
   \or  % PU - punctuation
    \mm@emitsym
    \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitsym
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitsym
    \mm@QTaction
   \or  % NL - newline
    \mm@emitsym
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitsym
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@dec@state}
% In the \textsc{dec} state the machine is constructing a lexeme that
% will be typeset as a number.  Numbers may be given in ``scientific''
% notation and may include a precision value. In \Magma\ an integer
% literal has the form |[0-9]+| and a real literal has the form
% \verb=[0-9]+(\.[0-9]+)?((e|E)-?[0-9]+)?((p|P)[0-9]+)?=.
%
%    \begin{macrocode}
\def\mm@dec@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitnum
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \ifx#1e%
     \edef\mm@tok{\mm@tok#1}%
     \let\next=\mm@dec@state
    \else\ifx#1p%
     \edef\mm@tok{\mm@tok#1}%
     \let\next=\mm@dec@state
    \else
     \mm@emitnum
     \def\mm@tok{#1}%
     \let\next=\mm@var@state
    \fi\fi
   \or  % UC - uppercase letters
    \ifx#1E%
     \edef\mm@tok{\mm@tok e}%
     \let\next=\mm@dec@state
    \else\ifx#1P%
     \edef\mm@tok{\mm@tok p}%
     \let\next=\mm@dec@state
    \else
     \mm@emitnum
     \def\mm@tok{#1}%
     \let\next=\mm@init@state
    \fi\fi
   \or  % DI - digits
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@dec@state
   \or  % SY - symbols
    \ifx#1.\let\next=\mm@decdot@state
    \else
      \mm@emitnum
      \def\mm@tok{#1}%
      \ifx#1/\let\next=\mm@slash@state\else\let\next=\mm@sym@state\fi
    \fi
   \or  % PU - punctuation
     \mm@emitnum
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \mm@emitnum
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \mm@emitnum
    \mm@QTaction
   \or  % NL - newline
    \mm@emitnum
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitnum
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitnum
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>      \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@decdot@state}
% This state is entered whenever a full stop is encountered within
% the \textsc{dec} state.
%    \begin{macrocode}
\def\mm@decdot@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \edef\mm@tok{\mm@tok .}%
    \mm@emitnum
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \ifx#1e%
     \edef\mm@tok{\mm@tok .#1}%
     \let\next=\mm@dec@state
    \else\ifx#1p%
     \edef\mm@tok{\mm@tok .#1}%
     \let\next=\mm@dec@state
    \else
     \edef\mm@tok{\mm@tok .}%
     \mm@emitnum
     \def\mm@tok{#1}%
     \let\next=\mm@var@state
    \fi\fi
   \or  % UC - uppercase letters
    \ifx#1E%
     \edef\mm@tok{\mm@tok .e}%
     \let\next=\mm@dec@state
    \else\ifx#1P%
     \edef\mm@tok{\mm@tok .p}%
     \let\next=\mm@dec@state
    \else
     \edef\mm@tok{\mm@tok .}%
     \mm@emitnum
     \def\mm@tok{#1}%
     \let\next=\mm@init@state
    \fi\fi
   \or  % DI - digits
    \edef\mm@tok{\mm@tok .#1}%
    \let\next=\mm@dec@state
   \or  % SY - symbols
     \ifx#1/%
       \edef\mm@tok{\mm@tok .}%
       \mm@emitnum
       \def\mm@tok{#1}%
       \let\next=\mm@slash@state
     \else
       \mm@emitnum
       \def\mm@tok{.#1}%
       \let\next=\mm@sym@state
     \fi
   \or  % PU - punctuation
     \edef\mm@tok{\mm@tok .}%
     \mm@emitnum
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
    \edef\mm@tok{\mm@tok .}%
    \mm@emitnum
    \def\mm@tok{}%
    \let\next=\mm@chr@state
   \or  % QT - double quotation mark
    \edef\mm@tok{\mm@tok .}%
    \mm@emitnum
    \mm@QTaction
   \or  % NL - newline
    \edef\mm@tok{\mm@tok .}%
    \mm@emitnum
    \mm@NLaction
   \or  % LB - left brace
     \edef\mm@tok{\mm@tok .}%
     \mm@emitnum
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \edef\mm@tok{\mm@tok .}%
    \mm@emitnum
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>      \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@circumflex@state}
% This state is entered whenever a circumflex ( |^| ) is encountered.
% The following \Magma\ expression will be typeset as a superscript.
% In many cases the expression will simply be the next lexeme. But it
% could be a bracketed expression or a reference to a list element
% (such as |a[3]|).  For this reason we need to keep a count of open
% parentheses, braces and brackets.
%    \begin{macrocode}
\def\mm@circumflex@state#1{%
 \mm@hightrue
%<magma> \def\mm@size{\mm@ssz}%
 \mm@brackets=0
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
     \let\next=\mm@circumflex@state
   \or  % LC - lowercase letters
     \def\mm@tok{#1}%
     \ifx#1p%
       \let\next=\mm@p@state
     \else
       \let\next=\mm@var@state
     \fi
   \or  % UC - uppercase letters
     \def\mm@tok{#1}%
     \let\next=\mm@init@state
   \or  % DI - digits
     \def\mm@tok{#1}%
     \let\next=\mm@dec@state
   \or  % SY - symbols
     \def\mm@tok{#1}%
     \ifx#1-\mm@emitsup
        \let\next=\mm@lex@state
     \else\ifx#1/%
       \let\next=\mm@slash@state
     \else
       \let\next=\mm@sym@state
     \fi\fi
   \or  % PU - punctuation
     \def\mm@tok{#1}%
     \mm@setbrackets#1%
     \mm@emitsym
     \let\next=\mm@lex@state
   \or  % AP - apostrophe
     \let\next=\mm@chr@state
   \or  % QT - double quotation mark
     \let\next=\mm@str@state
   \or  % NL - newline
     \let\next=\mm@newline@state
   \or  % LB - left brace
     \ifmm@intr
       \let\next=\mm@doc@state
     \else
       \def\mm@tok{#1}%
       \mm@emitsym
       \let\next=\mm@lex@state
     \fi
   \or  % CX - circumflex
     \def\mm@tok{#1}%
     \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>      \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Literals}
%
% Any string enclosed by a pair of apostrophes represents
% the name of an identifier.  Thus identifiers can be constructed whose
% names include non-alphabetic characters and even spaces. A
% backslash within the literal is used as an escape character.
%
% \begin{macro}{\mm@chr@state}
% The \textsc{chr} state is entered whenever an apostrophe is encountered.
% All characters up to the next apostrophe are considered part
% of a literal symbol.  The only way out of this state is the
% transition to \textsc{lex} when the next apostrophe is seen or if
% the line ends before the literal is complete.  Newlines are not allowed
% in literal identifiers and so in the latter case an error is raised.
%    \begin{macrocode}
\def\mm@chr@state#1{%
  \ifnum`#1=13
%<*magma>
    \PackageError{MagmaTeX}
      {Line ended before apostrophe was seen}
      {You probably need to insert an apostrophe}%
%</magma>
%<plain>     \errmessage{Line ended before apostrophe was seen}%
    \mm@emitchr
    \let\next=\mm@newline@state
  \else\ifnum`#1=92
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@chresc@state
  \else\ifnum`#1=`'
    \mm@emitchr
    \let\next=\mm@lex@state
  \else
    \edef\mm@tok{\mm@tok#1}%
    \let\next=\mm@chr@state
  \fi\fi\fi
  \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@chresc@state}
%  We reach this state when a backslash is encountered. Its
%  purpose is to turn off special processing of the following
%  character.
%    \begin{macrocode}
\def\mm@chresc@state#1{\edef\mm@tok{\mm@tok#1}\mm@chr@state}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Comments and strings}
%  In \Magma\ there are three types of comments:
% \begin{center}
% \begin{tabular}{ll}
%   C++ style & all text from |//| to the end of the line is the comment\\
%   C style   & all text between |/*| and |*/| is the comment\\
%   intrinsic & all text between  |{| and |}| is the (documentation) comment
% \end{tabular}
% \end{center}
%
% In the second and third style of comment newlines are allowed.
% Similary, it is not an error for a \Magma\ string (enclosed in
% quotes (|"|) to be entered over several lines.  Thus the
% macros in this section need to handle newlines correctly.
%
% \begin{macro}{\mm@slash@state}
% The \textsc{slash} state is entered whenever / is encountered
% as the first character of a lexeme. This could be the
% beginning of a comment; either extending to the end
% of the line if the next character is another / or
% potentially multiline if the next character is an asterisk.
% Anything other than / or * causes the slash to be emitted
% as a symbol.
%    \begin{macrocode}
\def\mm@slash@state#1{%
 \mm@getcc#1%
 \ifcase\mm@cc
    % SP - space
    \mm@emitsym
    \mm@space=\mmwordspace
    \let\next=\mm@lex@state
   \or  % LC - lowercase letters
    \mm@emitsym
    \def\mm@tok{#1}%
    \ifx#1p%
     \let\next=\mm@p@state
    \else
     \let\next=\mm@var@state
    \fi
   \or  % UC - uppercase letters
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@init@state
   \or  % DI - digits
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@dec@state
   \or  % SY - symbols
    \edef\mm@tok{\mm@tok#1}%
    \ifx#1*%
     \let\next=\mm@slashstar@state
    \else\ifx#1/%
     \let\next=\mm@slashslash@state
    \else
     \let\next=\mm@sym@state
    \fi\fi
   \or  % PU - punctuation
     \mm@emitsym
     \mm@PUaction{#1}%
   \or  % AP - apostrophe
     \mm@emitsym
     \def\mm@tok{}%
     \let\next=\mm@chr@state
   \or  % QT - double quotation mark
     \mm@emitsym
     \mm@QTaction
   \or  % NL - newline
    \mm@emitsym
    \mm@NLaction
   \or  % LB - left brace
     \mm@emitsym
     \mm@LBaction{#1}%
   \or  % CX - circumflex
    \mm@emitsym
    \def\mm@tok{#1}%
    \let\next=\mm@circumflex@state
   \else
%<*magma>
     \PackageError{MagmaTeX}
       {Illegal character in Magma mode: #1}
       {Possibly a bug}%
%</magma>
%<plain>    \errmessage{Illegal character in Magma mode: #1}%
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@slashslash@state}
% This state marks the beginning of a C++ style comment.
%    \begin{macrocode}
\def\mm@slashslash@state#1{%
  \ifmm@inline
%<*magma>
    \PackageError{MagmaTeX}
      {Comment in inline Magma mode will be ignored}
      {Better remove it}%
%</magma>
%<plain>     \errmessage{Comment in inline Magma mode}%
    \def\mm@tok{#1}%
    \let\next=\mm@lex@state
  \else
    \mm@getcc#1%
    \ifnum\mm@cc=0       % SP - space
      \edef\mm@tok{\space}%
      \mm@preparecomment
      \let\next=\mm@comment@state
    \else\ifnum\mm@cc=8  % NL - newline
     \def\mm@tok{}%
     \mm@emitslashes
     \let\next=\mm@newline@state
    \else
      \def\mm@tok{#1}%
      \mm@preparecomment
      \let\next=\mm@comment@state
    \fi\fi\fi
  \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@comment@state}
% This state simply collects all the text up to the end of
% the line and passes it to the emitter.
%    \begin{macrocode}
{\catcode13=12\gdef\mm@comment@state#1^^M{\mm@emitcomment{#1}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@doc@state}
% This state is entered when we encounter a left brace
% immediately following the signature of an intrinsic.
% The following text, up to the closing right brace,
% is a documentation comment
%    \begin{macrocode}
\def\mm@doc@state{%
  \mm@intrfalse
  \def\mm@strprefix{{\mm@strface\char123\kern .1em}}%
  \def\mm@strsuffix{{\mm@strface\kern .1em\char125}}%
  \mm@delim=125
  \def\mm@tok{}%
  \mm@getchr@state}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@str@state}
% This state is entered when we encounter a quote character.  This
% macro and the preceding one simply set the prefix and suffix
% characters and then fall through to the \textsc{getchr} state.
%    \begin{macrocode}
\def\mm@str@state{%
  \def\mm@strprefix{{\mm@funface``}}%
  \def\mm@strsuffix{{\mm@funface''}}%
  \mm@delim=34
  \def\mm@tok{}%
  \mm@getchr@state}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@getchr@state}
% This state deals with documentation comments and string
% literals.  All characters are accummulated until the
% closing delimiter is found.  Newlines are allowed and so
% the only exit from the state is either to \textsc{lex} through the
% closing delimiter or out of the mode if |>| is not found after
% a newline.
%    \begin{macrocode}
\def\mm@getchr@state#1{%
 \mm@getcc#1%
 \ifnum`#1=\mm@delim
  \mm@emitstr{\mm@strprefix}{\mm@strsuffix}%
  \let\next=\mm@lex@state
 \else\ifnum\mm@cc=\mm@NL
  \mm@emitstr{\mm@strprefix}{}%
  \def\mm@strprefix{}%
  \let\next=\mm@strnewline@state
 \else\ifnum`#1=92
  \edef\mm@tok{\mm@tok#1}%
  \let\next=\mm@stresc@state
 \else
  \edef\mm@tok{\mm@tok#1}%
  \let\next=\mm@getchr@state
 \fi\fi\fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@stresc@state}
%  We reach this state when a backslash is encountered in a string
% or documentation comment. Its purpose is to turn off special
% processing of the following character.
%    \begin{macrocode}
\def\mm@stresc@state#1{\edef\mm@tok{\mm@tok#1}\mm@getchr@state}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\mm@strnewline@state}
% This deals with embedded newlines in documentation
% comments and string literals. It really should raise
% an error if the mode ends and a blank line does not follow.
%    \begin{macrocode}
\def\mm@strnewline@state#1{%
 \mm@outputline
 \ifx#1>%
  \mm@space=0pt
  \let\next=\mm@strcode@state
 \else
  \par
  \endgroup
  \aftermm
  \par\noindent\ignorespaces
  \let\next=\relax
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@strcode@state}
% We arrive here when a newline followed by |>| is encountered
% whilst reading a string.  We gather up the leading whitespace
% to use as an offset and then return to one of the previous states
% to complete the string.
%    \begin{macrocode}
\def\mm@strcode@state#1{%
 \mm@getcc#1%
 \ifnum\mm@cc=\mm@SP
   % SP - space
   \ifnum`#1=9\global\advance\mm@indent by \mmtabwidth
   \else\global\advance\mm@indent by \mmspacewidth\fi
   \let\next=\mm@strcode@state
 \else\ifnum\mm@cc=\mm@NL
   \let\next=\mm@strnewline@state
 \else\ifnum`#1=\mm@delim
   \mm@emitstr{\mm@strprefix}{\mm@strsuffix}%
   \let\next=\mm@lex@state
 \else\ifnum`#1=92
   \def\mm@tok{#1}%
   \let\next=\mm@stresc@state
 \else
   \def\mm@tok{#1}%
   \let\next=\mm@getchr@state
 \fi\fi\fi\fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@slashstar@state}
%  This state is entered at the beginning of a (potentially)
%  multiline comment.  We simply set the prefix and suffix
%  macros and go directly to the \textsc{comchr} state.
%  A backslash has no effect in this type of comment and so there
%  is no need to handle `escapes'.
%    \begin{macrocode}
\def\mm@slashstar@state{%
 \def\mm@tok{}%
 \def\mm@strprefix{{\mm@strface/*}}%
 \def\mm@strsuffix{{\mm@strface*/}}%
 \mm@comchr@state}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@comchr@state}
% In this state we accumulate characters until we hit a newline or *
%    \begin{macrocode}
\def\mm@comchr@state#1{%
 \mm@getcc#1%
 \ifx#1*%
  \let\next=\mm@comstar@state
 \else\ifnum\mm@cc=\mm@NL
  \mm@emitstr{\mm@strprefix}{}%
  \def\mm@strprefix{}%
  \let\next=\mm@comnewline@state
 \else
  \edef\mm@tok{\mm@tok#1}%
  \let\next=\mm@comchr@state
 \fi\fi %\fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@comstar@state}
% We've arrived here because we've just seen an asterisk inside
% a multiline comment.  If the next character is a slash, the
% comment will end, otherwise we go back to the \textsc{comchr} state.
%    \begin{macrocode}
\def\mm@comstar@state#1{%
 \mm@getcc#1%
 \ifx#1/%
  \mm@emitstr{\mm@strprefix}{\mm@strsuffix}%
  \let\next=\mm@lex@state
 \else\ifnum\mm@cc=\mm@NL
  \mm@emitstr{\mm@strprefix}{}%
  \def\mm@strprefix{}%
  \let\next=\mm@comnewline@state
 \else
  \edef\mm@tok{\mm@tok*#1}%
  \let\next=\mm@comchr@state
 \fi\fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@comstar@state}
%  This is where we deal with a newline inside a multiline comment.
%    \begin{macrocode}
\def\mm@comnewline@state#1{%
 \mm@outputline
 \ifx#1>%
  \mm@space=0pt
  \let\next=\mm@comcode@state
 \else
  \par
  \endgroup
  \aftermm
  \par\noindent\ignorespaces
  \let\next=\relax
 \fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mm@comcode@state}
%  We arrive here when a newline followed by |>| is encountered.
%  The code is almost the same as that of |\mm@strcode@state| but
%  there are just enough differences (e.g., handling of escaped
%  characters) so that its not really worthwhile to combine the code.
%    \begin{macrocode}
\def\mm@comcode@state#1{%
 \mm@getcc#1%
 \ifnum\mm@cc=\mm@SP
  \ifnum`#1=9\global\advance\mm@indent by \mmtabwidth
  \else\global\advance\mm@indent by \mmspacewidth\fi
  \let\next=\mm@comcode@state
 \else\ifx#1*%
  \let\next=\mm@comstar@state
 \else\ifnum\mm@cc=\mm@NL
  \let\next=\mm@comnewline@state
 \else
  \def\mm@tok{#1}%
  \let\next=\mm@comchr@state
 \fi\fi\fi
 \next}
%    \end{macrocode}
% \end{macro}
%
% \section{The \Lpkg{code} environment}
%    \begin{macrocode}
%<*code>
%    \end{macrocode}
%
%  \begin{environment}{code}
%    \changes{v1.4}{2002/08/17}{Added the \texttt{code} environment}
%    The \Lenv{code} environment is similar to the \Lenv{verbatim} and
%    \Lenv{alltt} environments (defined by Leslie Lamport and by Johannes
%    Braams), except that |\|, |{| and |}| have their usual behaviour.
%    Internal names have been changed so that they do not conflict with
%    those in \Lenv{verbatim}.
%    \begin{macrocode}
\begingroup
\lccode`\~=`\'
\lowercase{\endgroup
\newenvironment{code}{%
  \begingroup
%    \end{macrocode}
% We turn off the active characters used by \Magma-\TeX.
%    \begin{macrocode}
  \catcode`\>=12 \catcode`\"=12 \catcode`\<=12
  \trivlist
  \item\relax
    \if@minipage
    \else
      \vskip\parskip
    \fi
    \leftskip\@totalleftmargin
    \advance\leftskip by \parindent
    \rightskip\z@skip
    \parindent\z@
    \parfillskip\@flushglue
    \parskip\z@skip
    \@@par
    \@tempswafalse
    \def\par{%
      \if@tempswa
        \leavevmode\null\@@par\penalty\interlinepenalty
      \else
        \@tempswatrue
        \ifhmode\@@par\penalty\interlinepenalty\fi
      \fi}
    \obeylines
    \verbatim@font
    \let\orig@prime~%
    \@noligs
    \everymath\expandafter{\the\everymath
      \catcode`\'=12 \let~\orig@prime}
    \everydisplay\expandafter{\the\everydisplay
      \catcode`\'=12 \let~\orig@prime}
    \let\orig@dospecials\dospecials
    \mm@delfromspecials{\\}
    \mm@delfromspecials{\{}
    \mm@delfromspecials{\}}
    \let\do\@makeother
    \dospecials
    \let\dospecials\orig@dospecials
    \frenchspacing\@vobeyspaces
    \everypar \expandafter{\the\everypar \unpenalty}}
{\endgroup\endtrivlist}}
%    \end{macrocode}
%  \end{environment}
%
%  \begin{macro}{\mm@delfromspecials}
%    In the old implementation of the \Lpkg{alltt} package, on which
%    \Lpkg{code} is based, a fixed \cmd{\dospecials} was used. However the
%    \cmd{\dospecials} command might contain more special characters at
%    run-time than was defined in the format. Therefore we remove the
%    necessary special character from \cmd{\dospecials} at the start of the
%    \Lenv{code} environment. For this we need a macro. Remember that
%    the list of special characters in \cmd{\dospecials} contains the
%    control sequence \cmd{\do} between the characters. We use that to
%    check whether a character has to be removed.
%
%    The macro \cmd{\mm@delfromspecials} takes one argument: the character
%    to be removed from the list.
%    \begin{macrocode}
\def\mm@delfromspecials#1{%
%    \end{macrocode}
%    We build up a new list in \cmd{\@newspecials}.
%    \begin{macrocode}
  \def\@newspecials{}
%    \end{macrocode}
%    The command \cmd{\@remove} compares its argument with the argument of\\
%    \cmd{\mm@delfrom@specials}.
%    \begin{macrocode}
  \def\@remove##1{%
    \ifx##1#1\else
%    \end{macrocode}
%    When they are not the same, the argument of \cmd{\@remove} is added
%    (together with \cmd{\do}) to the new list.  Note that \cmd{\g@addto@macro}
%    is defined in the \LaTeXe{} kernel.
%    \begin{macrocode}
    \g@addto@macro\@newspecials{\do ##1}\fi}
%    \end{macrocode}
%    Now we set \cmd{\do} to \cmd{\@remove} and execute \cmd{\dospecials}.
%    \begin{macrocode}
  \let\do\@remove\dospecials
%    \end{macrocode}
%    All that's left is to make |\dospecials| point to the new list.
%    \begin{macrocode}
  \let\dospecials\@newspecials
  }
%</code>
%    \end{macrocode}
%  \end{macro}
%
% \section{End game}
%
% The characters |<|, |>| and |"| will be made active and serve as
% the entry points into the |italic|, |magma| and |inline| modes,
% respectively.  But in math mode we need their usual behaviour.
%
%    \begin{macrocode}
\everymath{\catcode`<=12\catcode`>=12\catcode`"=12\relax}
\everydisplay{\catcode`<=12\catcode`>=12\catcode`"=12\relax}
%    \end{macrocode}
%
%  \begin{macro}{\lt}
%  \begin{macro}{\gt}
% To make amends for the quirky behaviour of |>| and |<| in math mode,
% define |\lt| and |\gt| to complement the |\le|, |\ge|, etc. already
% in \TeX{}:
%
%    \begin{macrocode}
\let\lt=<
\let\gt=>
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% Finally, we are ready to set up the entry points into the various modes.
%
% \begin{macro}{\mm@beginItalic}
% We are about to make |>| an active character and so we'll take |<| too
% and use |<...>| to typeset |...| in italic.
%    \begin{macrocode}
{\catcode`>=\active
 \gdef\mm@beginItalic{\begingroup\it\catcode`>=\active\let>=\endgroup}}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
{\catcode`"=\active
 \catcode`>=\active
 \catcode`<=\active
 \gdef\@ctivate{%
   \catcode`"=\active \let"=\mm@beginInline
   \catcode`>=\active \let>=\mm@beginMagma
   \catcode`<=\active \let<=\mm@beginItalic
}}
%<*magma>
\AtBeginDocument{%
 \check@mathfonts
 \math@fontsfalse
%</magma>
 \@ctivate
%<magma>}
%    \end{macrocode}
%  The final act of the \texttt{plain} version is to restore the catcode of @.
%
%    \begin{macrocode}
%<plain>\csname MagmaTeX.tex\endcsname
%</magma|plain>
%    \end{macrocode}
%
% \Finale
%
\endinput
