% \iffalse     ---!!! FIRST META-COMMENT !!!---
% 
% 
% This file is mathfont-code.dtx from version 2.4a of the
% free and open-source LaTeX package "mathfont," released
% June 2025, to be used with the XeTeX or LuaTeX engines.
% 
% Running Plain TeX on mathfont-code.dtx will produce the
% following files:
% 
%   (1) the package file mathfont.sty;
% 
%   (2) the derived files mathfont-symbol-list.tex,
%       mathfont-user-guide.tex, and four files called
%       mathfont-example-<fontname>.tex, which can be
%       used to typeset further documentation for
%       mathfont;
% 
%   (3) the stand-alone derived files mathfont-doc-patch.tex,
%       mathfont-equations.tex, and mathfont-heading.tex,
%       which are used to produce documentation;
% 
%     and
% 
%   (4) a number of other derived files.
% 
% Running LaTeX on mathfont-code.dtx will produce the files
% listed above as well as the following:
% 
%   (5) the pdf documentation file mathfont-code.pdf;
% 
%     and
% 
%   (6) a number of other derived files.
% 
% To install mathfont on your computer, run this file through
% Plain TeX or LaTeX and move mathfont.sty into a directory 
% searchable by TeX. See the associated README.txt file for
% installation information.
% 
% 
% \fi
% \iffalse     ---!!! SECOND META-COMMENT !!!---
% 
% 
% This file is from version 2.4a of the free and open-source
% LaTeX package "mathfont," released June 2025, to be used
% with the XeTeX or LuaTeX engines. (As of version 2.0, LuaTeX
% is recommended.)
% 
% Copyright 2018-2023, 2025 Conrad Kosowsky
% 
% This Work may be used, distributed, and modified under the
% terms of the LaTeX Public Project License, version 1.3c or
% any later version. The most recent version of this license
% is available online at
% 
%           https://www.latex-project.org/lppl/.
% 
% This Work has the LPPL status "maintained," and the current
% maintainer is the package author, Conrad Kosowsky. He can
% be reached at kosowsky.latex@gmail.com. The Work consists
% of the following items:
% 
%   (1) the base file:
%         mathfont-code.dtx
% 
%   (2) the package file:
%         mathfont.sty
% 
%   (3) the derived files:
%         mathfont-doc_patch.tex
%         mathfont-equations.tex
%         mathfont-example-cormorant.tex
%         mathfont-example-kelvinch.tex
%         mathfont-example-roboto.tex
%         mathfont-example-typey.tex
%         mathfont-heading.tex
%         mathfont-symbol-list.tex
%         mathfont-user-guide.tex
% 
%   (4) the pdf documentation files:
%         mathfont-code.pdf,
%         mathfont-example-cormorant.pdf
%         mathfont-example-kelvinch.pdf
%         mathfont-example-roboto.pdf
%         mathfont-example-typey.pdf
%         mathfont-symbol-list.pdf
%         mathfont-user-guide.pdf
% 
%   (5) all other files created through the configuration
%       process
% 
%     and
% 
%   (6) the associated README.txt file
% 
% The Work does not include any fonts, and the installation
% does not contain any font files. The fonts Bona Nova,
% Cormorant, Crimson, Kelvinch, Overpass, STIXGeneral, and
% Typey McTypeface have been released under the SIL Open
% Font License and are used pursuant to that license. The
% font Roboto has been released under the Apache License
% and is used pursuant to that license.
% 
% PLEASE KNOW THAT THIS FREE SOFTWARE IS PROVIDED WITHOUT
% ANY WARRANTY. SPECIFICALLY, THE "NO WARRANTY" SECTION OF
% THE LATEX PROJECT PUBLIC LICENSE STATES THE FOLLOWING:
% 
% THERE IS NO WARRANTY FOR THE WORK. EXCEPT WHEN OTHERWISE
% STATED IN WRITING, THE COPYRIGHT HOLDER PROVIDES THE WORK
% `AS IS’, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
% OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
% PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
% OF THE WORK IS WITH YOU. SHOULD THE WORK PROVE DEFECTIVE,
% YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
% CORRECTION.
% 
% IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
% TO IN WRITING WILL THE COPYRIGHT HOLDER, OR ANY AUTHOR
% NAMED IN THE COMPONENTS OF THE WORK, OR ANY OTHER PARTY
% WHO MAY DISTRIBUTE AND/OR MODIFY THE WORK AS PERMITTED
% ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
% SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT
% OF ANY USE OF THE WORK OR OUT OF INABILITY TO USE THE WORK
% (INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA, DATA BEING
% RENDERED INACCURATE, OR LOSSES SUSTAINED BY ANYONE AS A
% RESULT OF ANY FAILURE OF THE WORK TO OPERATE WITH ANY
% OTHER PROGRAMS), EVEN IF THE COPYRIGHT HOLDER OR SAID
% AUTHOR OR SAID OTHER PARTY HAS BEEN ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGES.
% 
% For more information, see the Latex Project Public License.
% Derivative works based on this package may come with their
% own license or terms of use, and the package author is not
% responsible for any third-party software.
% 
% Happy TeXing!
% 
% 
% \fi
% \iffalse
% 
% The installation and driver files are incorporated into
% mathfont-code.dtx, so we do not need to generate them
% separately. The <batchfile> and <driver> tags are for 
% reference.
% 
%<*batchfile>
\begingroup
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\preamble

This file is from version 2.4a of the free and open-source
LaTeX package "mathfont," released June 2025, to be used
with the XeTeX or LuaTeX engines. (As of version 2.0, LuaTeX
is recommended.)

Copyright 2018-2023, 2025 Conrad Kosowsky

This Work may be used, distributed, and modified under the
terms of the LaTeX Public Project License, version 1.3c or
any later version. The most recent version of this license
is available online at

          https://www.latex-project.org/lppl/.

This Work has the LPPL status "maintained," and the current
maintainer is the package author, Conrad Kosowsky. He can
be reached at kosowsky.latex@gmail.com.

PLEASE KNOW THAT THIS FREE SOFTWARE IS PROVIDED WITHOUT
ANY WARRANTY. SPECIFICALLY, THE "NO WARRANTY" SECTION OF
THE LATEX PROJECT PUBLIC LICENSE STATES THE FOLLOWING:

THERE IS NO WARRANTY FOR THE WORK. EXCEPT WHEN OTHERWISE
STATED IN WRITING, THE COPYRIGHT HOLDER PROVIDES THE WORK
`AS IS’, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
OF THE WORK IS WITH YOU. SHOULD THE WORK PROVE DEFECTIVE,
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
TO IN WRITING WILL THE COPYRIGHT HOLDER, OR ANY AUTHOR
NAMED IN THE COMPONENTS OF THE WORK, OR ANY OTHER PARTY
WHO MAY DISTRIBUTE AND/OR MODIFY THE WORK AS PERMITTED
ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT
OF ANY USE OF THE WORK OR OUT OF INABILITY TO USE THE WORK
(INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA, DATA BEING
RENDERED INACCURATE, OR LOSSES SUSTAINED BY ANYONE AS A
RESULT OF ANY FAILURE OF THE WORK TO OPERATE WITH ANY
OTHER PROGRAMS), EVEN IF THE COPYRIGHT HOLDER OR SAID
AUTHOR OR SAID OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

For more information, see the LaTeX Project Public License.
Derivative works based on this package may come with their
own license or terms of use, and the package author is not
responsible for any third-party software.

For more information, see mathfont-code.dtx. Happy TeXing!

\endpreamble
\generate{
  \file{mathfont.sty}{\from{mathfont-code.dtx}{package}}
  \file{mathfont-symbol-list.tex}{\from{mathfont-code.dtx}{chars}}
  \file{mathfont-user-guide.tex}{\from{mathfont-code.dtx}{user}}
  \file{mathfont-heading.tex}{\from{mathfont-code.dtx}{heading}}
  \file{mathfont-doc-patch.tex}{\from{mathfont-code.dtx}{doc}}
  \file{mathfont-equations.tex}{\from{mathfont-code.dtx}{equations}}
  \file{mathfont-example-cormorant.tex}{\from{mathfont-code.dtx}{cormorant}}
  \file{mathfont-example-kelvinch.tex}{\from{mathfont-code.dtx}{kelvinch}}
  \file{mathfont-example-roboto.tex}{\from{mathfont-code.dtx}{roboto}}
  \file{mathfont-example-typey.tex}{\from{mathfont-code.dtx}{typey}}}
\catcode`\ =12\relax
\immediate\write0{^^J%
***************************************************^^J%
*  Step 1 of the mathfont installation complete!  *^^J%
***************************************************^^J^^J%
***************************************************^^J%
*  To finish the installation, move mathfont.sty  *^^J%
*      to a directory searchable by TeX once      *^^J%
*      mathfont-code.dtx is done typesetting      *^^J%
***************************************************^^J^^J}
\endgroup
\ifx\LaTeX\undefined
  \immediate\write0{Plain TeX format used; quitting now.}
  \immediate\write0{To create mathfont-code.pdf, run^^J%
  mathfont-code.dtx through LaTeX.^^J^^J}
  \expandafter\end
\fi
%</batchfile>
%<*driver>
\documentclass[12pt,doc2,letterpaper,oneside]{ltxdoc}
\makeatletter
\flushbottom
\usepackage[margin=1.5in]{geometry}
\usepackage[factor=700,stretch=14,shrink=14,step=1]{microtype}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{enumitem}
\usepackage{soul}
\usepackage{amsmath}
\setlist{itemsep=\smallskipamount,topsep=\smallskipamount,
  parsep=\z@,partopsep=\z@}
\c@IndexColumns=2
\c@topnumber\@ne
\columnsep=20pt
\MacroIndent=1.5em
\AtBeginDocument{%
  \baselineskip=\the\baselineskip plus 0.3pt minus 0.3pt\relax}
\let\index@prologue\relax
\EnableCrossrefs\CodelineIndex
\begin{document}
  \def\documentname{Implementation}
  \def\showabstract{1}
  \input mathfont-doc-patch.tex
  \input mathfont-heading.tex
  \DocInput{mathfont-code.dtx}
  \vfil\eject
  \immediate\closeout\@indexfile
  \ifx\directlua\@undefined
    \immediate\write18{makeindex -s gind.ist mathfont-code.idx}
  \else
    \directlua{os.execute("makeindex -s gind.ist mathfont-code.idx")}
  \fi
  
  \section*{Index}
  
  Upright entries refer to lines in the code, and italic
  entries indicate pages in the document. Bold means a
  definition.
  
  \hfuzz=20pt
  
  %\medskip
  \input mathfont-code.ind
  
\end{document}
%</driver>
%<*package>
% 
% \fi
% 
% 
% \CheckSum{7075}
% \init@checksum
% 
% 
% \makeatother\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          \~}
% \makeatletter
% 
% 
% \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\DeclareOption,\ProcessOptions,%
%   \def,\edef,\global,\let,\csname,\endcsname,\expandafter,\relax,\advance,
%   \newcount,\newif,\z@,\@ne,\m@ne,\ifx,\ifcat,\ifnum,\ifeof,\ifmmode,
%   \else,\fi,\PackageInfo,\PackageWarning,\PackageError,\message,\@undefined,%
%   \space,\MessageBreak,\string,\M@count,\count@,\noexpand,\@empty,
%   \@tempa,\@tempb,\@tempc,\@temp@opt,\@temp@sub,\@i,\@j,\@k,\count,\tw@,%
%   \do,\DeclareMathSymbol,\the,\mathalpha,\mathord,\multiply,
%   \mathop,\mathbin,\mathrel,\mathopen,\mathclose,\mathpunct,\mathinner,%
%   \DeclareRobustCommand,\joinrel,\smash,\newtoks,\if,\\,\@nil,\leavevmode,
%   \begingroup,\endgroup,\+,\active,\@gobbletwo,\GenericError,\catcode,
%   \wlog,\typeout,\E@sterEggUpd@te,\show,\@temperror,%
%   \xdef,\@for,\@tfor,\@ifundefined,\@ifpackageloaded,\@nnil,\@onlypreamble,%
%   \AtBeginDocument,\AtEndOfPackage,\AtVeryVeryEnd,\bgroup,\CurrentOption,%
%   \egroup,\escapechar,\ifM@upper,\ifM@lower,\ifM@diacritics,%
%   \ifM@greekupper,\ifM@greeklower,\ifM@agreekupper,%
%   \ifM@agreeklower,\ifM@cyrillicupper,\ifM@cyrilliclower,%
%   \ifM@hebrew,\ifM@digits,\ifM@operator,\ifM@symbols,%
%   \ifM@extsymbols,\ifM@delimiters,\ifM@arrows,\ifM@bigops,%
%   \ifM@extbigops,\ifM@bb,\ifM@cal,\ifM@frak,\ifM@bcal,\M@font@loadedtrue,%
%   \ifM@bfrak,\if@optionpresent,\if@suboptionpresent,%
%   \mathgroup,\nolimits,\on@line,\PackageWarningNoLine,\RequirePackage,%
%   \thr@@,\M@toks,\inputlineno,\mathchar@type,\DeclareMathAccent,%
%   \ifM@EasterEgg@declare,\M@EasterEgg@declaretrue,\M@EasterEgg@declarefalse,%
%   \IfFileExists,\E@sterEggHook,\@gobblefour,\@gobble@brackets,%
%   \protected,\@eha,\@cclv,\new@mathgroup,\new@symbolfont,\@latex@error,%
%   \ifcase,\or,\thr@@,\gdef,\rmdefault,\openin,\closein,\immediate,%
%   \M@Decl@reF@milytrue,\M@Decl@reF@milyfalse,\itdefault,\shapedefault,%
%   \mddefault,\bfdefault,\E@sterEggDecl@redtrue,\detokenize,\scdefault,%
%   \@next,\@suboptionpresenttrue,\@suboptionpresentfalse,\@break@tfor,%
%   \M@adjust@fonttrue,\M@adjust@fontfalse,\M@fromCharmFiletrue,%
%   \M@fromCharmFilefalse,\M@arg@goodtrue,\M@arg@goodfalse,\M@Noluaotfloadtrue,%
%   \M@Noluaotfloadfalse,\M@XeTeXLuaTeXtrue,\ifcsname,\ifdefined,\TU,\",%
%   \@@DeclareSymbolFont,\@@set@mathaccent,\@@set@mathchar,\@@set@mathsymbol,%
%   \@expandedtwoargs,\@spaces,\@tempswatrue,\@tempswafalse,\@iftempswa,%
%   \copy,\e@mathgroup@top,\endlinechar,\everyeof,%
%   \globaldefs,\m@th,\newbox,\newread,\newmuskip,\number,\setmainfont,%
%   \zap@space,\setbox,\clap,\hss,\ht,\wd,\dp,\raise,\M@arrows@font,%
%   \M@delimiters@font,\M@extbigops@font,\M@extsymbols@font,\M@symbols@font,%
%   \M@greekupper@font,\M@greeklower@font,\M@agreekupper@font,%
%   \M@agreeklower@font,\M@bigops@font,\M@upper@font,\M@lower@font,%
%   \M@radical@font,\M@diacritics@font,\M@cyrillicupper@font,\M@digits@font,%
%   \M@cyrilliclower@font,\M@hebrew@font,\Umathcode,\EasterEggUpdate,%
%   \@firstofone,\if@arg@good,\M@f@ntn@me,\M@f@ntn@meb@se,\dimen@,%
%   \math@E@sterEggUpd@te,\@DMA,\@DMS,\@tempwarning,\@mathfontinfo,\everymath,%
%   \Udelcode,\Udelimiter,\restoremathinternals,\@@set@mathchar,%
%   \@@set@mathsymbol,\@@set@mathaccent,\set@mathchar,\set@mathsymbol,%
%   \set@mathaccent,\Umathcode,\Umathchardef,\Umathaccent,\@easter@egg@,%
%   \@expandtwoargs,\afterassignment,\aftergroup,\AtEndDocument,%
%   \DeclareSymbolFont@m@dropped,\directlua,\ifodd,\edef@nospace,\hb@xt@,%
%   \hbox,\hfil,\if@operator@s,\ifE@sterEggDecl@red,\ifin@,in@,\llap,%
%   \mathpalette,\mathsm@sh,\meaning,\numexpr,\scantokens,\scantextokens,%
%   \strip@prefix,\vphantom,\XeTeXrevision,\symMupright,\ProcessE@sterEgg,%
%   \@ifnextchar,\@testopt,\endinput,\Umathcharnumdef,\Umathcodes,\Umathcodenum,%
%   \seriesdefault,\@@DeclareSymbolFont@m@dropped,\ifM@radical,\@backslashchar,%
%   \}
% 
% 
% \DoNotIndex{\cyrA,\cyrBe,\cyrVe,\cyrGhe,\cyrDe,%
%   \cyrIe,\cyrZhe,\cyrZe,\cyrI,\cyrKa,\cyrEl,%
%   \cyrEm,\cyrEn,\cyrO,\cyrPe,\cyrEr,\cyrEs,%
%   \cyrTe,\cyrU,\cyrEf,\cyrHa,\cyrTse,\cyrChe,%
%   \cyrSha,\cyrShcha,\cyrHard,\cyrYeru,\cyrSoft,%
%   \cyrE,\cyrYu,\cyrYa,\cyrvarI,\cyra,\cyrbe,%
%   \cyrve,\cyrghe,\cyrde,\cyrie,\cyrzhe,\cyrze,%
%   \cyri,\cyrka,\cyrel,\cyrem,\cyren,\cyro,%
%   \cyrpe,\cyrer,\cyres,\cyrte,\cyru,\cyref,%
%   \cyrha,\cyrtse,\cyrche,\cyrsha,\cyrshcha,%
%   \cyrhard,\cyryeru,\cyrsoft,\cyre,\cyryu,%
%   \cyrya,\cyrvari}
% 
%  
% \DoNotIndexMain{\colon,\mathellipsis,\angle,\sqsubset,\sqsupset,\bowtie,%
%   \doteq,\neq,\ng,\clubsuit,\spadesuit,\diamondsuit,%
%   \heartsuit,\cong,\uparrow,\Uparrow,\downarrow,\Downarrow,%
%   \updownarrow,\Updownarrow,\longrightarrow,\longleftarrow,$
%   \longleftrightarrow,\hookrightarrow,\hookleftarrow,%
%   \Longrightarrow,\Longleftarrow,\Longleftrightarrow,%
%   \rightleftharpoons,\to,\mapsto,\mapsto,\longmapsto,%
%   \from,\mapsfrom,\longmapsfrom,\lightningboltarrow,\sum,%
%   \prod,\coprod,\bigvee,\bigwedge,\bigcup,\bigcap,%
%   \bigoplus,\bigotimes,\bigodot,\bigsqcup,\iint,\iiint,%
%   \oint,\oiint,\oiiint,\lbrace,\rbrace,\lguil,\rguil,%
%   \backslash,\mathbackslash,\textng,\simeq,\vert,\llguil,%
%   \rrguil,\fakelangle,\fakerangle,\fakellangle,\fakerrangle,%
%   \models,\bigtimes,\@@relbar,\@@Relbar}
% 
% \noindent This file documents the code for the \textsf{mathfont} package. It is not a user guide! If you are looking for instructions on how to use \textsf{mathfont} in your document, see |mathfont-user-guide.pdf|, which is included with the \textsf{mathfont} installation and is available on \textsc{ctan}. See also the other |pdf| documentation files for \textsf{mathfont}. Section~1 of this document begins with the implementation basics, including package declaration and package options. Section~2 deals with errors and messaging, and section~3 provides package default settings. Section~4 contains fontloader, and section~5 contains the optional-argument parser for |\mathfont|. Section 6 documents the code for the |\mathfont| command itself. Section~7 contains the code for local font changes. Section~8 contains miscellaneous material. Sections~9--11 contain the Lua code to modify font objects at loading, and section~12 lists the unicode hex values used in symbol declaration. Version history and code index appear at the end of the document.
% 
% \section{Setup}
% 
% 
% 
% First, the package should declare itself. The first 61 lines of |mathfont.sty| are comments. \c@CodelineNo=61\relax
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mathfont}[2025/06/05 v. 2.4a]
%    \end{macrocode}
% Informational message.
%    \begin{macrocode}
\def\@mathfontinfo#1{\wlog{Package mathfont Info: #1}}
%    \end{macrocode}
% We specify conditionals and one count variable that we use later in handling options and setup.
%    \begin{macrocode}
\newif\ifM@XeTeXLuaTeX     % is engine one of xetex or luatex?
\newif\ifM@Noluaotfload    % cannot find luaotfload.sty?
\newif\ifM@adjust@font     % should adjust fonts with lua script?
\newif\ifM@font@loaded     % load mathfont with font specified?
\newif\ifE@sterEggDecl@red % already did easter egg?
\newcount\M@loader         % specifies which font-loader to use
%    \end{macrocode}
% We disable the twenty user-level commands. If \textsf{mathfont} runs normally, it will overwrite these ``bad'' definitions later, but if it throws one of its two fatal errors, it will |\endinput| while the user-level commands are error messages. That way the commands don't do anything in the user's document, and the user gets information on why not. The bad definitions gobble their original arguments to avoid a ``missing |\begin{document}|'' error. To streamline the process, we metacode most of the error messages. We do so in three batches: those that |\@gobble| their argument, those that |\@gobbletwo| their argument, and those that accept an optional argument.\indexpage{invalid command}
%    \begin{macrocode}
\long\def\@gobble@brackets[#1]{}
\def\M@NoMathfontError#1{\PackageError{mathfont}
  {\MessageBreak Invalid command\MessageBreak
  \string#1 on line \the\inputlineno}
  {Your command was ignored. I couldn't\MessageBreak
  load mathfont, so I never defined this\MessageBreak
  control sequence.}}
%    \end{macrocode}
% First the commands that normally accept a single argument---the ``bad'' versions |\@gobble| the argument. To keep the syntax straightforward, we put the |\def| declaration inside |\@tempa| and the definition itself inside |\@tempb|. We need to do this because the macro name is stored in |\@i|, and otherwise, we would end up with a mess of |\expandafter|s to expand all instances of |\@i|.
%    \begin{macrocode}
\@tfor\@i:=\setfont
  \RuleThicknessFactor
  \IntegralItalicFactor
  \SurdVerticalFactor
  \SurdHorizontalFactor
  \CharmLine
  \CharmFile\do{%
    \edef\@tempa{\protected\def\expandafter\noexpand\@i{%
      \noexpand\M@NoMathfontError\expandafter\noexpand\@i
      \noexpand\@gobble}}
    \@tempa}
%    \end{macrocode}
% Now for the macros that |\@gobbletwo| their argument. The code is essentially the same.
%    \begin{macrocode}
\@tfor\@i:=\newmathrm
  \newmathit
  \newmathbf
  \newmathbfit
  \newmathsc
  \newmathscit
  \newmathbfsc
  \newmathbfscit\do{%
    \edef\@tempa{\protected\def\expandafter\noexpand\@i{%
      \noexpand\M@NoMathfontError\expandafter\noexpand\@i
      \noexpand\@gobbletwo}}
    \@tempa}
%    \end{macrocode}
% For the optional argument, we check if the following character is a |[|. If yes, we gobble first the brackets and then the mandatory argument. If not, we gobble the single mandatory argument.
%    \begin{macrocode}
\protected\def\mathfont{%
  \M@NoMathfontError\mathfont
  \@ifnextchar[{\expandafter\@gobble\@gobble@brackets}
    {\@gobble}}
\protected\def\mathconstantsfont{%
  \M@NoMathfontError\mathconstantsfont
  \@ifnextchar[{\expandafter\@gobble\@gobble@brackets}
    {\@gobble}}
%    \end{macrocode}
% We code |\newmathfontcommand| by hand because it is the only command with four arguments.
%    \begin{macrocode}
\protected\def\newmathfontcommand{%
  \M@NoMathfontError\newmathfontcommand\@gobblefour}
%    \end{macrocode}
% Check that the engine is \XeTeX\ or Lua\TeX. If yes, set |\ifM@XeTeXLuaTeX| to true. (Otherwise the conditional will be false by default.)
%    \begin{macrocode}
\ifdefined\directlua
  \M@XeTeXLuaTeXtrue
\fi
\ifdefined\XeTeXrevision
  \M@XeTeXLuaTeXtrue
\fi
%    \end{macrocode}
% The package can raise two fatal errors: one if the engine is not \XeTeX\ or Lua\TeX\ (and cannot load OpenType fonts) and one if \TeX\ cannot find the \textsf{luaotfload} package. In both cases, the package will stop loading, so we want a particularly conspicuous error message. For each message, we check the appropriate conditional to determine if we need to raise the error. If yes, we change space to catcode 12 inside a group.\indexpage{catcode changes} We define a |\GenericError| inside a macro and then call the macro for a cleaner error context line. The |\@gobbletwo| eats the extra period and return that \LaTeX\ adds to the error message. Notice that we expand the error before the |\endgroup|\textemdash this is because we need to switch |\M@XeTeXLuaTeXError| with its replacement text while it is still defined before we leave the group. At the same time, we want |\AtBeginDocument| and |\endinput| outside the group. The second |\expandafter| means that we expand the final |\fi| before |\endinput|, which balances the original conditional.\indexpage{unable to load}\indexpage{missing xetex or luatex=missing \XeTeX\ or Lua\TeX}
%    \begin{macrocode}
\ifM@XeTeXLuaTeX\else
\begingroup
\catcode`\ =12\relax
\def\M@XeTeXLuaTeXError{\GenericError{}%
{\MessageBreak\MessageBreak
Package mathfont error:%
\MessageBreak\MessageBreak
*************************\MessageBreak
*                       *\MessageBreak
*       UNABLE TO       *\MessageBreak
*     LOAD MATHFONT     *\MessageBreak
*                       *\MessageBreak
*     Missing XeTeX     *\MessageBreak
*       or LuaTeX       *\MessageBreak
*                       *\MessageBreak
*************************\MessageBreak\@gobbletwo}%
{See the mathfont package documentation for explanation.}%
{I need XeTeX or LuaTeX to use mathfont. It\MessageBreak
looks like the current engine is something\MessageBreak
else, so I'm going to stop reading in the\MessageBreak
package file now. (You won't be able to use\MessageBreak
commands from mathfont in your document.) To\MessageBreak
load mathfont correctly, please retypeset your\MessageBreak
document with one of those two engines.^^J}}%
\expandafter\endgroup
\M@XeTeXLuaTeXError
  \AtEndOfPackage{%
    \typeout{:: mathfont :: Failed to load\on@line.}}
  \expandafter\endinput % we \endinput with a balanced conditional
\fi
%    \end{macrocode}
% Now do the same thing in checking for \textsf{luaotfload}. If the engine is Lua\TeX, we tell \textsf{mathfont} to implement Lua-based font adjustments by default. The conditional |\ifM@Noluaotfload| will keep track of whether \TeX\ could find |luaotfload.sty|. If the engine is \XeTeX, issue a warning.
%    \begin{macrocode}
\ifdefined\directlua
  \M@adjust@fonttrue % if engine is LuaTeX, adjust font by default
  \IfFileExists{luaotfload.sty}
    {\M@Noluaotfloadfalse\RequirePackage{luaotfload}}
    {\M@Noluaotfloadtrue}
\else
  \AtEndOfPackage{\PackageWarningNoLine{mathfont}{%
    The current engine is XeTeX, but as\MessageBreak
    of mathfont version 2.0, LuaTeX is\MessageBreak
    recommended. Consider compiling with\MessageBreak
    LuaLaTeX. Certain features will not\MessageBreak
    work with XeTeX}}
\fi
%    \end{macrocode}
% If the engine is Lua\TeX, we must have \textsf{luaotfload} because Lua\TeX\ needs this package to load OpenType fonts. Before anything else, \TeX\ should check whether it can find |luaotfload.sty| and stop reading in \textsf{mathfont} if it cannot. Same command structure as before. Newer \LaTeX\ versions load \textsf{luaotfload} as part of the format, but it never hurts to double check.\indexpage{unable to load}\indexpage{cannot not find the file luaotfloadsty=cannot find the file \texttt{luaotfload}}
%    \begin{macrocode}
\ifM@Noluaotfload % true if LuaTeX AND no luaotfload.sty
\begingroup
\catcode`\ =12\relax
\def\M@NoluaotfloadError{\GenericError{}%
{\MessageBreak\MessageBreak
Package mathfont error:%
\MessageBreak\MessageBreak
*************************\MessageBreak
*                       *\MessageBreak
*       UNABLE TO       *\MessageBreak
*     LOAD MATHFONT     *\MessageBreak
*                       *\MessageBreak
*    Cannot find the    *\MessageBreak
*  file luaotfload.sty  *\MessageBreak
*                       *\MessageBreak
*************************\MessageBreak\@gobbletwo}%
{You are likely seeing this message because you haven't^^J%
installed luaotfload. Check your TeX distribution for a^^J%
list of the packages on your system.^^J^^J%
See the mathfont documentation for further explanation.}%
{You're in trouble here. It looks like the current\MessageBreak
engine is LuaTeX, so I need the luaotfload package\MessageBreak
to make mathfont work properly. However, I can't\MessageBreak
find luaotfload, which likely means something is\MessageBreak
wrong with your TeX installation. I'm going to stop\MessageBreak
reading in the mathfont package file. (You won't be\MessageBreak
able to use commands from mathfont in your document.)\MessageBreak
To load mathfont work correctly, make sure you have\MessageBreak
installed luaotfload.sty in a directory searchable\MessageBreak
by TeX or compile with XeLaTeX.^^J}}%
\expandafter\endgroup
\M@NoluaotfloadError
  \AtEndOfPackage{%
    \typeout{:: mathfont :: Failed to load\on@line.}}
  \expandafter\endinput % we \endinput with a balanced conditional
\fi
%    \end{macrocode}
% As of version 2.4, I'm taking out the deprecated package options, which used to live here. Easter egg!!
%    \begin{macrocode}
\DeclareOption{easter-egg}{%
  \ifE@sterEggDecl@red\else
    \E@sterEggDecl@redtrue
    \newcount\@easter@egg@
    \def\EasterEggUpdate{\ProcessE@sterEgg\show\E@sterEggUpd@te}
    \let\ProcessE@sterEgg\relax
%    \end{macrocode}
% Two status updates during package loading.
%    \begin{macrocode}
    \edef\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        Okay, opening your Easter egg.^^J%
        Type \string\EasterEggUpdate\space in your^^J%
        document to see the status.^^J^^J}
      \EasterEggUpdate
    \def\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        Uh oh. It looks like your Easter^^J%
        egg flew out the window. I don't^^J%
        I don't suppose you know the best^^J%
        kind of bait to lure an egg?^^J^^J}
      \EasterEggUpdate
%    \end{macrocode}
% Possible updates if the user types |\EasterEggUpdate|. We define the status update with |\ProcessE@sterEgg|, which stores the current message in |\E@sterEggUpd@te| and changes the message as the user calls |\EasterEggUpdate|. The count |\@easter@egg@| keeps track of how many times the user has requested a status update.
%    \begin{macrocode}
    \def\ProcessE@sterEgg{%
      \edef\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        \ifodd\@easter@egg@
          \ifcase\numexpr(\@easter@egg@ - 1) / 2\relax
            An Easter bunny must be related to a^^J%
            platypus, no? Some sort of monotreme...%
          \or
            Don't count your chickens before they hatch^^J%
            out of Easter eggs! But we don't have any^^J%
            chickens right now because there are no eggs,^^J%
            and the supply chain is sad.%
          \or
            Sorry, I'm late to a meeting. Can't talk right now.%
          \or
            Sunday, Monday, Tuesday, Wednesday, also^^J%
            known as hump day, as in camel humps, which^^J%
            I must say look distinctly egg-like if you^^J%
            squint.%
          \or
            I'm calling Eggs Anonymous!%
          \or
            Sorry, I'm on the phone. Can't talk right now.%
          \or
            Still haven't found your Easter egg. I know^^J%
            it's floating around here somewhere. Like an^^J%
            asteroid in space, hopefully without the^^J%
            massive extinction event.%
          \or
            Did you know eggs are used to make certain^^J%
            types of vaccines? PSA: get your flu shot^^J%
            and your covid shot!%
          \or
            Three large eggs.^^J%
            Three large eggs.^^J%
            See how they crack.^^J%
            See how they crack.^^J%
            Their broken shells are so pearly white.^^J%
            In simmering water they catch the light.^^J%
            Did you ever see such a sight in your life^^J%
            As three poached eggs?%
          \or
            Do gnus eat eggs? Surely they must.%
          \or
            Okay, I have a fishing rod, some twine, and^^J%
            a hook, but I still haven't caught your Easter^^J%
            egg. Apparently it's harder to catch an egg^^J%
            than a fish.%
          \or
            Sorry, I'm out fishing. Can't talk right now.%
          \or
            Is ghoti really an acceptable phonetic^^J%
            spelling of fish? I am skeptical.%
          \or
            Perhaps an Easter bunny is actually a species^^J%
            of fish. A rabbit fish.%
          \else
            Sorry, I'm all out of witty things to say.^^J%
            Check back later.%
          \fi
        \else
          Still wrangling. Check back later.%
        \fi^^J^^J}%
      \global\advance\@easter@egg@\@ne}
%    \end{macrocode}
% One status update |\AtBeginDocument|.
%    \begin{macrocode}
    \AtBeginDocument{\bgroup
      \let\ProcessE@sterEgg\relax
      \def\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        If we have zero eggs^^J%
        and zero bunnies, how^^J%
        many gnats does it take^^J%
        to change a lightbulb??^^J^^J}
      \EasterEggUpdate
      \egroup}
%    \end{macrocode}
% One update at the first instance of math mode, assuming another package doesn't overwrite the contents of |\everymath| first.
%    \begin{macrocode}
    \def\math@E@sterEggUpd@te{\begingroup
      \let\ProcessE@sterEgg\relax
      \def\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        Scrambled, poached, or sunny side up?^^J^^J}%
      \EasterEggUpdate
      \endgroup
      \global\let\math@E@sterEggUpd@te\relax}
    \everymath\expandafter{\the\everymath\math@E@sterEggUpd@te}
%    \end{macrocode}
% Two status updates |\AtEndDocument|, including the egg itself. First, we disable |\ProcessE@sterEgg| since we don't need it anymore. Then inside a group, we make the control symbols |\*|, |\/|, and |\=| expand to their own names and do some extreme catcode sports. We convert |+| to active and make it expand to a space. Because everything has already been tokenized inside |\DeclareOption|, we have to retokenize the definition of |+| inside |\scantokens|, and we set |\everyeof| to |\noexpand| to avoid an end-of-file error.
%    \begin{macrocode}
    \AtEndDocument{\let\ProcessE@sterEgg\relax
      \begingroup
        \edef\*{\@backslashchar*}
        \edef\/{\@backslashchar/}
        \edef\={\@backslashchar=}
        \catcode`\+=\active
        \everyeof{\noexpand}
        \scantokens{\def+{ }}
%    \end{macrocode}
% At this point we are ready to make the egg message Again, we have to retokenize everything with |\scantokens| because it was previously tokenized. However, if we write |^^J| directly inside |\scantokens|, that primitive will convert the newline to a blank space, so instead we store |^^J| in |\@tempb|. After the |\edef| expands |\scantokens|, it also expands each |\@tempb|, so |\@tempa| has the line breaks we want.
%    \begin{macrocode}
        \def\@tempb{^^J}
        \edef\@tempa{\scantokens{Easter Egg Status:\@tempb\@tempb
        The egg has been retrieved. What\@tempb
        pinnacle of pulchritude!\@tempb\@tempb
        +++++++++++++******\@tempb
        ++++++++++************\@tempb
        +++++++******************\@tempb
        +++++----------------------\@tempb
        +++**************************\@tempb
        ++****/\****/\****/\****/\****\@tempb
        +*****\/****\/****\/****\/*****\@tempb
        +******************************\@tempb
        ********************************\@tempb
        ***/\****/\****/\****/\****/\***\@tempb
        ***\/****\/****\/****\/****\/***\@tempb
        ********************************\@tempb
        ********************************\@tempb
        ******/\****/\****/\****/\******\@tempb
        +*****\/****\/****\/****\/*****\@tempb
        ++****************************\@tempb
        +++--------------------------\@tempb
        +++++**********************\@tempb
        +++++++******************\@tempb
        +++++++++\============/\@tempb
        +++++++++++\========/\@tempb
        ++++++++++++\======/\@tempb
        +++++++++++++|====|\@tempb
        ++++++++++++/======\@backslashchar\@tempb
        +++++++++++(________)\@tempb}}
%    \end{macrocode}
% Then end the group and store the message in |\E@sterEggUpd@te|.
%    \begin{macrocode}
      \expandafter\endgroup\expandafter
      \def\expandafter\E@sterEggUpd@te\expandafter{\@tempa}
      \EasterEggUpdate
      \def\E@sterEggUpd@te{Easter Egg Status:^^J^^J%
        Happy, happy day! Happy,^^J%
        happy day! Clap your hands,^^J%
        and be glad your hovercraft^^J%
        isn't full of eels!^^J^^J}
      \EasterEggUpdate
      \let\E@sterEggUpd@te\relax
      \let\EasterEggUpdate\relax}
  \fi}% my easter egg :)
%    \end{macrocode}
% The five real package options. The |default-loader| and |fontspec-loader| tell \textsf{mathfont} what to use as a backend for loading fonts.
%    \begin{macrocode}
\DeclareOption{default-loader}{\M@loader\z@}
\DeclareOption{fontspec-loader}{\M@loader\@ne}
%    \end{macrocode}
% The options |adjust| and |no-adjust| determine whether \textsf{mathfont} applies Lua-based font adjustments to fonts loaded in the future.
%    \begin{macrocode}
\DeclareOption{adjust}{\M@adjust@fonttrue}
\DeclareOption{no-adjust}{\M@adjust@fontfalse}
%    \end{macrocode}
% Interpret an unknown option as a font name and save it for loading. In this case, the package sets |\ifM@font@loaded| to true and stores the font name in |\M@font@load|.
%    \begin{macrocode}
\DeclareOption*{\M@font@loadedtrue
  \edef\M@font@load{\CurrentOption}}
\ProcessOptions*
%    \end{macrocode}
% For the font-loader, we have a bit of processing to do. First print an informational message in the |log| file. The default loader is easy, but if the user requests \textsf{fontspec}, we have to make sure to load everything properly.
%    \begin{macrocode}
\ifcase\M@loader
  \@mathfontinfo{Default font-loader was
    requested for font loading.}
\or
  \@mathfontinfo{Package fontspec was
    requested for font loading.}
%    \end{macrocode}
% If \textsf{fontspec} was already loaded, check whether |\g__fontspec_math_bool| is true or not. If it is, change it to false.
%    \begin{macrocode}
  \@ifpackageloaded{fontspec}
    {\@mathfontinfo{Package fontspec detected.}
      \csname bool_if:NTF\expandafter\endcsname
        \csname g__fontspec_math_bool\endcsname
        {\@mathfontinfo{Setting
          \string\g__fontspec_math_bool to false.}
          \csname bool_set_false:N\expandafter\endcsname
          \csname g__fontspec_math_bool\endcsname}{\relax}}
%    \end{macrocode}
% If \textsf{fontspec} was not loaded, check that the package file exists. 
%    \begin{macrocode}
    {\@mathfontinfo{Package fontspec not detected.}
      \IfFileExists{fontspec.sty}
        {\@mathfontinfo{File fontspec.sty was found.}
          \@mathfontinfo{Loading fontspec.}
          \RequirePackage[no-math]{fontspec}}
        {\PackageError{mathfont}
          {Missing package fontspec;\MessageBreak
          using default font-loader instead}
          {You requested fontspec as
          the font-loader for\MessageBreak
          mathfont. However, I can't
          find the fontspec\MessageBreak
          package file, so I'm going
          to use the default\MessageBreak
          font-loader instead. (This
          likely means that\MessageBreak
          something is wrong with your
          TeX installation.)\MessageBreak
          Check your TeX distribution
          for a list of the\MessageBreak
          packages installed on your
          system. To resolve\MessageBreak
          this error, make sure fontspec
          is installed in\MessageBreak
          a directory searchable by TeX or
          load mathfont\MessageBreak
          with the default-loader option.^^J}
          \M@loader\z@}}
\fi
%    \end{macrocode}
% We print an informational message specifying the font-loader in use. We store default OpenType features in |\M@otf@features|. The contents depend on the font-loader because we use \XeTeX/\textsf{luaotfload} syntax versus \textsf{fontspec} syntax. By default, \textsf{mathfont} loads fonts with Latin script, default language, \TeX\ and common ligatures, and lining numbers.
%    \begin{macrocode}
\ifcase\M@loader
  \@mathfontinfo{Using default font-loader.}
  \AtEndOfPackage{%
    \typeout{:: mathfont :: Using default font-loader.}}
  \def\M@otf@features{script=latin;language=DFLT;%
    +tlig;+liga;+lnum}
\or
  \@mathfontinfo{Using fontspec as font-loader.}
  \AtEndOfPackage{%
    \typeout{:: mathfont :: Using fontspec as font-loader.}}
  \def\M@otf@features{Script=Latin,
    Language=Default,
    Ligatures={TeX,Common},
    Numbers=Lining}
\fi
%    \end{macrocode}
% We print an informational message depending on whether the user enabled Lua-based font adjustments. If |\directlua| is defined, that means we are using Lua\TeX, so we print a message depending on |\ifM@adjust@font|.
%    \begin{macrocode}
\ifdefined\directlua
  \ifM@adjust@font
    \@mathfontinfo{Enabling Lua-based font adjustments.}
    \AtEndOfPackage{%
      \typeout{:: mathfont :: Lua-based font adjustments
        enabled.}}
  \else
    \@mathfontinfo{Disabling Lua-based font adjustments.}
    \AtEndOfPackage{%
      \typeout{:: mathfont :: Lua-based font adjustments
        disabled.}}
  \fi
\else
%    \end{macrocode}
% If |\directlua| is undefined, we make sure Lua-based font adjustments are disabled, and we issue an error if the user tried to manually enable them.
%    \begin{macrocode}
  \ifM@adjust@font
    \PackageError{mathfont}{Option^^J"adjust" ignored with XeTeX}
    {Your package option "adjust" was ignored.\MessageBreak
    This option works only with LuaTeX, and it\MessageBreak
    looks like the current engine is XeTeX. To\MessageBreak
    enable Lua-based font adjustments, typeset\MessageBreak
    with LuaLaTeX.^^J}
    \M@adjust@fontfalse
  \fi
  \@mathfontinfo{Disabling Lua-based font adjustments.}
  \AtEndOfPackage{%
    \typeout{:: mathfont :: Lua-based font adjustments disabled.}}
\fi
%    \end{macrocode}
% 
% 
% \section{Messages and Errors}
% 
% 
% 
% Some error and informational messages. Table~1 lists all macros defined in this section along with a brief description of their use. We begin with general informational messages.\indexpage{Package mathfont Info}
% 
% \begin{figure}[tbp]
% \def\vrb#1{\texttt{\string#1}}
% \centerline{\bfseries Table 1: Various Messages and Errors and Their Uses\strut}
% \begin{tabularx}\textwidth{lX<{\raggedright\arraybackslash}}
% \toprule
% Command & Use\\\midrule
% \vrb\@mathfontinfo & General informational macro\\
% \vrb\M@FontChangeInfo & When using a new symbol font\\
% \vrb\M@NewFontCommandInfo & New local font-change command\\
% \vrb\M@SymbolFontInfo & Declare new symbol font\\\midrule
% \vrb\M@CharsSetWarning & Warning when calling \vrb\mathfont\ multiple times for same keyword\\
% \vrb\M@InternalsRestoredError & User called \vrb\mathfont\ after restoring kernel\\\midrule
% \vrb\M@MissingNFSSShapesWarning & Warning if font is missing shapes\\
% \vrb\M@NoBaseModeDetectedWarning & Warning if no base-mode version of a font\\\midrule
% \vrb\M@InvalidOptionError & Bad option for \vrb\mathfont\\
% \vrb\M@InvalidSupoptionError & Bad suboption for \vrb\mathfont\\
% \vrb\M@MissingOptionError & Missing an option for \vrb\mathfont\\
% \vrb\M@MissingSuboptionError & Missing suboption for \vrb\mathfont\\\midrule
% \vrb\M@BadMathConstantsFontError & Argument not previously fed to \vrb\mathfont\\
% \vrb\M@BadMathConstantsFontTypeError & Argument not ``upright'' or ``italic''\\
% \vrb\M@LuaTeXOnlyWarning & User called \vrb\mathcontsantsfont\ in \XeTeX\\\midrule
% \vrb\M@DoubleArgError & Gave multiple tokens to be the font-change macro\\
% \vrb\M@HModeError & Font-change command used outside math mode\\
% \vrb\M@MissingControlSequenceError & No macro for font-change command\\\midrule
% \vrb\M@BadIntegerError & Font metric adjustment value was not an integer\\
% \vrb\M@ForbiddenCharmFile & Bad character in charm file\\
% \vrb\M@ForbiddenCharmLine & Bad character in charm line\\
% \vrb\M@NoFontAdjustError & Command called when Lua-based font adjustment was disabled\\
% \bottomrule
% \end{tabularx}
% \end{figure}
% 
% \indexpage{I already set the font}
% \indexpage{The nfss family}
% \indexpage{I couldn't find a base-mode}
%    \begin{macrocode}
\def\M@SymbolFontInfo#1#2#3#4{\wlog{}%
  \@mathfontinfo{Declaring new symbol font from #1!^^J%
  NFSS Family Name: \space#2^^J%
  Series/Shape Info: #3^^J%
  Symbol Font Name:  \space#4^^J}}
\def\M@FontChangeInfo#1#2{\@mathfontinfo{Setting #1 chars to #2!}}
\def\M@NewFontCommandInfo#1#2#3#4#5{\wlog{}%
  \@mathfontinfo{Creating \string#1 using #2!^^J%
  NFSS Family Name: \space#3^^J%
  Series/Shape Info: #4/#5^^J}}
\def\M@CharsSetWarning#1{%
  \PackageWarning{mathfont}
  {I already set the font for\MessageBreak
  #1 chars, so I'm ignoring\MessageBreak
  this option for \string\mathfont\space
  on line \the\inputlineno\@gobble}}
\def\M@MissingNFSSShapesWarning#1#2{%
  \PackageWarning{mathfont}
  {The nfss family "#1"\MessageBreak
  from line \the\inputlineno\space
  is missing shapes. You\MessageBreak
  may see some substitutions or errors.\MessageBreak
  Missing shape(s):#2\@gobble}}
\def\M@NoBaseModeDetectedWarning#1{%
  \PackageWarning{mathfont}
  {I couldn't find a base-mode version of\MessageBreak
  the nfss family "#1"\MessageBreak
  from line \the\inputlineno,
  so I'm using the family\MessageBreak
  you specified for the math font. Some\MessageBreak
  font features may not work in math\MessageBreak
  mode\@gobble}}
%    \end{macrocode}
% Error messages associated with |\mathfont|.
% \indexpage{invalid option for mathfont=Invalid option for \texttt{\char`\\mathfont}}
% \indexpage{invalid suboption for mathfont=Invalid suboption for \texttt{\char`\\mathfont}}
% \indexpage{missing option for mathfont=Missing option for \texttt{\char`\\mathfont}}
% \indexpage{missing suboption for mathfont=Missing suboption for \texttt{\char`\\mathfont}}
% \indexpage{no previous font}\indexpage{missing package fontspec=Missing package \texttt{fontspec}}
%    \begin{macrocode}
\def\M@InvalidOptionError#1{%
  \PackageError{mathfont}
  {Invalid^^Joption "#1"
  for \string\mathfont\on@line}
  {Hm. You used a keyword that
  isn't actually an optional\MessageBreak
  argument for \string\mathfont. Check 
  that you spelled the keyword\MessageBreak
  correctly. Otherwise, I'm not sure
  what's wrong. Is this\MessageBreak
  option listed in the package documentation?
  In any event,\MessageBreak
  I'm going to ignore it.^^J}}
\def\M@InvalidSuboptionError#1{%
  \PackageError{mathfont}
  {Invalid^^Jsuboption "#1"
  for \string\mathfont\on@line}
  {Hm. You used a keyword that
  isn't actually a suboption\MessageBreak
  for \string\mathfont. Check that you 
  spelled the keyword correctly.\MessageBreak
  Otherwise, I'm not sure what's wrong.
  Is this suboption\MessageBreak
  listed in the package documentation?
  In any event, I'm\MessageBreak
  going to ignore it.^^J}}
\def\M@MissingOptionError{%
  \PackageError{mathfont}
  {Missing^^Joption for
  \string\mathfont\on@line}
  {It looks like you
  included a , or = in\MessageBreak
  the optional argument of
  \string\mathfont\space but\MessageBreak
  didn't put anything before it.^^J}}
\def\M@MissingSuboptionError{%
  \PackageError{mathfont}
  {Missing^^Jsuboption for
  \string\mathfont\on@line}
  {It looks like you
  included an = somewhere\MessageBreak
  in the optional argument of
  \string\mathfont\space but\MessageBreak
  didn't put the suboption
  after it. Either\MessageBreak
  that or you typed == instead of =.^^J}}
%    \end{macrocode}
% Error messages for |\mathconstantsfont|.
% \indexpage{Invalid font specifier}
% \indexpage{your mathconstants on line=Your \texttt{\char`\\mathconstants} on line}
%    \begin{macrocode}
\def\M@BadMathConstantsFontError#1{%
  \PackageError{mathfont}
  {Invalid font specifier\MessageBreak
  for \string\mathconstantsfont:\MessageBreak
  "#1"}
  {Your command was ignored---I
  can't parse your argument.\MessageBreak
  Please make sure to use text
  that you have previously\MessageBreak
  fed to \string\mathfont\space
  for the argument of 
  \string\mathconstantsfont.^^J}}
\def\M@BadMathConstantsFontTypeError#1{%
  \PackageError{mathfont}
  {Invalid\MessageBreak font specifier for
  \string\mathconstantsfont:\MessageBreak"#1"}
  {The optional argument of
  \string\mathconstantsfont\MessageBreak
  should be "upright" or "italic."
  Right now,\MessageBreak
  it's "#1."^^J}}
\def\M@MathConstantsNoAdjustWarning{%
  \PackageWarning{mathfont}
  {Your \string\mathconstantsfont\space
  on line \the\inputlineno\MessageBreak
  is mainly for use in
  LuaTeX with font\MessageBreak
  adjustments enabled.
  In the current\MessageBreak
  situation, it is
  probably not doing\MessageBreak
  anything\@gobble}}
%    \end{macrocode}
% Error messages for the |\newmathrm|, etc.\ commands.
% \indexpage{Missing control sequence}
% \indexpage{Multiple characters in argument}
% \indexpage{Missing \$ inserted=Missing \texttt\$ inserted}
%    \begin{macrocode}
\def\M@MissingControlSequenceError#1#2{%
  \PackageError{mathfont}
  {Missing control sequence\MessageBreak
  for\string#1\MessageBreak
  on input line \the\inputlineno}
  {Your command was ignored.
  Right now the\MessageBreak
  first argument of
  \string#1\space is "#2."\MessageBreak
  Please use a control
  sequence instead.^^J}}
\def\M@DoubleArgError#1#2{%
  \PackageError{mathfont}
  {Multiple characters in\MessageBreak
  first argument of \string#1\MessageBreak
  on input line \the\inputlineno}
  {Your command was ignored.
  Right now the\MessageBreak
  first argument of
  \string#1\space is "#2,"\MessageBreak
  which is multiple characters.
  Please use\MessageBreak
  a single character instead.^^J}}
\def\M@HModeError#1{%
  \PackageError{mathfont}
  {Missing \string$ inserted\MessageBreak
  on input line line \the\inputlineno}
  {I generated an error because 
  you used \string#1\space
  outside of\MessageBreak
  math mode. I inserted a \string$
  before your \string#1,
  so we\MessageBreak
  should be all good now.^^J}}
%    \end{macrocode}
% We need error messages related to Lua-based font adjustments.
% \indexpage{Forbidden charm info}
% \indexpage{Your command is invalid without Lua-based}
% \indexpage{Bad argument for}
%    \begin{macrocode}
\def\M@ForbiddenCharmLine#1{%
  \PackageError{mathfont}
  {Forbidden charm info contains #1}
  {The argument of your \string\CharmLine\space
  macro on line \the\inputlineno\MessageBreak
  contains the character #1,
  which will mess me up\MessageBreak
  if I try to read it, so I'm
  ignoring this call\MessageBreak
  to \string\CharmLine. To resolve
  this error, make sure\MessageBreak
  your charm information
  contains only integers,\MessageBreak
  floats, asterisks, commas, and spaces.^^J}}
\def\M@ForbiddenCharmFile#1{%
  \PackageError{mathfont}
  {Forbidden charm info contains #1}
  {One of the lines in your
  \string\CharmFile\space
  from line \the\inputlineno\MessageBreak
  contains the character #1,
  which will mess me up\MessageBreak
  if I try to read it, so I'm
  ignoring this line\MessageBreak
  from your file. To resolve
  this error, make sure\MessageBreak
  your charm information
  contains only integers,\MessageBreak
  floats, asterisks, commas, and spaces.^^J}}
\def\M@NoFontAdjustError#1{%
  \PackageError{mathfont}
  {Your command \MessageBreak
  \string#1 is invalid\MessageBreak
  without Lua-based font adjustments}
  {You haven't enabled Lua-based
  font adjustments,\MessageBreak
  but the macro you called won't
  do anything without\MessageBreak
  them. I'm going to ignore your
  command for now. To\MessageBreak
  resolve this error, load mathfont
  with the package\MessageBreak
  option "adjust" or compile with LuaLaTeX.^^J}}
\def\M@BadIntegerError#1#2{%
  \PackageError{mathfont}
  {Bad argument for\MessageBreak\string#1}
  {Your command was ignored.
  Please make sure\MessageBreak
  that your argument of
  \string#1\space\MessageBreak
  is a nonnegative integer.
  Right now it's\MessageBreak
  "#2".^^J}}
%    \end{macrocode}
% 
% 
% \section{Default Settings}
% 
% We save four macros from the \LaTeX\ kernel for safe-keeping, and then we change their definitions. To make the symbol declaration macros from the kernel compatible with unicode fonts, we convert the hexadecimal digits in |\count0| and |\count2| back to decimal and change the |\math| primitive to |\Umath|.\indexpage{LaTeX kernel=\LaTeX\ kernel}
%    \begin{macrocode}
\let\@@set@mathchar\set@mathchar
\let\@@set@mathsymbol\set@mathsymbol
\let\@@set@mathaccent\set@mathaccent
\let\@@DeclareSymbolFont\DeclareSymbolFont
\let\@@DeclareSymbolFont@m@dropped\DeclareSymbolFont@m@dropped
\@onlypreamble\@@set@mathchar
\@onlypreamble\@@set@mathsymbol
\@onlypreamble\@@set@mathaccent
\@onlypreamble\@@DeclareSymbolFont
\@onlypreamble\@@DeclareSymbolFont@m@dropped
\@mathfontinfo{Adapting \noexpand\set@mathchar for unicode.}
\@mathfontinfo{Adapting \noexpand\set@mathsymbol for unicode.}
\@mathfontinfo{Adapting \noexpand\set@mathaccent for unicode.}
\@mathfontinfo{Increasing upper bound on
  \noexpand\DeclareSymbolFont to 256.}
%    \end{macrocode}
% Kernel command to set math characters from keystrokes.
%    \begin{macrocode}
\def\set@mathchar#1#2#3#4{%
  \multiply\count\z@ by 16\relax
  \advance\count\z@\count\tw@
  \global\Umathcode`#2=\mathchar@type#3+#1+\count\z@\relax}
%    \end{macrocode}
% Kernel command to set math characters from control sequences.
%    \begin{macrocode}
\def\set@mathsymbol#1#2#3#4{%
  \multiply\count\z@ by 16\relax
  \advance\count\z@\count\tw@
  \global\Umathchardef#2=\mathchar@type#3+#1+\count\z@\relax}
%    \end{macrocode}
% Kernel command to set accents.
%    \begin{macrocode}
\def\set@mathaccent#1#2#3#4{%
  \multiply\count\z@ by 16\relax
  \advance\count\z@\count\tw@
  \protected\xdef#2{%
    \Umathaccent\mathchar@type#3+\number#1+\the\count\z@\relax}}
%    \end{macrocode}
% We increase the upper bound on the number of symbol fonts to be 256. Lua\TeX\ and \XeTeX\ allow up to 256 math families, but the \LaTeX\ kernel keeps the old upper bound of 16 symbol fonts under these two engines. We patch |\DeclareSymbolFont| to change the |\count18<15| to |\count18|\penalty0|<\e@mathgroup@top|, where |\e@mathgroup@top| is the number of math families, which is 256 in \XeTeX\ and Lua\TeX. We get a sanitized definition with |\meaning| and |\strip@prefix|, implement the patch by expanding |\M@p@tch@decl@re|, and retokenize the whole thing. A simpler approach, such as calling |\M@p@tch@decl@re| directly on the expansion of |\DeclareSymbolFont|, won't work because of how \TeX\ stores and expands parameter symbols inside macros.
% 
% As of November 2022, the \LaTeX\ team renamed |\DeclareSymbolFont| to |\DeclareSymbolFont@m@dropped|, and now |\DeclareSymbolFont| is a wrapper around the old version of itself. This was done for error checking purposes to remove extra |m|'s from certain \textsc{nfss} family names. This means that if |\DeclareSymbolFont@m@dropped| is defined, we should patch that macro, and otherwise, we should patch |\DeclareSymbolFont|.
%    \begin{macrocode}
\ifx\DeclareSymbolFont@m@dropped\@undefined
  \edef\@tempa{\expandafter
    \strip@prefix\meaning\DeclareSymbolFont}
  \def\@tempb{\def\DeclareSymbolFont##1##2##3##4##5}
\else
  \edef\@tempa{\expandafter
    \strip@prefix\meaning\DeclareSymbolFont@m@dropped}
  \def\@tempb{\def\DeclareSymbolFont@m@dropped##1##2##3##4##5}
\fi
\def\M@p@tch@decl@re#1<15#2\@nil{#1<\e@mathgroup@top#2}
\edef\M@DecSymDef{\expandafter\M@p@tch@decl@re\@tempa\@nil}
%    \end{macrocode}
% Now |\M@DecSymDef| contains the patched text of our new |\DeclareSymbolFont|, all with catcode 12. In order to make it useable, we have to retokenize it. We use |\scantextokens| in Lua\TeX\ and a safe version of |\scantokens| in \XeTeX. We store the |\def\DeclareSymbolFont| and parameter declaration in a separate macro |\@tempa| to make it easy to expand around them when we redefine |\DeclareSymbolFont|.
%    \begin{macrocode}
\ifdefined\directlua
  \expandafter\@tempb\expandafter{\scantextokens
    \expandafter{\M@DecSymDef}}
%    \end{macrocode}
% Unfortunately, while |\scantextokens| is straightforward, |\scantokens| is a menace. The problem is that when it expands, the primitive inserts an end-of-file token (because |\scantokens| mimics writing to a file and |\input|ing what it just wrote) after the retokenized code, and as a result, |\scantokens| can produce an end-of-file error. We can make the command usable by putting a |\noexpand| inside |\everyeof|. In order to prevent the |\edef| from also expanding our retokenized definition of |\DeclareSymbolFont|, we put the definition inside |\unexpanded|.
%    \begin{macrocode}
\else
  \begingroup
  \everyeof{\noexpand}
%    \end{macrocode}
% The first |\edef| expands |\M@DecSymDef| and defines |\M@retokenize| to be |\scantokens|\penalty0|{|\penalty0|\unexpanded|\penalty0|{|\meta{new definition}|}}|, and the second |\edef| carries out the retokenization. Once we have stored the patched definition in |\M@retokenize|, we expand |\M@retokenize| before the |\endgroup| and redefine |\DeclareSymbolFont| by calling |\@tempa|.
%    \begin{macrocode}
  \edef\M@retokenize{\noexpand\scantokens
    {\noexpand\unexpanded{\M@DecSymDef}}}
  \edef\M@retokenize{\M@retokenize}
  \expandafter\endgroup
    \expandafter\@tempb\expandafter{\M@retokenize}
\fi
%    \end{macrocode}
% We need to keep track of the number of times we have loaded fonts, and |\M@count| fulfills this role. The |\toks| will record a message that displays in the |log| file when the user calls |\mathfont|. The |\newread| is for Lua-based font adjustments.
%    \begin{macrocode}
\newbox\surdbox
\newcount\M@count
\newcount\M@num@localfonts
\newcount\M@RuleThicknessFactor
\newcount\M@IntegralItalicFactor
\newcount\M@SurdVerticalFactor
\newcount\M@SurdHorizontalFactor
\newmuskip\radicandoffset
\newread\M@Charm
\newtoks\M@toks
\M@count\z@
\M@RuleThicknessFactor\@m
\M@IntegralItalicFactor=400\relax
\M@SurdHorizontalFactor\@m
\M@SurdVerticalFactor\@m
\radicandoffset=2mu\relax
%    \end{macrocode}
% Macro that we use later to store font names for local font changes.
%    \begin{macrocode}
\let\M@localfonts\@empty
%    \end{macrocode}
% Necessary booleans and default math font shapes.
%    \begin{macrocode}
\newif\ifM@upper
\newif\ifM@lower
\newif\ifM@diacritics
\newif\ifM@greekupper
\newif\ifM@greeklower
\newif\ifM@agreekupper
\newif\ifM@agreeklower
\newif\ifM@cyrillicupper
\newif\ifM@cyrilliclower
\newif\ifM@hebrew
\newif\ifM@digits
\newif\ifM@operator
\newif\ifM@symbols
\newif\ifM@extsymbols
\newif\ifM@delimiters
\newif\ifM@radical
\newif\ifM@arrows
\newif\ifM@bigops
\newif\ifM@extbigops
\newif\ifM@bb
\newif\ifM@cal
\newif\ifM@frak
\newif\ifM@bcal
\newif\ifM@bfrak
\newif\if@optionpresent
\newif\if@suboptionpresent
\newif\ifM@arg@good
\newif\ifM@Decl@reF@mily
\newif\ifM@fromCharmFile
%    \end{macrocode}
% Default shapes.
% \let\@@marginmacro\marginmacro ^^A temporarily disable writing macros
% ^^A in the margin
% \def\marginmacro#1\@nil{}
% \indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
\def\M@uppershape{italic}          % latin upper
\def\M@lowershape{italic}          % latin lower
\def\M@diacriticsshape{upright}    % diacritics
\def\M@greekuppershape{upright}    % greek upper
\def\M@greeklowershape{italic}     % greek lower
\def\M@agreekuppershape{upright}   % ancient greek upper
\def\M@agreeklowershape{italic}    % ancient greek lower
\def\M@cyrillicuppershape{upright} % cyrillic upper
\def\M@cyrilliclowershape{italic}  % cyrillic lower
\def\M@hebrewshape{upright}        % hebrew
\def\M@digitsshape{upright}        % numerals
\def\M@operatorshape{upright}      % operator font
\def\M@delimitersshape{upright}    % delimiters
\def\M@radicalshape{upright}       % surd
\def\M@bigopsshape{upright}        % big operators
\def\M@extbigopsshape{upright}     % extended big operators
\def\M@symbolsshape{upright}       % basic symbols
\def\M@extsymbolsshape{upright}    % extended symbols
\def\M@arrowsshape{upright}        % arrows
\def\M@bbshape{upright}            % blackboard bold
\def\M@calshape{upright}           % caligraphic
\def\M@frakshape{upright}          % fraktur
\def\M@bcalshape{upright}          % bold caligraphic
\def\M@bfrakshape{upright}         % bold fraktur
%    \end{macrocode}
% \let\marginmacro\@@marginmacro
% The |\M@keys| list stores all the possible keyword options, and |\M@defaultkeys| stores the character classes that |\mathfont| acts on by default.\indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
\def\M@keys{upper,lower,diacritics,greekupper,%
  greeklower,agreekupper,agreeklower,cyrillicupper,%
  cyrilliclower,hebrew,digits,operator,delimiters,%
  radical,bigops,extbigops,symbols,extsymbols,arrows,%
  bb,cal,frak,bcal,bfrak}
\def\M@defaultkeys{upper,lower,diacritics,greekupper,%
  greeklower,digits,operator,symbols}
%    \end{macrocode}
%  If the user enabled Lua-based font adjustments, the |\M@defaultkeys| list also includes delimiters, surd, and big operator symbols.
%    \begin{macrocode}
\ifM@adjust@font
  \edef\M@defaultkeys{\M@defaultkeys,delimiters,radical,bigops}
\fi
%    \end{macrocode}
% 
% 
% \section{Fontloader}
% 
% We come to the fontloader. The main font-loading macro is |\M@newfont|. It expects a font name and OpenType feature information in its argument, and it parses the information, adds fonts to the \textsc{nfss} if necessary, and stores \textsc{nfss} font family names in |\M@f@ntn@me| and |\M@f@nt@n@me@base|. (Advanced users: please do not call |\M@newfont| directly because its implementation may change. Instead call |\mathfont| with the |empty| keyword and extract the \textsc{nfss} family name from |\M@f@ntn@me| or |\M@f@ntn@meb@se|.) Our general approach is to feed the mandatory argument of |\mathfont| to |\M@newfont|, then proceed in one of three ways: (1) if the argument of |\mathfont| corresponds to a font family already in the \textsc{nfss}, including one that \textsf{mathfont} created through the built-in font-loader, check what shapes are present and issue a warning if we appear to be missing any important ones; (2) if the argument is not a family in the \textsc{nfss} and |\M@loader| is 0, we use the default font-loader, which is essentially a wrapper around code that we would expect to find in a typical |fd| file; or (3) otherwise, we feed the font name and feature information directly to \textsf{fontspec} and save the corresponding family name for reference later.
% 
% We use two control sequences for the family names because in Lua\TeX, we load the font twice. The first time uses a default or user-specified renderer (typically node mode), and the second time uses base mode. Node mode is better for text, but it has more limited capabilities in math mode. Accordingly, we use a node-mode version of the font for text and the base-mode version for math, and advanced users who want to manually switch to a given |\fontfamily| at some point in their document are probably better off using the family that \textsf{mathfont} loaded with the default renderer. The package stores the \textsc{nfss} family name for this version of the font in |\M@f@ntn@me|, and |\M@f@nt@n@me@base| contains the \textsc{nfss} family name of the base-mode version. In \XeTeX, these control sequences will be identical. Given a font family name from |\M@f@ntn@me|, it is possible to find the corresponding base-mode family name by calling |\csname|\penalty0|\M@f@ntn@me-base|\penalty0|\endcsname|. With \textsf{mathfont}'s built-in font-loader, the family name will be the mandatory argument of |\mathfont| with spaces removed, and the family name from using \textsf{fontspec} will be different.
% 
% We begin with commands to add series and shape information to the \textsc{nfss} for a given font family. The |\M@declare@shape| macro takes several arguments. It checks whether the series/shape pair exists in the \textsc{nfss}, and if not, it adds it using |\DeclareFontShape|. The argument structure is
%   \begin{itemize}
%   \item |#1|---\textsc{nfss} font family name
%   \item |#2|---optional |/B| or |/I| (or |/BI|) suffix on the font name
%   \item |#3|---a list of (default) OpenType feature tags
%   \item |#4|---a list of (the user's) OpenType feature tags
%   \item |#5|---\textsc{nfss} series identifier
%   \item |#6|---\textsc{nfss} shape identifier
%   \end{itemize}
% We assume that the font file reference has already been stored in |\@tempbase|.
%    \begin{macrocode}
\def\M@declare@shape#1#2#3#4#5#6{%
  \ifcsname TU/#1/#5/#6\endcsname
  \else
    \DeclareFontShape{TU}{#1}{#5}{#6}{<->"\@tempbase#2:#3;#4"}{}
  \fi}
%    \end{macrocode}
% The |\M@fill@nfss@shapes| command does the work of populating the \textsc{nfss} with the correct shape information. The argument structure is:
%   \begin{itemize}
%   \item |#1|---\textsc{nfss} font family name
%   \item |#2|---a list of (default) OpenType feature tags
%   \item |#3|---a list of (the user's) OpenType feature tags
%   \end{itemize}
% We call |\M@declare@shape| for each combination of medium/bold series and upright/italic shape, and the result is an entry in the \textsc{nfss} for each combination. We have separate declarations for regular and small caps because they have different shape identifiers in the \textsc{nfss}. We manually set |smcp| to be |true| or |false| accordingly.
%    \begin{macrocode}
\def\M@fill@nfss@shapes#1#2#3{%
  \@for\@i:={#1}{}{#2;-smcp}{#3}{\mddefault}{\shapedefault},%
    {#1}{/I}{#2;-smcp}{#3}{\mddefault}{\itdefault},%
    {#1}{/B}{#2;-smcp}{#3}{\bfdefault}{\shapedefault},%
    {#1}{/BI}{#2;-smcp}{#3}{\bfdefault}{\itdefault},%
%    \end{macrocode}
% And do small caps. If a small caps font face is separate from the main font file, \TeX\ won't be able to find it automatically. In that case, you will have to write your own |fd| file or |\DeclareFontShape| commands.
%    \begin{macrocode}
    {#1}{}{#2;+smcp}{#3}{\mddefault}{\scdefault},%
    {#1}{/I}{#2;+smcp}{#3}{\mddefault}{\scdefault\itdefault},%
    {#1}{/B}{#2;+smcp}{#3}{\bfdefault}{\shapedefault},%
    {#1}{/BI}{#2;+smcp}{#3}{\bfdefault}{\scdefault\itdefault}%
      \do{\expandafter\M@declare@shape\@i}}
%    \end{macrocode}
% The |\M@check@nfss@shapes| macro checks if a font family has shapes declared in upright, italic, bold, and bold italic. If any of those shapes are missing, we issue a warning. We store the missing series/shape pairs in |\@tempb| to print them as part of the warning message.
%    \begin{macrocode}
\def\M@check@nfss@shapes#1{%
  \let\@tempb\@empty
  \let\@tempwarning\@gobble
  \@for\@i:=\mddefault/\shapedefault,%
    \mddefault/\itdefault,%
    \bfdefault/\shapedefault,%
    \bfdefault/\itdefault\do{%
      \expandafter\ifx\csname TU/#1/\@i\endcsname\relax
        \def\@tempwarning{\M@MissingNFSSShapesWarning{#1}}
        \edef\@tempb{\@tempb, \@i}
      \fi}
%    \end{macrocode}
% We use a small hack to get everything to print correctly. If all shapes are present, then |\@tempwarning| is |\@gobble|, and the argument disappears. Otherwise, the argument becomes part of the warning message. The |\@gobble| eats the (unnecessary) first comma inside |\@tempb|.
%    \begin{macrocode}
  \@tempwarning{\expandafter\@gobble\@tempb}}
%    \end{macrocode}
% We use |\M@split@colon| and |\M@strip@colon| for parsing the argument of |\mathfont|. If the user calls |\mathfont{|\meta{name}|:|\meta{features}|}|, we store the name in |\@tempbase| and the features in |\@tempfeatures|. If the user specifies a name only, then |\@tempfeatures| will be empty. Syntactically, we use |\M@strip@colon| to remove a final |:| the same way we remove a final |=| when we parse the optional argument in the next section.
%    \begin{macrocode}
\def\M@split@colon#1:#2\@nil{%
  \def\@tempbase{#1}
  \def\@tempfeatures{#2}}
\def\M@strip@colon#1:{#1}
%    \end{macrocode}
% The main font-loading macro. The command takes a single argument, which should have the form \meta{\textup{\textsc{nfss}} family} or \meta{font name}|:|\meta{optional features}, and it begins by parsing the argument. It splits the argument at a |:| and stores each portion in |\@tempbase| and |\@tempfeatures|. If |\@tempfeatures| is not empty, it has an extra colon at the end. We remove it. Previous versions of \textsf{mathfont} allowed users to say |\mathfont{fontspec}|, but this functionality is no longer supported.
%    \begin{macrocode}
\def\M@newfont#1{%
  \edef\@tempa{#1}
  \expandafter\M@split@colon\@tempa:\@nil
  \ifx\@tempfeatures\@empty\else
    \edef\@tempfeatures{\expandafter\M@strip@colon\@tempfeatures}
  \fi
%    \end{macrocode}
% First we check if the argument is an entry in the \textsc{nfss}. If yes, we check if the shapes are present using |\M@check@nfss@shapes|. We assume that if the user specifies a font family identifier here, they know what they are doing, and the font-loader makes no attempt to fill in missing shapes.
%    \begin{macrocode}
  \ifcsname TU+\@tempbase\endcsname % is font family in the nfss?
    \let\M@f@ntn@me\@tempbase
    \M@check@nfss@shapes\M@f@ntn@me
    \ifx\directlua\@undefined % if XeTeX
      \expandafter\edef
        \csname\M@f@ntn@me-base\endcsname{\M@f@ntn@me}
      \let\M@f@ntn@meb@se\M@f@ntn@me
    \else % if LuaTeX
%    \end{macrocode}
% With Lua\TeX, we would like to have a proper base-mode version of the font. If the font declaration happened outside of \textsf{mathfont} and the engine is Lua\TeX, then \textsf{mathfont} expects to find another font family whose \textsc{nfss} identifier is stored in |\|\meta{font family}|-base|, and we assume this second font was loaded with |mode=base|. If that information exists, we use it for the base-mode version. Otherwise, we issue a warning if the engine is Lua\TeX.
%    \begin{macrocode}
      \ifcsname\M@f@ntn@me-base\endcsname % if base-mode version
        \edef\M@f@ntn@meb@se
          {\csname\M@f@ntn@me-base\endcsname}
        \M@check@nfss@shapes\M@f@ntn@meb@se
      \else
        \M@NoBaseModeDetectedWarning{\M@f@ntn@me}
        \edef\M@f@ntn@meb@se{\M@f@ntn@me}
        \expandafter\edef
          \csname\M@f@ntn@me-base\endcsname{\M@f@ntn@me}
      \fi
    \fi
%    \end{macrocode}
% Now save the font families for reference later.
%    \begin{macrocode}
    \expandafter\edef
      \csname M@fontfamily@\@tempbase\endcsname
      {\M@f@ntn@me}
    \expandafter\edef
      \csname M@fontfamily@base@\@tempbase\endcsname
      {\M@f@ntn@meb@se}
  \else
%    \end{macrocode}
% If the argument is not a font family identifier, then we check if \textsf{mathfont} has previously loaded a font using this argument. If yes, it will be stored in |\M@fontfamily@|\meta{arg}, and we use the font family name from the previous call to |\M@newfont|. We remove the spaces before using the argument because in general, we do not want \textsf{mathfont} to use space characters internally to distinguish font names.
%    \begin{macrocode}
    \edef@nospace\@tempa{\@tempa}
    \ifcsname M@fontfamily@\@tempa\endcsname
      \edef\M@f@ntn@me{\csname M@fontfamily@\@tempa\endcsname}
      \edef\M@f@ntn@meb@se
        {\csname M@fontfamily@base@\@tempa\endcsname}
    \else
%    \end{macrocode}
% If |\M@newfont| doesn't find anything previously that matches |#1|, we load the font. Under the built-in font-loader, the name for the font family will be |#1| with spaces removed, which we store in |\M@f@ntn@me|. (A properly declared \textsc{nfss} font family does not have spaces in its name because \LaTeX\ ignores spaces when scanning a font family declaration.) Then we call |\M@fill@nfss@shapes| to declare all the shapes.
% \indexpage{log file=\texttt{log} file}
%    \begin{macrocode}
      \edef@nospace\@tempa{\@tempa}
      \ifcase\M@loader % are we using default font-loader?
        \let\M@f@ntn@me\@tempa
        \@mathfontinfo{^^JAdding \@tempbase\space
          to the nfss!}
        \wlog{Family name: \M@f@ntn@me}
        \DeclareFontFamily{TU}{\M@f@ntn@me}{}
        \M@fill@nfss@shapes{\M@f@ntn@me}{\M@otf@features}
          {\@tempfeatures}
%    \end{macrocode}
% If the engine is Lua\TeX, we load a separate version of the font with |mode=base|. Then we link the base-mode and regular versions.
%    \begin{macrocode}
        \ifdefined\directlua
          \edef\M@f@ntn@meb@se{\M@f@ntn@me-base}
          \@mathfontinfo{Adding \@tempbase\space with mode=base
            to the nfss!}
          \wlog{Family name: \M@f@ntn@meb@se}
          \DeclareFontFamily{TU}{\M@f@ntn@meb@se}{}
          \M@fill@nfss@shapes{\M@f@ntn@meb@se}{\M@otf@features}
            {\@tempfeatures;mode=base}
        \else
          \edef\M@f@ntn@meb@se{\M@f@ntn@me}
        \fi
      \or              % are we using fontspec as font-loader?
%    \end{macrocode}
% If the user requested \textsf{fontspec} as the font-loader, we pass the font name and features to |\fontspec_set_family:Nnn| for loading and store the \textsc{nfss} family name in |\M@f@ntn@me|. In Lua\TeX, we request a separate base-mode version by specifying |Renderer=Base|.
%    \begin{macrocode}
        \@mathfontinfo{^^JPassing \@tempbase\space
          to fontspec for handling!}
        \csname fontspec_set_family:Nnn\endcsname\M@f@ntn@me
          {\M@otf@features,\@tempfeatures}{\@tempbase}
        \ifdefined\directlua
          \@mathfontinfo{Passing \@tempbase\space
            with Renderer=Base to fontspec for handling!}
          \csname fontspec_set_family:Nnn\endcsname\M@f@ntn@meb@se
            {\M@otf@features,\@tempfeatures,Renderer=Base}
            {\@tempbase}
        \else
            \edef\M@f@ntn@meb@se{\M@f@ntn@me}
        \fi
      \fi
%    \end{macrocode}
% Now link the base-mode family name and store the family names for future reference.
%    \begin{macrocode}
      \expandafter\edef\csname\M@f@ntn@me-base\endcsname
        {\M@f@ntn@meb@se}
      \expandafter\edef\csname M@fontfamily@\@tempa\endcsname
        {\M@f@ntn@me}
      \expandafter\edef\csname M@fontfamily@base@\@tempa\endcsname
        {\M@f@ntn@meb@se}
    \fi
  \fi}
%    \end{macrocode}
% Finally, the font-loading commands should appear only in the preamble.
%    \begin{macrocode}
\@onlypreamble\M@declare@shape
\@onlypreamble\M@fill@nfss@shapes
\@onlypreamble\M@newfont
%    \end{macrocode}
% At this point, the font information is stored in the \textsc{nfss}, but nothing has been loaded. For text fonts, that happens during a call to |\selectfont|, and for math fonts, that happens the first time entering math mode. I've considered forcing some fonts to load now, but I'm hesitant to change \LaTeX's standard font-loading behavior. On this issue, I plan to leave \textsf{mathfont} as is for the foreseeable future. (Which probably means forever because backwards compatibility.)
% 
% 
% 
% \section{Parse Input}
% 
% This section provides the macros to parse the optional argument of |\mathfont|. We have two parts to this section: error checking and parsing. For parsing, we extract option and suboption information, and for error checking, we make sure that both are valid. The command |\M@check@option@valid| accepts a macro containing (what is hopefully) the text of a keyword-option. The macro defines |\@temperror| to be an invalid option error and loops through all possible options. If the argument matches one of the correct possibilities, \textsf{mathfont} changes |\@temperror| to |\relax|. The macro ends by calling |\@temperror| and issuing an error if and only if the argument is invalid. If |\M@check@option@valid| finds a valid keyword-option, it changes |\if@optionpresent| to true.\indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
\def\M@check@option@valid#1{%
  \let\@temperror\M@InvalidOptionError % error by default
  \@for\@j:=\M@keys\do{%
    \ifx\@j#1
      \let\@temperror\@gobble % eliminate error
      \@optionpresenttrue     % set switch to true
    \fi}
  \def\@j{empty} % if option is "empty," we do nothing
  \ifx\@j#1
    \let\@temperror\@gobble
    \@optionpresentfalse
  \fi
  \@temperror{#1}}
%    \end{macrocode}
% Do the same thing for the suboption.
% \indexpage{suboption roman=suboption \texttt{roman}}%
% \indexpage{suboption upright=suboption \texttt{upright}}%
% \indexpage{suboption italic=suboption \texttt{italic}}%
%    \begin{macrocode}
\def\M@check@suboption@valid#1{%
  \let\@temperror\M@InvalidSuboptionError % error by default
  \@for\@j:=roman,upright,italic\do{%
    \ifx\@j#1
      \let\@temperror\@gobble % eliminate error
      \@suboptionpresenttrue  % set switch to true
    \fi}
  \@temperror{#1}}
%    \end{macrocode}
% Now we have to actually parse the optional argument. We want to allow the user to specify options using an \textsf{xkeyval}-type syntax. However, we do not need the full package; a slim 30 lines of code will suffice. When |\mathfont| reads one segment of \textit{text} from its optional argument, it calls |\M@parse@option|\meta{text}|=\@nil|. The |\M@parse@option| macro splits the option and suboption by looking for the first |=|. It puts its |#1| argument (hopefully the keyword-option) in |\@temp@opt| and puts |#2| (hopefully the keyword-suboption) in |\@temp@sub|. If the user specifies a suboption, |\@tempb| contains \meta{suboption}|=|, and we use |\M@strip@equals| to get rid of the extra |=|. If the user does not specify a suboption, |\@tempb| will be empty.
% \indexpage{parse mathfont arguments=parse \texttt{\char`\\mathfont} arguments}
%   \begin{macrocode}
\def\M@strip@equals#1={#1}
\def\M@parse@option#1=#2\@nil{%
  \@optionpresentfalse    % set switch to false by default
  \@suboptionpresentfalse % set switch to false by default
  \def\@temp@opt{#1}      % store option
  \def\@temp@sub{#2}      % store suboption
%    \end{macrocode}
% After storing the option in |\@temp@opt| and suboption in |\@temp@sub|, check for errors. We check for errors by determining if (1) |\@tempa| is empty, meaning the user did not specify an option; or (2) |@tempb| is |=|, meaning the user typed |=| but did not follow it with a suboption.
%    \begin{macrocode}
  \ifx\@temp@opt\@empty
    \M@MissingOptionError
  \else
%    \end{macrocode}
% Check that the user specified a valid option. We redefine |\@tempa| inside a group to keep the change local, and we end the group as quickly as possible after the comparison, which means separate |\egroup|s in both branches of |\ifx|.
%    \begin{macrocode}
    \M@check@option@valid\@temp@opt
    \bgroup\def\@tempa{=}
    \ifx\@temp@sub\@tempa
      \egroup % first branch \egroup
      \M@MissingSuboptionError
    \else
      \egroup % second branch \egroup
%    \end{macrocode}
% If |\@temp@sub| is nonempty, strip the final |=| and check that it contains a valid suboption.
%    \begin{macrocode} 
      \ifx\@temp@sub\@empty
      \else
        \edef\@temp@sub{\expandafter\M@strip@equals\@temp@sub}
        \M@check@suboption@valid\@temp@sub % is suboption legit?
      \fi
    \fi
%    \end{macrocode}
% If the user specified suboption |roman|, we accept it for backwards compatibility and convert it to |upright|. Again, we redefine |\@tempa| inside a group to keep the change local.
%    \begin{macrocode}
    \bgroup\def\@tempa{roman}
    \ifx\@temp@sub\@tempa
      \egroup % first branch \egroup
      \def\@temp@sub{upright}
    \else
      \egroup % second branch \egroup
    \fi
  \fi}
%    \end{macrocode}
% We code a general-purpose definition macro that defines its first argument to be the second argument fully expanded and with spaces removed.
%    \begin{macrocode}
\long\def\edef@nospace#1#2{%
  \edef#1{#2}%
  \edef#1{\expandafter\zap@space#1 \@empty}}
%    \end{macrocode}
% Perhaps something that sets spaces to |\catcode9| and then retokenizes |#2| would be better, but I don't think it matters very much.
% 
% 
% \section{Default Font Changes}\indexpage{default font changes}
% 
% This\vadjust{\penalty-100} section documents default math font changes. The user-level font-changing command is |\mathfont|, and it feeds the font information to |\@mathfont|, the internal command that does the actual font changing. This macro is basically a wrapper around |\DeclareSymbolFont| and a bunch of calls to |\DeclareMathSymbol|, and when the user calls |\@mathfont|, the command declares the user's font in the \textsc{nfss} with |\M@newfont| and loops through the optional argument. On each iteration, |\@mathfont| validates the option and suboption, calls |\DeclareSymbolFont| if necessary, and sets the math codes with |\M@|\meta{keyword}|@set|. 
% \indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
\protected\def\mathfont{\@testopt{\@mathfont}{\M@defaultkeys}}
%    \end{macrocode}
% The internal font-changing command. As of version 2.4, I'm taking out |\restoremathinternals|, so we don't need to check for restored primitives anymore.
%    \begin{macrocode}
\def\@mathfont[#1]#2{%
  \M@toks{}
%    \end{macrocode}
% We call |\M@newfont| on the mandatory argument of |\mathfont|, which stores the two \textsc{nfss} family names (one for default renderer and one for base-mode renderer if using Lua\TeX) in |\M@f@ntn@me| and |\M@f@ntn@meb@se|. If we need a new value of |\M@count|, we store it in |\M@fontid@|\meta{\textup{\textsc{nfss}} family name}. We will not need a new value of |\M@count| if the user asks for the same \textsc{nfss} font family twice. Throughout the definition of |\mathfont|, |\@tempa| stores the value of |\M@count| that corresponds to the current font.
% \indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
  \M@newfont{#2}
  \ifcsname M@fontid@\M@f@ntn@me\endcsname % need new \M@count?
  \else
    \expandafter\edef
      \csname M@fontid@\M@f@ntn@me\endcsname{\the\M@count}
    \expandafter\edef
      \csname M@fontid@\M@f@ntn@meb@se\endcsname{\the\M@count}
    \advance\M@count\@ne
  \fi
  \edef\@tempa{\csname M@fontid@\M@f@ntn@me\endcsname}
%    \end{macrocode}
% Expand, zap spaces from, and store the optional argument in |\@tempa|, and then perform the loop. We store the current keyword-suboption pair in |\@i| and then feed it to |\M@parse@option|. We need two |\edef|s here because |\zap@space| appears before |\@tempa| in |\M@eat@spaces|. We expand the argument with the first |\edef| and remove the spaces with the second.
%    \begin{macrocode}
  \edef@nospace\@tempb{#1}
  \@for\@i:=\@tempb\do{\expandafter\M@parse@option\@i=\@nil
    \if@optionpresent
%    \end{macrocode}
% If the user calls |\mathfont| and tries multiple times to set the font for a certain class of characters, \textsf{mathfont} will issue a warning,  and the package will not adjust the font for those characters. Notice the particularly awkward syntax with the |\csname|-|\endcsname| pairs. Without this construct, \TeX\ won't realize that |\csname if@\@tempa\endcsname| matches the eventual |\fi|, and the |\@for| loop will break. (\TeX\ does not have a smart if-parser!)
% \indexpage{I already set the font}
% \indexpage{if-parser}
% \indexpage{keyword options=keyword options for \texttt{\char`\\mathfont}}
%    \begin{macrocode}
      \expandafter\ifx % next lines are two cs to be compared
          \csname ifM@\@temp@opt\expandafter\endcsname
          \csname iftrue\endcsname
        \M@CharsSetWarning{\@temp@opt}
      \else
%    \end{macrocode}
% The case where the current option has not had its math font set. We add the keyword-option to the |\toks|.
%    \begin{macrocode}
        \edef\@tempc{\the\M@toks^^J\@temp@opt}
        \M@toks\expandafter{\@tempc}
%    \end{macrocode}
% If it's present, store the suboption in |\@|\meta{option}|shape| and overwrite the default definition from earlier. Then add the shape information to the toks and store it in |\@tempc|. When it actually sets the font by calling |\M@|\meta{keyword}|@set|, \textsf{mathfont} will determine shape information for the current character class by calling the same |\@|\meta{option}|shape| macro that we store in |\@tempc|.
%    \begin{macrocode}
        \if@suboptionpresent
          \expandafter\edef
            \csname M@\@temp@opt shape\endcsname{\@temp@sub}
        \fi
        \edef\@tempc{\the\M@toks\space
          (\csname M@\@temp@opt shape\endcsname)}
        \M@toks\expandafter{\@tempc}
        \edef\@tempc{\csname M@\@temp@opt shape\endcsname}
%    \end{macrocode}
% \indexpage{suboption roman=suboption \texttt{roman}}
% \indexpage{suboption italic=suboption \texttt{italic}}
% We store the font shape information in |\@tempb|, specifically |\@tempb| will be the default \textsc{nfss} shape code corresponding to the current suboption. At this point, |\@tempc| is either ``upright'' or ``italic,'' so we temporarily let |\@tempb| be the string ``upright'' and check if it equals |\@tempc|. We redefine |\@tempb| depending on the results.
%    \begin{macrocode}
        \def\@tempb{upright}
        \ifx\@tempb\@tempc
          \let\@tempb\shapedefault
        \else
          \let\@tempb\itdefault
        \fi
%    \end{macrocode}
% At this point we have the information we need to declare the symbol font, namely the \textsc{nfss} family (|\M@f@ntn@me|), series (|\mddefault|), and shape (|\@tempb|). The symbol font name will be |M|\meta{suboption}\meta{value of \textrm{\texttt{\string\M@count}}}. We check if the symbol font we need for the current set of characters is defined, and if not, we define it using this information.
%    \begin{macrocode}
        \ifcsname symM\@tempc\@tempa\endcsname\else
          \M@SymbolFontInfo{\@tempbase}{\M@f@ntn@meb@se}
            {\mddefault/\@tempb}{M\@tempc\@tempa}
          \DeclareSymbolFont{M\@tempc\@tempa}{TU}
            {\M@f@ntn@meb@se}{\mddefault}{\@tempb}
        \fi
%    \end{macrocode}
% We store the new font information so we can write it to the |log| file |\AtBeginDocument| and send an informational message to the user.\indexpage{log file=\texttt{log} file}
%    \begin{macrocode}
        \expandafter\edef
          \csname M@\@temp@opt @fontinfo\endcsname{\@tempbase}
        \M@FontChangeInfo{\@temp@opt}{\@tempbase}
%    \end{macrocode}
% We have extra information to keep track of when |\@temp@opt| is |bb|, |cal|, |frak|, |bcal|, or |bfrak| because then \textsf{mathfont} effectively creates a new local font-change command, and we want to make sure that information gets added to |\M@localfonts|.
%    \begin{macrocode}
        \@tfor\@j:={bb}{cal}{frak}{bcal}{bfrak}\do{%
          \ifx\@temp@opt\@j
            \@expandtwoargs\M@addto@localfonts
              {\expandafter\string
                \csname math\@temp@opt\endcsname}
              {\@tempbase}
            \@break@tfor
          \fi}
%    \end{macrocode}
% And now the magic happens!
% \bgroup
% \advance\c@CodelineNo\@ne
% \SpecialIndex{\M@upper@set}
% \SpecialIndex{\M@lower@set}
% \SpecialIndex{\M@diacritics@set}
% \SpecialIndex{\M@greekupper@set}
% \SpecialIndex{\M@greeklower@set}
% \SpecialIndex{\M@agreekupper@set}
% \SpecialIndex{\M@agreeklower@set}
% \SpecialIndex{\M@cyrillicupper@set}
% \SpecialIndex{\M@cyrilliclower@set}
% \SpecialIndex{\M@hebrew@set}
% \SpecialIndex{\M@digits@set}
% \SpecialIndex{\M@operator@set}
% \SpecialIndex{\M@delimiters@set}
% \SpecialIndex{\M@radical@set}
% \SpecialIndex{\M@bigops@set}
% \SpecialIndex{\M@extbigops@set}
% \SpecialIndex{\M@symbols@set}
% \SpecialIndex{\M@extsymbols@set}
% \SpecialIndex{\M@arrows@set}
% \SpecialIndex{\M@bb@set}
% \SpecialIndex{\M@cal@set}
% \SpecialIndex{\M@frak@set}
% \SpecialIndex{\M@bcal@set}
% \SpecialIndex{\M@bfrak@set}
% \egroup
%    \begin{macrocode}
        \csname M@\@temp@opt @set\endcsname % set default font
        \csname M@\@temp@opt true\endcsname % set switch to true
      \fi
    \fi}
%    \end{macrocode}
% Display concluding messages for the user.
% \indexpage{log file=\texttt{log} file}
% \indexpage{terminal}
%    \begin{macrocode}
  \edef\@tempa{\the\M@toks}
  \ifx\@tempa\@empty
    \wlog{The \string\mathfont\space command on line 
      \the\inputlineno\space did not change the font
      for any characters!}
  \else
    \wlog{}
    \typeout{:: mathfont :: Using font \@tempbase\space
      on line \the\inputlineno.}
    \wlog{Character classes changed:\the\M@toks}
  \fi}
\@onlypreamble\mathfont
\@onlypreamble\m@thf@nt
\@onlypreamble\@mathfont
%    \end{macrocode}
% The |\setfont| command will call |\mathfont| and set the text font.
%    \begin{macrocode}
\protected\def\setfont#1{%
  \mathfont{#1}
  \mathconstantsfont{#1}
  \setmathfontcommands{#1}
  \let\rmdefault\M@f@ntn@me}
\@onlypreamble\setfont
%    \end{macrocode}
% The macro |\mathconstantsfont| chooses a font for setting math parameters. It is intended for Lua\TeX\ when \textsf{mathfont} can adjust text fonts and add a MathConstants table. It issues a warning if called without font adjustments enabled. First, it checks if the argument was previously fed to |\mathfont| by seeing whether |\M@fontfamily@|\meta{|\string#1|} is equal to |\relax|. If yes, |#1| was never an argument of |\mathfont|, and we raise an error.
%    \begin{macrocode}
\let\M@SetMathConstants\relax
\protected\def\mathconstantsfont{%
  \@testopt{\@mathconstantsfont}{upright}}
\def\@mathconstantsfont[#1]#2{%
  \edef@nospace\@tempa{#2}
  \edef\@tempa{\csname M@fontfamily@base@\@tempa\endcsname}
  \expandafter\ifx\@tempa\relax
    \M@BadMathConstantsFontError{#2}
  \else
%    \end{macrocode}
% Some error checking. If |#1| isn't ``upright'' or ``italic,'' we should raise an error. If the |\@tempa| font doesn't correspond to a symbol font, we declare it. Before defining |\M@SetMathConstants| if necessary, we store the \textsc{nfss} family name in |\m@th@const@nts@font|.
%    \begin{macrocode}
    \def\@tempb{#1}
    \def\@tempc{upright}
    \ifx\@tempb\@tempc
      \let\m@th@const@nts@font@sh@pe\shapedefault
    \else
      \def\@tempc{italic}
      \ifx\@tempb\@tempc
        \let\m@th@const@nts@font@sh@pe\itdefault
      \else
        \M@BadMathConstantsFontTypeError{#1}
      \fi
    \fi
    \ifcsname symM#1\csname M@fontid@\@tempa\endcsname\endcsname
    \else
      \DeclareSymbolFont{M#1\csname M@fontid@\@tempa\endcsname}
        {TU}{\@tempa}{\mddefault}{\m@th@const@nts@font@sh@pe}
    \fi
    \let\m@th@const@nts@font\@tempa
%    \end{macrocode}
% We come to the tricky problem of making sure to use the correct MathConstants table. Lua\TeX\ automatically initializes all math parameters based on the most recent |\textfont|, etc.\ assignment, so we want to tell \LaTeX\ to reassign whatever default font we're using to the correct math family whenever we load new math fonts. This is possible, but the implementation is super hacky. When \LaTeX\ enters math mode, it checks whether it needs to redo any math family assignments, typically because of a change in font size, and if so, it calls |\getanddefine@fonts| repeatedly to append |\textfont|, etc.\ assignments onto the macro |\math@fonts|. Usually |\math@fonts| is empty because this process always happens inside a group, so we can hook into the code by defining |\math@font| to be |\aftergroup|\meta{extra code}. In this case, the \textit{extra code} will be another call to |\getanddefine@fonts|.
% 
% We initialize |\M@SetMathConstants| to be |\relax|, and we define it the first time the user calls |\mathconstantsfont|. When that happens, \textsf{mathfont} begins by calling |\getanddefine@fonts| inside a group and uses as arguments the upright face of the font corresponding to |#1|. That puts the |\textfont|, |\scriptfont|, and |\scriptscriptfont| assignments corresponding to |#1| inside |\math@fonts|. Then we call |\math@fonts|, and to avoid an infinite loop, we gobble the |\aftergroup||\M@SetMathConstants| macros that \textsf{mathfont} has inserted at the start of |\math@fonts|. Setting |\globaldefs| to 1 makes the |\textfont|, etc.\ assignments from |\getanddefine@fonts| global when we call |\math@fonts|.\indexpage{LaTeX kernel=\LaTeX\ kernel}^^A
%    \begin{macrocode}
    \protected\def\M@SetMathConstants{%
      \begingroup
      \escapechar\m@ne
      \expandafter\getanddefine@fonts
        \csname symM#1%
          \csname M@fontid@\m@th@const@nts@font\endcsname
          \expandafter
        \endcsname % expands to \symMupright<id>
        \csname TU/\m@th@const@nts@font
                  /\seriesdefault
                  /\m@th@const@nts@font@sh@pe
        \endcsname % expands to \TU/<nfss family name>/m/<shape>
      \globaldefs\@ne
      \expandafter\@gobbletwo\math@fonts % avoid infinite loop
      \endgroup}
    \fi
  \ifM@adjust@font\else
    \M@MathConstantsNoAdjustWarning
  \fi}
\def\math@fonts{\aftergroup\M@SetMathConstants}
\@onlypreamble\mathconstantsfont
%    \end{macrocode}
% If the user did not enable Lua font adjustments, then |\mathconstantsfont| will generate an error message and gobble its argument. This definition happens later in |mathfont.sty| when we define other Lua-related macros such as |\IntegralItalicFactor| to do the same thing absent font adjustments.
% 
% 
% 
% \section{Local Font Changes}\indexpage{local font changes}
% 
% This section deals with local font changes. The |\newmathfontcommand| creates macros that change the font for math alphabet characters and is basically a wrapper around |\DeclareMathAlphabet|. First we code |\M@check@csarg|, which accepts two arguments. The |#1| argument is the user-level command that called |\M@check@csarg|, which we use for error messaging, and |#2| should be a single control sequence. The way |\M@check@csarg| scans the following tokens is a bit tricky: (1) check the length of the argument by seeing if |\@gobble| eats it completely; and (2) check that the argument is a control sequence. If the user specifies an argument of the form |{..}|, i.e.\ extra text inside braces, the |\ifcat| will catch it and issue an error. If |\M@check@csarg| likes the input, it sets |\ifM@good@arg| to true, and otherwise, it sets |\ifM@arg@good| to false.
%    \begin{macrocode}
\def\M@check@csarg#1#2{%
  \expandafter\ifx\expandafter\@nnil\@gobble#2\@nnil % good
    \ifcat\relax\noexpand#2 % good
      \M@arg@goodtrue
    \else % if #2 not a control sequence
      \M@MissingControlSequenceError#1{#2}
      \M@arg@goodfalse
    \fi
  \else % if #2 is multiple tokens
    \M@DoubleArgError#1{#2}
    \M@arg@goodfalse
  \fi}
%    \end{macrocode}
% The macro |\M@checkspecials| accepts a control sequence as its |#1| argument and a font name as its |#2| argument, and it checks whether |#1| is |\mathbb| or a related command. If yes, we assume that the user is using some variant of |\newmathrm| instead of |\mathfont[bb]|, so we do some processing analogous to what we do inside |\mathfont|.
%    \begin{macrocode}
\def\M@checkspecials#1#2{%
  \in@#1{\mathbb\mathcal\mathfrak\mathbcal\mathbfrak}
  \ifin@
%    \end{macrocode}
% We set |\escapechar| to $-1$ and use |\@gobblefour| to remove the |\math| from the start of |#1|. The string of |\expandafter|s hits the |\string| inside |\@tempa|, and then the |\edef| expands the |\@gobblefour|. We are left with just the keyword inside |\@tempa|.
%    \begin{macrocode}
    \begingroup
      \escapechar\m@ne
      \expandafter
    \endgroup
    \expandafter\edef\expandafter\@tempa\expandafter{%
      \expandafter\@gobblefour\string#1}
%    \end{macrocode}
% Then write a message to the |log| file and set the corresponding boolean to true.
%    \begin{macrocode}
    \@mathfontinfo{Interpreting your new macro \string#1\space
      as \@tempa\space chars.}
    \@mathfontinfo{Setting \expandafter\string
      \csname ifM@\@tempa\endcsname\space to true.}
    \csname M@\@tempa true\endcsname
%    \end{macrocode}
% And store the information to write to the |log| file |\AtBeginDocument|. The structure of |\M@|\meta{keyword}|shape| is unusual because we want the macro to gobble ``|\space shape|'' in |\M@keyword@info@begin|.
%    \begin{macrocode}
    \expandafter\edef\csname M@\@tempa @fontinfo\endcsname{#2}
    \expandafter\edef\csname M@\@tempa shape\endcsname
      \space shape{inferred from \string#1}
  \fi}
%    \end{macrocode}
% Now declare the math alphabet. This macro first checks that its |#1| argument is a control sequence using |\M@check@csarg|. If yes, load the |#2| argument with |\M@newfont|, call |\DeclareMathAlphabet|, and check whether |#1| is |\mathbb| or a related command, and finally add |#1| and |#2| to the list of local font-change commands.
%    \begin{macrocode}
\protected\def\newmathfontcommand#1#2#3#4{%
  \M@check@csarg\newmathfontcommand{#1}
  \ifM@arg@good
    \M@newfont{#2}
    \M@NewFontCommandInfo{#1}{\@tempbase}{\M@f@ntn@meb@se}{#3}{#4}
    \DeclareMathAlphabet{#1}{TU}{\M@f@ntn@meb@se}{#3}{#4}
    \M@checkspecials{#1}{\@tempbase}
    \M@addto@localfonts{\string#1}{\@tempbase}
  \fi}
\@onlypreamble\newmathfontcommand
%    \end{macrocode}
% A helper macro that accepts two arguments. Its |#1| argument is a control sequence (from |\string|), and the |#2| argument is a font name. This macro checks whether |#2| is a new font, increments |\M@num@localfonts| if so, and then adds both |#1| and |#2| to |\M@localfonts|. If |\M@localfonts| is |\@empty|, that means we haven't added any fonts to the list yet, so in that case, we obviously increase |\M@num@localfonts|. Otherwise we loop through |\M@localfonts|, and if any of them are equal to |\@tempbase|, we do not need to increase |\M@num@localfonts|. We have to use |\@tempb| instead of |\@tempa| here because we use |\M@addto@localfonts| inside |\mathfont| where we need to preserve the definition of |\@tempb|.
%    \begin{macrocode}
\def\M@addto@localfonts#1#2{%
  \ifx\M@localfonts\@empty
    \advance\M@num@localfonts\@ne
    \edef\M@localfonts{{#1}{#2}}
  \else
    \@tempswatrue      % increase by default
    \@for\@j:=\M@localfonts\do{%
      \edef\@tempb{\expandafter\@secondoftwo\@j}
      \ifx\@tempbase\@tempb
        \@tempswafalse % if \@tempbase is in list, don't add
      \fi}
    \if@tempswa
      \advance\M@num@localfonts\@ne
    \fi
    \edef\M@localfonts{\M@localfonts,{#1}{#2}}
  \fi}
%    \end{macrocode}
% Then define macros that create local font-changing commands with default series and shape information. Because they're all similar, we metacode them. We define the commands themselves with |\define@newmath@cmd|. The argument structure is:
%   \begin{itemize}
%   \item |#1|---|\newmath|\meta{key} macro name
%   \item |#2|---font series
%   \item |#3|---font shape
%   \item |##1|---the user's control sequence
%   \item |##2|---the user's font information (family name)
%   \end{itemize}
% We feed |##1|, |##2|, |#2|, and |#3| to |\newmathfontcommand|, and we load |##2| with |\M@newfont|. Each |\newmath|\meta{key} macro will check its first argument using |\M@check@csarg| and then call |\newmathfontcommand| on both of its two arguments. We store the list of |\newmath|\meta{key} commands that we want to define with their series and shape information in |\M@default@newmath@cmds|, and we loop through it with |\@for|.
%    \begin{macrocode}
\def\M@define@newmath@cmd#1#2#3{%
  \protected\def#1##1##2{%
    \M@check@csarg{#1}{##1}
    \newmathfontcommand{##1}{##2}{#2}{#3}}}
\def\M@default@newmath@cmds{%
  \newmathrm{\mddefault}{\shapedefault},%
  \newmathit{\mddefault}{\itdefault},%
  \newmathbf{\bfdefault}{\shapedefault},%
  \newmathbfit{\bfdefault}{\itdefault},%
  \newmathsc{\mddefault}{\scdefault},%
  \newmathscit{\mddefault}{\scdefault\itdefault},%
  \newmathbfsc{\bfdefault}{\scdefault},%
  \newmathbfscit{\bfdefault}{\scdefault\itdefault}}
\@for\@i:=\M@default@newmath@cmds\do{%
  \expandafter\M@define@newmath@cmd\@i}
\@onlypreamble\newmathrm
\@onlypreamble\newmathit
\@onlypreamble\newmathbf
\@onlypreamble\newmathbfit
\@onlypreamble\newmathsc
\@onlypreamble\newmathscit
\@onlypreamble\newmathbfsc
\@onlypreamble\newmathbfscit
\@onlypreamble\M@define@newmath@cmd
\let\M@default@newmath@cmds\relax
%    \end{macrocode}
% The command |\setmathfontcommands| sets all the default local font-change commands at once.
%    \begin{macrocode}
\protected\def\setmathfontcommands#1{%
  \newmathrm\mathrm{#1}
  \newmathit\mathit{#1}
  \newmathbf\mathbf{#1}
  \newmathbfit\mathbfit{#1}
  \newmathsc\mathsc{#1}
  \newmathscit\mathscit{#1}
  \newmathbfsc\mathbfsc{#1}
  \newmathbfscit\mathbfscit{#1}}
\@onlypreamble\setmathfontcommands
%    \end{macrocode}
% 
% 
% \section{Miscellaneous}
% 
% 
% We begin this section with the user-level macros that provide information for Lua-based font adjustments. If font adjustments are allowed, we begin with a macro |\M@check@int| that checks whether |#1| is a nonnegative integer. Depending on the result, \textsf{mathfont} sets |\ifM@arg@good| to true or false. The use of |\afterassignment| is inspired by |\@defaultunits| from the \LaTeX\ kernel.
%    \begin{macrocode}
\ifM@adjust@font
  \def\M@check@int#1{%
    \def\@tempa##1\relax{\def\@tempb{##1}}
    \afterassignment\@tempa\count@=0#1\relax
    \expandafter\ifx\expandafter\@nnil\@tempb\@nnil
      \M@arg@goodtrue
    \else
      \M@arg@goodfalse
    \fi}
%    \end{macrocode}
% We meta-code the definitions of |\RuleThicknessFactor|, etc. To keep the syntax relatively clean, we temporarily eliminate the |\escapechar| and redefine |~| to |\noexpand|.
%    \begin{macrocode}
  \let\@tempa~
  \let~\noexpand
  \count@\escapechar
  \escapechar\m@ne
  \@tfor\@i:=\RuleThicknessFactor\IntegralItalicFactor
    \SurdHorizontalFactor\SurdVerticalFactor\do{%
      \protected\expandafter\edef\@i#1{%
        ~\M@check@int{#1}%
        ~\ifM@arg@good
          ~\global\expandafter
            ~\csname
              M@\expandafter\string\@i
            \endcsname=#1\relax
        ~\else
          ~\M@BadIntegerError\expandafter~\@i{#1}%
        ~\fi}}
  \let~\@tempa
  \escapechar\count@
%    \end{macrocode}
% If automatic font adjustments are disabled, we should also disable the related user-level commands. In this case, each of the font-adjustment macros expands to raise an |\M@NoFontAdjustError| and gobble its argument.
%    \begin{macrocode}
\else
  \@tfor\@i:=\RuleThicknessFactor\IntegralItalicFactor
    \SurdHorizontalFactor\SurdVerticalFactor\CharmLine\CharmFile
      \do{%
        \protected\expandafter\edef\@i{%
          \noexpand\M@NoFontAdjustError\expandafter\noexpand\@i
          \noexpand\@gobble}}
\fi
%    \end{macrocode}
% These commands should appear in the preamble only.
%    \begin{macrocode}
\@onlypreamble\RuleThicknessFactor
\@onlypreamble\IntegralItalicFactor
\@onlypreamble\SurdHorizontalFactor
\@onlypreamble\SurdVerticalFactor
\@onlypreamble\CharmLine
\@onlypreamble\CharmFile
%    \end{macrocode}
% As of version 2.4, I'm taking out |\restoremathinternals|. We use the next three macros in defining |\simeq| and |\cong|. The construction is clunky and needs the intermediate macro |\st@ck@fl@trel| because |\mathchoice| is a bit of an odd macro. It feels like it should be expandable, but it isn't. Instead, it fully typesets each of its four arguments and then takes the one corresponding to the correct style. A cleaner implementation would use |\mathstyle| from Lua\TeX, but this control sequence isn't always accurate. In fact, the Lua\TeX\ manual suggests that it is impossible to have an expandable version of |\mathchoice| that is always correct because of how \TeX's math mode algorithm works.. 
%    \begin{macrocode}
\protected\gdef\clap#1{\hb@xt@\z@{\hss#1\hss}}
\protected\def\stack@flatrel#1#2{\expandafter
  \st@ck@fl@trel\expandafter#1\@firstofone#2}
\protected\gdef\st@ck@fl@trel#1#2#3{%
  {\setbox0\hbox{$\m@th#1#2$}% contains \mathrel symbol
  \setbox1\hbox{$\m@th#1#3$}% gets raised over \box0
  \if\wd0>\wd1\relax
    \hb@xt@\wd0{%
      \hfil
      \clap{\raise0.7\ht0\box1}%
      \clap{\box0}\hfil}%
  \else
    \hb@xt@\wd1{%
      \hfil
      \clap{\raise0.7\ht0\box1}%
      \clap{\box0}\hfil}%
  \fi}}
%    \end{macrocode}
% Some fonts do not contain characters that \textsf{mathfont} can declare as math symbols. We want to make sure that if this happens, \TeX\ prints a message in the |log| file and terminal.\indexpage{log file=\texttt{log} file}\indexpage{terminal}
%    \begin{macrocode}
\ifnum\tracinglostchars<\tw@
  \tracinglostchars\tw@
\fi
%    \end{macrocode}
% If \textsf{mathfont} is adjusting fonts, it also changes the |\Umathcode|s for Latin letters. As a result, math alphabet commands will no longer work for fonts where \textsf{mathfont} as not added new Latin letters in the correct encoding slots. The |\M@normal@mathcodes| macro addresses this issue by resetting all Latin letters to their usual encoding slots in math mode. This macro should always appear inside a group, and I am intending for it to be used alongside math alphabet commands from other packages. In particular, we use this macro to make \textsf{mathfont} compatible with any |\mathbb| or related commands that don't come from \textsf{mathfont}.
%    \begin{macrocode}
\ifM@adjust@font
  \protected\def\M@normal@mathcodes{%
    \ifM@upper
      \Umathcode`A=7+0+`A\relax
      \Umathcode`B=7+0+`B\relax
      \Umathcode`C=7+0+`C\relax
      \Umathcode`D=7+0+`D\relax
      \Umathcode`E=7+0+`E\relax
      \Umathcode`F=7+0+`F\relax
      \Umathcode`G=7+0+`G\relax
      \Umathcode`H=7+0+`H\relax
      \Umathcode`I=7+0+`I\relax
      \Umathcode`J=7+0+`J\relax
      \Umathcode`K=7+0+`K\relax
      \Umathcode`L=7+0+`L\relax
      \Umathcode`M=7+0+`M\relax
      \Umathcode`N=7+0+`N\relax
      \Umathcode`O=7+0+`O\relax
      \Umathcode`P=7+0+`P\relax
      \Umathcode`Q=7+0+`Q\relax
      \Umathcode`R=7+0+`R\relax
      \Umathcode`S=7+0+`S\relax
      \Umathcode`T=7+0+`T\relax
      \Umathcode`U=7+0+`U\relax
      \Umathcode`V=7+0+`V\relax
      \Umathcode`W=7+0+`W\relax
      \Umathcode`X=7+0+`X\relax
      \Umathcode`Y=7+0+`Y\relax
      \Umathcode`Z=7+0+`Z\relax
    \fi
    \ifM@lower
      \Umathcode`a=7+0+`a\relax
      \Umathcode`b=7+0+`b\relax
      \Umathcode`c=7+0+`c\relax
      \Umathcode`d=7+0+`d\relax
      \Umathcode`e=7+0+`e\relax
      \Umathcode`f=7+0+`f\relax
      \Umathcode`g=7+0+`g\relax
      \Umathcode`h=7+0+`h\relax
      \Umathcode`i=7+0+`i\relax
      \Umathcode`j=7+0+`j\relax
      \Umathcode`k=7+0+`k\relax
      \Umathcode`l=7+0+`l\relax
      \Umathcode`m=7+0+`m\relax
      \Umathcode`n=7+0+`n\relax
      \Umathcode`o=7+0+`o\relax
      \Umathcode`p=7+0+`p\relax
      \Umathcode`q=7+0+`q\relax
      \Umathcode`r=7+0+`r\relax
      \Umathcode`s=7+0+`s\relax
      \Umathcode`t=7+0+`t\relax
      \Umathcode`u=7+0+`u\relax
      \Umathcode`v=7+0+`v\relax
      \Umathcode`w=7+0+`w\relax
      \Umathcode`x=7+0+`x\relax
      \Umathcode`y=7+0+`y\relax
      \Umathcode`z=7+0+`z\relax
    \fi}
%    \end{macrocode}
% We loop through each |bb|, etc.\ keyword and check whether the corresponding |\math|\meta{keyword} is defined. For convenience, we store |\math|\meta{keyword} inside |\@tempa|. If the definition didn't come from \textsf{mathfont}, we wrap a call to |\M@normal@mathcodes| around the macro. This has to happen |\AtBeginDocument| because the user could load a package after \textsf{mathfont} that defines |\mathbb|.
%    \begin{macrocode}
  \AtBeginDocument{\@tfor\@i:={bb}{cal}{frak}{bcal}{bfrak}\do{%
    \ifcsname math\@i\endcsname
%    \end{macrocode}
% If |\math|\meta{keyword} is defined, check whether the definition came from \textsf{mathfont}. Once again, we use |\ifx| with two booleans inside |\csname|/|\endcsname| pairs becuase otherwise \TeX\ will get confused and think we have an unbalanced boolean inside |\@tfor|.
%    \begin{macrocode}
      \expandafter\ifx % next two lines are cs to be compared
          \csname ifM@\@i\expandafter\endcsname
          \csname iffalse\endcsname % is \ifM@<keyword> false?
%    \end{macrocode}
% If \textsf{mathfont} did not define the control sequence, we have to do things. First an informational message in the |log| file.
%    \begin{macrocode}
        \@mathfontinfo{Restoring \string\Umathcode\space values
          for \expandafter\string\csname math\@i\endcsname.}
%    \end{macrocode}
% Then save |\math|\meta{keyword} as |\@@math|\meta{keyword}, and make |\math|\meta{keyword} into a wrapper around its original definition.
%    \begin{macrocode}
        \expandafter\let\csname @@math\@i\expandafter\endcsname
          \csname math\@i\endcsname
        \protected\expandafter\edef\csname math\@i\endcsname#1{%
          \begingroup
            \noexpand\M@normal@mathcodes
            \expandafter\noexpand\csname @@math\@i\endcsname{#1}
          \endgroup}
      \fi
    \fi}}
%    \end{macrocode}
% If \textsf{mathfont} is not adjusting fonts, then we do not need to change any |\Umathcodes|.
%    \begin{macrocode}
\else
  \let\M@normal@mathcodes\relax
\fi
%    \end{macrocode}
% Now a messages about local font changes. We |\typeout| a message about local font-change commands.
%    \begin{macrocode}
\AtBeginDocument{%
  \ifcase\M@num@localfonts
  \or
    \def\@tempa#1#2#3\@nil{#2}
    \wlog{}
    \typeout{:: mathfont :: Using
      \expandafter\@tempa\M@localfonts\@nil\space
      for local font changes.}
  \else
    \wlog{}
    \typeout{:: mathfont :: Using \the\M@num@localfonts\space
      fonts for local font changes.}
  \fi}
%    \end{macrocode}
% Write to the |log| file |\AtBeginDocument| all font changes carried out by \textsf{mathfont}. The command |\M@keyword@info@begin| accepts two arguments and prints an informational message about default font changes for keyword options for |\mathfont|. The |#1| argument is a keyword, and the |#2| argument is a number of spaces. The spaces make the messages line up with each other in the log file.\indexpage{log file=\texttt{log} file}
%    \begin{macrocode}
\def\M@keyword@info@begin#1:#2\@nil{%
  \expandafter\ifx % next lines are two cs to be compared
        \csname ifM@#1\expandafter\endcsname
        \csname iftrue\endcsname
    \wlog{#1#2\@spaces\space\space\space Set to
      \csname M@#1@fontinfo\endcsname,
      \csname M@#1shape\endcsname\space shape}
  \else
    \wlog{#1#2\@spaces\space\space\space No change}
  \fi}
%    \end{macrocode}
% The macro |\M@local@info@begin| does the same thing except for the local font-change commands. The |#1| argument is a control sequence from |\string|, and the |#2| argument is a font name. We use |\count@| and |\@tfor| to count out the number of characters in |#1|, and if we get to 13, we cut it off and add three dots. We need to use this approach here because the control sequences in |\M@localfonts| have an unknown number of characters. We could have coded up an algorithm like this for |\M@keyword@info@begin| too, but I didn't do it before, and it won't make any practical difference to do it now.
%    \begin{macrocode}
\def\M@local@info@begin#1#2{%
  \let\@tempa\@empty
  \count@\z@
  \@tfor\@i:=#1\do{%
    \edef\@tempa{\@tempa\@i}
    \advance\count@\@ne
    \ifnum\count@=15\relax
      \edef\@tempa{\@tempa...}
      \advance\count@\thr@@
      \@break@tfor
    \fi}
%    \end{macrocode}
% Now add spaces to |\@tempa| until we get up to 20 characters. At that point, we can write the message to the |log| file.
%    \begin{macrocode}
  \@whilenum\count@<20\do{%
    \edef\@tempa{\@tempa\space}
    \advance\count@\@ne}
  \wlog{\@tempa#2}}
%    \end{macrocode}
% Now print the messages.
%    \begin{macrocode}
\AtBeginDocument{%
  \wlog{}
  \wlog{********************************************^^J%
        * Changes made by mathfont in the preamble *^^J%
        ********************************************^^J}
  \wlog{Fonts for character classes:}
  \def\@tempa{%    <-- everything should be 14 characters long
    upper:\@spaces\@spaces,%
    lower:\@spaces\@spaces,%
    diacritics:\space\space\space,%
    greekupper:\space\space\space,%
    greeklower:\space\space\space,%
    agreekupper:\space\space,%
    agreeklower:\space\space,%
    cyrillicupper:,%
    cyrilliclower:,%
    hebrew:\@spaces\space\space\space,%
    digits:\@spaces\space\space\space,%
    operator:\@spaces\space,%
    delimiters:\space\space\space,%
    radical:\@spaces\space\space,%
    bigops:\@spaces\space\space\space,%
    extbigops:\@spaces,%
    symbols:\@spaces\space\space,%
    extsymbols:\space\space\space,%
    arrows:\@spaces\space\space\space,%
    bb:\@spaces\@spaces\space\space\space,%
    cal:\@spaces\@spaces\space\space,%
    frak:\@spaces\@spaces\space,%
    bcal:\@spaces\@spaces\space,%
    bfrak:\@spaces\@spaces}
  \@for\@i:=\@tempa\do{%
    \expandafter\M@keyword@info@begin\@i\@nil}
  \wlog{}
%    \end{macrocode}
% And information in the |log| file about local font-change commands.
%    \begin{macrocode}
  \wlog{Local font-change commands:}
  \ifnum\M@num@localfonts=\z@
    \wlog{No local font change commands declared.}
  \else
    \@for\@j:=\M@localfonts\do{\expandafter\M@local@info@begin\@j}
  \fi
  \wlog{}}
%    \end{macrocode}
% Warn the user about possible problems with a multi-word optional package argument in \XeTeX.
%    \begin{macrocode}
\ifdefined\XeTeXrevision
  \ifM@font@loaded
    \AtEndOfPackage{%
    \PackageWarningNoLine{mathfont}
    {XeTeX detected. It looks like you\MessageBreak
    specified a font when you loaded\MessageBreak
    mathfont. If you run into problems\MessageBreak
    with a font whose name is multiple\MessageBreak
    words, try compiling with LuaLaTeX\MessageBreak
    or call \string\setfont\space or \string\mathfont\MessageBreak
    manually}}
  \fi
\fi
%    \end{macrocode}
% If the user passed a font name to \textsf{mathfont}, we set it as the default |\AtEndOfPackage|.
%    \begin{macrocode}
\ifM@font@loaded
  \AtEndOfPackage{\setfont\M@font@load}
\fi
%    \end{macrocode}
% Finally, make all character-setting commands inaccessible outside the preamble.
%    \begin{macrocode}
\@onlypreamble\M@upper@set
\@onlypreamble\M@lower@set
\@onlypreamble\M@diacritics@set
\@onlypreamble\M@greekupper@set
\@onlypreamble\M@greeklower@set
\@onlypreamble\M@agreekupper@set
\@onlypreamble\M@agreeklower@set
\@onlypreamble\M@cyrillicupper@set
\@onlypreamble\M@cyrilliclower@set
\@onlypreamble\M@hebrew@set
\@onlypreamble\M@digits@set
\@onlypreamble\M@operator@set
\@onlypreamble\M@delimiters@set
\@onlypreamble\M@radical@set
\@onlypreamble\M@bigops@set
\@onlypreamble\M@extbigops@set
\@onlypreamble\M@symbols@set
\@onlypreamble\M@extsymbols@set
\@onlypreamble\M@arrows@set
\@onlypreamble\M@bb@set
\@onlypreamble\M@cal@set
\@onlypreamble\M@frak@set
\@onlypreamble\M@bcal@set
\@onlypreamble\M@bfrak@set
%    \end{macrocode}
% 
% 
% \section{Adjust Fonts: Setup}
% 
% 
% The next three sections implement Lua-based font adjustments and apply only if the user has enabled font adjustment. Most of the implementation happens through Lua code, but we need some \TeX\ code in case the user wants to adjust character metric information. Here is a rough outline of what happens in the next three sections:
% \begin{enumerate}\itemsep\smallskipamount
% \item Initialize a Lua table that contains new metrics for certain characters specific to math mode, such as letters with wider bounding boxes and large operator symbols.
% \item Provide an interface for the user to change this metric information.
% \item Write functions that accept a fontdata object and (a) change top-level math specs to indicate that we have a math function; (b) alter characters according to our Lua table of new metric information; and (c) populate a MathConstants table for the font.
% \item Create callbacks that call these functions. Put a wrapper around them, and insert the wrapper-function into |luaotfload.patch_font|.
% \end{enumerate}
% Step 2 happens on the \TeX\ side of things and is documented next, and everything else happens inside |\directlua|. On the Lua side of things, we store all the functions and character metric information in the table |mathfont|. Every entry in mathfont is a function or is a subtable indexed within |mathfont| by an \meta{integer}. The \textit{integer} is a unicode encoding number and tells which unicode character the subtable keeps track of. See tables~2 and 3 for a list of the functions in |mathfont| and the fields in character subtables. See section 11 for discussion of the callbacks for editing fontdata objects.
% 
% 
% \begin{figure}[t]
% \centerline{\bfseries Table 2: Fields of Character Subtables in |mathfont|\strut}
% \begin{tabularx}\textwidth{lllllX<{\raggedright\arraybackslash}}\toprule
% Field & Data Type & In |a| & In |e| & In |u| & Used For\\\midrule
% |type| & string & Yes & Yes & Yes & Type is |a|, |e|, |u|\\
% |next| & depends & Yes & Yes & No & Unicode index of next-larger character(s);
%                                     integer for type |a|, table for type |u|\\
% |left_stretch| & numeric & Yes & No & No & Stretch bounding box left\\
% |right_stretch| & numeric & Yes & No & No & Stretch bounding box right\\
% |top_accent_stretch| & numeric & Yes & Yes & Yes & Position top accent\\
% |bot_accent_stretch| & numeric & Yes & Yes & Yes & Position bottom accent\\
% |total_variants| & integer & No & Yes & No & Number of large variants\\
% |smash| & integer & No & Yes & No & Unicode index for storing a smashed version\\
% |data| & table & No & Yes & No & Scale factors\\\bottomrule
% \end{tabularx}
% \end{figure}
% 
% 
% \begin{figure}[tbp]
% \centerline{\bfseries Table 3: Functions in |mathfont|\strut}
% \begin{tabularx}\textwidth{lp{1.5in}X<{\raggedright\arraybackslash}}\toprule
% Function & Argument(s) & Used For\\\midrule
% |new_type_a| & |index|, |next|, data & Add type |a| entry to |mathfont|\\
% |new_type_e| & |index|, |smash|, |next|, data & Add type |e| entry to |mathfont|\\
% |new_type_u| & |index|, |smash|, |next|, data & Add type |u| entry to |mathfont|\\\midrule
% |add_to_charm| & string of new charm info & Add new charm into to |mathfont|\\
% |parse_charm| & string of new charm info & Split string, validate inputs\\\midrule
% |empty| & none & Does nothing\\
% |glyph_info| & character subtable & Return height, width, depth, italic\\
% |make_a_commands| & |index|, offset & Return virtual font commands\\
% |make_a_table| & |index|, charm data, fontdata & Make new character table for type |a|\\
% |make_e_commands| & |index|, scale factors & Return virtual font commands\\
% |make_e_table| & |index|, charm data, fontdata & Make new character table for type |e|\\
% |make_hex_value| & integer & Return hexadecimal string\\
% |make_u_commands| & |index|, offset & Return virtual font commands\\
% |make_u_table| & |index|, charm data, fontdata & Make new character table for type |u|\\
% |modify_e_base| & |index|, offset & Modify base glyph for type |e|\\
% |smash_glyph| & |index|, fontdata & Return table for smashed character\\\midrule
% |adjust_font| & fontdata & Call callbacks\\
% |apply_charm_info| & fontdata & Change character metrics in fontdata\\
% |get_font_name| & fontdata & Return font name\\
% |info| & string & Writes a message in the |log| file\\
% |math_constants| & fontdata & Creates a MathConstants table\\
% |set_nomath_false| & fontdata & Set top-level font specs for math\\\bottomrule
% \end{tabularx}
% \end{figure}
% 
% Changing top-level flags in a font object is straightforward. Creating a MathConstants table is complicated but largely self-contained. We take a few parameters that the user has set, define traditional \TeX\ math parameters based on the essential parameters of the font, and assign their values to corresponding entries in a MathConstants table. However, editing character metrics is convoluted with many moving parts. For every glyph that we want modify when \TeX\ loads a text font, we store character metric information about that glyph as a subtable in |mathfont|. The entries of the subtable describe how to stretch the glyph bounds, scale the glyph itself, or determine math accent placement. For characters of type |u|, we only specify accent placement. For characters of type |a|, which is the upper and lower-case Latin letters, we stretch the bounding box of the glyph horizontally to widen the letters slightly. When we load a text font, we create 52 virtual characters in the Unicode Supplementary Private Use Area-A that typeset the Latin letter glyphs in elongated bounding boxes, and later in \textsf{mathfont}, we set the mathcodes of Latin letters to be these virtual characters. For type |e|, we do the same thing except that for each character, we create an ensamble of scaled versions, which we use as a family of large variants.
% 
% Here's how to think about the dynamics of our approach. We use character metric information at three different times: pre-processing, interim processing, and post-processing. In pre-processing, which we implement in this section, we assemble initial character metric information into entries in |mathfont|. In other words, pre-processing means creating the initial |mathfont| subtables and happens during package loading. Interim processing means the user altering entries in |mathfont| and happens through |\CharmLine| and |\CharmFile|. This can occur at any point in the pramble. In post-processing, which we implement in the next section, \textsf{mathfont} extracts information from the current state of the |mathfont| table and uses it to alter a fontdata object. Post-processing happens through the |luaotfload.patch_font| callback and occurs once at the point when \TeX\ loads the font file. As a rule, \LaTeX\ does not like to load fonts before it uses them, so post-processing typically happens |\AtBeginDocument| in the case of the main text font or whenever the user calls a |\text|\meta{font keyword} command or enters math mode, whichever happens first. This is also why you cannot adjust fonts that \TeX\ loaded before \textsf{mathfont}.
% 
% 
% We set |mathnolimitsmode| to 4 to make integral signs look nice. Or at least nicer than they would otherwise.
%    \begin{macrocode}
\ifM@adjust@font
\mathnolimitsmode=4\relax
%    \end{macrocode}
% We need some error messages. We change the catcode of \expandafter|\textbackslash| to 12 in order to use it freely as a Lua escape character. We change |~| to catcode 0 to define the macros.
%    \begin{macrocode}
\bgroup
  \catcode`\~=0
  ~catcode`~\=12
  ~@firstofone{
~egroup
~def~M@number@ssert{"\n%
  Package mathfont error: Nonnumeric charm value.\n\n%
  I'm having trouble with a character metric.\n%
  Your \\CharmLine or \\CharmFile contains \""
  .. temp_string .. "\"\n%
  which is not a number. Make sure that your\n%
  charm information is all integers, floats,\n%
  or asterisks separated by commas or spaces.\n"}
~def~M@index@ssert{"\n%
  Package mathfont error: Invalid unicode index.\n\n%
  The unicode index \""
  .. split_string[1] .. "\" is invalid. Make sure\n%
  that the first number in your \\CharmLine and in each\n%
  line of your \\CharmFile is an integer between 0 and\n%
  1,114,111.\n"}
~def~M@entries@ssert{"\n%
  Package mathfont error: Charm values too short.\n\n%
  Your charm information for U+" .. index .. " needs more\n%
  entries. Right now you have "
  .. number_of_entries .. " entries, and\n%
  you need at least "
  .. entries_needed .. ". If you aren't sure what\n%
  to do, try adding asterisks to your \\CharmLine\n%
  or line in your \\CharmFile.\n"}}
%    \end{macrocode}
% The user inputs charm information at the \TeX\ level. We define the macros |\CharmLine| that interfaces with |mathfont:add_to_charm| directly and |\CharmFile| that reads lines from a file and individually feeds them to |\CharmLine|. For |\CharmLine|, we check that the argument contains no |"| or \expandafter|\textbackslash| symbols because that could mess up the Lua parsing.
%    \begin{macrocode}
\protected\def\CharmLine#1{%
  \begingroup
  \edef\@tempa{#1}
  \edef\@tempa{\detokenize\expandafter{\@tempa}}
  \@expandtwoargs\in@{"}{\@tempa}
%    \end{macrocode}
% If |#1| contains a |"|, we issue an error. The error help message is different depending on whether the |\CharmLine| came from a call to |\CharmFile| or not, which we check with |\ifM@fromCharmFile|.
%    \begin{macrocode}
  \ifin@ % is " in #1?
    \ifM@fromCharmFile
      \M@ForbiddenCharmFile{"}
    \else
      \M@ForbiddenCharmLine{"}
    \fi
  \else
    \@expandtwoargs\in@{\@backslashchar}{\@tempa}
    \ifin@ % is backslash in #1?
      \ifM@fromCharmFile
        \M@ForbiddenCharmFile{\@backslashchar}
      \else
        \M@ForbiddenCharmLine{\@backslashchar}
      \fi
    \else
%    \end{macrocode}
% If |#1| does not contain a quotation mark or escape char, we feed it to |mathfont:add_to_charm| as a string.
%    \begin{macrocode}
      \directlua{mathfont:add_to_charm("\@tempa")}
    \fi
  \fi
  \endgroup}
%    \end{macrocode}
% The argument of |\CharmFile| should be a valid filename, and we open it in |\M@Charm|. The |\M@fromCharmFiletrue| command sets the boolean for an open charm file to true. This command and the corresponding false command are global because of how the kernel defines |\newif|. We can't check |\ifeof\M@Charm| because during processing of the last line from |\M@Charm|, we are at the end of the file even though it is still open.
%    \begin{macrocode}
\protected\def\CharmFile#1{%
  \begingroup
  \M@fromCharmFiletrue
  \immediate\openin\M@Charm{#1}
%    \end{macrocode}
% The macro |\@next| will read a line in |#1|, feed it to |\CharmLine|, and call itself if the file has more lines.
%    \begin{macrocode}
  \def\@next{%
    \read\M@Charm to \@tempa
    \CharmLine\@tempa
    \ifeof\M@Charm\else % if file has more lines?
      \expandafter\@next
    \fi}
%    \end{macrocode}
% Call |\@next|, close the file, and end the group.
%    \begin{macrocode}
  \@next
  \immediate\closein\M@Charm
  \M@fromCharmFilefalse
  \endgroup}
%    \end{macrocode}
% This concludes the \TeX-based portion of font adjustments. The rest of this section and the next two sections are the Lua code that adapts a text font for math mode. First, we create the |mathfont| table.
%    \begin{macrocode}
\directlua{
mathfont = {}
%    \end{macrocode}
% Each character whose metrics we want to change will have one of three types: |a| for alphabet, |e| for extensible, and |u| for (other) unicode. (We don't really create extensibles---type |e| means any character that we need artificially larger sizes for.) We begin with type |a|. The |index| is the base-10 unicode value of the character that we will later modify, and |next| is the base-10 unicode value of the slot we will use to store the modified glyph. The |data| variable is a table with 4 entries that stores sizing information and information regarding accent placement. We divide the information by 1000 as is standard in \TeX.
%    \begin{macrocode}
function mathfont:new_type_a(index, next, data)
  self[index] = {}
  self[index].type = "a"
  self[index].next = next
  self[index].left_stretch = data[1] / 1000
  self[index].right_stretch = data[2] / 1000
  self[index].top_accent_stretch = data[3] / 1000
  self[index].bot_accent_stretch = data[4] / 1000
end
%    \end{macrocode}
% Initializing type |e| characters is more complicated. The |index| argument is the base-10 unicode value of the caracter we will modify. The |smash| value is a unicode slot where we will store a smashed version of the glyph with no height, depth, or width, which we need to scale the glyph correctly. We use |next| and |data| to add large variants of characters to the font. Specifically, |next| is a table of unicode slots where we will add larger versions of the character with unicode value |index|, and |data| stores the sizing information.
%    \begin{macrocode}
function mathfont:new_type_e(index, smash, next, data)
%    \end{macrocode}
% We determine the number of larger variants |v| from the length of |next|, and we store that number in |total_variants|.
%    \begin{macrocode}
  local v = \string# next
  self[index] = {}
  self[index].type = "e"
  self[index].smash = smash
  self[index].next = next
  self[index].total_variants = v
  self[index].data = {}
%    \end{macrocode}
% We expect |data| to have $2|v|+2$ entries, which we consider in pairs. The $i$th pair (i.e.\ entries $i$ and $i+1$ of |data|) encodes the horizontal and vertical scale factors for the $i$th large variant, and the final two entries determine top and bottom accent placement. We store each pair as a two-element table in the larger table |mathfont[index].data|, and we use |x| and |y| as the keys for the horizontal and vertical stretch. Again we divide both scale factors by 1000.
%    \begin{macrocode}
  for i = 1, v, 1 do
    self[index].data[i] = {}
    self[index].data[i].x = data[2*i-1] / 1000
    self[index].data[i].y = data[2*i] / 1000
  end
  self[index].top_accent_stretch = data[2*v+1] / 1000
  self[index].bot_accent_stretch = data[2*v+2] / 1000
end
%    \end{macrocode}
% The type |u| characters are simplest. We need to specify the unicode index in the first argument. The second function argument is a table with two entries that stores accent information.
%    \begin{macrocode}
function mathfont:new_type_u(index, data)
  self[index] = {}
  self[index].type = "u"
  self[index].top_accent_stretch = data[1] / 1000
  self[index].bot_accent_stretch = data[2] / 1000
end
%    \end{macrocode}
% Interim processing. We let the user edit resizing and accent information for the characters in |mathfont|. The function |mathfont.parse_charm| parses and validates the user's input, and the function |mathfont:add_to_charm| incorporates the user's information into the tables already in |mathfont|. The |mathfont:add_to_charm| function expects a single string of integers, floats, or asterisks separated by spaces or commas and immediately passes it to |parse_charm|. Our first task is to split the string into components, and we store the results in |split_string|. The dummy variable |i| keeps track of the number of entries currently in |split_string|.
%    \begin{macrocode}
function mathfont.parse_charm(charm_input)
  local split_string = {}
  local charm_string = charm_input
  local temp_string = ""
  local i = 1
%    \end{macrocode}
% We loop through |charm_string| as long as it contains a comma or space. At each iteration, we remove the portion of |charm_string| preceeding the first comma or space and append it to |split_string| as a separate entry.
%    \begin{macrocode}
  while string.find(charm_string, " ") or 
        string.find(charm_string, ",") do
    local length = string.len(charm_string)
    local first_space = string.find(charm_string, " ") or length
    local first_comma = string.find(charm_string, ",") or length
%    \end{macrocode}
% We store the location of the first comma or space in |sep|.
%    \begin{macrocode}
    local sep = first_space
    if first_comma < first_space then
      sep = first_comma
    end
%    \end{macrocode}
% Now split |charm_string| at |sep|. We store the portion before |sep| in |temp_string|, and the portion after |sep| becomes the new |charm_string|.
%    \begin{macrocode}
    temp_string = string.sub(charm_string, 1, sep-1)
    charm_string = string.sub(charm_string, sep+1)
%    \end{macrocode}
% If |temp_string| is not empty, we store it in position |i| in |split_string|, then increment |i| by 1. If |temp_string| does not contain a number or asterisk, we raise an error.
%    \begin{macrocode}
    if temp_string \noexpand~= "" then
      if tonumber(temp_string) then  % if a number, append it
        split_string[i] = tonumber(temp_string)
        i = i+1
      elseif temp_string == "*" then % if asterisk, append it
        split_string[i] = temp_string
        i = i+1
      else % if neither, raise error
        error(\M@number@ssert)
      end
    end
  end
%    \end{macrocode}
% After iteratinf the splitting procedure, we have a final portion of |charm_string| with no commas or spaces, and we perform the same check as on |temp_string| above. 
%    \begin{macrocode}
  temp_string = charm_string
  if temp_string \noexpand~= "" then
    if tonumber(temp_string) then % if a number, append number
      split_string[i] = tonumber(temp_string)
    elseif temp_string == "*" then % if asterisk, append asterisk
      split_string[i] = temp_string
    else % if neither, raise error
      error(\M@number@ssert)
    end
  end
%    \end{macrocode}
% The last step is to make sure that the first entry of |split_string| is a valid unicode index. We know that the first entry is either an asterisk or a number, and we make sure it is not an asterisk.
%    \begin{macrocode}
  local index = split_string[1]
  if index == "*" then
    error(\M@index@ssert)
  end
%    \end{macrocode}
% The last check is to make sure the entry is (1) an integer and not a float; (2) nonnegative; and (3) less than 1,114,111, the maximum unicode entry. We round the entry down by subtracting the decimal portion, and the result will be equal to the original entry if and only if we begn with an integer. We perform the three checks inside an |assert| and issue an error if any of them fail, and if |split_string| is valid, we return it to |mathfont:add_to_charm|.
%    \begin{macrocode}
  local rounded = index - (index \@percentchar 1) % round down
  local max = 1114111
  assert(index == rounded and
         index >= 0       and
         index <= max, \M@index@ssert)
  return split_string
end
%    \end{macrocode}
% We feed the user's charm information directly to |mathfont:add_to_charm|, which first calls |parse_charm| to parse the input and then modifies |mathfont| accordingly. After being parsed, we store the user's input in |charm_metrics|. The |index| is the base-10 unicode value of the character whose information we want to modify, and the |number_of_entries| is the length of |charm_metrics|.
%    \begin{macrocode}
function mathfont:add_to_charm(charm_string)
  local charm_metrics = self.parse_charm(charm_string)
  local index = charm_metrics[1]
  local number_of_entries = \string# charm_metrics
%    \end{macrocode}
% If |mathfont| does not already have an entry for the unicode character |index|, we create an entry with type |u|.
%    \begin{macrocode}
  if not self[index] then
    self:new_type_u(index, {0, 0})
  end
%    \end{macrocode}
% Handling the user's input depends on the type of entry |index|. The basic procedure is to first check that the input has enough entries and, if yes, to overwrite the numbers stored in |mathfont|'s corresponding subtable with the new information. If the user included an asterisk, we do nothing to that metric value. For type |a|, we need four entries besides the |index|. The first two wll overwrite the left and right offset, and the last two overwrite accent placement.
%    \begin{macrocode}
  if self[index].type == "a" then
    local entries_needed = 5
    assert(number_of_entries >= entries_needed, \M@entries@ssert)
    if charm_metrics[2] \noexpand~= "*" then
      self[index].left_stretch = charm_metrics[2] / 1000
    end
    if charm_metrics[3] \noexpand~= "*" then
      self[index].right_stretch = charm_metrics[3] / 1000
    end
    if charm_metrics[4] \noexpand~= "*" then
      self[index].top_accent_stretch = charm_metrics[4] / 1000
    end
    if charm_metrics[5] \noexpand~= "*" then
      self[index].bot_accent_stretch = charm_metrics[5] / 1000
    end
%    \end{macrocode}
% Type |e| is more complicated. The number of entries in the |charm_metrics| must be at least $2*|total_variants|+3$. We loop through the information and, for each $i$th pair of charm values, set those numbers to be the horizontal and vertical stretch information for the $i$th variant. We handle type |r| in the same way.
%    \begin{macrocode}
  elseif self[index].type == "e" then
    local tot_variants = self[index].total_variants
    local entries_needed = 2 * tot_variants + 3
    assert(number_of_entries >= entries_needed, \M@entries@ssert)
    for i = 1, tot_variants, 1 do
      if charm_metrics[2*i] \noexpand~= "*" then
        self[index].data[i].x = charm_metrics[2*i] / 1000
      end
      if charm_metrics[2*i+1] \noexpand~= "*" then
        self[index].data[i].y = charm_metrics[2*i+1] / 1000
      end
    end
%    \end{macrocode}
% The final two entries for type |e| or |r| are the accent information.
%    \begin{macrocode}
    if charm_metrics[2 * tot_variants + 2] \noexpand~= "*" then
      self[index].top_accent_stretch = 
        charm_metrics[2 * tot_variants + 2] / 1000
    end
    if charm_metrics[2 * tot_variants + 3] \noexpand~= "*" then
      self[index].bot_accent_stretch =
        charm_metrics[2 * tot_variants + 3] / 1000
    end
%    \end{macrocode}
% Again the information for type |u| is the simplest. We need two values besides the |index|, one for the top accent and one for the bottom accent.
%    \begin{macrocode}
  elseif self[index].type == "u" then
    local entries_needed = 3
    assert(number_of_entries >= entries_needed, \M@entries@ssert)
    if charm_metrics[2] \noexpand~= "*" then
      self[index].top_accent_stretch = charm_metrics[2] / 1000
    end
    if charm_metrics[3] \noexpand~= "*" then
      self[index].bot_accent_stretch = charm_metrics[3] / 1000
    end
  end
end
%    \end{macrocode}
% We end this section with three general-purpose Lua functions. The first function, |make_hex_value|, accepts a nonnegative integer and returns its hexadecimal representation as a string. The result will go in the variable |hex_string|. We handle the cases of 0 and 1 manually.
%    \begin{macrocode}
function mathfont.make_hex_value(integer)
  if integer == 0 then
    return "0000"
  end
  if integer == 1 then
    return "0001"
  end
  local hex_digits = "0123456789ABCDEF" % for reference
  local hex_string = ""
  local curr_val = integer
  local remainder = 0
%    \end{macrocode}
% Otherwise, we find the number of hexadecimal digits that we will need to represent the |integer|. We loop through the integers and stop when we reach the first power of 16 that is greater than |integer|.
%    \begin{macrocode}
  local i = 0
  while 16^i <= curr_val do
    i = i+1
  end
%    \end{macrocode}
% Once we know how many hex digits we will need, we subtract off successively smaller powers of 16. Our dummy variable |j| starts as the greatest power of 16 less than or equal to |integer|, and we divide by $16^{\hbox{\texttt{\footnotesize j}}}$. The quotient becomes the first hexadecimal digit, and we repeat the process with the remainder and a smaller value of |j|. The final result is the hexadecimal representation of our original |integer|.
%    \begin{macrocode}
  for j = i-1, 0, -1 do
    remainder = curr_val \@percentchar (16^j)
    curr_val = (curr_val - remainder) / (16^j)
    hex_string = hex_string .. 
      string.sub(hex_digits, curr_val+1, curr_val+1)
    curr_val = remainder
  end
%    \end{macrocode}
% If |hex_string| has fewer than 4 digits, we add enough leading 0's to bring it to 4 digits.
%    \begin{macrocode}
  if \string# hex_string < 4 then
    for i = \string# hex_string, 4, 1 do
      hex_string = "0" .. hex_string
    end
  end
  return hex_string
end
%    \end{macrocode}
% The |glyph_info| function does exactly what it sounds like. It accepts a character table from a font and returns the width, height, depth, and italic correction values.
%    \begin{macrocode}
function mathfont.glyph_info(char)
  local glyph_width = char.width or 0
  local glyph_height = char.height or 0
  local glyph_depth = char.depth or 0
  local glyph_italic = char.italic or 0
  return glyph_width, glyph_height, glyph_depth, glyph_italic
end
%    \end{macrocode}
% The |:smash_glyph| function returns a character table that will produce a smashed version of the unicode character with value |index|. The character has no width, height, or depth and typesets the glyph virtually using a |char| font command.
%    \begin{macrocode}
function mathfont:smash_glyph(index, fontdata)
  local smash_table = {}
  smash_table.width = 0
  smash_table.height = 0
  smash_table.depth = 0
  smash_table.commands = {{"char", index}}
  return smash_table
end
%    \end{macrocode}
% An empty function that does nothing. Used later for creating callbacks.
%    \begin{macrocode}
function mathfont.empty(arg)
end
%    \end{macrocode}
% 
% 
% 
% \section{Adjust Fonts: Changes}
%
%
%
% 
% This section contains the Lua functions\vadjust{\penalty\z@} that actually modify the font during loading. The three functions |set_nomath_false|, |math_constants|, and |apply_charm_info| do most of the heavy lifting, and we set them as the default behavior for three callbacks. In total, \textsf{mathfont} defines six different callbacks and calls them inside the function |adjust_font|---see table~4 for a list. Each callback accepts a fontdata object as an argument and returns nothing. You can use these callbacks to change \textsf{mathfont}'s default modifications or to modify a fontdata object before or after \textsf{mathfont} looks at it. Be aware that if you add a function to any of the |disable_nomath|, |add_math_constants|, or |fix_character_metrics| callbacks, Lua\TeX\ will not call the default |mathfont| function associated with the callback anymore. In other words, do not mess with these three callbacks unless you are duplicating the functionality of the corresponding ``Default Behavior'' function from table~4. 
% 
% \begin{figure}[bp]
% \centerline{\bfseries Table 4: Callbacks Created by \textsf{mathfont}\strut}
% \begin{tabularx}\textwidth{lX}\toprule
% Callback Name & Default Behavior\\\midrule
% |"mathfont.inspect_font"| & None\\\midrule
% |"mathfont.pre_adjust"|  & None\\
% |"mathfont.disable_nomath"| & |mathfont.set_nomath_false|\\
% |"mathfont.add_math_constants"| & |mathfont.math_constants|\\
% |"mathfont.fix_character_metrics"|& |mathfont.apply_charm_info|\\
% |"mathfont.post_adjust"| & None\\\bottomrule
% \end{tabularx}
% \end{figure}
% 
% 
% 
% We begin with the functions that modify character subtables in the font table, and in all cases, we return a new character table (or set of character tables in the case of type |e|) that we insert into the font object. For types |a| and |e|, we code the table from scratch, and for type |u|, we add information to the character tables that already exist in the font object. The three functions for assembling character tables take three arguments. The |index| argument is the unicode index of the base character that the function is modifying. The |charm_data| argument is the subtable in |mathfont| of charm information that corresponds to |index|, and the |fontdata| argument is a font object. We will pull information from |charm_data| and |fontdata| to assemble the new table.
% 
% We will incorporate five categories of information into our new character tables: glyph dimensions, unicode values, accent placement dimensions, virtual font commands, and math kerning. For type |a|, we increase the original horizontal glyph dimensions based on charm information, and for type |e|, we increase the width by horizontal scale factors and the height and depth by vertical scale factors. Accent placement dimensions come from charm information. For types |a| and |e|, we return a character table that will become a virtual character in the font, and we need to include commands to typeset certain base characters. For type |e|, we also create the large variants through |pdf| commands that stretch the base glyphs.
%  
% The type |a| commands include one command to move to the right by some offset and one command to typeset the base glyph.
%    \begin{macrocode}
function mathfont.make_a_commands(index, offset)
  local c_1 = {"right", offset}
  local c_2 = {"char", index}
  return {c_1, c_2}
end
%    \end{macrocode}
% The |:make_a_table| returns a character table for type |a| characters. We store the information to return in the variable |a_table| and the character subtable in |char|. The |slant| is the font's |slant| parameter and is used for calculating accent placement.
%    \begin{macrocode}
function mathfont:make_a_table(index, charm_data, fontdata)
  local a_table = {}
  local char = fontdata.characters[index] or {}
  local slant = fontdata.parameters.slant / 65536 or 0
%    \end{macrocode}
% The |left_stretch| and |right_stretch| values come from charm data and tell us how much extra space to add to the left and right sides of the character. Importantly, these values are additive. 
%    \begin{macrocode}
  local left_stretch = charm_data.left_stretch
  local right_stretch = charm_data.right_stretch
  local width, height, depth, italic = self.glyph_info(char)
%    \end{macrocode}
% Incorporate the italic correction into the character width.
%    \begin{macrocode}
  width = width + italic
%    \end{macrocode}
% The new width is $1+|left_stretch|+|right_stretch|$ times the original width. The horizontal offset that appears in the commands is the |left_stretch| portion of the new width.
%    \begin{macrocode}
  local offset = width * left_stretch
  a_table.width = width * (1 + left_stretch + right_stretch)
  a_table.height = height
  a_table.depth = depth
  a_table.italic = italic
  a_table.unicode = index
%    \end{macrocode}
% The |tounicode| entry is a hexadecimal string that encodes the unicode value of the base character.
%    \begin{macrocode}
  a_table.tounicode = self.make_hex_value(index)
%    \end{macrocode}
% We specify accent placement information by including |top_accent| and |bot_accent| entries in the |a_table|. We determine placement by setting the |top_accent| to be a base value plus a distance determined by the charm data and similarly for |bot_accent|. We imagine dividing up the character's bounding box as follows: (1)~some rectangular portion of the left and right areas of the bounding box is empty space added according to |left_stretch| and |right_stretch|; (2)~accordingly, the glyph occupies some rectangular area in the middle of the bounding box; (3)~if the font is slanted, that rectangle will actually be a parallogram where the rectangle overhangs both slanted edges of the parallogram in two triangles; and (4)~we can determine the size of these triangles according to the |slant| font parameter. We want the base measurement for the top accent to be located in the middle of the parallogram from step~(3) previously, and we end up with
% \begin{align*}
% \hbox{base measurement}&={\texttt{left\_stretch}}*{\texttt{width}}\\
%   &\qquad{}+0.5*({\texttt{width}}-\sigma_1*{\texttt{height}})+\sigma_1*{\texttt{height}},
% \end{align*}
% where $\sigma_1$ is the |slant| parameter and |width| and |height| refer to the character in question. This equation simplifies to 
% \[
% (0.5 + {|left_stretch|}) * {|width|} + 0.5 \sigma_1 * {|height|},
% \]
% which is the formula we use for the base value of the top accent. We determine the base value of the bottom accent similarly. For the shift amount, we take the corresponding factor from the charm information and multiply it by the width of the character. Note that in all these cases, we use the |width|, not the |new_width| as our unit of measurement. This keeps the scaling of the accent placement independent of the |left_stretch| and |right_stretch| values.
%    \begin{macrocode}
  local top_base = (0.5 + left_stretch) * width + 
    0.5 * slant * height
  local bot_base = (0.5 + left_stretch) * width - 
    0.5 * slant * height
  local top_accent_shift = charm_data.top_accent_stretch * width
  local bot_accent_shift = charm_data.bot_accent_stretch * width
  a_table.top_accent = top_base + top_accent_shift
  a_table.bot_accent = bot_base + bot_accent_shift
%    \end{macrocode}
% Add the commands to the table.
%    \begin{macrocode}
  a_table.commands = self.make_a_commands(index, offset)
%    \end{macrocode}
% Because we are keeping the character's italic correction, we have superscripts and subscripts that are too far from the glyph if we leave things as is. The reason is that Lua\TeX\ adds italic correction of the nucleus to the horizontal position of superscripts when it formats exponents. Accordingly we want to move both superscript and subscript left by the italic correction of the nucleus, so we add a mathkern table to the character. A mathkern table contains up to four subtables, one for each corner of the character. Within each subtable, we store pairs of |height| and |kern| values, where |height| means to apply |kern| to exponents at that height. In this case, we have a |kern| value of minus italic correction in the upper and lower right corners.
%    \begin{macrocode}
  a_table.mathkern = {}
  a_table.mathkern.top_right = {{height = 0, kern = -italic}}
  a_table.mathkern.bottom_right = {{height = 0, kern = -italic}}
  a_table.mathkern.top_left = {{height = 0, kern = 0}}
  a_table.mathkern.bottom_left = {{height = 0, kern = 0}}
  return a_table
end
%    \end{macrocode}
% For type |e| characters, we need a function to modify the base glyph. We incorporate the italic correction into the width and add extra italic correction in the case of the integral symbol.
%    \begin{macrocode}
function mathfont:modify_e_base(index, fontdata)
  local char = fontdata.characters[index] or {}
  local width, height, depth, italic = self.glyph_info(char)
  char.width = width + italic
%    \end{macrocode}
% We trim the bounding box on the surd if the user requests it. Some text fonts extend the bounding box of the surd past the edge of the glyph, and we trim the edge of the box according to the values of |\M@SurdHorizontalFactor| and |\M@SurdVerticalFactor|.
%    \begin{macrocode}
  if index == 8730 then
%    \end{macrocode}
% Now get the scale factors from the \TeX\ side of things and scale down (or up) the height and with of the surd.
%    \begin{macrocode}
    local horizontal_scale = 
      tex.getcount("M@SurdHorizontalFactor") / 1000
    local vertical_scale = 
      tex.getcount("M@SurdVerticalFactor") / 1000
    char.width = horizontal_scale * char.width
    char.height = vertical_scale * height
  end
%    \end{macrocode}
% For the integral symbol, get the scale factor add the appropriate italic correction.
%    \begin{macrocode}
  if index == 8747 then
    local scale_factor = 
      tex.getcount("M@IntegralItalicFactor") / 1000
    char.italic = scale_factor * width
  end
end
%    \end{macrocode}
% For the |e| commands, we not only typeset a certain glyph but also instruct the |pdf| backend to scale by a horizontal and vertical factor before doing so. In this way, we artificially add larger variants of a particular base glyph. The |pdf| command sends code directly to the pdf backend that handles the transformation. The |q| command indicates a linear transformation of the output, and the following string contains the transformation coordinates. The |Q| command restores the original coordinate system, and because it occurs between the transformation commands, the typeset glyph from the |char| command will be enlarged according to the transformation matrix.
%    \begin{macrocode}
function mathfont.make_e_commands(index, h_stretch, v_stretch)
  local c_1 = {"pdf", "origin", 
    string.format("q \@percentchar s 0 0 \@percentchar s 0 0 cm",
    h_stretch, v_stretch)}
  local c_2 = {"char", index}
  local c_3 = {"pdf", "origin", "Q"}
  return {c_1, c_2, c_3}
end
%    \end{macrocode}
% The function for type |e| characters returns a table with different structure because we need to create multiple characters at once. Specifically, the function returns a table with one entry for each larger variant that we want to add to the font. Many of the variables are the same as in |:make_type_a|. We store the base character subtable in |char| and the font's |slant| parameter in |slant|. The |tounicode| stores the hexadecimal unicode value of the base character for reference later, and |smash_index| is the index of the unicode slot that we are using to hold the smashed version of the base character.
%    \begin{macrocode}
function mathfont:make_e_table(index, charm_data, fontdata)
  local e_table = {}
  local char = fontdata.characters[index] or {}
  local slant = fontdata.parameters.slant / 65536
  local tounicode = self.make_hex_value(index)
  local smash_index = charm_data.smash
  local width, height, depth, italic = self.glyph_info(char)
%    \end{macrocode}
% We will create a number of entries in |e_table| equal to the number of variants we want, which is stored in |charm_data.total_variants|. We iteratively assemble the |e_table|, and we begin the iteration by extracting the |i|th horizontal and vertical scale factors from |charm_data|. The width, height, and depth of the |i|th new character will be scalings of these values from the original character.
%    \begin{macrocode}
  for i = 1, charm_data.total_variants, 1 do
    local h_stretch = charm_data.data[i].x
    local v_stretch = charm_data.data[i].y
    local new_width = width * h_stretch
    local new_height = height * v_stretch
    local new_depth = depth * v_stretch
    local new_italic = italic * h_stretch
%    \end{macrocode}
% We add new character bounds to the |i|th entry of |e_table|.
%    \begin{macrocode}
    e_table[i] = {}
    e_table[i].width = new_width
    e_table[i].height = new_height
    e_table[i].depth = new_depth
    e_table[i].italic = new_italic
%    \end{macrocode}
% Add the unicode information.
%    \begin{macrocode}
    e_table[i].unicode = index
    e_table[i].tounicode = tounicode
%    \end{macrocode}
% We handle accent placement the same way as with type |a| characters.
%    \begin{macrocode}
    local base_top_accent = 0.5 * new_width +
      0.5 * slant * new_height
    local base_bot_accent = 0.5 * new_width -
      0.5 * slant * new_height
    local top_accent_shift =
      charm_data.top_accent_stretch * new_width
    local bot_accent_shift =
      charm_data.bot_accent_stretch * new_width
    e_table[i].top_accent = base_top_accent + top_accent_shift
    e_table[i].bot_accent = base_bot_accent + bot_accent_shift
%    \end{macrocode}
% Add the commands.
%    \begin{macrocode}
    e_table[i].commands = 
      self.make_e_commands(smash_index, h_stretch, v_stretch)
%    \end{macrocode}
% If we aren't dealing with the last entry in the table, we need to add the character's |next| fields. The next larger variant after the |i|th character will the the ${|i|}+1$st character, and we can extract the index from the |charm_information|.
%    \begin{macrocode}
    if i < charm_data.total_variants then
      e_table[i].next = charm_data.next[i+1]
    end
  end
  return e_table
end
%    \end{macrocode}
% Making the |u| table is the easiest. We take the character subtable from |fontdata| as our starting point rather than assembling a new character subtable from scratch. The structure here is very similar to type |a| without the extra space from the |left_stretch| and |right_stretch|. Again, we incorporate the italic correction into the bounding box and add a negative mathkern to compensate.
%    \begin{macrocode}
function mathfont:make_u_table(index, charm_data, fontdata)
  local u_table = fontdata.characters[index] or {}
  local slant = fontdata.parameters.slant / 65536 or 0
  local width, height, depth, italic = self.glyph_info(u_table)
  local new_width = width + italic
  u_table.width = new_width
%    \end{macrocode}
% We handle accents in the same way as with the other types.
%    \begin{macrocode}
  local base_top_accent = 0.5 * new_width +
    0.5 * slant * height
  local base_bot_accent = 0.5 * new_width -
    0.5 * slant * height
  local top_accent_shift =
    charm_data.top_accent_stretch * new_width
  local bot_accent_shift =
    charm_data.bot_accent_stretch * new_width
  u_table.top_accent = base_top_accent + top_accent_shift
  u_table.bot_accent = base_bot_accent + bot_accent_shift
%    \end{macrocode}
% Add a mathkern table as in the case of type |a| characters.
%    \begin{macrocode}
  u_table.mathkern = {}
  u_table.mathkern.top_right = {{height = 0, kern = -italic}}
  u_table.mathkern.bottom_right = {{height = 0, kern = -italic}}
  u_table.mathkern.top_left = {{height = 0, kern = 0}}
  u_table.mathkern.bottom_left = {{height = 0, kern = 0}}
  return u_table
end
%    \end{macrocode}
% Before we get to the main font-changing functions, we code |make_fake_angle|, which returns a character table for the fake angle brackets. The function accepts the index of the smashed character as |index| and the index of the smashed gillement as |smash|. We form the fake angle bracket by using only the top 90\% of the original glyph, and we scale it to have the same height and depth as the left parenthesis. 
%    \begin{macrocode}
function mathfont.make_fake_angle(index, smash, fontdata)
  local temp = {}
  local lparen = fontdata.characters[40] or {}
  local lparen_height = lparen.height or 0
  local lparen_depth = lparen.depth or 0
  local glyph = fontdata.characters[index] or {}
  local glyph_height = glyph.height or 0
  local base_height = 0.9 * glyph_height
  local factor = 0
  if glyph_height \noexpand~= 0 then
    factor = (lparen_height + lparen_depth) / base_height
  end
  local shift = 0.1 * glyph_height * factor + lparen_depth
  temp.height = lparen_height
  temp.depth = lparen_depth
  temp.width = glyph.width or 0
  temp.italic = glyph.italic or 0
  temp.top_accent = glyph.top_accent or 0.5 * temp.width
  temp.bot_accent = glyph.bot_accent or 0.5 * temp.width
  temp.commands = {
    {"down", shift},
    {"pdf", "origin",
      string.format("q 1 0 0 \@percentchar s 0 0 cm", factor)},
    {"char", smash},
    {"pdf", "origin", "Q"},
    {"down", -shift}}
  return temp
end
%    \end{macrocode}
% We come to the main functions that modify the font. We need to accomplish three tasks, and we define separate functions for each one. First, we set the font's |nomath| entry to |false|. Second, we incorporate the modifications based on charm information into the font, i.e.\ set the font's character subtables using the previous functions from this section. Third, we need to add a MathConstants table. The first task is very easy.
%    \begin{macrocode}
function mathfont.set_nomath_false(fontdata)
  fontdata.nomath = false
  fontdata.oldmath = false
end
%    \end{macrocode}
% The second task is more involved. The basic idea is to loop through |mathfont|, and whenever we find an entry that is a subtable, we treat it as charm information that we use to modify the font object. We begin by storing the character information from the font in |chars| for easier reference later.
%    \begin{macrocode}
function mathfont.apply_charm_info(fontdata)
  local chars = fontdata.characters or {}
%    \end{macrocode}
% Before we loop through the charm data, we need to add fake angle brackets and |\nabla| to the font. We begin with the angle brackets.
%    \begin{macrocode}
  chars[1044538] = mathfont:smash_glyph(8249, fontdata) % \lguil
  chars[1044539] = mathfont:smash_glyph(8250, fontdata) % \rguil
  chars[1044540] = mathfont:smash_glyph(171, fontdata)  % \llguil
  chars[1044541] = mathfont:smash_glyph(187, fontdata)  % \rrguil
%    \end{macrocode}
% Now add the characters to the font.
%    \begin{macrocode}
  chars[1044508] = mathfont.make_fake_angle(
    8249, 1044538, fontdata)
  chars[1044509] = mathfont.make_fake_angle(
    8250, 1044539, fontdata)
  chars[1044510] = mathfont.make_fake_angle(
    171, 1044540, fontdata)
  chars[1044511] = mathfont.make_fake_angle(
    187, 1044541, fontdata)
%    \end{macrocode}
% Add the nabla (inverted Delta) character to the font if it is missing.
%    \begin{macrocode}
  if not chars[8711] then
    chars[8710] = chars[8710] or {}
    chars[1044508] = mathfont:smash_glyph(8710, fontdata)
    chars[8711] = {}
    chars[8711].width = chars[8710].width or 0
    chars[8711].height = chars[8710].height or 0
    chars[8711].depth = chars[8710].depth or 0
    chars[8711].italic = chars[8710].italic or 0
    chars[8711].top_accent = chars[8710].top_accent or
      0.5 * chars[8711].width
    chars[8711].bot_accent = chars[8710].bot_accent or
      0.5 * chars[8711].width
    chars[8711].unicode = 8711
    chars[8711].tounicode = mathfont.make_hex_value(8711)
    chars[8711].commands = {
      {"down", -chars[8711].height},
      {"pdf", "origin", "q 1 0 0 -1 0 0 cm"},
      {"char", 1044508},
      {"pdf", "origin", "Q"},
      {"down", chars[8711].height}}
  end
%    \end{macrocode}
% Perform the loop. We care about entries |info| whose type is a table.
%    \begin{macrocode}
  for index, info in pairs(mathfont) do
    if type(info) == "table" then
%    \end{macrocode}
% If the character's type is |a|, all we need to do is replace the character subtable in the font with our version.
%    \begin{macrocode}
      if info.type == "a" then
        chars[info.next] =
          mathfont:make_a_table(index, info, fontdata)
%    \end{macrocode}
% Again, type |e| is more complicated. This time we need to insert multiple character subtables into the font, one for the smashed version of the base glyph and others corresponding to the large variants that we create using the |:make_e_table| function from above. We also need to add |next| entries to the caracters in the font linking all the variants together.
%    \begin{macrocode}
      elseif info.type == "e" then
        local smash = info.smash
        chars[index] = chars[index] or {}
%    \end{macrocode}
% Set the |next| entry on the current character, modify the character's dimensions to incorporate italic correction into the width, and add a smashed version of the glyph into the font.
%    \begin{macrocode}
        chars[index].next = info.next[1]
        mathfont:modify_e_base(index, fontdata)
        chars[smash] = mathfont:smash_glyph(index, fontdata)
%    \end{macrocode}
% The function that creates the character table for type |e| produces one character subtable for each larger variant that we want to add, so we loop through the resulting table and add the contents to the font one at time. Each subtable goes in unicode slots that we take from the charm information, specifically the |next| table from |info|.
%    \begin{macrocode}
        local variants_table =
          mathfont:make_e_table(index, info, fontdata)
        for i = 1, info.total_variants, 1 do
          chars[info.next[i]] = variants_table[i]
        end
%    \end{macrocode}
% We deal with type |u| in the same way as we do type |a|.
%    \begin{macrocode}
      elseif info.type == "u" then
        chars[index] =
          mathfont:make_u_table(index, info, fontdata)
      end
    end
  end
end
%    \end{macrocode}
% The |populate_math_constants| function is even more complicated because we need to add a full MathConstants table to the font object, which has some fifty parameters that we need to set. To keep things simple, we set the font parameters in terms of traditional \TeX\ |\fontdimen| parameters. Besides the eight essential parameters found in all fonts, \TeX\  traditionally uses some fifteen extra parameters to typeset math formulas. To preserve whatever structure may already exist in the font object, we do not override any MathConstants that the font already contains.
%    \begin{macrocode}
function mathfont.math_constants(fontdata)
  fontdata.MathConstants = fontdata.MathConstants or {}
%    \end{macrocode}
% First evaluate the dimensions from the font object that we will use in determining other math parameter values. The |A_height| is the height of the capital ``A'' character, and the |y_depth| is the depth of the lower-case ``y'' character. Both will be 0 if the font does not have the correct character.
%    \begin{macrocode}
  local size = fontdata.size or 0
  local ex = fontdata.parameters.x_height or 0
  local em = fontdata.parameters.quad or 0
  local A_height = 0
  local y_depth = 0
  if fontdata.characters[65] then
    A_height = fontdata.characters[65].height or 0 % A
  end
  if fontdata.characters[121] then
    y_depth = fontdata.characters[121].depth or 0 % y
  end
%    \end{macrocode}
% We begin by setting the axis height and default rule thickness. We need to start with these parameters because we will use them to calculate other constants. We set both values to 0 initially and then change them.
%    \begin{macrocode}
  local axis = 0
  local rule_thickness = 0
%    \end{macrocode}
% Set the default rule thickness. If the font already has a value set for the parameter |FractionRuleThickness|, we take that as the default rule thickness, and otherwise we set it to be 1/18 of the font size times the adjustment factor from |\M@RuleThicknessFactor|, which is the value of that |\count| divided by 1000. 
%    \begin{macrocode}
  local dim = "FractionRuleThickness"
  if not fontdata.MathConstants[dim] then
    local scale_factor =
      tex.getcount("M@RuleThicknessFactor") / 1000
    rule_thickness = (size / 18) * scale_factor
    fontdata.MathConstants[dim] = rule_thickness
  else
    rule_thickness = fontdata.MathConstants[dim]
  end
%    \end{macrocode}
% If the font does not have |AxisHeight| already set, we set the axis to be the height of a minus sign (character 45). As a fallback, we set the axis to 0.8ex if the font does not have a character in unicode slot 45. If the font has an |AxisHeight|, we take that value as the |axis|.
%    \begin{macrocode}
  local dim = "AxisHeight"
  if fontdata.MathConstants[dim] then
    axis = fontdata.MathConstants[dim]
  else
    if fontdata.characters[45] then
      axis = fontdata.characters[45].height - 0.5 * rule_thickness
    else
      axis = 0.8 * ex
    end
    fontdata.MathConstants[dim] = axis
  end
%    \end{macrocode}
% Apart from the axis height and rule thickness, we can group the traditional mathematics |\fontdimen| parameters into three categories: four for large operators, five for fractions, and six for superscripts and subscripts. (OpenType math does not use the fifth large-operator parameter $\xi_{13}$ and the seventh script parameter $\sigma_{14}$.) We define variables with the same names as their traditional references from Appendix G in the \textit{\TeX Book}. I have taken the design approach of using twice the rule height as a standard minimum clearance, and I am assuming that script styles are roughly 70\% as large as text and display styles. We begin with the parameters for large operators.
% 
% The parameter $\xi_9$ is the minimum clearance between the top of a large operator and the limit above it, and we set it to be twice the rule thickness. Before ensuring that the bottom of the upper limit is at least $\xi_9$ away from the operator character, \TeX\ attempts to position the baseline of the limit at $\xi_{10}$ distance above the operator character, and we set $\xi_{10}$ to be slightly larger than $\xi_9$. If the upper limit has no decender, \TeX\ will raise its baseline by $\xi_{10}$, and if it has a descener, \TeX\ will position the bottom of the descender to be $\xi_9$ above the operator, which in practice means it will be higher than limits without descenders. This approach balances the desire for consistency in whitespace with the desire for consistency in baseline height. Similarly, we set the minimum clearance $\xi_{11}$ for the lower limit to be equal to the attempted clearance for the upper limit, and the attempted clearance $\xi_{12}$ for the lower limit will be the minimum clearance plus the average of the |\scriptfont| x-height and |\scriptfont| A-height.
%    \begin{macrocode}
  local xi_9 = 2 * rule_thickness     % top limit min clearance
  local xi_10 = xi_9 + 0.35 * y_depth % bottom limit try placement
  local xi_11 = xi_10                 % top limit min clearance
  local xi_12 = xi_10 + 0.35 * (A_height + ex) % bottom attempt
%    \end{macrocode}
% Our general approach for |\displaystyle| fractions is to place the baseline of the numerator numerator at a distance above the fraction rule of 1.5 times the rule height plus descender depth plus a small extra space. The minimum clearance will be the rule height, so we expect the numerator to strictly exceed the minimum clearance in most situations. Doing so produces consistent baselines of numerators and gives our value for $\sigma_8$, the attempted height of the numerator in |\displaystyle| fractions. For smaller styles, we use a single rule height as clearance, so we add $0.5*|rule_thickness|+|y_depth|$ scaled down by 0.7 to the rule thickness. The minimum clearance for numerator and denominator are separate OpenType parameters, and we set them later. The extra 0.1 A-height in the attempted clearance relative to the minimum clearance appears because we measure attempted clearance from the axis, whereas we measure minimum clearance from the top or bottom of the fraction rule.
%    \begin{macrocode}
  local sigma_8 = axis + 1.5 * rule_thickness + y_depth +
    0.1 * A_height
  local sigma_9 = (axis + 1.35 * rule_thickness + 0.7 * y_depth +
    0.07 * A_height)
  local sigma_10 = sigma_9
%    \end{macrocode}
% Our approach in the denominators is the same except that we add half the descender depth to the minimum clearance. This creates extra space below the fraction rule so that the typographical color above the rule matches that below the rule when the numerator contains descenders.
%    \begin{macrocode}
  local sigma_11 = (-axis + 1.5  * rule_thickness +
    0.5 * y_depth + 1.1 * A_height)
  local sigma_12 = (-axis + 1.35 * rule_thickness +
    0.35 * y_depth + 0.77 * A_height)
%    \end{macrocode}
% For superscripts we think in terms of the top of the superscript. We raise the baseline of the superscript by the desired height of the superscript top minus the |\scriptfont| A-height. Choosing $1.3*|A_height|$ for regular styles and $1.2*|A_height|$ for cramped styles was a design choice that worked well. The attempted drop for subscripts is one-fifth the A-height or slightly more than the y-depth, whichever is greater. This way the subscript baseline is slightly lower than any descenders, and for fonts without descenders, we still clearly lower the subscript. Setting $\sigma_{18}$ and $\sigma_{19}$ was another design choice that worked well.
%    \begin{macrocode}
  local sigma_13 = 0.6 * A_height   % attempted superscript height
  local sigma_15 = 0.5 * A_height   % attempt for cramped scripts
  local sigma_16 = 1.1 * y_depth    % attempted subscript lower
  if sigma_16 < 0.2 * A_height then
    sigma_16 = 0.2 * A_height
  end
  local sigma_17 = sigma_16         % sigma_16 when superscript
  local sigma_18 = 0.5 * A_height   % superscript lower for boxed
  local sigma_19 = 0.1 * A_height   % subscript lower for boxed
%    \end{macrocode}
% The MathConstants themselves come from the unicode equivalents of the traditional \TeX\ |\fontdimen| parameters where appropriate. Where not appropriate, I made design choices as indicated. Setting the next three parameters was purely a design choice. 
%    \begin{macrocode}
  local dim = "DisplayOperatorMinHeight"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 1.8 * A_height
  end
  local dim = "FractionDelimiterDisplayStyleSize"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 2 * size
  end
  local dim = "FractionDelimiterSize"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 1.3 * size
  end
  local dim = "FractionDenominatorDisplayStyleShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_11
  end
  local dim = "FractionDenominatorShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_12
  end
%    \end{macrocode}
% We set the minium clearance for the numerator to be twice the rule height in |\displaystyle| and the rule height in other styles. Our approach in setting the attempted height of the numerator ($\sigma_8$ and $\sigma_9$) was to add the minimum clearance plus the descender depth plus a small extra space, so in general, we do not expect the numerator to run into the minimum clearance. For the denominator, we do the same thing except add half the descender depth to the clearance, which balances the amount of color above and below the fraction rule and is similar to what we did for the lower limits on big operators when we set $\xi_{11}$ larger than $\xi_9$.
%    \begin{macrocode}
  local dim = "FractionDenominatorDisplayStyleGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness + 0.5 * y_depth
  end
  local dim = "FractionDenominatorGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness + 0.35 * y_depth
  end
  local dim = "FractionNumeratorDisplayStyleShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_8
  end
  local dim = "FractionNumeratorShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_9
  end
  local dim = "FractionNumeratorDisplayStyleGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "FractionNumeratorGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
%    \end{macrocode}
% The |SkewedFractionHorizontalGap| and |SkewedFractionVerticalGap| take the values that Lua\TeX would set for a traditional \TeX\ font.
%    \begin{macrocode}
  local dim = "SkewedFractionHorizontalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 0.5 * em
  end
  local dim = "SkewedFractionVerticalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = ex
  end
%    \end{macrocode}
% The |UpperLimit| and |LowerLimit| dimensions correspond exactly to traditional \TeX\ math |\fontdimen| parameters.
%    \begin{macrocode}
  local dim = "UpperLimitBaselineRiseMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_11
  end
  local dim = "UpperLimitGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_9
  end
  local dim = "LowerLimitBaselineDropMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_12
  end
  local dim = "LowerLimitGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_10
  end
%    \end{macrocode}
% Traditional \TeX\ doesn't have stack objects, but they are meant to be similar to large operators, so we set the same parameters.
%    \begin{macrocode}
  local dim = "StretchStackGapBelowMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_10
  end
  local dim = "StretchStackTopShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_11
  end
  local dim = "StretchStackGapAboveMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_9
  end
  local dim = "StretchStackBottomShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = xi_12
  end
%    \end{macrocode}
% For the three |Overbar| parameters, we take the approach that the bar itself should be as thick as the rule height. The gap will be twice the rule height, and the extra clearance will be a single rule height.
%    \begin{macrocode}
  local dim = "OverbarExtraAscender"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "OverbarRuleThickness"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "OverbarVerticalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 2 * rule_thickness
  end
%    \end{macrocode}
% For the radical sign, we take the same approach as with the |Overbar| parameters. We insert one rule thickness of extra space above the radical symbol and two rule thickness of extra space under it. For |\textstyle| and smaller, we reduce the space to a single rule height.
%    \begin{macrocode}
  local dim = "RadicalExtraAscender"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "RadicalRuleThickness"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "RadicalDisplayStyleVerticalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 2 * rule_thickness
  end
  local dim = "RadicalVerticalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
%    \end{macrocode}
% The final three |Radical| parameters aren't used if we handle degree placement at the macro level rather than at the font level. We set them to the default values that Lua\TeX\ uses for traditional tfm fonts.
%    \begin{macrocode}
  local dim = "RadicalKernBeforeDegree"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = (5/18) * em
  end
  local dim = "RadicalKernAfterDegree"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = (10/18) * em
  end
  local dim = "RadicalDegreeBottomRaisePercent"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 60
  end
%    \end{macrocode}
% The |SpaceAfterShift| is a design choice. Somewhat arbitrary.
%    \begin{macrocode}
  local dim = "SpaceAfterScript"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 0.1 * em
  end
%    \end{macrocode}
% The |Stack| parameters come from their traditional |\fontdimen| analogues.
%    \begin{macrocode}
  local dim = "StackBottomDisplayStyleShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_11
  end
  local dim = "StackBottomShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_12
  end
  local dim = "StackTopDisplayStyleShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_8
  end
  local dim = "StackTopShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_10
  end
%    \end{macrocode}
% Traditionally \TeX\ uses an internal method rather than a parameter to determine the minimum distance between two boxes in an |\atop| stack. We set the minimum distance to be one rule thickness plus the combined minimum clearance for numerators and denominators in fractions. For |\displaystyle|, that gives us 
% \[
% |rule_thickness|+(2*|rule_thickness|)+(2*|rule_thickness|+0.5*|y_depth|)
% \]
% For smaller styles, we use single rule height values and scale down the |y_depth| by 0.7.
%    \begin{macrocode}
  local dim = "StackDisplayStyleGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 5 * rule_thickness +
      0.5 * y_depth
  end
  local dim = "StackGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 3 * rule_thickness +
      0.35 * y_depth
  end
%    \end{macrocode}
% With three exceptions, superscript and subscript parameters come from traditional \TeX\ dimensions.
%    \begin{macrocode}
  local dim = "SubscriptShiftDown"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_16
  end
  local dim = "SubscriptBaselineDropMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_19
  end
  local dim = "SubscriptShiftDownWithSuperscript"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_17
  end
%    \end{macrocode}
% The top of a subscript should be less than half the A-height. This is a somewhat arbitrary design choice.
%    \begin{macrocode}
  local dim = "SubscriptTopMax"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 0.5 * A_height
  end
%    \end{macrocode}
% The minimum gap between superscripts and subscripts will be the height of the rule. This is less space than \TeX\ traditionally allocates.
%    \begin{macrocode}
  local dim = "SubSuperscriptGapMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
%    \end{macrocode}
% We set the minimum height for the bottom of a subscript to be the height of a superscript in cramped styles minus the depth of a possible descender. Theoretically this is the lowest that any portion of a superscript should ever be if it contains only text.
%    \begin{macrocode}
  local dim = "SuperscriptBottomMin"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_15 - 0.7 * y_depth
  end
  local dim = "SuperscriptBaselineDropMax"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_18
  end
  local dim = "SuperscriptShiftUp"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_13
  end
  local dim = "SuperscriptShiftUpCramped"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = sigma_15
  end
%    \end{macrocode}
% If the superscript and subscript overlap, we choose the new position such that the baselines of subscripts are roughly consistent across subformulas. In this case, the bottom of the superscript box will rise at most to the point such that a subscript containing only text at 70\% of the next-larger style will align with all similar subscripts. The top of the subscript will have approximate height $-\sigma_{16}+0.7*|A_height|$ above the baseline, so to find our desired position for the bottom of the superscript, we add the minimum clearance of a single rule thickness. Putting this parameter in terms of the subscript sizing is necessary because we don't know how large the descender will be in a given subscript.
%    \begin{macrocode}
  local dim = "SuperscriptBottomMaxWithSubscript"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = -sigma_16 +
      0.7 * A_height + rule_thickness
  end
%    \end{macrocode}
% As with the |Overbar| parameters, we set the extra clearance to be the rule height and the gap to be twice the rule height.
%    \begin{macrocode}
  local dim = "UnderbarExtraDescender"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "UnderbarRuleThickness"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = rule_thickness
  end
  local dim = "UnderbarVerticalGap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 2 * rule_thickness
  end
%    \end{macrocode}
% No reason not to set |MinConnectorOverlap| to 0. It doesn't matter for our purposes because \textsf{mathfont} doesn't use extensibles.
%    \begin{macrocode}
  local dim = "MinConnectorOverlap"
  if not fontdata.MathConstants[dim] then
    fontdata.MathConstants[dim] = 0
  end
end
%    \end{macrocode}
% Time for callbacks! We create six of them.
%    \begin{macrocode}
luatexbase.create_callback("mathfont.inspect_font",
  "simple", mathfont.empty)
luatexbase.create_callback("mathfont.pre_adjust",
  "simple", mathfont.empty)
luatexbase.create_callback("mathfont.disable_nomath",
  "simple", mathfont.set_nomath_false)
luatexbase.create_callback("mathfont.add_math_constants",
  "simple", mathfont.math_constants)
luatexbase.create_callback("mathfont.fix_character_metrics",
  "simple", mathfont.apply_charm_info)
luatexbase.create_callback("mathfont.post_adjust",
  "simple", mathfont.empty)
%    \end{macrocode}
% The functions |mathfont.info| and |mathfont.get_font_name| are used for informational messaging. The first prints a message in the |log| file, and the second returns a font name.
%    \begin{macrocode}
function mathfont.info(msg)
  texio.write_nl("log", "Package mathfont Info: " .. msg)
end
function mathfont.get_font_name(fontdata)
  return fontdata.fullname or 
         fontdata.psname or 
         fontdata.name or "<??>"
end
%    \end{macrocode}
% The |adjust_font| function is what actually goes in |luaotfload.patch_font|. This function calls the six callbacks at appropriate times and writes informational messages in the |log| file.
%    \begin{macrocode}
function mathfont.adjust_font(fontdata)
  luatexbase.call_callback("mathfont.inspect_font", fontdata)
  local the_font = mathfont.get_font_name(fontdata)
  if fontdata.nomath then
    mathfont.info("Adjusting font " .. the_font .. ".")
    luatexbase.call_callback("mathfont.pre_adjust",
      fontdata)
    luatexbase.call_callback("mathfont.disable_nomath",
      fontdata)
    luatexbase.call_callback("mathfont.add_math_constants",
      fontdata)
    luatexbase.call_callback("mathfont.fix_character_metrics",
      fontdata)
    luatexbase.call_callback("mathfont.post_adjust",
      fontdata)
  else
    mathfont.info("No changes made to " .. the_font .. ".")
  end
end
%    \end{macrocode}
% Finally, add the processing function to \textsf{luaotfload}'s |patch_font| callback.
%    \begin{macrocode}
luatexbase.add_to_callback("luaotfload.patch_font",
  mathfont.adjust_font, "mathfont.adjust_font")
%    \end{macrocode}
% 
% 
% 
% \section{Adjust Fonts: Metrics}
% 
% 
% 
% 
% This section contains the default charm information for the characters that \textsf{mathfont} adjusts upon loading a font. We will make new variants in the private use area of the font. Lower-case Latin letters will fill unicode slots U+FF000 through U+FF021, which are located in the Supplemental Private Use Area-A portion of the unicode table.
%    \begin{macrocode}
mathfont:new_type_a(97, 1044480, {50, 50, -50, 0})     % a
mathfont:new_type_a(98, 1044481, {50, 50, -50, 0})     % b
mathfont:new_type_a(99, 1044482, {50, 50, 0, 0})       % c
mathfont:new_type_a(100, 1044483, {50, -50, -50, 0})   % d
mathfont:new_type_a(101, 1044484, {50, 50, 0, 0})      % e
mathfont:new_type_a(102, 1044485, {200, 0, 0, 0})      % f
mathfont:new_type_a(103, 1044486, {100, 50, -50, 0})   % g
mathfont:new_type_a(104, 1044487, {50, 0, -50, 0})     % h
mathfont:new_type_a(105, 1044488, {50, 100, -100, 0})  % i
mathfont:new_type_a(106, 1044489, {400, 50, -50, 0})   % j
mathfont:new_type_a(107, 1044490, {50, 50, -100, 0})   % k
mathfont:new_type_a(108, 1044491, {100, 150, -100, 0}) % l
mathfont:new_type_a(109, 1044492, {50, 0, 0, 0})       % m
mathfont:new_type_a(110, 1044493, {50, 0, 0, 0})       % n
mathfont:new_type_a(111, 1044494, {50, 0, 0, 0})       % o
mathfont:new_type_a(112, 1044495, {200, 50, -50, 0})   % p
mathfont:new_type_a(113, 1044496, {50, 0, -50, 0})     % q
mathfont:new_type_a(114, 1044497, {100, 100, -50, 0})  % r
mathfont:new_type_a(115, 1044498, {50, 50, -50, 0})    % s
mathfont:new_type_a(116, 1044499, {50, 50, -50, 0})    % t
mathfont:new_type_a(117, 1044500, {0, 50, 0, 0})       % u
mathfont:new_type_a(118, 1044501, {0, 50, -50, 0})     % v
mathfont:new_type_a(119, 1044502, {0, 50, 0, 0})       % w
mathfont:new_type_a(120, 1044503, {50, 0, -50, 0})     % x
mathfont:new_type_a(121, 1044504, {150, 50, -50, 0})   % y
mathfont:new_type_a(122, 1044505, {100, 50, -100, 0})  % z
mathfont:new_type_a(305, 1044506, {100, 100, -150, 0}) % \imath
mathfont:new_type_a(567, 1044507, {700, 50, -150, 0})  % \jmath
%    \end{macrocode}
% Upper-case Latin letters will fill unicode slots U+FF020 through U+FF039.
%    \begin{macrocode}
mathfont:new_type_a(65, 1044512, {50, 0, 150, 0})      % A
mathfont:new_type_a(66, 1044513, {50, 0, 0, 0})        % B
mathfont:new_type_a(67, 1044514, {0, 0, 0, 0})         % C
mathfont:new_type_a(68, 1044515, {50, 0, -50, 0})      % D
mathfont:new_type_a(69, 1044516, {50, 0, 0, 0})        % E
mathfont:new_type_a(70, 1044517, {50, 0, 0, 0})        % F
mathfont:new_type_a(71, 1044518, {0, 0, 0, 0})         % G
mathfont:new_type_a(72, 1044519, {50, 0, -50, 0})      % H
mathfont:new_type_a(73, 1044520, {100, 0, 0, 0})       % I
mathfont:new_type_a(74, 1044521, {50, 0, 100, 0})      % J
mathfont:new_type_a(75, 1044522, {50, 0, 0, 0})        % K
mathfont:new_type_a(76, 1044523, {50, 0, -180, 0})     % L
mathfont:new_type_a(77, 1044524, {50, 0, -50, 0})      % M
mathfont:new_type_a(78, 1044525, {50, 0, -50, 0})      % N
mathfont:new_type_a(79, 1044526, {0, 0, 0, 0})         % O
mathfont:new_type_a(80, 1044527, {0, 0, -50, 0})       % P
mathfont:new_type_a(81, 1044528, {0, 50, 0, 0})        % Q
mathfont:new_type_a(82, 1044529, {50, 0, -50, 0})      % R
mathfont:new_type_a(83, 1044530, {0, 0, -50, 0})       % S
mathfont:new_type_a(84, 1044531, {0, 0, -50, 0})       % T
mathfont:new_type_a(85, 1044532, {0, 0, -50, 0})       % U
mathfont:new_type_a(86, 1044533, {0, 50, 0, 0})        % V
mathfont:new_type_a(87, 1044534, {0, 50, -50, 0})      % W
mathfont:new_type_a(88, 1044535, {50, 0, 0, 0})        % X
mathfont:new_type_a(89, 1044536, {0, 0, -50, 0})       % Y
mathfont:new_type_a(90, 1044537, {50, 0, -50, 0})      % Z
%    \end{macrocode}
% The Greek characters will be type |u|, so we don't need extra unicode slots for them. In future editions of \textsf{mathfont}, they may becoeme type |a| with adjusted bounding boxes, but I don't have immediate plans for such a change.
%    \begin{macrocode}
mathfont:new_type_u(945, {0, 0})    % \alpha
mathfont:new_type_u(946, {0, 0})    % \beta
mathfont:new_type_u(947, {-50, 0})  % \gamma
mathfont:new_type_u(948, {0, 0})    % \delta
mathfont:new_type_u(1013, {50, 0})  % \epsilon
mathfont:new_type_u(950, {0, 0})    % \zeta
mathfont:new_type_u(951, {-50, 0})  % \eta
mathfont:new_type_u(952, {0, 0})    % \theta
mathfont:new_type_u(953, {-50, 0})  % \iota
mathfont:new_type_u(954, {0, 0})    % \kappa
mathfont:new_type_u(955, {-150, 0}) % lambda
mathfont:new_type_u(956, {0, 0})    % \mu
mathfont:new_type_u(957, {-50, 0})  % \nu
mathfont:new_type_u(958, {0, 0})    % \xi
mathfont:new_type_u(959, {0, 0})    % \omicron
mathfont:new_type_u(960, {-100, 0}) % \pi
mathfont:new_type_u(961, {-50, 0})  % \rho
mathfont:new_type_u(963, {-100, 0}) % \sigma
mathfont:new_type_u(964, {-100, 0}) % \tau
mathfont:new_type_u(965, {-50, 0})  % \upsilon
mathfont:new_type_u(981, {0, 0})    % \phi
mathfont:new_type_u(967, {-50, 0})  % \chi
mathfont:new_type_u(968, {-50, 0})  % \psi
mathfont:new_type_u(969, {0, 0})    % \omega
mathfont:new_type_u(976, {0, 0})    % \varbeta
mathfont:new_type_u(949, {-50, 0})  % \varepsilon
mathfont:new_type_u(977, {50, 0})   % \vartheta
mathfont:new_type_u(1009, {-50, 0}) % \varrho
mathfont:new_type_u(962, {-50, 0})  % \varsigma
mathfont:new_type_u(966, {0, 0})    % \varphi
%    \end{macrocode}
% Upper-case Greek characters. Same as previously.
%    \begin{macrocode}
mathfont:new_type_u(913, {0, 0})    % \Alpha
mathfont:new_type_u(914, {0, 0})    % \Beta
mathfont:new_type_u(915, {0, 0})    % \Gamma
mathfont:new_type_u(916, {0, 0})    % \Delta
mathfont:new_type_u(917, {0, 0})    % \Epsilon
mathfont:new_type_u(918, {0, 0})    % \Zeta
mathfont:new_type_u(919, {0, 0})    % \Eta
mathfont:new_type_u(920, {0, 0})    % \Theta
mathfont:new_type_u(921, {0, 0})    % \Iota
mathfont:new_type_u(922, {0, 0})    % \Kappa
mathfont:new_type_u(923, {0, 0})    % \Lambda
mathfont:new_type_u(924, {0, 0})    % \Mu
mathfont:new_type_u(925, {0, 0})    % \Nu
mathfont:new_type_u(926, {0, 0})    % \Xi
mathfont:new_type_u(927, {0, 0})    % \Omicron
mathfont:new_type_u(928, {0, 0})    % \Pi
mathfont:new_type_u(929, {0, 0})    % \Rho
mathfont:new_type_u(931, {0, 0})    % \Sigma
mathfont:new_type_u(932, {0, 0})    % \Tau
mathfont:new_type_u(933, {0, 0})    % \Upsilon
mathfont:new_type_u(934, {0, 0})    % \Phi
mathfont:new_type_u(935, {0, 0})    % \Chi
mathfont:new_type_u(936, {0, 0})    % \Psi
mathfont:new_type_u(937, {0, 0})    % \Omega
mathfont:new_type_u(1012, {0, 0})   % \varTheta
%    \end{macrocode}
% We add the charm information for delimiters and other resizable characters. We divide the characters into four categories depending on how we want to magnify the base glyph to create large variants: delimiters, big operators, vertical characters, and the integral sign. We automate the process by putting charm information for each category of character into a separate table and feeding the whole thing to a wrapper around |:new_type_e|.
%    \begin{macrocode}
local delim_glyphs = {40, % (
  41,      % )
  47,      % /
  91,      % [
  92,      % backslash
  93,      % ]
  123,     % {
  125,     % }
  8249,    % \lguil
  8250,    % \rguil
  171,     % \llguil
  187,     % \rrguil
  1044508, % \fakelangle
  1044509, % \fakerangle
  1044510, % \fakellangle
  1044511} % \fakerrangle
local big_op_glyphs = {33, % !
  35,      % #
  36,      % $
  37,      % %
  38,      % &
  43,      % +
  63,      % ?
  64,      % @
  167,     % \S
  215,     % \times
  247,     % \div
  8719,    % \prod
  8721,    % \sum
  8720,    % \coprod
  8897,    % \bigvee
  8896,    % \bigwedge
  8899,    % \bigcup
  8898,    % \bigcap
  10753,   % \bigoplus
  10754,   % \bigotimes
  10752,   % \bigodot
  10757,   % \bigsqcap
  10758}   % \bigsqcup
local vert_glyphs = {124, 8730} % | and \surd
local int_glyphs = {8747, % \intop
  8748,    % \iint
  8749,    % \iiint
  8750,    % \oint
  8751,    % \oiint
  8752}    % \oiiint
%    \end{macrocode}
% The variable |smash| will keep track of the unicode index used to store the smashed version of the character. 
%    \begin{macrocode}
local smash = 1044544
%    \end{macrocode}
% Each category of type |e| character will have its own table of charm information with different magnification values. each table is initially empty.
%    \begin{macrocode}
local delim_scale = {}
local big_op_scale = {}
local vert_scale = {}
local int_scale = {}
%    \end{macrocode}
% Populate each table with magnification information. For every type |e| character we will create fifteen larger variants in the font. Delimiters stretch mostly vertically and some horzontally. Vertical characters stretch vertically only, so their horizontal scale factors are all constant. Big operators stretch the same in vertical and horizoontal directions.
%    \begin{macrocode}
for i = 1, 15, 1 do
  delim_scale[2*i-1] = 1000 + 100*i  % delimiters - horizontal
  delim_scale[2*i] = 1000 + 500*i    % delimiters - vertical
  vert_scale[2*i-1] = 1000
  vert_scale[2*i] = 1000 + 500*i     % vertically scaled chars
  big_op_scale[2*i-1] = 1000 + 100*i % big operators - horizontal
  big_op_scale[2*i] = 1000 + 100*i   % big operators - vertical
%    \end{macrocode}
% The integral sign is particular. Visually, we would like an integral symbol that is larger than the large operators, which means that the integral sign should have no variants between the font's value of |\Umathoperatorsize| and the desired larger size. Accordingly, I decided it would be easiest to have large variants of the integral sign jump by large enough scale factors that the smallest variant larger than the regular size is already significantly larger than the |\Umathoperatorsize| setting in |populate_math_constants|. Effectively this means that the user should take the size of the integral operator as fixed and should set |\Umathoperatorsize| to make all other big operators the desired size.
%    \begin{macrocode}
  int_scale[2*i-1] = 1000 + 500*i    % integral sign - horizontal
  int_scale[2*i] = 1000 + 1500*i     % integral sign - vertical
end
%    \end{macrocode}
% We do not modify accent placement.
%    \begin{macrocode} 
delim_scale[31] = 0
delim_scale[32] = 0
big_op_scale[31] = 0
big_op_scale[32] = 0
vert_scale[31] = 0
vert_scale[32] = 0
int_scale[31] = 0
int_scale[32] = 0
%    \end{macrocode}
% The wrapper for |:new_type_e|. We feed it the index to use for the smashed base character, a list of characters to create charm information for, and a table of scaling information.
%    \begin{macrocode}
function mathfont:add_extensible_variants(first_smash, glyph_list,
    scale_list)
  local variants = (\string# scale_list - 2) / 2
  local curr_smash = first_smash
  for i = 1, \string# glyph_list, 1 do
    local curr_char = glyph_list[i]
%    \end{macrocode}
% The |curr_slots| list will hold the base-10 unicode index values of each larger variant of the base character. We will take a number of unicode slots following the smashed character equal to the number of large variants we want to create, which we stored in |variants|.
%    \begin{macrocode}
    local curr_slots = {}
    for j = 1, variants, 1 do
      curr_slots[j] = curr_smash + j
    end
%    \end{macrocode}
% Add the charm information and increment |smash|.
%    \begin{macrocode}
    self:new_type_e(curr_char, curr_smash, curr_slots, scale_list)
    smash = smash + variants + 1
    curr_smash = smash
  end
end
%    \end{macrocode}
% Add the charm information for the type |e| characters.
%    \begin{macrocode}
mathfont:add_extensible_variants(smash, delim_glyphs, delim_scale)
mathfont:add_extensible_variants(smash,big_op_glyphs,big_op_scale)
mathfont:add_extensible_variants(smash, vert_glyphs, vert_scale)
mathfont:add_extensible_variants(smash, int_glyphs, int_scale)
%    \end{macrocode}
% Finally, end the call to |\directlua| and balance the preceeding conditional.
%    \begin{macrocode}
}
\fi % matches previous \ifM@adjust@font
%    \end{macrocode}
% 
% 
% 
% 
% \section{Unicode Hex Values}
% 
% We make aliases for |\DeclareMathAccent| and |\DeclareMathSymbol| to save space.
%    \begin{macrocode}
\let\@DMA\DeclareMathAccent
\let\@DMS\DeclareMathSymbol
\@onlypreamble\@DMA
\@onlypreamble\@DMS
%    \end{macrocode}
% Set upper-case Latin characters. We use an |\edef| for |\M@upper@font| because
% every expansion now will save \LaTeX\ twenty-six expansions later when it 
% evaluates each |\DeclareMathSymbol|. If the user has enabled Lua font adjustments, we set the math codes to be the large values from the Supplemental Private Use Area-A.\indexpage{keywordupper=keyword \texttt{upper}}%
%    \begin{macrocode}
\ifM@adjust@font
  \def\M@upper@set{%
    \edef\M@upper@font{M\M@uppershape\@tempa}
    \@DMS{A}{\mathalpha}{\M@upper@font}{1044512}
    \@DMS{B}{\mathalpha}{\M@upper@font}{1044513}
    \@DMS{C}{\mathalpha}{\M@upper@font}{1044514}
    \@DMS{D}{\mathalpha}{\M@upper@font}{1044515}
    \@DMS{E}{\mathalpha}{\M@upper@font}{1044516}
    \@DMS{F}{\mathalpha}{\M@upper@font}{1044517}
    \@DMS{G}{\mathalpha}{\M@upper@font}{1044518}
    \@DMS{H}{\mathalpha}{\M@upper@font}{1044519}
    \@DMS{I}{\mathalpha}{\M@upper@font}{1044520}
    \@DMS{J}{\mathalpha}{\M@upper@font}{1044521}
    \@DMS{K}{\mathalpha}{\M@upper@font}{1044522}
    \@DMS{L}{\mathalpha}{\M@upper@font}{1044523}
    \@DMS{M}{\mathalpha}{\M@upper@font}{1044524}
    \@DMS{N}{\mathalpha}{\M@upper@font}{1044525}
    \@DMS{O}{\mathalpha}{\M@upper@font}{1044526}
    \@DMS{P}{\mathalpha}{\M@upper@font}{1044527}
    \@DMS{Q}{\mathalpha}{\M@upper@font}{1044528}
    \@DMS{R}{\mathalpha}{\M@upper@font}{1044529}
    \@DMS{S}{\mathalpha}{\M@upper@font}{1044530}
    \@DMS{T}{\mathalpha}{\M@upper@font}{1044531}
    \@DMS{U}{\mathalpha}{\M@upper@font}{1044532}
    \@DMS{V}{\mathalpha}{\M@upper@font}{1044533}
    \@DMS{W}{\mathalpha}{\M@upper@font}{1044534}
    \@DMS{X}{\mathalpha}{\M@upper@font}{1044535}
    \@DMS{Y}{\mathalpha}{\M@upper@font}{1044536}
    \@DMS{Z}{\mathalpha}{\M@upper@font}{1044537}}
\else
  \def\M@upper@set{%
    \edef\M@upper@font{M\M@uppershape\@tempa}
    \@DMS{A}{\mathalpha}{\M@upper@font}{`A}
    \@DMS{B}{\mathalpha}{\M@upper@font}{`B}
    \@DMS{C}{\mathalpha}{\M@upper@font}{`C}
    \@DMS{D}{\mathalpha}{\M@upper@font}{`D}
    \@DMS{E}{\mathalpha}{\M@upper@font}{`E}
    \@DMS{F}{\mathalpha}{\M@upper@font}{`F}
    \@DMS{G}{\mathalpha}{\M@upper@font}{`G}
    \@DMS{H}{\mathalpha}{\M@upper@font}{`H}
    \@DMS{I}{\mathalpha}{\M@upper@font}{`I}
    \@DMS{J}{\mathalpha}{\M@upper@font}{`J}
    \@DMS{K}{\mathalpha}{\M@upper@font}{`K}
    \@DMS{L}{\mathalpha}{\M@upper@font}{`L}
    \@DMS{M}{\mathalpha}{\M@upper@font}{`M}
    \@DMS{N}{\mathalpha}{\M@upper@font}{`N}
    \@DMS{O}{\mathalpha}{\M@upper@font}{`O}
    \@DMS{P}{\mathalpha}{\M@upper@font}{`P}
    \@DMS{Q}{\mathalpha}{\M@upper@font}{`Q}
    \@DMS{R}{\mathalpha}{\M@upper@font}{`R}
    \@DMS{S}{\mathalpha}{\M@upper@font}{`S}
    \@DMS{T}{\mathalpha}{\M@upper@font}{`T}
    \@DMS{U}{\mathalpha}{\M@upper@font}{`U}
    \@DMS{V}{\mathalpha}{\M@upper@font}{`V}
    \@DMS{W}{\mathalpha}{\M@upper@font}{`W}
    \@DMS{X}{\mathalpha}{\M@upper@font}{`X}
    \@DMS{Y}{\mathalpha}{\M@upper@font}{`Y}
    \@DMS{Z}{\mathalpha}{\M@upper@font}{`Z}}
\fi
%    \end{macrocode}
% Set lower-case Latin characters.\indexpage{keywordlower=keyword \texttt{lower}}
%    \begin{macrocode}
\ifM@adjust@font
  \def\M@lower@set{%
    \edef\M@lower@font{M\M@lowershape\@tempa}
    \@DMS{a}{\mathalpha}{\M@lower@font}{1044480}
    \@DMS{b}{\mathalpha}{\M@lower@font}{1044481}
    \@DMS{c}{\mathalpha}{\M@lower@font}{1044482}
    \@DMS{d}{\mathalpha}{\M@lower@font}{1044483}
    \@DMS{e}{\mathalpha}{\M@lower@font}{1044484}
    \@DMS{f}{\mathalpha}{\M@lower@font}{1044485}
    \@DMS{g}{\mathalpha}{\M@lower@font}{1044486}
    \@DMS{h}{\mathalpha}{\M@lower@font}{1044487}
    \@DMS{i}{\mathalpha}{\M@lower@font}{1044488}
    \@DMS{j}{\mathalpha}{\M@lower@font}{1044489}
    \@DMS{k}{\mathalpha}{\M@lower@font}{1044490}
    \@DMS{l}{\mathalpha}{\M@lower@font}{1044491}
    \@DMS{m}{\mathalpha}{\M@lower@font}{1044492}
    \@DMS{n}{\mathalpha}{\M@lower@font}{1044493}
    \@DMS{o}{\mathalpha}{\M@lower@font}{1044494}
    \@DMS{p}{\mathalpha}{\M@lower@font}{1044495}
    \@DMS{q}{\mathalpha}{\M@lower@font}{1044496}
    \@DMS{r}{\mathalpha}{\M@lower@font}{1044497}
    \@DMS{s}{\mathalpha}{\M@lower@font}{1044498}
    \@DMS{t}{\mathalpha}{\M@lower@font}{1044499}
    \@DMS{u}{\mathalpha}{\M@lower@font}{1044500}
    \@DMS{v}{\mathalpha}{\M@lower@font}{1044501}
    \@DMS{w}{\mathalpha}{\M@lower@font}{1044502}
    \@DMS{x}{\mathalpha}{\M@lower@font}{1044503}
    \@DMS{y}{\mathalpha}{\M@lower@font}{1044504}
    \@DMS{z}{\mathalpha}{\M@lower@font}{1044505}
    \@DMS{\imath}{\mathalpha}{\M@lower@font}{1044506}
    \@DMS{\jmath}{\mathalpha}{\M@lower@font}{1044507}
    \@DMS{\hbar}{\mathord}{\M@lower@font}{"127}}
\else
  \def\M@lower@set{%
    \edef\M@lower@font{M\M@lowershape\@tempa}
    \@DMS{a}{\mathalpha}{\M@lower@font}{`a}
    \@DMS{b}{\mathalpha}{\M@lower@font}{`b}
    \@DMS{c}{\mathalpha}{\M@lower@font}{`c}
    \@DMS{d}{\mathalpha}{\M@lower@font}{`d}
    \@DMS{e}{\mathalpha}{\M@lower@font}{`e}
    \@DMS{f}{\mathalpha}{\M@lower@font}{`f}
    \@DMS{g}{\mathalpha}{\M@lower@font}{`g}
    \@DMS{h}{\mathalpha}{\M@lower@font}{`h}
    \@DMS{i}{\mathalpha}{\M@lower@font}{`i}
    \@DMS{j}{\mathalpha}{\M@lower@font}{`j}
    \@DMS{k}{\mathalpha}{\M@lower@font}{`k}
    \@DMS{l}{\mathalpha}{\M@lower@font}{`l}
    \@DMS{m}{\mathalpha}{\M@lower@font}{`m}
    \@DMS{n}{\mathalpha}{\M@lower@font}{`n}
    \@DMS{o}{\mathalpha}{\M@lower@font}{`o}
    \@DMS{p}{\mathalpha}{\M@lower@font}{`p}
    \@DMS{q}{\mathalpha}{\M@lower@font}{`q}
    \@DMS{r}{\mathalpha}{\M@lower@font}{`r}
    \@DMS{s}{\mathalpha}{\M@lower@font}{`s}
    \@DMS{t}{\mathalpha}{\M@lower@font}{`t}
    \@DMS{u}{\mathalpha}{\M@lower@font}{`u}
    \@DMS{v}{\mathalpha}{\M@lower@font}{`v}
    \@DMS{w}{\mathalpha}{\M@lower@font}{`w}
    \@DMS{x}{\mathalpha}{\M@lower@font}{`x}
    \@DMS{y}{\mathalpha}{\M@lower@font}{`y}
    \@DMS{z}{\mathalpha}{\M@lower@font}{`z}
    \@DMS{\imath}{\mathalpha}{\M@lower@font}{"131}
    \@DMS{\jmath}{\mathalpha}{\M@lower@font}{"237}
    \@DMS{\hbar}{\mathord}{\M@lower@font}{"127}}
\fi
%    \end{macrocode}
% Set diacritics.\indexpage{keyworddiacritics=keyword \texttt{diacritics}}
%    \begin{macrocode}
\def\M@diacritics@set{%
  \edef\M@diacritics@font{M\M@diacriticsshape\@tempa}
  \@DMA{\acute}   {\mathalpha}{\M@diacritics@font}{"B4}
  \@DMA{\aacute}  {\mathalpha}{\M@diacritics@font}{"2DD}
  \@DMA{\dot}     {\mathalpha}{\M@diacritics@font}{"2D9}
  \@DMA{\ddot}    {\mathalpha}{\M@diacritics@font}{"A8}
  \@DMA{\grave}   {\mathalpha}{\M@diacritics@font}{"60}
  \@DMA{\breve}   {\mathalpha}{\M@diacritics@font}{"2D8}
  \@DMA{\hat}     {\mathalpha}{\M@diacritics@font}{"2C6}
  \@DMA{\check}   {\mathalpha}{\M@diacritics@font}{"2C7}
  \@DMA{\bar}     {\mathalpha}{\M@diacritics@font}{"2C9}
  \@DMA{\mathring}{\mathalpha}{\M@diacritics@font}{"2DA}
  \@DMA{\tilde}   {\mathalpha}{\M@diacritics@font}{"2DC}}
%    \end{macrocode}
% Set capital Greek characters. We undefine |\Chi| because \textsf{math-operator} defines it to be the hyperbolic cosine integral function.\indexpage{keywordgreeklower=keyword \texttt{greekupper}}
%    \begin{macrocode}
\def\M@greekupper@set{%
  \edef\M@greekupper@font{M\M@greekuppershape\@tempa}
  \let\Chi\@undefined
  \@DMS{\Alpha}   {\mathalpha}{\M@greekupper@font}{"391}
  \@DMS{\Beta}    {\mathalpha}{\M@greekupper@font}{"392}
  \@DMS{\Gamma}   {\mathalpha}{\M@greekupper@font}{"393}
  \@DMS{\Delta}   {\mathalpha}{\M@greekupper@font}{"394}
  \@DMS{\Epsilon} {\mathalpha}{\M@greekupper@font}{"395}
  \@DMS{\Zeta}    {\mathalpha}{\M@greekupper@font}{"396}
  \@DMS{\Eta}     {\mathalpha}{\M@greekupper@font}{"397}
  \@DMS{\Theta}   {\mathalpha}{\M@greekupper@font}{"398}
  \@DMS{\Iota}    {\mathalpha}{\M@greekupper@font}{"399}
  \@DMS{\Kappa}   {\mathalpha}{\M@greekupper@font}{"39A}
  \@DMS{\Lambda}  {\mathalpha}{\M@greekupper@font}{"39B}
  \@DMS{\Mu}      {\mathalpha}{\M@greekupper@font}{"39C}
  \@DMS{\Nu}      {\mathalpha}{\M@greekupper@font}{"39D}
  \@DMS{\Xi}      {\mathalpha}{\M@greekupper@font}{"39E}
  \@DMS{\Omicron} {\mathalpha}{\M@greekupper@font}{"39F}
  \@DMS{\Pi}      {\mathalpha}{\M@greekupper@font}{"3A0}
  \@DMS{\Rho}     {\mathalpha}{\M@greekupper@font}{"3A1}
  \@DMS{\Sigma}   {\mathalpha}{\M@greekupper@font}{"3A3}
  \@DMS{\Tau}     {\mathalpha}{\M@greekupper@font}{"3A4}
  \@DMS{\Upsilon} {\mathalpha}{\M@greekupper@font}{"3A5}
  \@DMS{\Phi}     {\mathalpha}{\M@greekupper@font}{"3A6}
  \@DMS{\Chi}     {\mathalpha}{\M@greekupper@font}{"3A7}
  \@DMS{\Psi}     {\mathalpha}{\M@greekupper@font}{"3A8}
  \@DMS{\Omega}   {\mathalpha}{\M@greekupper@font}{"3A9}
  \@DMS{\varTheta}{\mathalpha}{\M@greekupper@font}{"3F4}
%    \end{macrocode}
% Declare |\increment| and |\nabla| if they haven't already been declared in the |symbols| or |extsymbols| fonts.
%    \begin{macrocode}
  \ifM@adjust@font
    \ifM@symbols\else
      \@DMS{\increment}
        {\mathord}{\M@greekupper@font}{"2206}
      \@DMS{\nabla}
        {\mathord}{\M@greekupper@font}{"2207}
    \fi
  \else
    \ifM@symbols\else
      \@DMS{\increment}
        {\mathord}{\M@greekupper@font}{"2206}
    \fi
    \ifM@extsymbols\else
      \@DMS{\nabla}
        {\mathord}{\M@greekupper@font}{"2207}
    \fi
  \fi}
%    \end{macrocode}
% Set minuscule Greek characters.\indexpage{keywordgreeklower=keyword \texttt{greeklower}}
%    \begin{macrocode}
\def\M@greeklower@set{%
  \edef\M@greeklower@font{M\M@greeklowershape\@tempa}
  \@DMS{\alpha}     {\mathalpha}{\M@greeklower@font}{"3B1}
  \@DMS{\beta}      {\mathalpha}{\M@greeklower@font}{"3B2}
  \@DMS{\gamma}     {\mathalpha}{\M@greeklower@font}{"3B3}
  \@DMS{\delta}     {\mathalpha}{\M@greeklower@font}{"3B4}
  \@DMS{\epsilon}   {\mathalpha}{\M@greeklower@font}{"3B5}
  \@DMS{\zeta}      {\mathalpha}{\M@greeklower@font}{"3B6}
  \@DMS{\eta}       {\mathalpha}{\M@greeklower@font}{"3B7}
  \@DMS{\theta}     {\mathalpha}{\M@greeklower@font}{"3B8}
  \@DMS{\iota}      {\mathalpha}{\M@greeklower@font}{"3B9}
  \@DMS{\kappa}     {\mathalpha}{\M@greeklower@font}{"3BA}
  \@DMS{\lambda}    {\mathalpha}{\M@greeklower@font}{"3BB}
  \@DMS{\mu}        {\mathalpha}{\M@greeklower@font}{"3BC}
  \@DMS{\nu}        {\mathalpha}{\M@greeklower@font}{"3BD}
  \@DMS{\xi}        {\mathalpha}{\M@greeklower@font}{"3BE}
  \@DMS{\omicron}   {\mathalpha}{\M@greeklower@font}{"3BF}
  \@DMS{\pi}        {\mathalpha}{\M@greeklower@font}{"3C0}
  \@DMS{\rho}       {\mathalpha}{\M@greeklower@font}{"3C1}
  \@DMS{\sigma}     {\mathalpha}{\M@greeklower@font}{"3C3}
  \@DMS{\tau}       {\mathalpha}{\M@greeklower@font}{"3C4}
  \@DMS{\upsilon}   {\mathalpha}{\M@greeklower@font}{"3C5}
  \@DMS{\phi}       {\mathalpha}{\M@greeklower@font}{"3C6}
  \@DMS{\chi}       {\mathalpha}{\M@greeklower@font}{"3C7}
  \@DMS{\psi}       {\mathalpha}{\M@greeklower@font}{"3C8}
  \@DMS{\omega}     {\mathalpha}{\M@greeklower@font}{"3C9}
  \@DMS{\varbeta}   {\mathalpha}{\M@greeklower@font}{"3D0}
  \@DMS{\varepsilon}{\mathalpha}{\M@greeklower@font}{"3F5}
  \@DMS{\varkappa}  {\mathalpha}{\M@greeklower@font}{"3F0}
  \@DMS{\vartheta}  {\mathalpha}{\M@greeklower@font}{"3D1}
  \@DMS{\varrho}    {\mathalpha}{\M@greeklower@font}{"3F1}
  \@DMS{\varsigma}  {\mathalpha}{\M@greeklower@font}{"3C2}
  \@DMS{\varphi}    {\mathalpha}{\M@greeklower@font}{"3D5}}
%    \end{macrocode}
% Set capital ancient Greek characters.\indexpage{keywordagreekupper=keyword \texttt{agreekupper}}
%    \begin{macrocode}
\def\M@agreekupper@set{%
  \edef\M@agreekupper@font{M\M@agreekuppershape\@tempa}
  \@DMS{\Heta}      {\mathalpha}{\M@agreekupper@font}{"370}
  \@DMS{\Sampi}     {\mathalpha}{\M@agreekupper@font}{"3E0}
  \@DMS{\Digamma}   {\mathalpha}{\M@agreekupper@font}{"3DC}
  \@DMS{\Koppa}     {\mathalpha}{\M@agreekupper@font}{"3D8}
  \@DMS{\Stigma}    {\mathalpha}{\M@agreekupper@font}{"3DA}
  \@DMS{\Sho}       {\mathalpha}{\M@agreekupper@font}{"3F7}
  \@DMS{\San}       {\mathalpha}{\M@agreekupper@font}{"3FA}
  \@DMS{\varSampi}  {\mathalpha}{\M@agreekupper@font}{"372}
  \@DMS{\varDigamma}{\mathalpha}{\M@agreekupper@font}{"376}
  \@DMS{\varKoppa}  {\mathalpha}{\M@agreekupper@font}{"3DE}}
%    \end{macrocode}
% Set minuscule ancient Greek characters.\indexpage{keywordagreeklower=keyword \texttt{agreeklower}}
%    \begin{macrocode}
\def\M@agreeklower@set{%
  \edef\M@agreeklower@font{M\M@agreeklowershape\@tempa}
  \@DMS{\heta}      {\mathalpha}{\M@agreeklower@font}{"371}
  \@DMS{\sampi}     {\mathalpha}{\M@agreeklower@font}{"3E1}
  \@DMS{\digamma}   {\mathalpha}{\M@agreeklower@font}{"3DD}
  \@DMS{\koppa}     {\mathalpha}{\M@agreeklower@font}{"3D9}
  \@DMS{\stigma}    {\mathalpha}{\M@agreeklower@font}{"3DB}
  \@DMS{\sho}       {\mathalpha}{\M@agreeklower@font}{"3F8}
  \@DMS{\san}       {\mathalpha}{\M@agreeklower@font}{"3FB}
  \@DMS{\varsampi}  {\mathalpha}{\M@agreeklower@font}{"373}
  \@DMS{\vardigamma}{\mathalpha}{\M@agreeklower@font}{"377}
  \@DMS{\varkoppa}  {\mathalpha}{\M@agreeklower@font}{"3DF}}
%    \end{macrocode}
% Set capital Cyrillic characters.\indexpage{keywordcyrillicupper=keyword \texttt{cyrillicupper}}
%    \begin{macrocode}
\def\M@cyrillicupper@set{%
  \edef\M@cyrillicupper@font{M\M@cyrillicuppershape\@tempa}
  \@DMS{\cyrA}    {\mathalpha}{\M@cyrillicupper@font}{"410}
  \@DMS{\cyrBe}   {\mathalpha}{\M@cyrillicupper@font}{"411}
  \@DMS{\cyrVe}   {\mathalpha}{\M@cyrillicupper@font}{"412}
  \@DMS{\cyrGhe}  {\mathalpha}{\M@cyrillicupper@font}{"413}
  \@DMS{\cyrDe}   {\mathalpha}{\M@cyrillicupper@font}{"414}
  \@DMS{\cyrIe}   {\mathalpha}{\M@cyrillicupper@font}{"415}
  \@DMS{\cyrZhe}  {\mathalpha}{\M@cyrillicupper@font}{"416}
  \@DMS{\cyrZe}   {\mathalpha}{\M@cyrillicupper@font}{"417}
  \@DMS{\cyrI}    {\mathalpha}{\M@cyrillicupper@font}{"418}
  \@DMS{\cyrKa}   {\mathalpha}{\M@cyrillicupper@font}{"41A}
  \@DMS{\cyrEl}   {\mathalpha}{\M@cyrillicupper@font}{"41B}
  \@DMS{\cyrEm}   {\mathalpha}{\M@cyrillicupper@font}{"41C}
  \@DMS{\cyrEn}   {\mathalpha}{\M@cyrillicupper@font}{"41D}
  \@DMS{\cyrO}    {\mathalpha}{\M@cyrillicupper@font}{"41E}
  \@DMS{\cyrPe}   {\mathalpha}{\M@cyrillicupper@font}{"41F}
  \@DMS{\cyrEr}   {\mathalpha}{\M@cyrillicupper@font}{"420}
  \@DMS{\cyrEs}   {\mathalpha}{\M@cyrillicupper@font}{"421}
  \@DMS{\cyrTe}   {\mathalpha}{\M@cyrillicupper@font}{"422}
  \@DMS{\cyrU}    {\mathalpha}{\M@cyrillicupper@font}{"423}
  \@DMS{\cyrEf}   {\mathalpha}{\M@cyrillicupper@font}{"424}
  \@DMS{\cyrHa}   {\mathalpha}{\M@cyrillicupper@font}{"425}
  \@DMS{\cyrTse}  {\mathalpha}{\M@cyrillicupper@font}{"426}
  \@DMS{\cyrChe}  {\mathalpha}{\M@cyrillicupper@font}{"427}
  \@DMS{\cyrSha}  {\mathalpha}{\M@cyrillicupper@font}{"428}
  \@DMS{\cyrShcha}{\mathalpha}{\M@cyrillicupper@font}{"429}
  \@DMS{\cyrHard} {\mathalpha}{\M@cyrillicupper@font}{"42A}
  \@DMS{\cyrYeru} {\mathalpha}{\M@cyrillicupper@font}{"42B}
  \@DMS{\cyrSoft} {\mathalpha}{\M@cyrillicupper@font}{"42C}
  \@DMS{\cyrE}    {\mathalpha}{\M@cyrillicupper@font}{"42D}
  \@DMS{\cyrYu}   {\mathalpha}{\M@cyrillicupper@font}{"42E}
  \@DMS{\cyrYa}   {\mathalpha}{\M@cyrillicupper@font}{"42F}
  \@DMS{\cyrvarI} {\mathalpha}{\M@cyrillicupper@font}{"419}}
%    \end{macrocode}
% Set minuscule Cyrillic characters.\indexpage{keywordcyrilliclower=keyword \texttt{cyrilliclower}}
%    \begin{macrocode}
\def\M@cyrilliclower@set{%
  \edef\M@cyrilliclower@font{M\M@cyrilliclowershape\@tempa}
  \@DMS{\cyra}    {\mathalpha}{\M@cyrilliclower@font}{"430}
  \@DMS{\cyrbe}   {\mathalpha}{\M@cyrilliclower@font}{"431}
  \@DMS{\cyrve}   {\mathalpha}{\M@cyrilliclower@font}{"432}
  \@DMS{\cyrghe}  {\mathalpha}{\M@cyrilliclower@font}{"433}
  \@DMS{\cyrde}   {\mathalpha}{\M@cyrilliclower@font}{"434}
  \@DMS{\cyrie}   {\mathalpha}{\M@cyrilliclower@font}{"435}
  \@DMS{\cyrzhe}  {\mathalpha}{\M@cyrilliclower@font}{"436}
  \@DMS{\cyrze}   {\mathalpha}{\M@cyrilliclower@font}{"437}
  \@DMS{\cyri}    {\mathalpha}{\M@cyrilliclower@font}{"438}
  \@DMS{\cyrka}   {\mathalpha}{\M@cyrilliclower@font}{"43A}
  \@DMS{\cyrel}   {\mathalpha}{\M@cyrilliclower@font}{"43B}
  \@DMS{\cyrem}   {\mathalpha}{\M@cyrilliclower@font}{"43C}
  \@DMS{\cyren}   {\mathalpha}{\M@cyrilliclower@font}{"43D}
  \@DMS{\cyro}    {\mathalpha}{\M@cyrilliclower@font}{"43E}
  \@DMS{\cyrpe}   {\mathalpha}{\M@cyrilliclower@font}{"43F}
  \@DMS{\cyrer}   {\mathalpha}{\M@cyrilliclower@font}{"440}
  \@DMS{\cyres}   {\mathalpha}{\M@cyrilliclower@font}{"441}
  \@DMS{\cyrte}   {\mathalpha}{\M@cyrilliclower@font}{"442}
  \@DMS{\cyru}    {\mathalpha}{\M@cyrilliclower@font}{"443}
  \@DMS{\cyref}   {\mathalpha}{\M@cyrilliclower@font}{"444}
  \@DMS{\cyrha}   {\mathalpha}{\M@cyrilliclower@font}{"445}
  \@DMS{\cyrtse}  {\mathalpha}{\M@cyrilliclower@font}{"446}
  \@DMS{\cyrche}  {\mathalpha}{\M@cyrilliclower@font}{"447}
  \@DMS{\cyrsha}  {\mathalpha}{\M@cyrilliclower@font}{"448}
  \@DMS{\cyrshcha}{\mathalpha}{\M@cyrilliclower@font}{"449}
  \@DMS{\cyrhard} {\mathalpha}{\M@cyrilliclower@font}{"44A}
  \@DMS{\cyryeru} {\mathalpha}{\M@cyrilliclower@font}{"44B}
  \@DMS{\cyrsoft} {\mathalpha}{\M@cyrilliclower@font}{"44C}
  \@DMS{\cyre}    {\mathalpha}{\M@cyrilliclower@font}{"44D}
  \@DMS{\cyryu}   {\mathalpha}{\M@cyrilliclower@font}{"44E}
  \@DMS{\cyrya}   {\mathalpha}{\M@cyrilliclower@font}{"44F}
  \@DMS{\cyrvari} {\mathalpha}{\M@cyrilliclower@font}{"439}}
%    \end{macrocode}
% Set Hebrew characters.\indexpage{keywordhebrew=keyword \texttt{hebrew}}
%    \begin{macrocode}
\def\M@hebrew@set{%
  \edef\M@hebrew@font{M\M@hebrewshape\@tempa}
  \@DMS{\aleph}   {\mathalpha}{\M@hebrew@font}{"5D0}
  \@DMS{\beth}    {\mathalpha}{\M@hebrew@font}{"5D1}
  \@DMS{\gimel}   {\mathalpha}{\M@hebrew@font}{"5D2}
  \@DMS{\daleth}  {\mathalpha}{\M@hebrew@font}{"5D3}
  \@DMS{\he}      {\mathalpha}{\M@hebrew@font}{"5D4}
  \@DMS{\vav}     {\mathalpha}{\M@hebrew@font}{"5D5}
  \@DMS{\zayin}   {\mathalpha}{\M@hebrew@font}{"5D6}
  \@DMS{\het}     {\mathalpha}{\M@hebrew@font}{"5D7}
  \@DMS{\tet}     {\mathalpha}{\M@hebrew@font}{"5D8}
  \@DMS{\yod}     {\mathalpha}{\M@hebrew@font}{"5D9}
  \@DMS{\kaf}     {\mathalpha}{\M@hebrew@font}{"5DB}
  \@DMS{\lamed}   {\mathalpha}{\M@hebrew@font}{"5DC}
  \@DMS{\mem}     {\mathalpha}{\M@hebrew@font}{"5DE}
  \@DMS{\nun}     {\mathalpha}{\M@hebrew@font}{"5E0}
  \@DMS{\samekh}  {\mathalpha}{\M@hebrew@font}{"5E1}
  \@DMS{\ayin}    {\mathalpha}{\M@hebrew@font}{"5E2}
  \@DMS{\pe}      {\mathalpha}{\M@hebrew@font}{"5E4}
  \@DMS{\tsadi}   {\mathalpha}{\M@hebrew@font}{"5E6}
  \@DMS{\qof}     {\mathalpha}{\M@hebrew@font}{"5E7}
  \@DMS{\resh}    {\mathalpha}{\M@hebrew@font}{"5E8}
  \@DMS{\shin}    {\mathalpha}{\M@hebrew@font}{"5E9}
  \@DMS{\tav}     {\mathalpha}{\M@hebrew@font}{"5EA}
  \@DMS{\varkaf}  {\mathalpha}{\M@hebrew@font}{"5DA}
  \@DMS{\varmem}  {\mathalpha}{\M@hebrew@font}{"5DD}
  \@DMS{\varnun}  {\mathalpha}{\M@hebrew@font}{"5DF}
  \@DMS{\varpe}   {\mathalpha}{\M@hebrew@font}{"5E3}
  \@DMS{\vartsadi}{\mathalpha}{\M@hebrew@font}{"5E5}}
%    \end{macrocode}
% Set digits.\indexpage{keyworddigits=keyword \texttt{digits}}
%    \begin{macrocode}
\def\M@digits@set{%
  \edef\M@digits@font{M\M@digitsshape\@tempa}
  \@DMS{0}{\mathalpha}{\M@digits@font}{`0}
  \@DMS{1}{\mathalpha}{\M@digits@font}{`1}
  \@DMS{2}{\mathalpha}{\M@digits@font}{`2}
  \@DMS{3}{\mathalpha}{\M@digits@font}{`3}
  \@DMS{4}{\mathalpha}{\M@digits@font}{`4}
  \@DMS{5}{\mathalpha}{\M@digits@font}{`5}
  \@DMS{6}{\mathalpha}{\M@digits@font}{`6}
  \@DMS{7}{\mathalpha}{\M@digits@font}{`7}
  \@DMS{8}{\mathalpha}{\M@digits@font}{`8}
  \@DMS{9}{\mathalpha}{\M@digits@font}{`9}}
%    \end{macrocode}
% Set new operator font.\indexpage{keywordoperator=keyword \texttt{operator}}
% If \textsf{mathfont} is set to adjust fonts, we will have a problem when typesetting operators because the |\operator@font| will pull modified (lengthened) letters from the operator font. Traditional \TeX\ addressed this problem by storing the Latin letters for math in the same endoding slots but in a different font from Computer Modern Roman and switching to Computer Modern Roman. Here we want to use the same font but different encoding slots. The macro |\M@default@latin| changes all |\Umathcode|s of Latin letters from their big (lengthened) values to their original values. Because |\operator@font| is always called inside a group, we don't have to worry about messing up any other math.
%    \begin{macrocode}
\def\M@operator@set{%
  \ifM@adjust@font
    \edef\M@operator@num{\number
      \csname symM\M@operatorshape\@tempa\endcsname}
    \protected\edef\M@operator@mathcodes{%
      \Umathcode`A=7+\M@operator@num+`A\relax
      \Umathcode`B=7+\M@operator@num+`B\relax
      \Umathcode`C=7+\M@operator@num+`C\relax
      \Umathcode`D=7+\M@operator@num+`D\relax
      \Umathcode`E=7+\M@operator@num+`E\relax
      \Umathcode`F=7+\M@operator@num+`F\relax
      \Umathcode`G=7+\M@operator@num+`G\relax
      \Umathcode`H=7+\M@operator@num+`H\relax
      \Umathcode`I=7+\M@operator@num+`I\relax
      \Umathcode`J=7+\M@operator@num+`J\relax
      \Umathcode`K=7+\M@operator@num+`K\relax
      \Umathcode`L=7+\M@operator@num+`L\relax
      \Umathcode`M=7+\M@operator@num+`M\relax
      \Umathcode`N=7+\M@operator@num+`N\relax
      \Umathcode`O=7+\M@operator@num+`O\relax
      \Umathcode`P=7+\M@operator@num+`P\relax
      \Umathcode`Q=7+\M@operator@num+`Q\relax
      \Umathcode`R=7+\M@operator@num+`R\relax
      \Umathcode`S=7+\M@operator@num+`S\relax
      \Umathcode`T=7+\M@operator@num+`T\relax
      \Umathcode`U=7+\M@operator@num+`U\relax
      \Umathcode`V=7+\M@operator@num+`V\relax
      \Umathcode`W=7+\M@operator@num+`W\relax
      \Umathcode`X=7+\M@operator@num+`X\relax
      \Umathcode`Y=7+\M@operator@num+`Y\relax
      \Umathcode`Z=7+\M@operator@num+`Z\relax
      \Umathcode`a=7+\M@operator@num+`a\relax
      \Umathcode`b=7+\M@operator@num+`b\relax
      \Umathcode`c=7+\M@operator@num+`c\relax
      \Umathcode`d=7+\M@operator@num+`d\relax
      \Umathcode`e=7+\M@operator@num+`e\relax
      \Umathcode`f=7+\M@operator@num+`f\relax
      \Umathcode`g=7+\M@operator@num+`g\relax
      \Umathcode`h=7+\M@operator@num+`h\relax
      \Umathcode`i=7+\M@operator@num+`i\relax
      \Umathcode`j=7+\M@operator@num+`j\relax
      \Umathcode`k=7+\M@operator@num+`k\relax
      \Umathcode`l=7+\M@operator@num+`l\relax
      \Umathcode`m=7+\M@operator@num+`m\relax
      \Umathcode`n=7+\M@operator@num+`n\relax
      \Umathcode`o=7+\M@operator@num+`o\relax
      \Umathcode`p=7+\M@operator@num+`p\relax
      \Umathcode`q=7+\M@operator@num+`q\relax
      \Umathcode`r=7+\M@operator@num+`r\relax
      \Umathcode`s=7+\M@operator@num+`s\relax
      \Umathcode`t=7+\M@operator@num+`t\relax
      \Umathcode`u=7+\M@operator@num+`u\relax
      \Umathcode`v=7+\M@operator@num+`v\relax
      \Umathcode`w=7+\M@operator@num+`w\relax
      \Umathcode`x=7+\M@operator@num+`x\relax
      \Umathcode`y=7+\M@operator@num+`y\relax
      \Umathcode`z=7+\M@operator@num+`z\relax
      \Umathchardef\imath=7+\M@operator@num+1044506\relax
      \Umathchardef\jmath=7+\M@operator@num+1044500\relax}
  \else
    \let\M@operator@mathcodes\@empty
  \fi
%    \end{macrocode}
% Then we change the |\operator@font| definition and, if applicable, change the math codes.
%    \begin{macrocode}
  \xdef\operator@font{\mathgroup
    \csname symM\M@operatorshape\@tempa\endcsname
    \M@operator@mathcodes}}
%    \end{macrocode}
% Set delimiters.\indexpage{keyworddelimiters=keyword \texttt{delimiters}}
%    \begin{macrocode}
\ifM@adjust@font
  \def\M@delimiters@set{%
    \edef\M@delimiters@font{M\M@delimitersshape\@tempa}
    \edef\M@delimiters@num{%
      \csname sym\M@delimiters@font\endcsname}
    \@DMS{(}          {\mathopen} {\M@delimiters@font}{"28}
    \@DMS{)}          {\mathclose}{\M@delimiters@font}{"29}
    \@DMS{[}          {\mathopen} {\M@delimiters@font}{"5B}
    \@DMS{]}          {\mathclose}{\M@delimiters@font}{"5D}
    \@DMS{\leftbrace} {\mathopen}{\M@delimiters@font}{"7B}
    \@DMS{\rightbrace}{\mathclose}{\M@delimiters@font}{"7D}
%    \end{macrocode}
% Set |\Udelcode|s for delimiters that come from individual characters.
%    \begin{macrocode}
    \global\Udelcode40 +\M@delimiters@num+40\relax  % (
    \global\Udelcode41 +\M@delimiters@num+41\relax  % )
    \global\Udelcode47 +\M@delimiters@num+47\relax  % /
    \global\Udelcode91 +\M@delimiters@num+91\relax  % [
    \global\Udelcode93 +\M@delimiters@num+93\relax  % ]
    \global\Udelcode124+\M@delimiters@num+124\relax % |
    \ifM@symbols\else
      \@DMS{|}{\mathord}{\M@delimiters@font}{"7C}
    \fi
    \global\let\vert=|
%    \end{macrocode}
% For the delimiters that come from control sequences, we use |\xdef| and |\Udelimiter|.
%    \begin{macrocode}
    \protected\xdef\backslash{%
      \ifmmode\mathbackslash\else\textbackslash\fi}
    \protected\xdef\mathbackslash{%
      \Udelimiter+2+\M@delimiters@num+92\relax}
    \protected\xdef\lbrace{%
      \Udelimiter+4+\M@delimiters@num+123\relax}
    \protected\xdef\rbrace{%
      \Udelimiter+5+\M@delimiters@num+125\relax}
    \protected\xdef\lguil{%
      \Udelimiter+4+\M@delimiters@num+8249\relax}
    \protected\xdef\rguil{%
      \Udelimiter+5+\M@delimiters@num+8250\relax}
    \protected\xdef\llguil{%
      \Udelimiter+4+\M@delimiters@num+171\relax}
    \protected\xdef\rrguil{%
      \Udelimiter+5+\M@delimiters@num+187\relax}
    \protected\xdef\fakelangle{%
      \Udelimiter+4+\M@delimiters@num+1044508\relax}
    \protected\xdef\fakerangle{%
      \Udelimiter+5+\M@delimiters@num+1044509\relax}
    \protected\xdef\fakellangle{%
      \Udelimiter+4+\M@delimiters@num+1044510\relax}
    \protected\xdef\fakerrangle{%
      \Udelimiter+5+\M@delimiters@num+1044511\relax}}
\else
  \def\M@delimiters@set{%
    \edef\M@delimiters@font{M\M@delimitersshape\@tempa}
    \@DMS{(}          {\mathopen} {\M@delimiters@font}{"28}
    \@DMS{)}          {\mathclose}{\M@delimiters@font}{"29}
    \@DMS{[}          {\mathopen} {\M@delimiters@font}{"5B}
    \@DMS{]}          {\mathclose}{\M@delimiters@font}{"5D}
    \@DMS{\lguil}     {\mathopen} {\M@delimiters@font}{"2039}
    \@DMS{\rguil}     {\mathclose}{\M@delimiters@font}{"203A}
    \@DMS{\llguil}    {\mathopen} {\M@delimiters@font}{"AB}
    \@DMS{\rrguil}    {\mathclose}{\M@delimiters@font}{"BB}
    \@DMS{\leftbrace} {\mathopen} {\M@delimiters@font}{"7B}
    \@DMS{\rightbrace}{\mathclose}{\M@delimiters@font}{"7D}}
\fi
%    \end{macrocode}
% Radicals.\indexpage{keywordradical=keyword \texttt{radical}}
%    \begin{macrocode}
\ifM@adjust@font
  \def\M@radical@set{%
    \edef\M@radical@font{M\M@radicalshape\@tempa}
    \@DMS{\surd}{\mathord}{\M@radical@font}{"221A}
    \xdef\@sqrts@gn##1{\Uradical+\number
      \csname sym\M@radical@font\endcsname+8730\relax{##1}}
%    \end{macrocode}
% We redefine |\r@@t|, which typesets the degree symbol on an $n$th root. We set the placement so that right side of the box containing the degree lies 60\% of the horizontal distance across the surd symbol, and the baseline of the degree symbol is 60\% of the vertical distance up the surd.
% \indexpage{LaTeX kernel=\LaTeX\ kernel}
%    \begin{macrocode}
    \gdef\r@@t##1##2{%
      \setbox\z@\hbox{$\m@th##1\sqrtsign{##2}$}%
      \setbox\surdbox\hbox{$\m@th##1\@sqrts@gn{%
        \hbox{\vphantom{$\m@th##1##2$}}}$}
      \dimen@\ht\surdbox
      \advance\dimen@\dp\surdbox
      \dimen@=0.6\dimen@
      \advance\dimen@-\dp\surdbox
      \ifdim\wd\rootbox<0.6\wd\surdbox
        \kern0.6\wd\surdbox
      \else
        \kern\wd\rootbox
      \fi
      \raise\dimen@\hbox{\llap{\copy\rootbox}}
      \kern-0.6\wd\surdbox
      \box\z@}
    \gdef\sqrtsign##1{\@sqrts@gn{\mkern\radicandoffset##1}}}
\else
  \def\M@radical@set{%
    \edef\M@radical@font{M\M@radicalshape\@tempa}
    \@DMS{\surd}{\mathord}{\M@radical@font}{"221A}}
\fi
%    \end{macrocode}
% Big operators.\indexpage{keywordbigops=keyword \texttt{bigops}}
%    \begin{macrocode}
\def\M@bigops@set{%
  \edef\M@bigops@font{M\M@bigopsshape\@tempa}
  \let\sum\@undefined
  \let\prod\@undefined
  \@DMS{\sum}{\mathop}{\M@bigops@font}{"2211}
  \@DMS{\prod}{\mathop}{\M@bigops@font}{"220F}
  \@DMS{\intop}{\mathop}{\M@bigops@font}{"222B}}
%    \end{macrocode}
% Extended big operators.\indexpage{keywordextbigops=keyword \texttt{extbigops}}
%    \begin{macrocode}
\def\M@extbigops@set{%
  \edef\M@extbigops@font{M\M@extbigopsshape\@tempa}
  \let\coprod\@undefined
  \let\bigvee\@undefined
  \let\bigwedge\@undefined
  \let\bigcup\@undefined
  \let\bigcap\@undefined
  \let\bigoplus\@undefined
  \let\bigotimes\@undefined
  \let\bigodot\@undefined
  \let\bigsqcup\@undefined
  \@DMS{\coprod}   {\mathop}{\M@extbigops@font}{"2210}
  \@DMS{\bigvee}   {\mathop}{\M@extbigops@font}{"22C1}
  \@DMS{\bigwedge} {\mathop}{\M@extbigops@font}{"22C0}
  \@DMS{\bigcup}   {\mathop}{\M@extbigops@font}{"22C3}
  \@DMS{\bigcap}   {\mathop}{\M@extbigops@font}{"22C2}
  \@DMS{\iintop}   {\mathop}{\M@extbigops@font}{"222C}
  \@DMS{\iiintop}  {\mathop}{\M@extbigops@font}{"222D}
  \@DMS{\ointop}   {\mathop}{\M@extbigops@font}{"222E}
  \@DMS{\oiintop}  {\mathop}{\M@extbigops@font}{"222F}
  \@DMS{\oiiintop} {\mathop}{\M@extbigops@font}{"2230}
  \@DMS{\bigoplus} {\mathop}{\M@extbigops@font}{"2A01}
  \@DMS{\bigotimes}{\mathop}{\M@extbigops@font}{"2A02}
  \@DMS{\bigodot}  {\mathop}{\M@extbigops@font}{"2A00}
  \@DMS{\bigsqcap} {\mathop}{\M@extbigops@font}{"2A05}
  \@DMS{\bigsqcup} {\mathop}{\M@extbigops@font}{"2A06}
  \protected\gdef\iint{\iintop\nolimits}
  \protected\gdef\iiint{\iiintop\nolimits}
  \protected\gdef\oint{\ointop\nolimits}
  \protected\gdef\oiint{\oiintop\nolimits}
  \protected\gdef\oiiint{\oiiintop\nolimits}}
%    \end{macrocode}
% Set symbols.\indexpage{keywordsymbols=keyword \texttt{symbols}}
%    \begin{macrocode}
\def\M@symbols@set{%
  \edef\M@symbols@font{M\M@symbolsshape\@tempa}
  \let\colon\@undefined
  \let\mathellipsis\@undefined
%    \end{macrocode}
% Before we start declaring symbols, specifically minus or equals signs, we have to address a minor clash with \textsf{amsmath}. That package defines |\relbar| and |\Relbar| as essentially a minus and equals sign respectively. However, those two control sequences are for making arrows, so they should come from the |arrows| font, not the |symbols| font. If the user already called |\mathfont| with the |arrows| keyword, we do nothing because |\M@arrows@set| defines |\relbar| and |\Relbar| correctly. If not, we make these two control sequences be the current minus and equals sign (before the font changes in |\M@symbols@set|) because that's as good a choice as any, and we prevent \textsf{amsmath} from changing them to the |symbols| font. Users or package authors who want to modify |\relbar| or |\Relbar| should change |\@relbar| or |\@Relbar| respectively.
%    \begin{macrocode}
  \ifM@arrows\else
    \global\Umathcharnumdef\@relbar=\Umathcodenum`\-
    \global\Umathcharnumdef\@Relbar=\Umathcodenum`\=
    \protected\gdef\relbar{\mathrel
      {\mathpalette\mathsm@sh\@relbar}}
    \protected\gdef\Relbar{\@Relbar}
%    \end{macrocode}
% We redefine stuff if \textsf{amsmath} gets loaded after \textsf{mathfont}.
%    \begin{macrocode}
    \@ifpackageloaded{amsmath}
      {\relax}{%
        \global\let\@@relbar\relbar
        \global\let\@@Relbar\Relbar
        \AtBeginDocument{\ifM@arrows\else
            \@ifpackageloaded{amsmath}{%
              \global\let\relbar\@@relbar
              \global\let\Relbar\@@Relbar}
            {\relax}
          \fi}}
  \fi
%    \end{macrocode}
% The rest of the symbols.
%    \begin{macrocode}
  \@DMS{.}             {\mathord}  {\M@symbols@font}{"2E}
  \@DMS{@}             {\mathord}  {\M@symbols@font}{"40}
  \@DMS{'}             {\mathord}  {\M@symbols@font}{"2032}
  \@DMS{\prime}        {\mathord}  {\M@symbols@font}{"2032}
  \@DMS{"}             {\mathord}  {\M@symbols@font}{"2033}
  \@DMS{\mathhash}     {\mathord}  {\M@symbols@font}{"23}
  \@DMS{\mathdollar}   {\mathord}  {\M@symbols@font}{"24}
  \@DMS{\mathpercent}  {\mathord}  {\M@symbols@font}{"25}
  \@DMS{\mathand}      {\mathord}  {\M@symbols@font}{"26}
  \@DMS{\mathparagraph}{\mathord}  {\M@symbols@font}{"B6}
  \@DMS{\mathsection}  {\mathord}  {\M@symbols@font}{"A7}
  \@DMS{\mathsterling} {\mathord}  {\M@symbols@font}{"A3}
  \@DMS{\neg}          {\mathord}  {\M@symbols@font}{"AC}
  \@DMS{|}             {\mathord}  {\M@symbols@font}{"7C}
  \@DMS{\infty}        {\mathord}  {\M@symbols@font}{"221E}
  \@DMS{\partial}      {\mathord}  {\M@symbols@font}{"2202}
  \@DMS{\degree}       {\mathord}  {\M@symbols@font}{"B0}
  \@DMS{\increment}    {\mathord}  {\M@symbols@font}{"2206}
  \@DMS{\comma}        {\mathord}  {\M@symbols@font}{"2C}
  \@DMS{+}             {\mathbin}  {\M@symbols@font}{"2B}
  \@DMS{-}             {\mathbin}  {\M@symbols@font}{"2212}
  \@DMS{*}             {\mathbin}  {\M@symbols@font}{"2A}
  \@DMS{\times}        {\mathbin}  {\M@symbols@font}{"D7}
  \@DMS{/}             {\mathord}  {\M@symbols@font}{"2F}
  \@DMS{\fractionslash}{\mathord}  {\M@symbols@font}{"2215}
  \@DMS{\div}          {\mathbin}  {\M@symbols@font}{"F7}
  \@DMS{\pm}           {\mathbin}  {\M@symbols@font}{"B1}
  \@DMS{\bullet}       {\mathbin}  {\M@symbols@font}{"2022}
  \@DMS{\dagger}       {\mathbin}  {\M@symbols@font}{"2020}
  \@DMS{\ddagger}      {\mathbin}  {\M@symbols@font}{"2021}
  \@DMS{\cdot}         {\mathbin}  {\M@symbols@font}{"2219}
  \@DMS{\setminus}     {\mathbin}  {\M@symbols@font}{"5C}
  \@DMS{=}             {\mathrel}  {\M@symbols@font}{"3D}
  \@DMS{<}             {\mathrel}  {\M@symbols@font}{"3C}
  \@DMS{>}             {\mathrel}  {\M@symbols@font}{"3E}
  \@DMS{\leq}          {\mathrel}  {\M@symbols@font}{"2264}
  \@DMS{\geq}          {\mathrel}  {\M@symbols@font}{"2265}
  \@DMS{\sim}          {\mathrel}  {\M@symbols@font}{"7E}
  \@DMS{\approx}       {\mathrel}  {\M@symbols@font}{"2248}
  \@DMS{\equiv}        {\mathrel}  {\M@symbols@font}{"2261}
  \@DMS{\mid}          {\mathrel}  {\M@symbols@font}{"7C}
  \@DMS{\parallel}     {\mathrel}  {\M@symbols@font}{"2016}
  \@DMS{:}             {\mathrel}  {\M@symbols@font}{"3A}
  \@DMS{?}             {\mathclose}{\M@symbols@font}{"3F}
  \@DMS{!}             {\mathclose}{\M@symbols@font}{"21}
  \@DMS{,}             {\mathpunct}{\M@symbols@font}{"2C}
  \@DMS{;}             {\mathpunct}{\M@symbols@font}{"3B}
  \@DMS{\colon}        {\mathpunct}{\M@symbols@font}{"3A}
  \@DMS{\mathellipsis} {\mathinner}{\M@symbols@font}{"2026}
%    \end{macrocode}
% Now a bit of housekeeping. We redefine |\#|, |\%|, and |\&| as |\protected| macros that expand to previously declared |\mathhash|, etc.\ commands in math mode and retain their standard |\char| definitions otherwise. Other commands that function in both math and horizontal modes such as |\S| or |\dag| also use this technique. Then we define macros |\cong| and |\simeq| if the user hasn't called |\mathfont| with |extsymbols|.
%    \begin{macrocode}
  \protected\gdef\#{\ifmmode\mathhash\else\char"23\relax\fi}
  \protected\gdef\%{\ifmmode\mathpercent\else\char"25\relax\fi}
  \protected\gdef\&{\ifmmode\mathand\else\char"26\relax\fi}
  \ifM@extsymbols\else
    \protected\gdef\simeq{%
      \mathrel{\mathpalette\stack@flatrel{{-}{\sim}}}}
    \protected\gdef\cong{%
      \mathrel{\mathpalette\stack@flatrel{{=}{\sim}}}}
  \fi
  \protected\gdef\models{\mathrel{|}\joinrel\mathrel{=}}
%    \end{macrocode}
% If the user enabled Lua-based font asjustments, we declare a few more big operators for fun. For brevity, we put the |adjust@font| conditional here rather than redefining |\M@symbols@set|. Apparently, \textsf{newtx} defines |\bigtimes|, so if that package gets loaded ahead of \textsf{mathfont}, we should make sure to clear that definition.
%    \begin{macrocode}
  \ifM@adjust@font
    \let\bigtimes\@undefined
    \@DMS{\bigat}     {\mathop}{\M@symbols@font}{"40}
    \@DMS{\bighash}   {\mathop}{\M@symbols@font}{"23}
    \@DMS{\bigdollar} {\mathop}{\M@symbols@font}{"24}
    \@DMS{\bigpercent}{\mathop}{\M@symbols@font}{"25}
    \@DMS{\bigand}    {\mathop}{\M@symbols@font}{"26}
    \@DMS{\bigplus}   {\mathop}{\M@symbols@font}{"2B}
    \@DMS{\bigp}      {\mathop}{\M@symbols@font}{"21}
    \@DMS{\bigq}      {\mathop}{\M@symbols@font}{"3F}
    \@DMS{\bigS}      {\mathop}{\M@symbols@font}{"A7}
    \@DMS{\bigtimes}  {\mathop}{\M@symbols@font}{"D7}
    \@DMS{\bigdiv}    {\mathop}{\M@symbols@font}{"F7}
%    \end{macrocode}
% Define |\nabla| here if we're adjusting the font. If we are not doing that, this declaration goes in |extsymbols|.
%    \begin{macrocode}
    \@DMS{\nabla}     {\mathord}{\M@symbols@font}{"2207}
  \fi}
%    \end{macrocode}
% Set extended symbols.\indexpage{keywordextsymbols=keyword \texttt{extsymbols}}
%    \begin{macrocode}
\def\M@extsymbols@set{%
  \edef\M@extsymbols@font{M\M@extsymbolsshape\@tempa}
  \let\angle\@undefined
  \let\simeq\@undefined
  \let\sqsubset\@undefined
  \let\sqsupset\@undefined
  \let\bowtie\@undefined
  \let\doteq\@undefined
  \let\neq\@undefined
  \@DMS{\wp}              {\mathord}{\M@extsymbols@font}{"2118}
  \@DMS{\ell}             {\mathord}{\M@extsymbols@font}{"2113}
  \@DMS{\forall}          {\mathord}{\M@extsymbols@font}{"2200}
  \@DMS{\exists}          {\mathord}{\M@extsymbols@font}{"2203}
  \@DMS{\emptyset}        {\mathord}{\M@extsymbols@font}{"2205}
  \@DMS{\in}              {\mathord}{\M@extsymbols@font}{"2208}
  \@DMS{\ni}              {\mathord}{\M@extsymbols@font}{"220B}
  \@DMS{\mp}              {\mathord}{\M@extsymbols@font}{"2213}
  \@DMS{\angle}           {\mathord}{\M@extsymbols@font}{"2220}
  \@DMS{\top}             {\mathord}{\M@extsymbols@font}{"22A4}
  \@DMS{\bot}             {\mathord}{\M@extsymbols@font}{"22A5}
  \@DMS{\vdash}           {\mathord}{\M@extsymbols@font}{"22A2}
  \@DMS{\dashv}           {\mathord}{\M@extsymbols@font}{"22A3}
  \@DMS{\flat}            {\mathord}{\M@extsymbols@font}{"266D}
  \@DMS{\natural}         {\mathord}{\M@extsymbols@font}{"266E}
  \@DMS{\sharp}           {\mathord}{\M@extsymbols@font}{"266F}
  \@DMS{\fflat}           {\mathord}{\M@extsymbols@font}{"1D12B}
  \@DMS{\ssharp}          {\mathord}{\M@extsymbols@font}{"1D12A}
  \@DMS{\bclubsuit}       {\mathord}{\M@extsymbols@font}{"2663}
  \@DMS{\bdiamondsuit}    {\mathord}{\M@extsymbols@font}{"2666}
  \@DMS{\bheartsuit}      {\mathord}{\M@extsymbols@font}{"2665}
  \@DMS{\bspadesuit}      {\mathord}{\M@extsymbols@font}{"2660}
  \@DMS{\wclubsuit}       {\mathord}{\M@extsymbols@font}{"2667}
  \@DMS{\wdiamondsuit}    {\mathord}{\M@extsymbols@font}{"2662}
  \@DMS{\wheartsuit}      {\mathord}{\M@extsymbols@font}{"2661}
  \@DMS{\wspadesuit}      {\mathord}{\M@extsymbols@font}{"2664}
    \global\let\spadesuit\bspadesuit
    \global\let\heartsuit\wheartsuit
    \global\let\diamondsuit\wdiamondsuit
    \global\let\clubsuit\bclubsuit
  \@DMS{\wedge}           {\mathbin}{\M@extsymbols@font}{"2227}
  \@DMS{\vee}             {\mathbin}{\M@extsymbols@font}{"2228}
  \@DMS{\cap}             {\mathord}{\M@extsymbols@font}{"2229}
  \@DMS{\cup}             {\mathbin}{\M@extsymbols@font}{"222A}
  \@DMS{\sqcap}           {\mathbin}{\M@extsymbols@font}{"2293}
  \@DMS{\sqcup}           {\mathbin}{\M@extsymbols@font}{"2294}
  \@DMS{\amalg}           {\mathbin}{\M@extsymbols@font}{"2A3F}
  \@DMS{\wr}              {\mathbin}{\M@extsymbols@font}{"2240}
  \@DMS{\ast}             {\mathbin}{\M@extsymbols@font}{"2217}
  \@DMS{\star}            {\mathbin}{\M@extsymbols@font}{"22C6}
  \@DMS{\diamond}         {\mathbin}{\M@extsymbols@font}{"22C4}
  \@DMS{\varcdot}         {\mathbin}{\M@extsymbols@font}{"22C5}
  \@DMS{\varsetminus}     {\mathbin}{\M@extsymbols@font}{"2216}
  \@DMS{\oplus}           {\mathbin}{\M@extsymbols@font}{"2295}
  \@DMS{\otimes}          {\mathbin}{\M@extsymbols@font}{"2297}
  \@DMS{\ominus}          {\mathbin}{\M@extsymbols@font}{"2296}
  \@DMS{\odiv}            {\mathbin}{\M@extsymbols@font}{"2A38}
  \@DMS{\oslash}          {\mathbin}{\M@extsymbols@font}{"2298}
  \@DMS{\odot}            {\mathbin}{\M@extsymbols@font}{"2299}
  \@DMS{\sqplus}          {\mathbin}{\M@extsymbols@font}{"229E}
  \@DMS{\sqtimes}         {\mathbin}{\M@extsymbols@font}{"22A0}
  \@DMS{\sqminus}         {\mathbin}{\M@extsymbols@font}{"229F}
  \@DMS{\sqdot}           {\mathbin}{\M@extsymbols@font}{"22A1}
  \@DMS{\in}              {\mathrel}{\M@extsymbols@font}{"2208}
  \@DMS{\ni}              {\mathrel}{\M@extsymbols@font}{"220B}
  \@DMS{\subset}          {\mathrel}{\M@extsymbols@font}{"2282}
  \@DMS{\supset}          {\mathrel}{\M@extsymbols@font}{"2283}
  \@DMS{\subseteq}        {\mathrel}{\M@extsymbols@font}{"2286}
  \@DMS{\supseteq}        {\mathrel}{\M@extsymbols@font}{"2287}
  \@DMS{\sqsubset}        {\mathrel}{\M@extsymbols@font}{"228F}
  \@DMS{\sqsupset}        {\mathrel}{\M@extsymbols@font}{"2290}
  \@DMS{\sqsubseteq}      {\mathrel}{\M@extsymbols@font}{"2291}
  \@DMS{\sqsupseteq}      {\mathrel}{\M@extsymbols@font}{"2292}
  \@DMS{\triangleleft}    {\mathrel}{\M@extsymbols@font}{"22B2}
  \@DMS{\triangleright}   {\mathrel}{\M@extsymbols@font}{"22B3}
  \@DMS{\trianglelefteq}  {\mathrel}{\M@extsymbols@font}{"22B4}
  \@DMS{\trianglerighteq} {\mathrel}{\M@extsymbols@font}{"22B5}
  \@DMS{\propto}          {\mathrel}{\M@extsymbols@font}{"221D}
  \@DMS{\bowtie}          {\mathrel}{\M@extsymbols@font}{"22C8}
  \@DMS{\hourglass}       {\mathrel}{\M@extsymbols@font}{"29D6}
  \@DMS{\therefore}       {\mathrel}{\M@extsymbols@font}{"2234}
  \@DMS{\because}         {\mathrel}{\M@extsymbols@font}{"2235}
  \@DMS{\ratio}           {\mathrel}{\M@extsymbols@font}{"2236}
  \@DMS{\proportion}      {\mathrel}{\M@extsymbols@font}{"2237}
  \@DMS{\ll}              {\mathrel}{\M@extsymbols@font}{"226A}
  \@DMS{\gg}              {\mathrel}{\M@extsymbols@font}{"226B}
  \@DMS{\lll}             {\mathrel}{\M@extsymbols@font}{"22D8}
  \@DMS{\ggg}             {\mathrel}{\M@extsymbols@font}{"22D9}
  \@DMS{\leqq}            {\mathrel}{\M@extsymbols@font}{"2266}
  \@DMS{\geqq}            {\mathrel}{\M@extsymbols@font}{"2267}
  \@DMS{\lapprox}         {\mathrel}{\M@extsymbols@font}{"2A85}
  \@DMS{\gapprox}         {\mathrel}{\M@extsymbols@font}{"2A86}
  \@DMS{\simeq}           {\mathrel}{\M@extsymbols@font}{"2243}
  \@DMS{\eqsim}           {\mathrel}{\M@extsymbols@font}{"2242}
  \@DMS{\simeqq}          {\mathrel}{\M@extsymbols@font}{"2245}
    \global\let\cong\simeqq
  \@DMS{\approxeq}        {\mathrel}{\M@extsymbols@font}{"224A}
  \@DMS{\sssim}           {\mathrel}{\M@extsymbols@font}{"224B}
  \@DMS{\seq}             {\mathrel}{\M@extsymbols@font}{"224C}
  \@DMS{\doteq}           {\mathrel}{\M@extsymbols@font}{"2250}
  \@DMS{\coloneq}         {\mathrel}{\M@extsymbols@font}{"2254}
  \@DMS{\eqcolon}         {\mathrel}{\M@extsymbols@font}{"2255}
  \@DMS{\ringeq}          {\mathrel}{\M@extsymbols@font}{"2257}
  \@DMS{\arceq}           {\mathrel}{\M@extsymbols@font}{"2258}
  \@DMS{\wedgeeq}         {\mathrel}{\M@extsymbols@font}{"2259}
  \@DMS{\veeeq}           {\mathrel}{\M@extsymbols@font}{"225A}
  \@DMS{\stareq}          {\mathrel}{\M@extsymbols@font}{"225B}
  \@DMS{\triangleeq}      {\mathrel}{\M@extsymbols@font}{"225C}
  \@DMS{\defeq}           {\mathrel}{\M@extsymbols@font}{"225D}
  \@DMS{\qeq}             {\mathrel}{\M@extsymbols@font}{"225F}
  \@DMS{\lsim}            {\mathrel}{\M@extsymbols@font}{"2272}
  \@DMS{\gsim}            {\mathrel}{\M@extsymbols@font}{"2273}
  \@DMS{\prec}            {\mathrel}{\M@extsymbols@font}{"227A}
  \@DMS{\succ}            {\mathrel}{\M@extsymbols@font}{"227B}
  \@DMS{\preceq}          {\mathrel}{\M@extsymbols@font}{"227C}
  \@DMS{\succeq}          {\mathrel}{\M@extsymbols@font}{"227D}
  \@DMS{\preceqq}         {\mathrel}{\M@extsymbols@font}{"2AB3}
  \@DMS{\succeqq}         {\mathrel}{\M@extsymbols@font}{"2AB4}
  \@DMS{\precsim}         {\mathrel}{\M@extsymbols@font}{"227E}
  \@DMS{\succsim}         {\mathrel}{\M@extsymbols@font}{"227F}
  \@DMS{\precapprox}      {\mathrel}{\M@extsymbols@font}{"2AB7}
  \@DMS{\succapprox}      {\mathrel}{\M@extsymbols@font}{"2AB8}
  \@DMS{\precprec}        {\mathrel}{\M@extsymbols@font}{"2ABB}
  \@DMS{\succsucc}        {\mathrel}{\M@extsymbols@font}{"2ABC}
  \@DMS{\asymp}           {\mathrel}{\M@extsymbols@font}{"224D}
  \@DMS{\nin}             {\mathrel}{\M@extsymbols@font}{"2209}
  \@DMS{\nni}             {\mathrel}{\M@extsymbols@font}{"220C}
  \@DMS{\nsubset}         {\mathrel}{\M@extsymbols@font}{"2284}
  \@DMS{\nsupset}         {\mathrel}{\M@extsymbols@font}{"2285}
  \@DMS{\nsubseteq}       {\mathrel}{\M@extsymbols@font}{"2288}
  \@DMS{\nsupseteq}       {\mathrel}{\M@extsymbols@font}{"2289}
  \@DMS{\subsetneq}       {\mathrel}{\M@extsymbols@font}{"228A}
  \@DMS{\supsetneq}       {\mathrel}{\M@extsymbols@font}{"228B}
  \@DMS{\nsqsubseteq}     {\mathrel}{\M@extsymbols@font}{"22E2}
  \@DMS{\nsqsupseteq}     {\mathrel}{\M@extsymbols@font}{"22E3}
  \@DMS{\sqsubsetneq}     {\mathrel}{\M@extsymbols@font}{"22E4}
  \@DMS{\sqsupsetneq}     {\mathrel}{\M@extsymbols@font}{"22E5}
  \@DMS{\neq}             {\mathrel}{\M@extsymbols@font}{"2260}
  \@DMS{\nl}              {\mathrel}{\M@extsymbols@font}{"226E}
  \@DMS{\nleq}            {\mathrel}{\M@extsymbols@font}{"2270}
  \@DMS{\ngeq}            {\mathrel}{\M@extsymbols@font}{"2271}
  \@DMS{\lneq}            {\mathrel}{\M@extsymbols@font}{"2A87}
  \@DMS{\gneq}            {\mathrel}{\M@extsymbols@font}{"2A88}
  \@DMS{\lneqq}           {\mathrel}{\M@extsymbols@font}{"2268}
  \@DMS{\gneqq}           {\mathrel}{\M@extsymbols@font}{"2269}
  \@DMS{\ntriangleleft}   {\mathrel}{\M@extsymbols@font}{"22EA}
  \@DMS{\ntriangleright}  {\mathrel}{\M@extsymbols@font}{"22EB}
  \@DMS{\ntrianglelefteq} {\mathrel}{\M@extsymbols@font}{"22EC}
  \@DMS{\ntrianglerighteq}{\mathrel}{\M@extsymbols@font}{"22ED}
  \@DMS{\nsim}            {\mathrel}{\M@extsymbols@font}{"2241}
  \@DMS{\napprox}         {\mathrel}{\M@extsymbols@font}{"2249}
  \@DMS{\nsimeq}          {\mathrel}{\M@extsymbols@font}{"2244}
  \@DMS{\nsimeqq}         {\mathrel}{\M@extsymbols@font}{"2247}
  \@DMS{\simneqq}         {\mathrel}{\M@extsymbols@font}{"2246}
  \@DMS{\nlsim}           {\mathrel}{\M@extsymbols@font}{"2274}
  \@DMS{\ngsim}           {\mathrel}{\M@extsymbols@font}{"2275}
  \@DMS{\lnsim}           {\mathrel}{\M@extsymbols@font}{"22E6}
  \@DMS{\gnsim}           {\mathrel}{\M@extsymbols@font}{"22E7}
  \@DMS{\lnapprox}        {\mathrel}{\M@extsymbols@font}{"2A89}
  \@DMS{\gnapprox}        {\mathrel}{\M@extsymbols@font}{"2A8A}
  \@DMS{\nprec}           {\mathrel}{\M@extsymbols@font}{"2280}
  \@DMS{\nsucc}           {\mathrel}{\M@extsymbols@font}{"2281}
  \@DMS{\npreceq}         {\mathrel}{\M@extsymbols@font}{"22E0}
  \@DMS{\nsucceq}         {\mathrel}{\M@extsymbols@font}{"22E1}
  \@DMS{\precneq}         {\mathrel}{\M@extsymbols@font}{"2AB1}
  \@DMS{\succneq}         {\mathrel}{\M@extsymbols@font}{"2AB2}
  \@DMS{\precneqq}        {\mathrel}{\M@extsymbols@font}{"2AB5}
  \@DMS{\succneqq}        {\mathrel}{\M@extsymbols@font}{"2AB6}
  \@DMS{\precnsim}        {\mathrel}{\M@extsymbols@font}{"22E8}
  \@DMS{\succnsim}        {\mathrel}{\M@extsymbols@font}{"22E9}
  \@DMS{\precnapprox}     {\mathrel}{\M@extsymbols@font}{"2AB9}
  \@DMS{\succnapprox}     {\mathrel}{\M@extsymbols@font}{"2ABA}
  \@DMS{\nequiv}          {\mathrel}{\M@extsymbols@font}{"2262}
%    \end{macrocode}
% The \textsf{math-operator} package renames |\Re| and |\Im| to |\varRe| and |\varIm|. To make \textsf{mathfont} compatible with that package, we test whether these commands have been redefined.
%    \begin{macrocode}
  \@ifpackageloaded{math-operator}{\if@operator@s
      \@DMS{\varRe}{\mathord}{\M@extsymbols@font}{"211C}
      \@DMS{\varIm}{\mathord}{\M@extsymbols@font}{"2111}
    \else
      \@DMS{\Re}{\mathord}{\M@extsymbols@font}{"211C}
      \@DMS{\Im}{\mathord}{\M@extsymbols@font}{"2111}
    \fi}{%
      \@DMS{\Re}{\mathord}{\M@extsymbols@font}{"211C}
      \@DMS{\Im}{\mathord}{\M@extsymbols@font}{"2111}}
%    \end{macrocode}
% We handle |\ng| specially. The \LaTeX\ kernel defines |\ng| as a text symbol, so we define |\mathng| like for |\$|, etc.
%    \begin{macrocode}
  \global\let\textng\ng
  \@DMS{\mathng}{\mathrel}{\M@extsymbols@font}{"226F}
  \protected\gdef\ng{\ifmmode\mathng\else\textng\fi}
%    \end{macrocode}
% If we're not adjusting the font, we declare |\nabla| here.
%    \begin{macrocode}
  \ifM@adjust@font\else
    \@DMS{\nabla}{\mathord}{\M@extsymbols@font}{"2207}
  \fi}
%    \end{macrocode}
% Set arrows.\indexpage{keywordarrows=keyword \texttt{arrows}}
%    \begin{macrocode}
\def\M@arrows@set{%
  \edef\M@arrows@font{M\M@arrowsshape\@tempa}
  \let\uparrow\@undefined
  \let\Uparrow\@undefined
  \let\downarrow\@undefined
  \let\Downarrow\@undefined
  \let\updownarrow\@undefined
  \let\Updownarrow\@undefined
  \let\longrightarrow\@undefined
  \let\longleftarrow\@undefined
  \let\longleftrightarrow\@undefined
  \let\hookrightarrow\@undefined
  \let\hookleftarrow\@undefined
  \let\Longrightarrow\@undefined
  \let\Longleftarrow\@undefined
  \let\Longleftrightarrow\@undefined
  \let\rightleftharpoons\@undefined
  \@DMS{\rightarrow}           {\mathrel}{\M@arrows@font}{"2192}
    \global\let\to\rightarrow
  \@DMS{\nrightarrow}          {\mathrel}{\M@arrows@font}{"219B}
  \@DMS{\Rightarrow}           {\mathrel}{\M@arrows@font}{"21D2}
  \@DMS{\nRightarrow}          {\mathrel}{\M@arrows@font}{"21CF}
  \@DMS{\Rrightarrow}          {\mathrel}{\M@arrows@font}{"21DB}
  \@DMS{\longrightarrow}       {\mathrel}{\M@arrows@font}{"27F6}
  \@DMS{\Longrightarrow}       {\mathrel}{\M@arrows@font}{"27F9}
  \@DMS{\rightbararrow}        {\mathrel}{\M@arrows@font}{"21A6}
    \global\let\mapsto\rightbararrow
  \@DMS{\Rightbararrow}        {\mathrel}{\M@arrows@font}{"2907}
  \@DMS{\longrightbararrow}    {\mathrel}{\M@arrows@font}{"27FC}
    \global\let\longmapsto\longrightbararrow
  \@DMS{\Longrightbararrow}    {\mathrel}{\M@arrows@font}{"27FE}
  \@DMS{\hookrightarrow}       {\mathrel}{\M@arrows@font}{"21AA}
  \@DMS{\rightdasharrow}       {\mathrel}{\M@arrows@font}{"21E2}
  \@DMS{\rightharpoonup}       {\mathrel}{\M@arrows@font}{"21C0}
  \@DMS{\rightharpoondown}     {\mathrel}{\M@arrows@font}{"21C1}
  \@DMS{\rightarrowtail}       {\mathrel}{\M@arrows@font}{"21A3}
  \@DMS{\rightoplusarrow}      {\mathrel}{\M@arrows@font}{"27F4}
  \@DMS{\rightwavearrow}       {\mathrel}{\M@arrows@font}{"219D}
  \@DMS{\rightsquigarrow}      {\mathrel}{\M@arrows@font}{"21DD}
  \@DMS{\longrightsquigarrow}  {\mathrel}{\M@arrows@font}{"27FF}
  \@DMS{\looparrowright}       {\mathrel}{\M@arrows@font}{"21AC}
  \@DMS{\curvearrowright}      {\mathrel}{\M@arrows@font}{"293B}
  \@DMS{\circlearrowright}     {\mathrel}{\M@arrows@font}{"21BB}
  \@DMS{\twoheadrightarrow}    {\mathrel}{\M@arrows@font}{"21A0}
  \@DMS{\rightarrowtobar}      {\mathrel}{\M@arrows@font}{"21E5}
  \@DMS{\rightwhitearrow}      {\mathrel}{\M@arrows@font}{"21E8}
  \@DMS{\rightrightarrows}     {\mathrel}{\M@arrows@font}{"21C9}
  \@DMS{\rightrightrightarrows}{\mathrel}{\M@arrows@font}{"21F6}
  \@DMS{\leftarrow}            {\mathrel}{\M@arrows@font}{"2190}
    \global\let\from\leftarrow
  \@DMS{\nleftarrow}           {\mathrel}{\M@arrows@font}{"219A}
  \@DMS{\Leftarrow}            {\mathrel}{\M@arrows@font}{"21D0}
  \@DMS{\nLeftarrow}           {\mathrel}{\M@arrows@font}{"21CD}
  \@DMS{\Lleftarrow}           {\mathrel}{\M@arrows@font}{"21DA}
  \@DMS{\longleftarrow}        {\mathrel}{\M@arrows@font}{"27F5}
  \@DMS{\Longleftarrow}        {\mathrel}{\M@arrows@font}{"27F8}
  \@DMS{\leftbararrow}         {\mathrel}{\M@arrows@font}{"21A4}
    \global\let\mapsfrom\leftbararrow
  \@DMS{\Leftbararrow}         {\mathrel}{\M@arrows@font}{"2906}
  \@DMS{\longleftbararrow}     {\mathrel}{\M@arrows@font}{"27FB}
    \global\let\longmapsfrom\longleftbararrow
  \@DMS{\Longleftbararrow}     {\mathrel}{\M@arrows@font}{"27FD}
  \@DMS{\hookleftarrow}        {\mathrel}{\M@arrows@font}{"21A9}
  \@DMS{\leftdasharrow}        {\mathrel}{\M@arrows@font}{"21E0}
  \@DMS{\leftharpoonup}        {\mathrel}{\M@arrows@font}{"21BC}
  \@DMS{\leftharpoondown}      {\mathrel}{\M@arrows@font}{"21BD}
  \@DMS{\leftarrowtail}        {\mathrel}{\M@arrows@font}{"21A2}
  \@DMS{\leftoplusarrow}       {\mathrel}{\M@arrows@font}{"2B32}
  \@DMS{\leftwavearrow}        {\mathrel}{\M@arrows@font}{"219C}
  \@DMS{\leftsquigarrow}       {\mathrel}{\M@arrows@font}{"21DC}
  \@DMS{\longleftsquigarrow}   {\mathrel}{\M@arrows@font}{"2B33}
  \@DMS{\looparrowleft}        {\mathrel}{\M@arrows@font}{"21AB}
  \@DMS{\curvearrowleft}       {\mathrel}{\M@arrows@font}{"293A}
  \@DMS{\circlearrowleft}      {\mathrel}{\M@arrows@font}{"21BA}
  \@DMS{\twoheadleftarrow}     {\mathrel}{\M@arrows@font}{"219E}
  \@DMS{\leftarrowtobar}       {\mathrel}{\M@arrows@font}{"21E4}
  \@DMS{\leftwhitearrow}       {\mathrel}{\M@arrows@font}{"21E6}
  \@DMS{\leftleftarrows}       {\mathrel}{\M@arrows@font}{"21C7}
  \@DMS{\leftleftleftarrows}   {\mathrel}{\M@arrows@font}{"2B31}
  \@DMS{\leftrightarrow}       {\mathrel}{\M@arrows@font}{"2194}
  \@DMS{\Leftrightarrow}       {\mathrel}{\M@arrows@font}{"21D4}
  \@DMS{\nLeftrightarrow}      {\mathrel}{\M@arrows@font}{"21CE}
  \@DMS{\longleftrightarrow}   {\mathrel}{\M@arrows@font}{"27F7}
  \@DMS{\Longleftrightarrow}   {\mathrel}{\M@arrows@font}{"27FA}
  \@DMS{\leftrightwavearrow}   {\mathrel}{\M@arrows@font}{"21AD}
  \@DMS{\leftrightarrows}      {\mathrel}{\M@arrows@font}{"21C6}
  \@DMS{\leftrightharpoons}    {\mathrel}{\M@arrows@font}{"21CB}
  \@DMS{\leftrightarrowstobar} {\mathrel}{\M@arrows@font}{"21B9}
  \@DMS{\rightleftarrows}      {\mathrel}{\M@arrows@font}{"21C4}
  \@DMS{\rightleftharpoons}    {\mathrel}{\M@arrows@font}{"21CC}
  \@DMS{\uparrow}              {\mathrel}{\M@arrows@font}{"2191}
  \@DMS{\Uparrow}              {\mathrel}{\M@arrows@font}{"21D1}
  \@DMS{\Uuparrow}             {\mathrel}{\M@arrows@font}{"290A}
  \@DMS{\upbararrow}           {\mathrel}{\M@arrows@font}{"21A5}
  \@DMS{\updasharrow}          {\mathrel}{\M@arrows@font}{"21E1}
  \@DMS{\upharpoonleft}        {\mathrel}{\M@arrows@font}{"21BF}
  \@DMS{\upharpoonright}       {\mathrel}{\M@arrows@font}{"21BE}
  \@DMS{\twoheaduparrow}       {\mathrel}{\M@arrows@font}{"219F}
  \@DMS{\uparrowtobar}         {\mathrel}{\M@arrows@font}{"2912}
  \@DMS{\upwhitearrow}         {\mathrel}{\M@arrows@font}{"21E7}
  \@DMS{\upwhitebararrow}      {\mathrel}{\M@arrows@font}{"21EA}
  \@DMS{\upuparrows}           {\mathrel}{\M@arrows@font}{"21C8}
  \@DMS{\downarrow}            {\mathrel}{\M@arrows@font}{"2193}
  \@DMS{\Downarrow}            {\mathrel}{\M@arrows@font}{"21D3}
  \@DMS{\Ddownarrow}           {\mathrel}{\M@arrows@font}{"290B}
  \@DMS{\downbararrow}         {\mathrel}{\M@arrows@font}{"21A7}
  \@DMS{\downdasharrow}        {\mathrel}{\M@arrows@font}{"21E3}
  \@DMS{\zigzagarrow}          {\mathrel}{\M@arrows@font}{"21AF}
    \global\let\lightningboltarrow\zigzagarrow
  \@DMS{\downharpoonleft}      {\mathrel}{\M@arrows@font}{"21C3}
  \@DMS{\downharpoonright}     {\mathrel}{\M@arrows@font}{"21C2}
  \@DMS{\twoheaddownarrow}     {\mathrel}{\M@arrows@font}{"21A1}
  \@DMS{\downarrowtobar}       {\mathrel}{\M@arrows@font}{"2913}
  \@DMS{\downwhitearrow}       {\mathrel}{\M@arrows@font}{"21E9}
  \@DMS{\downdownarrows}       {\mathrel}{\M@arrows@font}{"21CA}
  \@DMS{\updownarrow}          {\mathrel}{\M@arrows@font}{"2195}
  \@DMS{\Updownarrow}          {\mathrel}{\M@arrows@font}{"21D5}
  \@DMS{\updownarrows}         {\mathrel}{\M@arrows@font}{"21C5}
  \@DMS{\downuparrows}         {\mathrel}{\M@arrows@font}{"21F5}
  \@DMS{\updownharpoons}       {\mathrel}{\M@arrows@font}{"296E}
  \@DMS{\downupharpoons}       {\mathrel}{\M@arrows@font}{"296F}
  \@DMS{\nearrow}              {\mathrel}{\M@arrows@font}{"2197}
  \@DMS{\Nearrow}              {\mathrel}{\M@arrows@font}{"21D7}
  \@DMS{\nwarrow}              {\mathrel}{\M@arrows@font}{"2196}
  \@DMS{\Nwarrow}              {\mathrel}{\M@arrows@font}{"21D6}
  \@DMS{\searrow}              {\mathrel}{\M@arrows@font}{"2198}
  \@DMS{\Searrow}              {\mathrel}{\M@arrows@font}{"21D8}
  \@DMS{\swarrow}              {\mathrel}{\M@arrows@font}{"2199}
  \@DMS{\Swarrow}              {\mathrel}{\M@arrows@font}{"21D9}
  \@DMS{\nwsearrow}            {\mathrel}{\M@arrows@font}{"2921}
  \@DMS{\neswarrow}            {\mathrel}{\M@arrows@font}{"2922}
  \@DMS{\lcirclearrow}         {\mathrel}{\M@arrows@font}{"27F2}
  \@DMS{\rcirclearrow}         {\mathrel}{\M@arrows@font}{"27F3}
%    \end{macrocode}
% The commands |\relbar| and |\Relbar| produce a smashed minus and an equals sign respectively. They are helper control sequences that \LaTeX\ uses to create other arrows. We have a small issue with \textsf{amsmath} because in \XeTeX\ and Lua\TeX, \textsf{amsmath} defines |\relbar| and |\Relbar| in terms of the |\Umathcodes| of the minus and equals signs respectively. That is a good approach in general, but it doesn't work when a package like \textsf{mathfont} allows users to pick different fonts for symbols and arrows. We really want |\relbar| and |\Relbar| to come from the |arrows| font, so our approach is to define the control sequences now and then redefine |\AtBeginDocument| if needed.
%    \begin{macrocode}
  \let\@relbar\@undefined
  \let\@Relbar\@undefined
  \@DMS{\@relbar}{\mathbin}{\M@arrows@font}{"2212}
  \@DMS{\@Relbar}{\mathrel}{\M@arrows@font}{"3D}
  \protected\gdef\relbar{\mathrel{\mathpalette\mathsm@sh\@relbar}}
  \protected\gdef\Relbar{\@Relbar}
%    \end{macrocode}
% We redefine stuff if \textsf{amsmath} gets loaded after \textsf{mathfont}.
%    \begin{macrocode}
  \@ifpackageloaded{amsmath}
    {\relax}{%
      \global\let\@@relbar\relbar
      \global\let\@@Relbar\Relbar
      \AtBeginDocument{\@ifpackageloaded{amsmath}{%
          \global\let\relbar\@@relbar
          \global\let\Relbar\@@Relbar}
        {\relax}}}}
%    \end{macrocode}
% Set blackboard bold letters and numbers. The alphanumeric keywords work a bit differently from the other font-setting commands. We define |\mathbb| here, which takes a single argument and is essentially a wrapper around |\M@bb@mathcodes|. That command changes the |\Umathcode|s of letters to the unicode hex values of corresponding blackboard-bold characters, and throughout, |\M@bb@num| stores the family number of the sumbol font for the |bb| character class. In the definition of |\mathbb|, we use |\begingroup| and |\endgroup| to avoid creating unexpected atoms. The other alphanumeric keywords work similarly.\indexpage{keywordbb=keyword \texttt{bb}}
%    \begin{macrocode}
\def\M@bb@set{%
  \protected\def\mathbb##1{\relax
    \ifmmode\else
      \M@HModeError\mathbb
      $%
    \fi
    \begingroup
      \M@bb@mathcodes
      ##1%
    \endgroup}
  \edef\M@bb@num{\number
    \csname symM\M@bbshape\@tempa\endcsname}
  \protected\edef\M@bb@mathcodes{%
    \Umathcode`A=0+\M@bb@num"1D538\relax
    \Umathcode`B=0+\M@bb@num"1D539\relax
    \Umathcode`C=0+\M@bb@num"2102\relax
    \Umathcode`D=0+\M@bb@num"1D53B\relax
    \Umathcode`E=0+\M@bb@num"1D53C\relax
    \Umathcode`F=0+\M@bb@num"1D53D\relax
    \Umathcode`G=0+\M@bb@num"1D53E\relax
    \Umathcode`H=0+\M@bb@num"210D\relax
    \Umathcode`I=0+\M@bb@num"1D540\relax
    \Umathcode`J=0+\M@bb@num"1D541\relax
    \Umathcode`K=0+\M@bb@num"1D542\relax
    \Umathcode`L=0+\M@bb@num"1D543\relax
    \Umathcode`M=0+\M@bb@num"1D544\relax
    \Umathcode`N=0+\M@bb@num"2115\relax
    \Umathcode`O=0+\M@bb@num"1D546\relax
    \Umathcode`P=0+\M@bb@num"2119\relax
    \Umathcode`Q=0+\M@bb@num"211A\relax
    \Umathcode`R=0+\M@bb@num"211D\relax
    \Umathcode`S=0+\M@bb@num"1D54A\relax
    \Umathcode`T=0+\M@bb@num"1D54B\relax
    \Umathcode`U=0+\M@bb@num"1D54C\relax
    \Umathcode`V=0+\M@bb@num"1D54D\relax
    \Umathcode`W=0+\M@bb@num"1D54E\relax
    \Umathcode`X=0+\M@bb@num"1D54F\relax
    \Umathcode`Y=0+\M@bb@num"1D550\relax
    \Umathcode`Z=0+\M@bb@num"2124\relax
    \Umathcode`a=0+\M@bb@num"1D552\relax
    \Umathcode`b=0+\M@bb@num"1D553\relax
    \Umathcode`c=0+\M@bb@num"1D554\relax
    \Umathcode`d=0+\M@bb@num"1D555\relax
    \Umathcode`e=0+\M@bb@num"1D556\relax
    \Umathcode`f=0+\M@bb@num"1D557\relax
    \Umathcode`g=0+\M@bb@num"1D558\relax
    \Umathcode`h=0+\M@bb@num"1D559\relax
    \Umathcode`i=0+\M@bb@num"1D55A\relax
    \Umathcode`j=0+\M@bb@num"1D55B\relax
    \Umathcode`k=0+\M@bb@num"1D55C\relax
    \Umathcode`l=0+\M@bb@num"1D55D\relax
    \Umathcode`m=0+\M@bb@num"1D55E\relax
    \Umathcode`n=0+\M@bb@num"1D55F\relax
    \Umathcode`o=0+\M@bb@num"1D560\relax
    \Umathcode`p=0+\M@bb@num"1D561\relax
    \Umathcode`q=0+\M@bb@num"1D562\relax
    \Umathcode`r=0+\M@bb@num"1D563\relax
    \Umathcode`s=0+\M@bb@num"1D564\relax
    \Umathcode`t=0+\M@bb@num"1D565\relax
    \Umathcode`u=0+\M@bb@num"1D566\relax
    \Umathcode`v=0+\M@bb@num"1D567\relax
    \Umathcode`w=0+\M@bb@num"1D568\relax
    \Umathcode`x=0+\M@bb@num"1D569\relax
    \Umathcode`y=0+\M@bb@num"1D56A\relax
    \Umathcode`z=0+\M@bb@num"1D56B\relax
    \Umathcode`0=0+\M@bb@num"1D7D8\relax
    \Umathcode`1=0+\M@bb@num"1D7D9\relax
    \Umathcode`2=0+\M@bb@num"1D7DA\relax
    \Umathcode`3=0+\M@bb@num"1D7DB\relax
    \Umathcode`4=0+\M@bb@num"1D7DC\relax
    \Umathcode`5=0+\M@bb@num"1D7DD\relax
    \Umathcode`6=0+\M@bb@num"1D7DE\relax
    \Umathcode`7=0+\M@bb@num"1D7DF\relax
    \Umathcode`8=0+\M@bb@num"1D7E0\relax
    \Umathcode`9=0+\M@bb@num"1D7E1\relax}}
%    \end{macrocode}
% Set caligraphic letters.\indexpage{keywordcal=keyword \texttt{cal}}
%    \begin{macrocode}
\def\M@cal@set{%
  \protected\def\mathcal##1{\relax
    \ifmmode\else
      \M@HModeError\mathcal
      $%
    \fi
    \begingroup
      \M@cal@mathcodes
      ##1%
    \endgroup}
  \edef\M@cal@num{\number
    \csname symM\M@calshape\@tempa\endcsname}
  \protected\edef\M@cal@mathcodes{%
    \Umathcode`A=0+\M@cal@num"1D49C\relax
    \Umathcode`B=0+\M@cal@num"212C\relax
    \Umathcode`C=0+\M@cal@num"1D49E\relax
    \Umathcode`D=0+\M@cal@num"1D49F\relax
    \Umathcode`E=0+\M@cal@num"2130\relax
    \Umathcode`F=0+\M@cal@num"2131\relax
    \Umathcode`G=0+\M@cal@num"1D4A2\relax
    \Umathcode`H=0+\M@cal@num"210B\relax
    \Umathcode`I=0+\M@cal@num"2110\relax
    \Umathcode`J=0+\M@cal@num"1D4A5\relax
    \Umathcode`K=0+\M@cal@num"1D4A6\relax
    \Umathcode`L=0+\M@cal@num"2112\relax
    \Umathcode`M=0+\M@cal@num"2133\relax
    \Umathcode`N=0+\M@cal@num"1D4A9\relax
    \Umathcode`O=0+\M@cal@num"1D4AA\relax
    \Umathcode`P=0+\M@cal@num"1D4AB\relax
    \Umathcode`Q=0+\M@cal@num"1D4AC\relax
    \Umathcode`R=0+\M@cal@num"211B\relax
    \Umathcode`S=0+\M@cal@num"1D4AE\relax
    \Umathcode`T=0+\M@cal@num"1D4AF\relax
    \Umathcode`U=0+\M@cal@num"1D4B0\relax
    \Umathcode`V=0+\M@cal@num"1D4B1\relax
    \Umathcode`W=0+\M@cal@num"1D4B2\relax
    \Umathcode`X=0+\M@cal@num"1D4B3\relax
    \Umathcode`Y=0+\M@cal@num"1D4B4\relax
    \Umathcode`Z=0+\M@cal@num"1D4B5\relax
    \Umathcode`a=0+\M@cal@num"1D4B6\relax
    \Umathcode`b=0+\M@cal@num"1D4B7\relax
    \Umathcode`c=0+\M@cal@num"1D4B8\relax
    \Umathcode`d=0+\M@cal@num"1D4B9\relax
    \Umathcode`e=0+\M@cal@num"212F\relax
    \Umathcode`f=0+\M@cal@num"1D4BB\relax
    \Umathcode`g=0+\M@cal@num"210A\relax
    \Umathcode`h=0+\M@cal@num"1D4BD\relax
    \Umathcode`i=0+\M@cal@num"1D4BE\relax
    \Umathcode`j=0+\M@cal@num"1D4BF\relax
    \Umathcode`k=0+\M@cal@num"1D4C0\relax
    \Umathcode`l=0+\M@cal@num"1D4C1\relax
    \Umathcode`m=0+\M@cal@num"1D4C2\relax
    \Umathcode`n=0+\M@cal@num"1D4C3\relax
    \Umathcode`o=0+\M@cal@num"2134\relax
    \Umathcode`p=0+\M@cal@num"1D4C5\relax
    \Umathcode`q=0+\M@cal@num"1D4C6\relax
    \Umathcode`r=0+\M@cal@num"1D4C7\relax
    \Umathcode`s=0+\M@cal@num"1D4C8\relax
    \Umathcode`t=0+\M@cal@num"1D4C9\relax
    \Umathcode`u=0+\M@cal@num"1D4CA\relax
    \Umathcode`v=0+\M@cal@num"1D4CB\relax
    \Umathcode`w=0+\M@cal@num"1D4CC\relax
    \Umathcode`x=0+\M@cal@num"1D4CD\relax
    \Umathcode`y=0+\M@cal@num"1D4CE\relax
    \Umathcode`z=0+\M@cal@num"1D4CF\relax}}
%    \end{macrocode}
% Set fraktur letters.\indexpage{keywordfrak=keyword \texttt{frak}}
%    \begin{macrocode}
\def\M@frak@set{%
  \protected\def\mathfrak##1{\relax
    \ifmmode\else
      \M@HModeError\mathfrak
      $%
    \fi
    \begingroup
      \M@frak@mathcodes
      ##1%
    \endgroup}
  \edef\M@frak@num{\number
    \csname symM\M@frakshape\@tempa\endcsname}
  \protected\edef\M@frak@mathcodes{%
    \Umathcode`A=0+\M@frak@num"1D504\relax
    \Umathcode`B=0+\M@frak@num"1D505\relax
    \Umathcode`C=0+\M@frak@num"212D\relax
    \Umathcode`D=0+\M@frak@num"1D507\relax
    \Umathcode`E=0+\M@frak@num"1D508\relax
    \Umathcode`F=0+\M@frak@num"1D509\relax
    \Umathcode`G=0+\M@frak@num"1D50A\relax
    \Umathcode`H=0+\M@frak@num"210C\relax
    \Umathcode`I=0+\M@frak@num"2111\relax
    \Umathcode`J=0+\M@frak@num"1D50D\relax
    \Umathcode`K=0+\M@frak@num"1D50E\relax
    \Umathcode`L=0+\M@frak@num"1D50F\relax
    \Umathcode`M=0+\M@frak@num"1D510\relax
    \Umathcode`N=0+\M@frak@num"1D511\relax
    \Umathcode`O=0+\M@frak@num"1D512\relax
    \Umathcode`P=0+\M@frak@num"1D513\relax
    \Umathcode`Q=0+\M@frak@num"1D514\relax
    \Umathcode`R=0+\M@frak@num"211C\relax
    \Umathcode`S=0+\M@frak@num"1D516\relax
    \Umathcode`T=0+\M@frak@num"1D517\relax
    \Umathcode`U=0+\M@frak@num"1D518\relax
    \Umathcode`V=0+\M@frak@num"1D519\relax
    \Umathcode`W=0+\M@frak@num"1D51A\relax
    \Umathcode`X=0+\M@frak@num"1D51B\relax
    \Umathcode`Y=0+\M@frak@num"1D51C\relax
    \Umathcode`Z=0+\M@frak@num"2128\relax
    \Umathcode`a=0+\M@frak@num"1D51E\relax
    \Umathcode`b=0+\M@frak@num"1D51F\relax
    \Umathcode`c=0+\M@frak@num"1D520\relax
    \Umathcode`d=0+\M@frak@num"1D521\relax
    \Umathcode`e=0+\M@frak@num"1D522\relax
    \Umathcode`f=0+\M@frak@num"1D523\relax
    \Umathcode`g=0+\M@frak@num"1D524\relax
    \Umathcode`h=0+\M@frak@num"1D525\relax
    \Umathcode`i=0+\M@frak@num"1D526\relax
    \Umathcode`j=0+\M@frak@num"1D527\relax
    \Umathcode`k=0+\M@frak@num"1D528\relax
    \Umathcode`l=0+\M@frak@num"1D529\relax
    \Umathcode`m=0+\M@frak@num"1D52A\relax
    \Umathcode`n=0+\M@frak@num"1D52B\relax
    \Umathcode`o=0+\M@frak@num"1D52C\relax
    \Umathcode`p=0+\M@frak@num"1D52D\relax
    \Umathcode`q=0+\M@frak@num"1D52E\relax
    \Umathcode`r=0+\M@frak@num"1D52F\relax
    \Umathcode`s=0+\M@frak@num"1D530\relax
    \Umathcode`t=0+\M@frak@num"1D531\relax
    \Umathcode`u=0+\M@frak@num"1D532\relax
    \Umathcode`v=0+\M@frak@num"1D533\relax
    \Umathcode`w=0+\M@frak@num"1D534\relax
    \Umathcode`x=0+\M@frak@num"1D535\relax
    \Umathcode`y=0+\M@frak@num"1D536\relax
    \Umathcode`z=0+\M@frak@num"1D537\relax}}
%    \end{macrocode}
% Set bold caligraphic letters.\indexpage{keywordbcal=keyword \texttt{bcal}}
%    \begin{macrocode}
\def\M@bcal@set{%
  \protected\def\mathbcal##1{\relax
    \ifmmode\else
      \M@HModeError\mathbcal
      $%
    \fi
    \begingroup
      \M@bcal@mathcodes
      ##1%
    \endgroup}
  \edef\M@bcal@num{\number
    \csname symM\M@bcalshape\@tempa\endcsname}
  \protected\edef\M@bcal@mathcodes{%
    \Umathcode`A=0+\M@bcal@num"1D4D0\relax
    \Umathcode`B=0+\M@bcal@num"1D4D1\relax
    \Umathcode`C=0+\M@bcal@num"1D4D2\relax
    \Umathcode`D=0+\M@bcal@num"1D4D3\relax
    \Umathcode`E=0+\M@bcal@num"1D4D4\relax
    \Umathcode`F=0+\M@bcal@num"1D4D5\relax
    \Umathcode`G=0+\M@bcal@num"1D4D6\relax
    \Umathcode`H=0+\M@bcal@num"1D4D7\relax
    \Umathcode`I=0+\M@bcal@num"1D4D8\relax
    \Umathcode`J=0+\M@bcal@num"1D4D9\relax
    \Umathcode`K=0+\M@bcal@num"1D4DA\relax
    \Umathcode`L=0+\M@bcal@num"1D4DB\relax
    \Umathcode`M=0+\M@bcal@num"1D4DC\relax
    \Umathcode`N=0+\M@bcal@num"1D4DD\relax
    \Umathcode`O=0+\M@bcal@num"1D4DE\relax
    \Umathcode`P=0+\M@bcal@num"1D4DF\relax
    \Umathcode`Q=0+\M@bcal@num"1D4E0\relax
    \Umathcode`R=0+\M@bcal@num"1D4E1\relax
    \Umathcode`S=0+\M@bcal@num"1D4E2\relax
    \Umathcode`T=0+\M@bcal@num"1D4E3\relax
    \Umathcode`U=0+\M@bcal@num"1D4E4\relax
    \Umathcode`V=0+\M@bcal@num"1D4E5\relax
    \Umathcode`W=0+\M@bcal@num"1D4E6\relax
    \Umathcode`X=0+\M@bcal@num"1D4E7\relax
    \Umathcode`Y=0+\M@bcal@num"1D4E8\relax
    \Umathcode`Z=0+\M@bcal@num"1D4E9\relax
    \Umathcode`a=0+\M@bcal@num"1D4EA\relax
    \Umathcode`b=0+\M@bcal@num"1D4EB\relax
    \Umathcode`c=0+\M@bcal@num"1D4EC\relax
    \Umathcode`d=0+\M@bcal@num"1D4ED\relax
    \Umathcode`e=0+\M@bcal@num"1D4EE\relax
    \Umathcode`f=0+\M@bcal@num"1D4EF\relax
    \Umathcode`g=0+\M@bcal@num"1D4F0\relax
    \Umathcode`h=0+\M@bcal@num"1D4F1\relax
    \Umathcode`i=0+\M@bcal@num"1D4F2\relax
    \Umathcode`j=0+\M@bcal@num"1D4F3\relax
    \Umathcode`k=0+\M@bcal@num"1D4F4\relax
    \Umathcode`l=0+\M@bcal@num"1D4F5\relax
    \Umathcode`m=0+\M@bcal@num"1D4F6\relax
    \Umathcode`n=0+\M@bcal@num"1D4F7\relax
    \Umathcode`o=0+\M@bcal@num"1D4F8\relax
    \Umathcode`p=0+\M@bcal@num"1D4F9\relax
    \Umathcode`q=0+\M@bcal@num"1D4FA\relax
    \Umathcode`r=0+\M@bcal@num"1D4FB\relax
    \Umathcode`s=0+\M@bcal@num"1D4FC\relax
    \Umathcode`t=0+\M@bcal@num"1D4FD\relax
    \Umathcode`u=0+\M@bcal@num"1D4FE\relax
    \Umathcode`v=0+\M@bcal@num"1D4FF\relax
    \Umathcode`w=0+\M@bcal@num"1D500\relax
    \Umathcode`x=0+\M@bcal@num"1D501\relax
    \Umathcode`y=0+\M@bcal@num"1D502\relax
    \Umathcode`z=0+\M@bcal@num"1D503\relax}}
%    \end{macrocode}
% Set bold fraktur letters.\indexpage{keywordbfrak=keyword \texttt{bfrak}}
%    \begin{macrocode}
\def\M@bfrak@set{%
  \protected\def\mathbfrak##1{\relax
    \ifmmode\else
      \M@HModeError\mathbfrak
      $%
    \fi
    \begingroup
      \M@bfrak@mathcodes
      ##1%
    \endgroup}
  \edef\M@bfrak@num{\number
    \csname symM\M@bfrakshape\@tempa\endcsname}
  \protected\edef\M@bfrak@mathcodes{%
    \Umathcode`A=0+\M@bfrak@num"1D56C\relax
    \Umathcode`B=0+\M@bfrak@num"1D56D\relax
    \Umathcode`C=0+\M@bfrak@num"1D56E\relax
    \Umathcode`D=0+\M@bfrak@num"1D56F\relax
    \Umathcode`E=0+\M@bfrak@num"1D570\relax
    \Umathcode`F=0+\M@bfrak@num"1D571\relax
    \Umathcode`G=0+\M@bfrak@num"1D572\relax
    \Umathcode`H=0+\M@bfrak@num"1D573\relax
    \Umathcode`I=0+\M@bfrak@num"1D574\relax
    \Umathcode`J=0+\M@bfrak@num"1D575\relax
    \Umathcode`K=0+\M@bfrak@num"1D576\relax
    \Umathcode`L=0+\M@bfrak@num"1D577\relax
    \Umathcode`M=0+\M@bfrak@num"1D578\relax
    \Umathcode`N=0+\M@bfrak@num"1D579\relax
    \Umathcode`O=0+\M@bfrak@num"1D57A\relax
    \Umathcode`P=0+\M@bfrak@num"1D57B\relax
    \Umathcode`Q=0+\M@bfrak@num"1D57C\relax
    \Umathcode`R=0+\M@bfrak@num"1D57D\relax
    \Umathcode`S=0+\M@bfrak@num"1D57E\relax
    \Umathcode`T=0+\M@bfrak@num"1D57F\relax
    \Umathcode`U=0+\M@bfrak@num"1D580\relax
    \Umathcode`V=0+\M@bfrak@num"1D581\relax
    \Umathcode`W=0+\M@bfrak@num"1D582\relax
    \Umathcode`X=0+\M@bfrak@num"1D583\relax
    \Umathcode`Y=0+\M@bfrak@num"1D584\relax
    \Umathcode`Z=0+\M@bfrak@num"1D585\relax
    \Umathcode`a=0+\M@bfrak@num"1D586\relax
    \Umathcode`b=0+\M@bfrak@num"1D587\relax
    \Umathcode`c=0+\M@bfrak@num"1D588\relax
    \Umathcode`d=0+\M@bfrak@num"1D589\relax
    \Umathcode`e=0+\M@bfrak@num"1D58A\relax
    \Umathcode`f=0+\M@bfrak@num"1D58B\relax
    \Umathcode`g=0+\M@bfrak@num"1D58C\relax
    \Umathcode`h=0+\M@bfrak@num"1D58D\relax
    \Umathcode`i=0+\M@bfrak@num"1D58E\relax
    \Umathcode`j=0+\M@bfrak@num"1D58F\relax
    \Umathcode`k=0+\M@bfrak@num"1D590\relax
    \Umathcode`l=0+\M@bfrak@num"1D591\relax
    \Umathcode`m=0+\M@bfrak@num"1D592\relax
    \Umathcode`n=0+\M@bfrak@num"1D593\relax
    \Umathcode`o=0+\M@bfrak@num"1D594\relax
    \Umathcode`p=0+\M@bfrak@num"1D595\relax
    \Umathcode`q=0+\M@bfrak@num"1D596\relax
    \Umathcode`r=0+\M@bfrak@num"1D597\relax
    \Umathcode`s=0+\M@bfrak@num"1D598\relax
    \Umathcode`t=0+\M@bfrak@num"1D599\relax
    \Umathcode`u=0+\M@bfrak@num"1D59A\relax
    \Umathcode`v=0+\M@bfrak@num"1D59B\relax
    \Umathcode`w=0+\M@bfrak@num"1D59C\relax
    \Umathcode`x=0+\M@bfrak@num"1D59D\relax
    \Umathcode`y=0+\M@bfrak@num"1D59E\relax
    \Umathcode`z=0+\M@bfrak@num"1D59F\relax}}
%    \end{macrocode}
% And that's everything!
% 
% \vfill\eject
% 
% \section*{Version History}
% 
% New features and updates with each version. Listed in no particular order.
% 
% \begin{multicols*}{2}
% \bgroup\raggedright\parskip\z@\parindent\z@\leftskip1em\obeylines
% \setbox0\hbox{\hskip 1pt.\hskip 1pt}
% \def\version#1#2{\par\bigskip
%   \hbox to \hsize{\textbf{#1}\kern2pt%
%   \cleaders\copy0\hfill\kern2pt#2\strut}\par}
% \def\item{\leavevmode\raise0.5ex\hbox{\vrule height 1pt width 0.5em}\kern1pt}
% \def\item{---\kern0.2ex\relax}^^A I like the em dash better than a vrule
% 
% \version{1.1b}{July 2018}
% \item initial release
% 
% \version{1.2}{August 2018}
% \item minor bug fix for |\mathfrak|
% \item eliminated redundant batchfile
% 
% \version{1.3}{January 2019}
% \item added |symbols| keyword\par
% \item created |mathfont_example.pdf|
% \item corrected the description of the \textsf{mathastext} package
% \item font-change |\message| added to |\mathfont|
% 
% \version{1.4}{April 2019}
% \item |\setfont| command added
% \item |\mathfont| optional argument can parse spaces
% \item |no-operators| now default package optional argument
% \item added |\comma| command
% \item new fancy fatal error message
% \item improved messaging for |\mathfont|
% \item internal command |\mathpound| changed to |\mathhash|
% \item added a missing |#1| after |\char`\"| in the example code redefining |"| in the user guide
% 
% \version{1.5}{April 2019}
% \item separated |\increment| and |\Delta|
% \item version history added
% \item initial off-the-shelf use insert added
% 
% \version{1.6}{December 2019}
% \item separated implementation and user documentation
% \item created |mathfont_heading.tex|
% \item created |mathfont_doc_patch.tex| for use with the index
% \item changed |mathfont_greek.pdf| to |mathfont_symbol_list.pdf|
% \item eliminated |mathfont_example.pdf|
% \item eliminated |operators| package option
% \item eliminated |packages| package option
% \item font name can be package option
% \item added Hebrew and Cyrillic characters
% \item separated ancient Greek from modern Greek characters
% \item created new keywords: |extsymbols|, |delimiters|, |arrows|, |diacritics|, |bigops|, |extbigops|
% \item improved messaging
% \item improved internal code for local font-change commands
% \item improved space parsing for the optional argument of |\mathfont|
% \item bug fix for |\#|, etc.\ commands
% \item bad input for |\mathbb|, etc.\ now gives a warning
% \item improved error checking for |\newmathrm|, etc.\ commands
% \item |\mathfont| now ignores bad options (on top of issuing an error)
% \item iternal commands now begin with |\M@|\dots
% \item added Easter Egg!
% \item improved indexing
% \item |mathfont.dtx| renamed as |mathfont_code.dtx|
% \item |\newmathbold| renamed as |\newmathbf|
% \item default local font changes now use |\updefault|, etc.
% \item added fatal error for missing \textsf{fontspec}
% \item fatal errors result in |\endinput| rather than |\@@end|
% 
% \version{2.0}{December 2021}
% {\smallskip\leftskip\z@
%   \fboxrule=1pt\relax
%   \dimen@\hsize
%   \advance\dimen@ by -2\fboxrule
%   \advance\dimen@ by -2\fboxsep
%   \fbox{\vbox{\hsize\dimen@
%     \strut\textbf{Big Change:} Font adjustments for Lua\TeX: new glyph boundaries for Latin letters in math mode, resizable delimiters, big operators, MathConstants table based on font metrics.\vphantom y}}\par\smallskip}
% \item added |\CharmLine| and |\CharmFile|
% \item added |\mathconstantsfont|
% \item certain dimensions in equations are now adjustable when typesetting with Lua\TeX
% \item added |adjust| and |no-adjust| package options
% \item automatic generation of |ind| file
% \item fixed symbols for |\leftharpoonup|, |\leftharpoondown|, and fraktur R
% \item cleaned up internal code and documentation
% \item font names for |\mathfont| stored to avoid multiple symbol font declarations with the same font
% \item more information about nfss family names stored and provided
% \item added option |empty|
% \item raised upper bound on |\DeclareSymbolFont| to 256
% \item reintroduced |mathfont_example.tex| with different contents
% \item changed several symbol-commands to |\protected| rather than robust macros
% \item many user-level commands are now |\protected|
% \item |\updefault| changed to |\shapedefault|
% \item eliminated |\catcode| change for space characters when scanning optional argument of |\mathfont|
% \item improved messaging for |\mathfont|
% \item removed dependence on \textsf{fontspec} and added internal font-loader
% \item switched |\epsilon| and |\varepsilon|
% \item switched |\phi| and |\varphi|
% \item changed |/| to produce a solidus in math mode and added |\fractionslash|
% \item removed |\restoremathinternals| from the user guide
% \item |\setfont| now sets |\mathrm|, etc.
% \item added |\newmathsc|, other math alphabet commands for small caps
% 
% \version{2.1}{November 2022}
% \item |\mathbb|, etc.\ commands change |\Umathcode|s of letters instead of |\M@|\meta{bb,etc.}|@|\meta{letter} commands
% \item removed warnings about non-letter contents of |\mathbb|, etc.
% \item fonts loaded twice, once with default settings (for text) and once in base mode (for math)
% \item |mathconstantsfont| accepts ``upright'' or ``italic'' as optional argument
% 
% \version{2.2}{December 2022}
% \item changed the easter egg text
% \item updated patch for |\DeclareSymbolFont| to work with changes to the kernel (eliminated |\M@p@tch@decl@re| error message)
% \item calling Plain \TeX\ on \texttt{mathfont\_code.dtx} produces sty file and no pdf file
% 
% \version{2.2a}{December 2022}
% \item bug fix for |\mathconstantsfont|
% \item bug fix for |\M@check@int|
% \item added |doc2| option to |ltxdoc| in \texttt{mathfont\_code.dtx}
% 
% \version{2.2b}{August 2023}
% \item minor changes to code and documentation
% \item |\ng| now works in math (as not greater than symbol) and text (as pronounciation symbol)
% 
% \version{2.3}{September 2023}
% \item solidus and |\fractionslash| are |\mathord| instead of |\mathbin|
% \item removed |\mathfont{fontspec}| functionality
% \item redesigned font-loader
% \item added package options |default-loader| and |fontspec-loader|
% 
% \version{2.4}{April 2025}
% \item |\colon| is |\mathpunct| instead of |\mathord|
% \item moved |\relbar| and |\Relbar| to |arrows|
% \item reformatted |mathfont_code.pdf|
% \item made compatible with |\mathbb|, etc.\ commands from other packages
% \item renamed |set_nomath_true| to |set_nomath_false|
% \item improved messaging |\AtBeginDocument|
% \item removed deprecated package options, |\newmathbold|, |\restoremathinternals|
% \item more Easter egg messages
% 
% \version{2.4a}{June 2025}
% \item bug fix involving nil value and |the_font|
% \item changed underscores in file names to hyphens
% 
% \egroup
% \end{multicols*}
% 
% 
% 
% \iffalse
% 
%</package>
%<*user>
\documentclass[12pt]{article}
\makeatletter
\usepackage[margin=72.27pt]{geometry}
\usepackage[factor=700,stretch=14,shrink=14,step=1]{microtype}
\usepackage[bottom]{footmisc}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{multirow}
\usepackage[implicit=false,colorlinks=true,allcolors=blue]{hyperref}
\usepackage{enumitem}
\SetEnumitemKey{special}{topsep=\smallskipamount,
  itemsep=\smallskipamount,
  parsep=\z@,partopsep=\z@}
\setlist{special}
\usepackage{doc}[=v2]
\MakeShortVerb{|}
\def\link#1{\href{#1}{\nolinkurl{#1}}}
\newcount\fig
\fig=1\relax
\c@topnumber\@ne
% \skip\footins=7pt

% Our own label/ref scheme because the standard one isn't working
\def\labelfig#1{\immediate\write\@auxout{\string\makelabel{#1}{\the\fig}}}
\def\makelabel#1#2{\expandafter\gdef\csname fig@#1\endcsname{#2}}

\begin{document}
\def\ref#1{\csname fig@#1\endcsname}


\def\documentname{User Guide}
\def\showabstract{1}
\input mathfont-heading.tex


\noindent Handling fonts in \TeX\ and \LaTeX\ is a notoriously difficult task because fonts are complicated.\footnote{The last few decades have seen huge advances in loading fonts with \TeX. Donald Knuth originally designed \TeX\ to load fonts created with Metafont, and only more recent engines such as Jonathan Kew's \XeTeX\ and Hans Hagen, et al.'s Lua\TeX\ have extended \TeX's font-loading capabilities to unicode. \XeTeX\ supports OpenType and TrueType fonts natively, and Lua\TeX\ can load OpenType fonts through the \textsf{luaotfload} package. Information on \XeTeX\ is available at \link{https://tug.org/xetex/}, and information on Lua\TeX\ is available at the official website for Lua\TeX: \link{http://www.luatex.org/}. See also Ulrike Fischer, et al., ``\textsf{luaotfload}---OpenType `loader' for Plain \TeX\ and \LaTeX,'' \link{https://ctan.org/pkg/luaotfload}. For discussion of fonts generally, see Yannis Haralambous, \textit{Fonts \& Encodings} (Sebastopol: O'Reilly Media, Inc., 2007).} The \textsf{mathfont} package addresses this situation by providing tools to load TrueType and OpenType fonts for use in math mode, and this document explains how to operate \textsf{mathfont}. For version history and code implementation, see |mathfont-code.pdf|, and for a list of all symbols accessible with \textsf{mathfont}, see |mathfont-symbol-list.pdf|. Those two pdf files, this user guide, and four example files are included in the \textsf{mathfont} installation and are available on \textsc{ctan}. Because unicode text fonts, particularly without built-in math support, are plentiful, I hope that this package expands the possibilities for typesetting math in \LaTeX. 


\section{Loading and Basic Functionality}

Loading fonts for math typesetting is more complicated than for regular text. First, selecting fonts for math mode, both in plain \TeX\ and in the \textsc{nfss}, involves additional macros above and beyond what we need to load text fonts. Second, \TeX\ expects fonts for math to contain extra information for formatting equations.\footnote{Specifically, this extra information is a set of large variants, math-specific parameter values associated with individual characters, and a MathConstants table. Also, math fonts often use slightly wider bounding boxes for letters in math mode---the Computer Modern $f$ is a well-known example. (Compare math-mode {\fboxsep=0pt\fbox{$f$}} and italic {\fboxsep=0pt\fbox{\textit{f}}}.) For this reason, \textsf{mathfont} also provides an interface to enlarge the bounding boxes of Latin letters when they appear in math mode. See section 5 for details.} Broadly speaking, we say that a \textit{math font} contains this extra information, whereas a \textit{text font} does not, and typesetting math with glyphs from one or more text fonts usually results in messier equations than using a properly prepared math font. The functionality of \textsf{mathfont} then is twofold: (1) provide a wrapper around the \textsc{nfss} commands for math typesetting that serves as a high-level interface; and (2) implement Lua\TeX\ callbacks that artificially convert text fonts into math fonts at loading.\footnote{Values for MathConstants table are different from but inspired by Ulrik Vieth, ``Understanding the \AE sthetics of Math Typesetting,'' (Bacho\TeX\ Conference, 2008) and Ulrik Vieth ``OpenType Math Illuminated,'' \textit{TUGboat} 30 (2009): 22--31. See also Bogus\l aw Jackowski, ``Appendix G Illuminated,'' \textit{TUGboat} 27 (2006): 83--90.} Although \textsf{mathfont} tries its best to get your fonts right, it may run into trouble when picking fonts to load. If this happens, you should declare your font family and shapes in the \textsc{nfss} before setting any fonts with \textsf{mathfont}.

You must use one of \XeLaTeX\ or Lua\LaTeX\ to typeset a document with \textsf{mathfont}. You can load \textsf{mathfont} with the standard |\usepackage| syntax, and the package accepts five optional arguments. If you use Lua\TeX, the options |adjust| or |no-adjust| will manually specify whether \textsf{mathfont} should adapt text fonts for math mode, and \textsf{mathfont} selects |adjust| by default. If you use \XeTeX, \textsf{mathfont} cannot adjust any font objects with Lua callbacks, and either of these package options will cause an error.\footnote{With \XeLaTeX, \textsf{mathfont} does not add big operators or resizable delimiters. This means you will have to use the Computer Modern defaults, load a separate math font for resizable characters, or end up with a document where large operators and delimiters do not scale like they do normally.} For this reason, using Lua\TeX\ with \textsf{mathfont} is recommended as of version 2.0. The options |default-loader| and |fontspec-loader| determine which font-loading code \textsf{mathfont} uses. If you load the package with the |default-loader| option, \textsf{mathfont} uses a built-in font-loader, and if you load the package with |fontspec-loader|, \textsf{mathfont} uses the font-loader from \textsf{fontspec}. If you load \textsf{mathfont} with any other optional argument, the package will interpret it as a font name and call |\setfont| (described in the next section) on your argument. Doing so selects that font for the text of your document and for the character classes in the upper section of Table~\ref{Keywords}.


\begin{figure}[t]\labelfig{packages}
\centerline{\bfseries Table \the\fig: Comparison of General Font-Loading Packages\strut}
\global\advance\fig\@ne
\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}lll}\toprule
& Text font & Math font\\\cmidrule{2-3}
Traditional \TeX\ font & \textsf{mathastext} & No general package\\
Unicode font (for math typesetting) & \textsf{mathfont} or \textsf{mathspec} & \textsf{unicode-math}\\
Unicode font (for text only) & \textsf{fontspec} & \textsf{fontspec} \\\bottomrule
\end{tabular*}
\end{figure}




\begin{figure}[t]\labelfig{Keywords}
\centerline{\bfseries Table \the\fig: Character Classes\strut}
\global\advance\fig by 1\relax
\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}llll}\toprule
Keyword & Meaning & Default Shape & Alphabetic?\\\midrule
|upper| & Upper-Case Latin & Italic & Yes\\
|lower| & Lower-Case Latin & Italic & Yes\\
|diacritics| & Diacritics & Upright & Yes\\
|greekupper| & Upper-Case Greek & Upright & Yes\\
|greeklower| & Lower-Case Greek & Italic & Yes\\
|digits| & Arabic Numerals & Upright & Yes\\
|operator| & Operator Font & Upright & Yes\\
|delimiters| & Delimiter & Upright & No\\
|radical| & Square Root Symbol & Upright & No\\
|symbols| & Basic Math Symbols & Upright & No\\
|bigops| & Big Operators & Upright & No\\\midrule
|agreekupper| & Upper-Case Ancient Greek & Upright & Yes\\
|agreeklower| & Lower-Case Ancient Greek & Italic & Yes\\
|cyrillicupper| & Upper-Case Cyrillic & Upright & Yes\\
|cyrilliclower| & Lower-Case Cyrillic & Italic & Yes\\
|hebrew| & Hebrew & Upright & Yes\\
|extsymbols| & Extended Math Symbols & Upright & No\\
|arrows| & Arrows & Upright & No\\
|extbigops| & Extended Big Operators & Upright & No\\
|bb| & Blackboard Bold (double-struck) & Upright & No\\
|cal| & Caligraphic & Upright & No\\
|frak| & Fraktur & Upright & No\\
|bcal| & Bold Caligraphic & Upright & No\\
|bfrak| & Bold Fraktur & Upright & No\\
\bottomrule
\end{tabular*}
\end{figure}




The \textsf{mathfont} package is closely related to several other \LaTeX\ packages. The functionality is closest to that of \textsf{mathspec} by Andrew Gilbert Moschou, which is compatible with \XeTeX\ only and selects characters from text fonts for math.\footnote{Andrew Gilbert Moschou, ``\textsf{mathspec}---Specify arbitrary fonts for mathematics in \XeTeX,'' \link{https://ctan.org/pkg/mathspec}.} The \textsf{unicode-math} package is a main \LaTeX\ package for loading actual unicode math fonts, and if you have a unicode font with proper math support, rather than a text font that you want to use for equations, consider using that package instead of \textsf{mathfont}.\footnote{Will Robertson, et al., ``\textsf{unicode-math}---Unicode mathematics support for XeTeX and LuaTeX,'' \link{https://ctan.org/pkg/unicode-math}.} Users who want a text font for math with pdf\LaTeX\ should consider Jean-Fran\c cois Burnol's \textsf{mathastext} because \textsf{mathfont} is incompatible with pdf\TeX.\footnote{Jean-Fran\c cois Burnol, ``\textsf{mathastext}---Use the text font in maths mode,'' \link{https://ctan.org/pkg/mathastext}. In several previous versions of this documentation, I mischaracterized the approach of \textsf{mathastext} to \TeX's internal mathematics spacing. In fact, \textsf{mathastext} preserves and in some cases extends rules for space between various math-mode characters.} Finally, you may be better off using \textsf{fontspec} if your document does not contain any math.\footnote{Will Robertson and Khaled Hosny, ``\textsf{fontspec}---Advanced font selection in \XeLaTeX\ and Lua\LaTeX,'' \link{https://ctan.org/pkg/fontspec}.} The \textsf{fontspec} package is designed to load TrueType and OpenType fonts for text and provides a high-level interface for selecting OpenType font features. Table~\ref{packages} summarizes this information. At the time of writing this document, I am not aware of a general font-loading package for traditional \TeX\ math fonts.



\section{Setting the Default Font}

The |\mathfont| command sets the default font for certain classes of characters when they appear in math mode. It accepts a single mandatory argument, which should be a system font name or a family name already present in the \textsc{nfss}. The macro also accepts an optional argument, which should be a comma-separated list of keywords from Table~\ref{Keywords}, so the full syntax is
\begin{code}
|\mathfont[|\meta{keywords}|]{|\meta{font name}|}|
\end{code}
When you use this command, \textsf{mathfont} sets the default font face for every character in those keywords to an upright or italic version of the font from the mandatory argument. See |mathfont-symbol-list.pdf| for a list of symbols corresponding to each keyword. If you do not include an optional argument, |\mathfont| acts on all keywords in the upper section of Table~\ref{Keywords} (but not including |delimiters|, |radical|, or |bigops| characters in \XeTeX), so calling |\mathfont| with no optional argument is a fast way to change the font for most common math characters. To change the shape, you should say ``|=upright|'' or ``|=italic|'' immediately after the keyword and before the following comma, and spaces are allowed throughout the optional argument. For example, the command
\begin{code}
|\mathfont[lower=upright, upper=upright]{Times New Roman}|
\end{code}
changes all Latin letters to upright Times New Roman. Once \textsf{mathfont} has set the default font for a keyword in Table~\ref{Keywords}, it will ignore any future instructions to change the font again for that keyword, and instead the package prints a warning message.


\begin{figure}[t]
\labelfig{SetFont}
\centerline{\bfseries Table \the\fig: Commands Defined by \vrb\setfont\strut}
\global\advance\fig by 1\relax
\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}lll}\toprule
Command & Series & Shape\\\midrule
|\mathrm| & Medium & Upright\\
|\mathit| & Medium & Italic\\
|\mathbf| & Bold & Upright\\
|\mathbfit| & Bold & Italic\\
|\mathsc| & Medium & Small Caps\\
|\mathscit| & Medium & Italic Small Caps\\
|\mathbfsc| & Bold & Small Caps\\
|\mathbfscit| & Bold & Italic Small Caps\\\bottomrule
\end{tabular*}
\end{figure}


If you want to change the font for both text and math, you should use |\setfont| instead of |\mathfont|. This command accepts a single mandatory argument:
\begin{code}
|\setfont{|\meta{font name}|}|.
\end{code}
It calls |\mathfont| without an optional argument---i.e.\ for the default keywords---on your \meta{font name} and sets your document's default text font to be the \meta{font name}. The command also defines the eight commands in Table~\ref{SetFont} using the \meta{font name} and the |\new| macros in the next section. Both |\mathfont| and |\setfont| should appear in the preamble only.


To select OpenType features, you should put a colon after the font name and follow it with appropriate OpenType tags.\footnote{By default, \textsf{mathfont} enables standard ligatures, traditional \TeX\ ligatures, and lining numbers. The package sets |smcp| to |true| or |false| depending on whether it is attempting to load a small-caps font. For the full list of OpenType features, see \link{https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist}.} The syntax for specifying features depends on the font-loader: with the built-in font-loader, you should use the standard ``|+|\meta{tag}'' or ``|-|\meta{tag}'' syntax, and when using \textsf{fontspec} as the font-loader, you can use that package's high-level interface.\footnote{See the \textsf{fontspec} documentation for instructions on selecting OpenType features with \textsf{fontspec}.} For example, suppose you want math with oldstyle numbers. With the built-in font-loader, you should add ``|+onum|,'' or if using \textsf{fontspec}, you should add |Numbers=OldStyle| to your |\mathfont| command. So to load Adobe Garamond Pro with oldstyle numbering, you would say
\begin{code}
|\mathfont{Adobe Garamond Pro:+onum}|
\end{code}
with the built-in font-loader or
\begin{code}
|\mathfont{Adobe Garamond Pro:Numbers=OldStyle}|
\end{code}
if using \textsf{fontspec}. With the built-in font-loader, you should separate OpenType tags with semi-colons, and \textsf{fontspec} allows you to use commas.

Whenever you select a font for anything in this package, \textsf{mathfont} first checks whether your argument corresponds to a font family identifier in the \textsc{nfss}, and if it does, \textsf{mathfont} uses that font.\footnote{Specifically, if you use \XeTeX, \textsf{mathfont} uses the font name as given, and if you use Lua\TeX, \textsf{mathfont} tries to use a font with family name \meta{\textup{\textsc{nfss}} family}|-base| instead. This is due to \textsf{mathfont}'s double font loading and means that if you add fonts to the \textsc{nfss} yourself in Lua\TeX\ to use with \textsf{mathfont}, you should declare the font family twice. The first declaration can be normal, and for the second declaration, you should append |-base| to the family name. If you want to use OpenType font features in your equations, the second declaration should also instruct \textsf{luaotfload} to use |base| mode. If \textsf{mathfont} doesn't see \meta{\textup{\textsc{nfss}} family}|-base| in the \textsc{nfss} in Lua\TeX, it will print a warning and use the \meta{\textup{\textsc{nfss}} family} instead.} Otherwise, the package loads the font, either through the built-in font-loader or with \textsf{fontspec}.\footnote{See |mathfont\_code.pdf| for instructions on how to access the \textsc{nfss} family name in this case.} Advanced users should know that when the engine is Lua\TeX, \textsf{mathfont} loads each font twice. During the first loading, \textsf{mathfont} makes no specifications for the renderer, so the first version of the font will typically use node mode. During the second loading, \textsf{mathfont} specifies base mode. My intention is that the font face with unspecified renderer is for text, and the font face with base mode is for math---using two different loading options provides the greatest access to OpenType font features throughout your document.\footnote{The \textsf{luaotfload} package supports two main modes for loading fonts: |node| mode is the default setting, and it supports full OpenType features in text but no OpenType features in math. The |base| mode supports fewer OpenType features, but the font features work in both text and math. Other loading options such as HarfBuzz are similarly useful for text but provide no access to OpenType features in math.}


You can access blackboard-bold, calligraphic, or fraktur letters in three ways. First, the Unicode standard contains encoding slots for these types of letters, and the last five keywords in Table~\ref{Keywords} access this portion of the Unicode table.\footnote{The Math Alphanumeric Symbols block is U+1D400--U+1D7FF. Most blackboard-bold, calligraphic, and fraktur letters live in this portion of the Unicode table, although a few live in other areas.} If you call |\mathfont| on one of these \meta{keyword}s, the package defines the macro
\begin{code}
|\math|\meta{keyword}|{|\meta{text}|}|,
\end{code}
which behaves like a local font-change command from the next section and converts Latin letters into \meta{keyword} style. For example,
\begin{code}
|\mathfont[bb]{STIXGeneral}|
\end{code}
defines |\mathbb| to typeset blackboard-bold letters using the glyphs from STIXGeneral. Second, you may have a Unicode font where the normal Latin letters are themselves double struck, calligraphic, or fraktur, and in that case, you should declare a local font-change command using the tools in the next section. If you declare any of the macros |\mathbb|, |\mathcal|, |\mathfrak|, |\mathbcal|, or |\mathbfrak| this way, \textsf{mathfont} will ignore the corresponding keyword in future calls to |\mathfont|. Third, as of version 2.4, \textsf{mathfont} tries to be compatible with any macros |\mathbb|, |\mathcal|, |\mathfrak|, |\mathbcal|, or |\mathbfrak| that come from other packages or the kernel.


\begin{figure}[t]
\labelfig{MathAlpha}
\centerline{\bfseries Table \the\fig: Macros to Create Local Font-Change Commands\strut}
\global\advance\fig by 1\relax
\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}lll}\toprule
Command & Series & Shape\\\midrule
|\newmathrm| & Medium & Upright\\
|\newmathit| & Medium & Italic\\
|\newmathbf| & Bold & Upright\\
|\newmathbfit| & Bold & Italic\\
|\newmathsc| & Medium & Small Caps\\
|\newmathscit| & Medium & Italic Small Caps\\
|\newmathbfsc| & Bold & Small Caps\\
|\newmathbfscit| & Bold & Italic Small Caps\\\bottomrule
\end{tabular*}
\end{figure}


\section{Local Font Changes}

With \textsf{mathfont}, it is possible to create commands that locally change the font for math alphabet characters, i.e.\ those marked as alphabetic in Table~\ref{Keywords}. The eight commands in Table~\ref{MathAlpha} accept a \meta{control sequence} as their first mandatory argument and a \meta{font name} as the second, and they define the \meta{control sequence} to typeset any math alphabet characters in their argument into the \meta{font name}. You can specify OpenType features as part of the \meta{font name} the same way as for |\mathfont|, described in the previous section.  For example, the macro |\newmathrm| looks like
\begin{code}
|\newmathrm{|\meta{control sequence}|}{|\meta{font name}|}|.
\end{code}
It defines the \textit{control sequence} in its first argument to accept a string of characters that it then converts to the \textit{font name} in the second argument with upright shape and medium weight. Writing
\begin{code}
|\newmathrm{\matharial}{Arial}|
\end{code}
creates the macro
\begin{code}
|\matharial{|\meta{argument}|}|,
\end{code}
which can be used only in math mode and which converts the math alphabet characters in its \meta{argument} into the Arial font with upright shape and medium weight. The other commands in Table~\ref{MathAlpha} function in the same way except that they select different series or shape values. Finally, know that if you specify the font for Greek letters using |\mathfont|, macros created with the commands from this section will affect those characters, unlike in traditional \LaTeX. Similarly, the local font-change commands will affect Cyrillic and Hebrew characters after you call |\mathfont| for those keywords.

Together these eight commands will provide tools for most local font changes, but they won't be able to address everything. Accordingly, \textsf{mathfont} provides the more general |\newmathfontcommand| macro. Its structure is
\begin{code}
|\newmathfontcommand{|\meta{control sequence}|}{|\meta{font name}|}{|\meta{series}|}{|\meta{shape}|}|,
\end{code}
where the \meta{control sequence} in the first argument again becomes the macro that changes characters to the \meta{font name}. You are welcome to use a system font name when you call |\newmathfontcommand|, but the intention behind this command is that you can use an \textsc{nfss} family name for the \meta{font name}. Then the series and shape values can correspond to more obscure font faces from the \textsc{nfss} family that you would be otherwise unable to access. The commands from this section should appear in the preamble only.


\section{Default Math Parameters}

Lua\TeX\ uses the MathConstants table from the most recent font assigned for use in math mode, and this means that in a document with multiple math fonts, the choice of MathConstants table can depend on the order of font declaration and be unpredictable. To avoid potential problems from using the wrong MathConstants table, \textsf{mathfont} provides the command
\begin{code}
|\mathconstantsfont[|\meta{shape}|]{|\meta{prev arg}|}|,
\end{code}
where \meta{shape} is an optional argument that can be ``|upright|'' (default) or ``|italic|,'' and \meta{prev arg} should be any argument that you have previously fed to |\mathfont|. When you call |\mathconstantsfont|, \textsf{mathfont} forces Lua\TeX\ to always use the MathConstants table from the font that corresponded to that instance of |\mathfont| in the specified \meta{shape}. You don't need to set the MathConstants table when you use |\setfont| because the package calls |\mathconstantsfont| automatically in this case. This command will not work in \XeTeX\ and should appear only in the preamble.



\section{Lua Font Adjustments}

\begin{figure}[t]
\labelfig{Charm}
\centerline{\bfseries Table \the\fig: Number of Integers Required in \vrb\CharmLine\strut}
\global\advance\fig by 1\relax
\begin{tabularx}\textwidth{Xl}\toprule
Type of Character & \hfil Total Number of Entries\\\midrule
Latin Letters & \hfil5 \\
Delimiters, Radical Sign (Surd Character), Big Operators & \hfil33\\
Everything Else & \hfil3\\\bottomrule
\end{tabularx}
\end{figure}


The \textsf{mathfont} package provides six user-level commands to change bounding box, size, and accent positioning of characters in math mode. The command |\CharmLine| sets these features for a single math-mode character relative to its text-mode counterpart, and |\CharmFile| does the same thing for multiple characters at a time. (Charm stands for ``character metric.'') The argument of |\CharmLine| should be a list of integers and/or asterisks separated by commas and/or spaces, and Table~\ref{Charm} shows how many integers you need for different types of characters. The first integer should be the unicode encoding value of the character to be adjusted, and \textsf{mathfont} interprets the remaining numbers as follows.
\begin{itemize}
\item If the unicode value corresponds to a Latin letter, you should specify four more numbers. The next two integers tell Lua\TeX\ how much to stretch the left and right sides of the glyph's bounding box when it appears in math mode, and the final two integers determine horizontal placement of top and bottom math accents respectively.
\item If the unicode value corresponds to a delimiter, the radical (surd) symbol, or a big operator, you need to specify 16 pairs numbers, for a total of 32 more integers. The first 15 pairs are horizontal and vertical scale factors that \textsf{mathfont} uses to create large variants, where successive pairs determine the scaling of each next-larger glyph. The last two integers determine horizontal placement of top and bottom math accents respectively.
\item If the unicode value corresponds to any other symbol, you should specify two more integers. They determine the horizontal placement of top and bottom math accents respectively.
\end{itemize}
Writing an asterisk tells \textsf{mathfont} to use whatever value it has saved in memory, either the default value or the value from the most recent call to |\CharmLine| or |\CharmFile|. If you specify too few charm values, \textsf{mathfont} will raise an error, and if you provide too many, \textsf{mathfont} will silently ignore the extras. These commands should appear only in your document preamble.

\begin{figure}[tb]
\labelfig{Factors}
\centerline{\bfseries Table \the\fig: Commands to Adjust Individual Characters\strut}
\global\advance\fig by 1\relax
\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}lll}\toprule
Command & Default Value & What It Does\\\midrule
|\RuleThicknessFactor| & 1000 & Thickness of fraction rule and radical overbar\\
|\IntegralItalicFactor| & 400 & Positioning of limits for integrals\\
|\SurdVerticalFactor| & 1000 & Vertical positioning of radical overbar\\
|\SurdHorizontalFactor| & 1000 & Horizontal positioning of radical overbar\\\bottomrule
\end{tabular*}
\end{figure}


For most applications, you can probably ignore charm information altogether, but if you find bounding boxes or accent placement to be off slightly in your equations or if you want to change the scaling for a delimiter or big operator, you should try calling |\CharmLine| with different values to see what works. As is standard with decimal inputs in \TeX, \textsf{mathfont} divides your inputs by 1000 before computing with them. Positive integers mean an increase, and negative integers mean a decrease. For a given character, the scale is usually the glyph width. For example,
\begin{code}
|\CharmLine{97, 200, -200, *, 50}|
\end{code}
tells \textsf{mathfont} to take the lower-case ``a'' (unicode encoding value of 97), increase the bounding box on the left side by 20\% of the glyph width, decrease the bounding box on the right side by 20\% of the glyph width, do nothing to the top accent, and shift the bottom accent right by 5\% of the glyph width. There is no general formula for what charm values to use for a given font! Rather, you will need to make a design choice based on what looks best, and if you regularly use a particular font, consider making a custom set of charm values and uploading it to \textsc{ctan}. Additionally, if you store your charm information in a file, you can read it in with |\CharmFile|. The argument of this command should be a file name, and \textsf{mathfont} reads the file and feeds each line individually to |\CharmLine|.



\begin{figure}[tb]
\labelfig{Callbacks}
\centerline{\bfseries Table \the\fig: Lua Callbacks Created by \textsf{mathfont}\strut}
\global\advance\fig by 1\relax
\begin{tabularx}\textwidth{XX}\toprule
Callback Name & What It Does By Default\\\midrule
|"mathfont.inspect_font"| &  Nothing\\\midrule
|"mathfont.pre_adjust"| & Nothing\\
|"mathfont.disable_nomath"| &  Tell Lua\TeX\ that we have a math font\\
|"mathfont.add_math_constants"| &  Create a MathConstants table\\
|"mathfont.fix_character_metrics"|&  \raggedright\arraybackslash Adjust bounding boxes, add character-specific math fields, create large variants\\
|"mathfont.post_adjust"| &  Nothing\\\bottomrule
\end{tabularx}
\end{figure}


The commands in Table~\ref{Factors} adjust other aspects of the font as indicated. Each command accepts a single integer as an argument, and \textsf{mathfont} divides the input by 1000. With each macro, \textsf{mathfont} multiplies the quotient by some default length, so values greater than 1000 mean scale up, and values less than 1000 mean scale down. For example,
\begin{code}
|\RuleThicknessFactor{2000}|
\end{code}
doubles the thickness of the fraction rule and radical overbar relative to the default, which varies between fonts. Changing the |\RuleThicknessFactor| is useful for fonts with particularly heavy or light weight. The |\IntegralItalicFactor| is important for making limits better fit integral signs, and the |\SurdVerticalFactor| and |\SurdHorizontalFactor| commands are essential when the top of the surd glyph differs from the top of its bounding box. The six control sequences from this section should appear in the preamble only.


Finally, advanced users who want to interact with the font adjustment process directly should use the six callbacks in Table~\ref{Callbacks}. When \textsf{luaotfload} loads a font, \textsf{mathfont} (1) always calls |mathfont.inspect_font| and (2) calls the other five callbacks in the order that they appear in Table~\ref{Callbacks} if the font object contains |nomath=true|. Functions added to these callbacks should accept a font object as a single argument and return nothing. Further, please be careful when loading functions in the |disable_nomath|, |add_math_constants|, and |fix_character_metrics| callbacks. If you add a function there, Lua\TeX\ will not carry out the default behavior associated with the callback, so do not mess with these three callbacks unless you are duplicating the default behavior or you really know what you're doing. Otherwise, you risk breaking the package. See |mathfont-code.pdf| for more information.


\end{document}
%</user>
%<*chars>
\documentclass[12pt]{article}
\makeatletter
\usepackage[margin=72.27pt]{geometry}
\usepackage{tabularx}
\usepackage{booktabs}
\usepackage{multicol}
\multicolsep=\bigskipamount
\premulticols=\z@
\postmulticols=4\bigskipamount
\usepackage{graphicx}
\usepackage{mathfont}
\mathfont[agreeklower=upright,agreekupper]{Crimson}
\mathfont[hebrew]{Coelacanth}
\mathfont[\M@keys]{STIXGeneral}
\usepackage{shortvrb}
\MakeShortVerb{|}
\def\meta#1{\ensuremath{\langle\textit{#1}\rangle}}
\raggedcolumns
\parskip=0pt
\fboxrule=1pt
\CharmLine{8747 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\CharmLine{8748 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\CharmLine{8749 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\CharmLine{8750 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\CharmLine{8751 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\CharmLine{8752 1200 1700 * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * }
\begin{document}

\def\documentname{Symbol List}
\def\showabstract{1}
\input mathfont-heading.tex

\noindent The \textsf{mathfont} package provides tools to access several hundred characters for math typesetting, and this document lists these symbols along with the control sequences to access them. To get access to the symbols from a section of this document, call |\mathfont| with the keyword-option for that section and the name of a font that contains those symbols. The package does not define any math symbols until you call |\mathfont| or |\setfont| (or load \textsf{mathfont} with a font name as package option), and if you see a symbol or control sequence here that is not part of standard \LaTeX, you will not be able to access it until you call |\mathfont| on the corresponding keyword. Further, \textsf{mathfont} does not come with or load any fonts by itself, so you are responsible for the fonts. Not all fonts contain all math symbols, so choose your font wisely!\footnote{Besides letters and digits, most unicode text fonts should contain diacritics, delimiters, and the basic math characters in the keyword |symbols|. Text fonts will often contain square root and basic operator symbols, but they may not be suitable for math typesetting. Greek characters are hit or miss, and it is unusual for English text fonts to contain Cyrillic, Hebrew, ancient Greek, arrows, letterlike characters, or any extended (keywords |extbigops| and |extsymbols|) set of symbols. After you load \textsf{mathfont}, \TeX\ will print a message to the terminal if you try to typeset a missing character from some font.} This document shows ancient Greek in Crimson, Hebrew in Coelacanth, and all other math characters in STIXGeneral.

\begin{figure}[t]
\centerline{\bfseries Table 1: Characters Defined by Multiple Keywords\strut}
\begin{tabularx}\textwidth{XXX}\toprule
Character & Keywords & Default Font\\\midrule
\vrb\increment & \texttt{greekupper} & \texttt{symbols}\\
 & \texttt{symbols} & \\\midrule
\vrb\nabla & \texttt{greekupper} & \texttt{(ext)symbols}\\
 & \texttt{symbols} with Lua\TeX & \\
 & \texttt{extsymbols} with \XeTeX & \\\midrule
\expandafter\vrb\string| & \texttt{symbols} & \texttt{symbols} normally\\
 & \texttt{delimiters} with Lua\TeX & \texttt{delimiters} after |\left|, \hfil\penalty0|\right|, etc.\\\midrule
\vrb\simeq\ and \vrb\cong & \texttt{symbols} & \texttt{extsymbols} \\
 & \texttt{extsymbols} & \\\bottomrule
\end{tabularx}
\end{figure}

As of version 2.0, \textsf{mathfont} artificially adds resizable delimiters and big operator characters to text fonts when you compile with Lua\LaTeX. In this case, square root symbols will automatically resize, big operators will appear larger in |\displaystyle|, and you can use |\left|, |\right|, and |\big|, etc.\ with characters from the keyword |delimiters|. If you use \XeTeX, \textsf{mathfont} will not create large variants of characters, and your unicode math symbols will all be the same size as they appear in the font. In this case, you may be best off sticking with the Computer Modern defaults for resizable characters provided they don't clash with the rest of your document. Throughout this document, anything labeled ``Lua\TeX\ only'' means that \textsf{mathfont} provides this functionality only if you enable Lua-based font adjustments. If you load \textsf{mathfont} in Lua\TeX\ with the |no-adjust| option, you will not be able to access these features the same as if you typeset with \XeTeX.


A few characters appear multiple times in this list. When that happens, it means that \textsf{mathfont} defines the control sequence for multiple keywords. If you call |\mathfont| for only one of those keywords, your symbol will appear in the font associated with that keyword. If you call |\mathfont| on multiple keywords, the package uses the font associated with the default keyword/font for that character. Table~1 lists the default keyword for each command that appears multiple times in this document. If you need unicode encoding slot numbers for character metric adjustments, each symbol corresponds to its standard unicode encoding value, with the exception of the fake angle brackets. When you typeset with Lua\TeX, \textsf{mathfont} artificially adds |\fakelangle|, |\fakerangle|, |\fakellangle|, and |\fakerrangle| to the font in encoding slots 1,044,508--1,044,511 respectively.

\bigskip\bigskip
\nointerlineskip\centerline{\vrule height 0.5pt width 2.5in}
\bigskip\bigskip

\catcode`\|=12

\blockheader{lower}{Lower-Case Latin}

\begin{multicols}{3}
\charexample a
\charexample b
\charexample c
\charexample d
\charexample e
\charexample f
\charexample g
\charexample h
\charexample i
\charexample j
\charexample k
\charexample l
\charexample m
\charexample n
\charexample o
\charexample p
\charexample q
\charexample r
\charexample s
\charexample t
\charexample u
\charexample v
\charexample w
\charexample x
\charexample y
\charexample z
\charexample\hbar
\charexample\imath
\charexample\jmath
\end{multicols}

\blockheader{upper}{Upper-Case Latin}

\begin{multicols}{3}
\charexample A
\charexample B
\charexample C
\charexample D
\charexample E
\charexample F
\charexample G
\charexample H
\charexample I
\charexample J
\charexample K
\charexample L
\charexample M
\charexample N
\charexample O
\charexample P
\charexample Q
\charexample R
\charexample S
\charexample T
\charexample U
\charexample V
\charexample W
\charexample X
\charexample Y
\charexample Z
\end{multicols}

\blockheader{diacritics}{Accent}

\begin{multicols}{3}
  \def\hook{\footnote{You will run into trouble if you load \textsf{amsmath} after calling \vrb\mathfont\ with the \texttt{accent} keyword. This is a known bug.}}
\accentexample\acute
  \let\hook\relax
\accentexample\aacute
\accentexample\dot
\accentexample\ddot
\accentexample\grave
\accentexample\breve
\accentexample\hat
\accentexample\check
\accentexample\bar
\accentexample\mathring
\accentexample\tilde
\end{multicols}

\blockheader{digits}{Arabic Numeral}

\begin{multicols}{3}
\charexample0
\charexample1
\charexample2
\charexample3
\charexample4
\charexample5
\charexample6
\charexample7
\charexample8
\charexample9
\end{multicols}

\blockheader{greekupper}{Upper-Case Greek}

\begin{multicols}{3}
\charexample\Alpha
\charexample\Beta
\charexample\Gamma
\charexample\Delta
\charexample\Epsilon
\charexample\Zeta
\charexample\Eta
\charexample\Theta
\charexample\Iota
\charexample\Kappa
\charexample\Lambda
\charexample\Mu
\charexample\Nu
\charexample\Xi
\charexample\Omicron
\charexample\Pi
\charexample\Rho
\charexample\Sigma
\charexample\Tau
\charexample\Upsilon
\charexample\Phi
\charexample\Chi
\charexample\Psi
\charexample\Omega
\charexample\varTheta
\charexample\increment
\charexample\nabla
\end{multicols}

\blockheader{greeklower}{Lower-Case Greek}

\begin{multicols}{3}
\charexample\alpha
\charexample\beta
\charexample\gamma
\charexample\delta
\charexample\epsilon
\charexample\zeta
\charexample\eta
\charexample\theta
\charexample\iota
\charexample\kappa
\charexample\lambda
\charexample\mu
\charexample\nu
\charexample\xi
\charexample\omicron
\charexample\pi
\charexample\rho
\charexample\sigma
\charexample\tau
\charexample\upsilon
\charexample\phi
\charexample\chi
\charexample\psi
\charexample\omega
\charexample\varbeta
\charexample\varepsilon
\charexample\varkappa
\charexample\vartheta
\charexample\varrho
\charexample\varsigma
\charexample\varphi
\end{multicols}

\blockheader{agreekupper}{Upper-Case Ancient Greek}

\begin{multicols}{3}
\charexample\Heta
\charexample\Sampi
\charexample\Digamma
\charexample\Koppa
\charexample\Stigma
\charexample\Sho
\charexample\San
\charexample\varSampi
\charexample\varDigamma
\charexample\varKoppa
\end{multicols}

\blockheader{agreeklower}{Lower-Case Ancient Greek}

\begin{multicols}{3}
\charexample\heta
\charexample\sampi
\charexample\digamma
\charexample\koppa
\charexample\stigma
\charexample\sho
\charexample\san
\charexample\varsampi
\charexample\vardigamma
\charexample\varkoppa
\end{multicols}

\blockheader{cyrillicupper}{Upper-Case Cyrillic}

\begin{multicols}{3}
\charexample\cyrA
\charexample\cyrBe
\charexample\cyrVe
\charexample\cyrGhe
\charexample\cyrDe
\charexample\cyrIe
\charexample\cyrZhe
\charexample\cyrZe
\charexample\cyrI
\charexample\cyrKa
\charexample\cyrEl
\charexample\cyrEm
\charexample\cyrEn
\charexample\cyrO
\charexample\cyrPe
\charexample\cyrEr
\charexample\cyrEs
\charexample\cyrTe
\charexample\cyrU
\charexample\cyrEf
\charexample\cyrHa
\charexample\cyrTse
\charexample\cyrChe
\charexample\cyrSha
\charexample\cyrShcha
\charexample\cyrHard
\charexample\cyrYeru
\charexample\cyrSoft
\charexample\cyrE
\charexample\cyrYu
\charexample\cyrYa
\charexample\cyrvarI
\end{multicols}

\blockheader{cyrilliclower}{Lower-Case Cyrillic}

\begin{multicols}{3}
\charexample\cyra
\charexample\cyrbe
\charexample\cyrve
\charexample\cyrghe
\charexample\cyrde
\charexample\cyrie
\charexample\cyrzhe
\charexample\cyrze
\charexample\cyri
\charexample\cyrka
\charexample\cyrel
\charexample\cyrem
\charexample\cyren
\charexample\cyro
\charexample\cyrpe
\charexample\cyrer
\charexample\cyres
\charexample\cyrte
\charexample\cyru
\charexample\cyref
\charexample\cyrha
\charexample\cyrtse
\charexample\cyrche
\charexample\cyrsha
\charexample\cyrshcha
\charexample\cyrhard
\charexample\cyryeru
\charexample\cyrsoft
\charexample\cyre
\charexample\cyryu
\charexample\cyrya
\charexample\cyrvari
\end{multicols}

\blockheader{hebrew}{Hebrew}

\begin{multicols}{3}
\charexample\aleph
\charexample\beth
\charexample\gimel
\charexample\daleth
\charexample\he
\charexample\vav
\charexample\zayin
\charexample\het
\charexample\tet
\charexample\yod
\charexample\kaf
\charexample\lamed
\charexample\mem
\charexample\nun
\charexample\samekh
\charexample\ayin
\charexample\pe
\charexample\tsadi
\charexample\qof
\charexample\resh
\charexample\shin
\charexample\tav
\charexample\varkaf
\charexample\varmem
\charexample\varnun
\charexample\varpe
\charexample\vartsadi
\end{multicols}

\medskip
\def\temp{; shown in \texttt{\vrb\big}, etc.\ sizes}
\blockheader{delimiters\aftergroup\temp}{Delimiter}
\medskip
\begin{multicols}{3}
\delimexample(
\delimexample)
\delimexample[
\delimexample]
\delimexample{\{\ifmmode\else\space(Lua\TeX\ only)\fi}
\delimexample{\}\ifmmode\else\space(Lua\TeX\ only)\fi}
\delimexample{|\,\ifmmode\else\space(Lua\TeX\ only)\fi}
\delimexample\lguil
\delimexample\rguil
\delimexample\llguil
\delimexample\rrguil
\luadelimexample\fakelangle
\luadelimexample\fakerangle
\luadelimexample\fakellangle
\luadelimexample\fakerrangle
\hbox to \hsize{\hbox to 0.8in{$\leftbrace$\hfil}\vrb\leftbrace\hfil}
\hbox to \hsize{\hbox to 0.8in{$\rightbrace$\hfil}\vrb\rightbrace\hfil}
\end{multicols}
\medskip

\blockheader{radical}{Square Root}
\smallskip
\begin{multicols}{2}
\charexample\surd
\def\temp{ (Lua\TeX\ only)\hfill}
\charexample{\sqrt{\ifmmode\mkern 12mu\vphantom{1}\else\temp\fi}}
\end{multicols}

\blockheader{bigops}{Big Operator}
\smallskip
\begin{multicols}{2}
\operatorexample\sum
\operatorexample\prod
\operatorexample\intop
\end{multicols}
\medskip

\blockheader{extbigops}{Extended Big Operators}
\smallskip
\begin{multicols}{3}
\operatorexample\coprod
\operatorexample\bigvee
\operatorexample\bigwedge
\operatorexample\bigcap
\operatorexample\bigcup
\operatorexample\bigoplus
\operatorexample\bigotimes
\operatorexample\bigodot
\operatorexample\bigsqcap
\operatorexample\bigsqcup
\operatorexample\iint
\operatorexample\iiint
\operatorexample\oint
\operatorexample\oiint
\operatorexample\oiiint
\end{multicols}

\medskip

\blockheader{symbols}{Basic Math}
\begin{multicols}{3}
\charexample.
\charexample @
\let\par\relax
\charexample\#
\charexample\$
\charexample\%
\charexample\&
\charexample\P
\charexample\S
\charexample\pounds
\charexample|
\charexample\neg
\charexample\infty
\charexample\partial
\charexample\mathbackslash
\charexample\degree
\charexample\increment
\def\temp{ (Lua\TeX\ only)}
\charexample{\nabla\ifmmode\else\temp\fi}
\charexample'
\charexample\prime
\charexample"
\charexample+
\charexample-
\charexample*
\charexample\times
\charexample/
\charexample\fractionslash
\charexample\div
\charexample\pm
\charexample\bullet
\charexample\dag
\charexample\ddag
\charexample\cdot
\charexample\setminus
\charexample=
\charexample<
\charexample>
\charexample\leq
\charexample\geq
\charexample\sim
\charexample\approx
\charexample\simeq
\charexample\equiv
\charexample\cong
\charexample\mid
\charexample\parallel
\charexample!
\charexample?
\charexample{,\ifmmode\else\phantom{\texttt{comma}} (as \rlap{\vrb\mathpunct)}\fi}
\charexample{\comma\ifmmode\else\space(as \vrb\mathord)\fi}
\charexample{:\ifmmode\else\phantom{\texttt{colon}} (as \vrb\mathrel)\fi}
\charexample{\colon\ifmmode\else\space(as \vrb\mathpunct)\fi}
\charexample;
\charexample\mathellipsis
\end{multicols}
\blockheader{symbols}{Lua\TeX-only (!) Operator}
\begin{multicols}{3}
\operatorexample\bigat
\operatorexample\bighash
\operatorexample\bigdollar
\operatorexample\bigpercent
\operatorexample\bigand
\operatorexample\bigplus
\operatorexample\bigp
\operatorexample\bigq
\operatorexample\bigS
\operatorexample\bigtimes
\operatorexample\bigdiv
\end{multicols}




\blockheader{extsymbols}{Extended Math}
\begin{multicols}{3}
\charexample\wp
\charexample\Re
\charexample\Im
\charexample\ell
\charexample\forall
\charexample\exists
\charexample\emptyset
\charexample{\nabla\ifmmode\else\space(\XeTeX\ only)\fi}
\charexample\in
\charexample\ni
\charexample\mp
\charexample\angle
\charexample\top
\charexample\bot
\charexample\vdash
\charexample\dashv
\charexample\flat
\charexample\natural
\charexample\sharp
\charexample\bclubsuit
\charexample\clubsuit
\charexample\bdiamondsuit
\charexample\bheartsuit
\charexample\bspadesuit
\charexample\spadesuit
\charexample\wclubsuit
\charexample\wdiamondsuit
\charexample\diamondsuit
\charexample\wheartsuit
\charexample\heartsuit
\charexample\wspadesuit
\charexample\wedge
\charexample\vee
\charexample\cap
\charexample\cup
\charexample\sqcap
\charexample\sqcup
\charexample\amalg
\charexample\wr
\charexample\ast
\charexample\star
\charexample\diamond
\charexample\varcdot
\charexample\varsetminus
\charexample\oplus
\charexample\otimes
\charexample\ominus
\charexample\odiv
\charexample\oslash
\charexample\odot
\charexample\sqplus
\charexample\sqtimes
\charexample\sqminus
\charexample\sqdot
\charexample\in
\charexample\ni
\charexample\subset
\charexample\supset
\charexample\subseteq
\charexample\supseteq
\charexample\sqsubset
\charexample\sqsupset
\charexample\sqsubseteq
\charexample\sqsupseteq
\charexample\triangleleft
\charexample\triangleright
\charexample\trianglelefteq
\charexample\trianglerighteq
\charexample\propto
\charexample\bowtie
\charexample\hourglass
\charexample\therefore
\charexample\because
\charexample\ratio
\charexample\proportion
\charexample\ll
\charexample\gg
\charexample\lll
\charexample\ggg
\charexample\leqq
\charexample\geqq
\charexample\lapprox
\charexample\gapprox
\charexample\simeq
\charexample\eqsim
\charexample\simeqq
\charexample\cong
\charexample\approxeq
\charexample\sssim
\charexample\seq
\charexample\doteq
\charexample\coloneq
\charexample\eqcolon
\charexample\ringeq
\charexample\arceq
\charexample\wedgeeq
\charexample\veeeq
\charexample\stareq
\charexample\triangleeq
\charexample\defeq
\charexample\qeq
\charexample\lsim
\charexample\gsim
\charexample\prec
\charexample\succ
\charexample\preceq
\charexample\succeq
\charexample\preceqq
\charexample\succeqq
\charexample\precsim
\charexample\succsim
\charexample\precapprox
\charexample\succapprox
\charexample\precprec
\charexample\succsucc
\charexample\asymp
\charexample\nin
\charexample\nni
\charexample\nsubset
\charexample\nsupset
\charexample\nsubseteq
\charexample\nsupseteq
\charexample\subsetneq
\charexample\supsetneq
\charexample\nsqsubseteq
\charexample\nsqsupseteq
\charexample\sqsubsetneq
\charexample\sqsupsetneq
\charexample\neq
\charexample\nl
  \def\hook{\footnote{In text mode, \vrb\ng\ produces \ng---as of version 2.2b, \textsf{mathfont} redefines the math-mode version only and leaves the text-mode version alone. If you are using the \textsf{hyperref} package, you should type \vrb\mathng\ instead of \vrb\ng.}}
\charexample\ng
  \let\hook\relax
\charexample\nleq
\charexample\ngeq
\charexample\lneq
\charexample\gneq
\charexample\lneqq
\charexample\gneqq
\charexample\ntriangleleft
\charexample\ntriangleright
\charexample\ntrianglelefteq
\charexample\ntrianglerighteq
\charexample\nsim
\charexample\napprox
\charexample\nsimeq
\charexample\nsimeqq
\charexample\simneqq
\charexample\nlsim
\charexample\ngsim
\charexample\lnsim
\charexample\gnsim
\charexample\lnapprox
\charexample\gnapprox
\charexample\nprec
\charexample\nsucc
\charexample\npreceq
\charexample\nsucceq
\charexample\precneq
\charexample\succneq
\charexample\precneqq
\charexample\succneqq
\charexample\precnsim
\charexample\succnsim
\charexample\precnapprox
\charexample\succnapprox
\charexample\nequiv
\end{multicols}


\blockheader{arrows}{Arrow}
\begin{multicols}{2}
  \def\hook{\footnote{Both \vrb\relbar\space and \vrb\Relbar\space are helper macros that certain packages use to elongate various horizontal arrows.}}
\charexample\relbar
  \let\hook\relax
\charexample\Relbar
\charexample\rightarrow
\charexample\to
\charexample\nrightarrow
\charexample\Rightarrow
\charexample\nRightarrow
\charexample\Rrightarrow
\charexample\longrightarrow
\charexample\Longrightarrow
\charexample\rightbararrow
\charexample\mapsto
\charexample\Rightbararrow
\charexample\longrightbararrow
\charexample\longmapsto
\charexample\Longrightbararrow
\charexample\hookrightarrow
\charexample\rightdasharrow
\charexample\rightharpoonup
\charexample\rightharpoondown
\charexample\rightarrowtail
\charexample\rightoplusarrow
\charexample\rightwavearrow
\charexample\rightsquigarrow
\charexample\longrightsquigarrow
\charexample\looparrowright
\charexample\curvearrowright
\charexample\circlearrowright
\charexample\twoheadrightarrow
\charexample\rightarrowtobar
\charexample\rightwhitearrow
\charexample\rightrightarrows
\charexample\rightrightrightarrows
\charexample\leftarrow
\charexample\from
\charexample\nleftarrow
\charexample\Leftarrow
\charexample\nLeftarrow
\charexample\Lleftarrow
\charexample\longleftarrow
\charexample\Longleftarrow
\charexample\leftbararrow
\charexample\mapsfrom
\charexample\Leftbararrow
\charexample\longleftbararrow
\charexample\longmapsfrom
\charexample\Longleftbararrow
\charexample\hookleftarrow
\charexample\leftdasharrow
\charexample\leftharpoonup
\charexample\leftharpoondown
\charexample\leftarrowtail
\charexample\leftoplusarrow
\charexample\leftwavearrow
\charexample\leftsquigarrow
\charexample\longleftsquigarrow
\charexample\looparrowleft
\charexample\curvearrowleft
\charexample\circlearrowleft
\charexample\twoheadleftarrow
\charexample\leftarrowtobar
\charexample\leftwhitearrow
\charexample\leftleftarrows
\charexample\leftleftleftarrows
\charexample\leftrightarrow
\charexample\Leftrightarrow
\charexample\nLeftrightarrow
\charexample\longleftrightarrow
\charexample\Longleftrightarrow
\charexample\leftrightwavearrow
\charexample\leftrightarrows
\charexample\leftrightharpoons
\charexample\leftrightarrowstobar
\charexample\rightleftarrows
\charexample\rightleftharpoons
\charexample\uparrow
\charexample\Uparrow
\charexample\Uuparrow
\charexample\upbararrow
\charexample\updasharrow
\charexample\upharpoonleft
\charexample\upharpoonright
\charexample\twoheaduparrow
\charexample\uparrowtobar
\charexample\upwhitearrow
\charexample\upwhitebararrow
\charexample\upuparrows
\charexample\downarrow
\charexample\Downarrow
\charexample\Ddownarrow
\charexample\downbararrow
\charexample\downdasharrow
\charexample\zigzagarrow
\charexample\lightningboltarrow
\charexample\downharpoonleft
\charexample\downharpoonright
\charexample\twoheaddownarrow
\charexample\downarrowtobar
\charexample\downwhitearrow
\charexample\downdownarrows
\charexample\updownarrow
\charexample\Updownarrow
\charexample\updownarrows
\charexample\downuparrows
\charexample\updownharpoons
\charexample\downupharpoons
\charexample\nearrow
\charexample\Nearrow
\charexample\nwarrow
\charexample\Nwarrow
\charexample\searrow
\charexample\Searrow
\charexample\swarrow
\charexample\Swarrow
\charexample\nwsearrow
\charexample\neswarrow
\charexample\lcirclearrow
\charexample\rcirclearrow
\end{multicols}


\blockheader{bb}{Blackboard Bold}

\vskip\multicolsep
\letterlikechars\mathbb
\hbox to \hsize{\printchars\digits\hfil}
\vskip\multicolsep

\blockheader{cal}{Caligraphic}

\vskip\multicolsep
\letterlikechars\mathcal
\vskip\multicolsep

\blockheader{frak}{Fraktur}

\vskip\multicolsep
\letterlikechars\mathfrak
\vskip\multicolsep

\blockheader{bcal}{Bold Calligraphic}

\vskip\multicolsep
\letterlikechars\mathbcal
\vskip\multicolsep

\blockheader{bfrak}{Bold Fraktur}

\vskip\multicolsep
\letterlikechars\mathbfrak

\end{document}
%</chars>
%<*equations>
\multicolsep=0pt\relax
\bigskip
\begin{multicols*}{2}

Black-Scholes Equation
\[
\frac{\partial V}{\partial t}+
  \frac12\sigma^2S^2\frac{\partial^2V}{\partial S^2}
  =rV-rS\frac{\partial V}{\partial X}
\]

\vfill

Cardano's Formula/Cubic Formula
\begin{align*}
t_i&=\omega_i\sqrt[3]{-\frac q2+\sqrt{\frac{q^2}4+\frac{p^3}{27}}}\\
  &\qquad\qquad{}+\omega_i^2\sqrt[3]{-\frac q2-\sqrt{\frac{q^2}4+\frac{p^3}{27}}}
\end{align*}

\vfill

Einstein's Field Equation (General Relativity)
\[
R_{\mu\nu}-\frac12Rg_{\mu\nu}+\Lambda g_{\mu\nu}=\frac{8\pi G}{c^4}T_{\mu\nu}
\]

\vfill

First Isomorphism Theorem
\[
\phi(X)\cong X/\ker(\phi)
\]

\vfill

Gauss-Bonnet Formula
\[
\int_MK\ dA+\int_{\partial M}k_g\ ds=2\pi\chi(M)
\]

\vfill

Maxwell's Equations
\begin{align*}
\nabla\bullet\mathbf E&=\frac\rho{\epsilon_0}&
\nabla\bullet\mathbf B&=0\\
\nabla\times\mathbf E&=-\frac{\partial\mathbf B}{\partial t}&
\nabla\times\mathbf B&=\mu_0\left(\mathbf J+
  \epsilon_0\frac{\partial\mathbf E}{\partial t}\right)
\end{align*}

\vfill

Michaelis-Menten Model
\bgroup
\belowdisplayskip=0pt\relax
\belowdisplayshortskip=0pt\relax
\[
v=\frac{d[P]}{dt}=V\frac{[S]}{K_M+[S]}
\]
\par\egroup
\hrule height 0pt
\columnbreak
%% next column begins here


Navier-Stokes Equation
\begin{align*}
\frac{\partial}{\partial t}(\rho\mathbf{u})+\nabla\bullet
  (\rho \mathbf{u}\otimes \mathbf{u})={}
  &{-}\nabla\bar p+\mu\nabla^2\mathbf{u}\\
  &+\frac13\mu\nabla(\nabla\bullet u)+
  \rho\mathbf{g}
\end{align*}

\vfill

Quadratic Formula
\[
x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}
\]

\vfill

Ramanujan's Approximation for $\Gamma$
\[
\Gamma(1+x)\approx\sqrt\pi\,x^xe^{-x}\,\sqrt[6]{8x^3+4x^2+x+\frac1{30}}
\]

\vfill

Residue Theorem
\[
\frac1{2i\pi}\int_{\gamma}f(z)\ dz=\sum_{k=1}^n\Res_{a_k}(f)
\]


\vfill

Riemann Zeta Function
\begin{align*}
\zeta(z)&=\sum_{i=1}^\infty\frac1{z^i}
  =\frac1{\Gamma(z)}\int_0^\infty\frac{x^{z-1}}{e^x-1}\ dx\\
  &=2^z\pi^{z-1}\sin\left(\frac{\pi z}2\right)\,\Gamma(1-z)\,\zeta(1-z)
\end{align*}


\vfill

Schrodinger Equation
\[
i\hbar\frac d{dt}|\Psi(t)\fakerangle=\hat H|\Psi(t)\fakerangle
\]

\vfill


Lorentz Transformation (Special Relativity)
\belowdisplayskip=0pt\relax
\belowdisplayshortskip=0pt\relax
\[
t'=\left(t-\frac{vx}{c^2}\right)\frac1{\sqrt{1-\frac{v^2}{c^2}}}
\]
\hrule height 0pt

\end{multicols*}
%</equations>
%<*cormorant>
\ifx\directlua\undefined
  \PackageError{mathfont}
  {\MessageBreak
  LuaLaTeX is recommended for\MessageBreak
  mathfont-example-cormorant.tex}
  {It's recommended that you typset this file\MessageBreak
  with LuaTeX. You can use XeLaTeX if you want,\MessageBreak
  but things will turn out weird. To resolve\MessageBreak
  this error, typeset the file with LuaLaTeX.}
\fi
\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{innerscript}
\usepackage{multicol}
\usepackage{amsmath}
\DeclareMathOperator{\Res}{Res}
\usepackage{mathfont}
\mathfont[greeklower=upright,greekupper]{Crimson}
\mathfont[diacritics]{Bona Nova}
\setfont{Cormorant:-liga}
\RuleThicknessFactor{600}
\DeclareMathSymbol{\nabla}{\mathord}{Mupright0}{"2207}
\parindent=0pt\relax
\begin{document}

\def\footnote#1{}
\def\showabstract{0}
\let\textsf\relax
\let\ttfamily\relax
\def\documentname{Example---Cormorant}

\input mathfont-heading.tex

This is Cormorant with Crimson for Greek characters and Bona Nova for diacritics. ``Testing. Testing.'' Brown foxes quickly jump over dazzling does and harts. This document shows an example of mathfont in action. Unfortunately, there are many more equations in the world than I have space for here. Nevertheless, I hope I hit some of the highlights. Happy \TeX ing!


\input{mathfont-equations.tex}

\end{document}
%</cormorant>
%<*kelvinch>
\ifx\directlua\undefined
  \PackageError{mathfont}
  {\MessageBreak
  LuaLaTeX is recommended for\MessageBreak
  mathfont-example-kelvinch.tex}
  {It's recommended that you typset this file\MessageBreak
  with LuaTeX. You can use XeLaTeX if you want,\MessageBreak
  but things will turn out weird. To resolve\MessageBreak
  this error, typeset the file with LuaLaTeX.}
\fi
\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{innerscript}
\usepackage{multicol}
\usepackage{amsmath}
\DeclareMathOperator{\Res}{Res}
\usepackage{mathfont}
\mathfont[radical]{Crimson}
\setfont{Kelvinch:-clig}
\IntegralItalicFactor{500}
\SurdHorizontalFactor{900}
\parindent=0pt\relax
\begin{document}

\def\footnote#1{}
\def\showabstract{0}
\let\textsf\relax
\let\ttfamily\relax
\def\documentname{Example---Kelvinch}

\input mathfont-heading.tex

This is Kelvinch with Crimson for the radical signs. ``Testing. Testing.'' Brown foxes quickly jump over dazzling does and harts. This document shows an example of mathfont in action. Unfortunately, there are many more equations in the world than I have space for here. Nevertheless, I hope I hit some of the highlights. Happy \TeX ing!

\input{mathfont-equations.tex}

\end{document}
%</kelvinch>
%<*roboto>
\ifx\directlua\undefined
  \PackageError{mathfont}
  {\MessageBreak
  LuaLaTeX is recommended for\MessageBreak
  mathfont-example-roboto.tex}
  {It's recommended that you typset this file\MessageBreak
  with LuaTeX. You can use XeLaTeX if you want,\MessageBreak
  but things will turn out weird. To resolve\MessageBreak
  this error, typeset the file with LuaLaTeX.}
\fi
\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{innerscript}
\usepackage{multicol}
\usepackage{amsmath}
\DeclareMathOperator{\Res}{Res}
\usepackage{mathfont}
\mathfont[radical]{Overpass}
\setfont{Roboto}
\mathfont[]{STIXGeneral}
\DeclareSymbolFont{Mupright2}{TU}{STIXGeneral}{m}{n}
\DeclareMathSymbol{\otimes}{\mathbin}{Mupright2}{"2297}
\RuleThicknessFactor{1900}
\IntegralItalicFactor{500}
\SurdHorizontalFactor{800}
\parindent=0pt\relax
\begin{document}

\def\footnote#1{}
\def\showabstract{0}
\let\textsf\relax
\let\ttfamily\relax
\def\documentname{Example---Roboto}

\input mathfont-heading.tex

This is Roboto with Overpass for the radical signs and STIXGeneral for the tensor product. ``Testing. Testing.'' Brown foxes quickly jump over dazzling does and harts. This document shows an example of mathfont in action. Unfortunately, there are many more equations in the world than I have space for here. Nevertheless, I hope I hit some of the highlights. Happy \TeX ing!


\input{mathfont-equations.tex}

\end{document}
%</roboto>
%<*typey>
\ifx\directlua\undefined
  \PackageError{mathfont}
  {\MessageBreak
  LuaLaTeX is recommended for\MessageBreak
  mathfont-example-typey.tex}
  {It's recommended that you typset this file\MessageBreak
  with LuaTeX. You can use XeLaTeX if you want,\MessageBreak
  but things will turn out weird. To resolve\MessageBreak
  this error, typeset the file with LuaLaTeX.}
\fi
\documentclass[12pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{innerscript}
\usepackage{multicol}
\usepackage{amsmath}
\DeclareMathOperator{\Res}{Res}
\usepackage{mathfont}
\mathfont[radical]{Crimson}

%% We have to declare Typey McTypeface manually because
%% it has no bold fontface---we use embolden from luaotflaod
%% to make a fake bold

\makeatletter
\DeclareFontFamily{TU}{Typey}{}
\DeclareFontShape{TU}{Typey}{m}{n}
  {<->"Typey McTypeface:\M@otf@features"}{}
\DeclareFontShape{TU}{Typey}{m}{it}
  {<->"Typey McTypeface/I:\M@otf@features"}{}
\DeclareFontShape{TU}{Typey}{b}{n}
  {<->"Typey McTypeface:\M@otf@features;embolden=6"}{}
\DeclareFontShape{TU}{Typey}{b}{it}
  {<->"Typey McTypeface/I:\M@otf@features;embolden=6"}{}

%% We also need to declare Typey-base family for math mode

\DeclareFontFamily{TU}{Typey-base}{}
\DeclareFontShape{TU}{Typey-base}{\mddefault}{\shapedefault}
  {<->"Typey McTypeface:\M@otf@features;mode=base"}{}
\DeclareFontShape{TU}{Typey-base}{\mddefault}{\itdefault}
  {<->"Typey McTypeface/I:\M@otf@features;mode=base"}{}
\DeclareFontShape{TU}{Typey-base}{\bfdefault}{\shapedefault}
  {<->"Typey McTypeface:\M@otf@features;embolden=6;mode=base"}{}
\DeclareFontShape{TU}{Typey-base}{\bfdefault}{\itdefault}
  {<->"Typey McTypeface/I:\M@otf@features;embolden=6;mode=base"}{}

%% And link the Typey-base font family to the Typey family
\expandafter\def\csname Typey-base\endcsname{Typey-base}
\makeatother

\setfont{Typey}
\mathfont[]{STIXGeneral}
\DeclareSymbolFont{stix}{TU}{STIXGeneral}{m}{n}
\DeclareMathSymbol{\otimes}{\mathbin}{stix}{"2297}
\RuleThicknessFactor{1300}
\SurdHorizontalFactor{860}
\parindent=0pt\relax
\begin{document}

\def\footnote#1{}
\def\showabstract{0}
\let\textsf\relax
\let\ttfamily\relax
\def\documentname{Example---Typey McTypeface}

\input mathfont-heading.tex

This is Typey McTypeface with Crimson for the radical signs and STIXGeneral for the tensor product. ``Testing. Testing.'' Brown foxes quickly jump over dazzling does and harts. This document shows mathfont in action. Unfortunately, there are many more equations in the world than I have space for here. Nevertheless, I hope I hit some of the highlights. Happy \TeX ing!

\let\bullet\cdot
\input{mathfont-equations.tex}

\end{document}
%</typey>
%<*heading>

\csname count@\endcsname\catcode`\@
\makeatletter

% package date and edition
\def\packagedate{June 2025}
\def\packageversion{2.4a}

% header and footer commands
\let\@@section\section
\def\section{%
  \vskip0.6in\relax
  \kern\z@
  \vskip-0.6in\relax
  \vskip\z@
  \@ifstar\star@sect\no@star@sect}
\def\star@sect#1{\@@section*{#1}\section@name{#1}}
\def\no@star@sect#1{\@@section{#1}\section@name{#1}}
\def\section@name#1{\expandafter
  \def\csname section@\thesection\endcsname{#1}}
\def\sectionname{\csname section@\thesection\endcsname}

\def\@oddhead{\ifnum\c@page>\@ne
    \ifodd\c@page
      \rlap{\textit{\sectionname}}\hfil
      \hbox to 0pt{\hss\documentname\hss}\hfil
      \llap{\the\c@page}\relax
    \else
      \rlap{\the\c@page}\hfil
      \hb@xt@\z@{\hss\documentname\hss}\hfil
      \llap{\textit{\sectionname}}\relax
    \fi
  \else
    \hfil
  \fi}
\def\@oddfoot{\hfil\ifnum\count0=1\relax1\fi\hfil}
\let\@evenfoot\@empty

% penalties
\pretolerance=20
\hyphenpenalty=10
\exhyphenpenalty=5
\brokenpenalty=0
\clubpenalty=5
\widowpenalty=5
\finalhyphendemerits=300
\doublehyphendemerits=500

\flushbottom

% general macros
\protected\def\XeTeX{X\kern-0.125em
  \raise-0.5ex\hbox{\reflectbox{E}}\kern-0.1667em
  \TeX}
\protected\def\XeLaTeX{X\kern-0.125em
  \raise-0.5ex\hbox{\reflectbox{E}}\kern-0.125em
  \LaTeX}
\bgroup
  \catcode`\|=12\relax
  \gdef\indexpage#1{\index{#1|usage}}
\egroup
\protected\def\usage#1{\textit{p.~#1}}
\bgroup
\catcode`\_=12
  \protected\gdef\fontspeccommand{\texttt{\string\fontspec_set_family:Nnn}}
  \protected\gdef\fontspecbool{\texttt{\string\g__fontspec_math_bool}}
\egroup
\def\topfraction{1}
\def\bottomfraction{1}
\let\code\@undefined
\newenvironment{code}
  {\strut\vadjust\bgroup\vskip 5pt plus 1pt minus 3pt\relax
    \parindent\z@\leftskip2em\relax
    \noindent\strut\ignorespaces}
  {\strut\par\vskip 5pt plus 1pt minus 3pt\relax
    \egroup\hfill\break\strut\ignorespacesafterend}
\def\vrb#1{\expandafter\texttt\expandafter{\string#1}}
\parskip=0pt

% symbol list macros
\def\charexample#1{\hbox to \hsize{\hbox to 0.4in{$#1$\hfil}\vrb#1\hook\hfil}}
\def\accentexample#1{\hbox to \hsize{\hbox to 0.4in{$#1 a$\hfil}\vrb#1\hook\hfil}}
\let\hook\relax
\def\delimexample#1{\hbox to \hsize{%
  \hbox to 0.8in{$#1\big#1\Big#1\bigg#1\Bigg#1$\hfil}\vrb#1\hfil}}
\def\luadelimexample#1{\hbox{\vbox{\hbox to 0.8in{%
    $#1\big#1\Big#1\bigg#1\Bigg#1$\hfil}\hrule width 0pt height 0pt\relax}%
  \hbox to \dimexpr\hsize-0.8in{\vbox{\vss
    \hbox{\vrb#1}
    \hbox{\quad(Lua\TeX only)}
    \vss}\hfil}}}
\def\operatorexample#1{\hbox to \hsize{%
  \hbox to 0.4in{$#1$\hfil}%
  \hbox to 0.4in{$\displaystyle#1$\hfil}\vrb#1\hfil}\smallskip}
\def\blockheader#1#2{%
  \hbox{\fbox{\hbox to \dimexpr\hsize-2\fboxrule-2\fboxsep\relax{%
    \hfil#2 Characters (Keyword \texttt{#1})\strut\hfil}}}}
\def\upperalphabet{ABCDEFGHIJKLMNOPQRSTUVWXYZ}
\def\loweralphabet{abcdefghijklmnopqrstuvwxyz}
\def\digits{0123456789}
\def\printchars#1{%
  \expandafter\@tfor\expandafter\letter\expandafter:\expandafter=#1\do{%
  \hbox to \dimexpr\hsize/26{$\@tempstyle{\letter}$\hfil}}}
\def\letterlikechars#1{\smallskip\let\@tempstyle#1
  \noindent\printchars\upperalphabet\par
  \noindent\printchars\loweralphabet\par}

% title information
{\large\parindent=0pt\leftskip=0pt plus 1 fil\rightskip=0pt plus 1fil\parfillskip=0pt
{\strut\Large Package \textsf{mathfont} v.\ \packageversion\ \documentname\let\thefootnote\relax\footnote{Acknowledgements: Thanks to Lyric Bingham for her work checking my unicode hex values. Thanks to Matthew Braham, Sergio Callegari, Daniel Flipo, Shyam Sundar, Adrian Vollmer, Herbert Voss, and Andreas Zidak for pointing out bugs in previous versions of \textsf{mathfont}. Thanks to Jean-Fran\c cois Burnol for pointing out an error in the documentation in reference to his \textsf{mathastext} package.}\global\advance\c@footnote\m@ne}\par
{\strut Conrad Kosowsky}\par
{\strut\packagedate}\par
{\strut\ttfamily kosowsky.latex@gmail.com}\par}

\bigskip

\ifnum\showabstract=1\relax

% off-the-shelf insert
\hrule height \p@\hbox{\vrule width \p@\kern-\p@\relax\vbox{\medskip
{\leftskip=0.8in\rightskip=0.8in
\noindent\strut For easy, off-the-shelf use, type the following in your preamble and compile with \XeLaTeX\ or Lua\LaTeX:\par
\medskip
\vbox{\noindent\hfil{|\usepackage[|\meta{font name}|]{mathfont}|}\hfil}
\medskip
\noindent As of version 2.0, using Lua\LaTeX\ is recommended.\par}
\medskip}\kern-\p@\vrule width \p@}\hrule height \p@

\bigskip

{\small
\leftskip=0.5in\relax
\rightskip=0.5in\relax

% abstract
\centerline{\bfseries Overview\strut}
\noindent The \textsf{mathfont} package adapts unicode text fonts for math mode. The package allows the user to specify a default unicode font for different classes of math symbols, and it provides tools to change the font locally for math alphabet characters. When typesetting with Lua\TeX, \textsf{mathfont} adds resizable delimiters, big operators, and a MathConstants table to text fonts.\par}

\bigskip\bigskip\nointerlineskip
\centerline{\vrule height 0.5pt width 2.5in}\bigskip\bigskip
\nointerlineskip
\fi

\catcode`\@\count@

%</heading>
%<*doc>

% definitions and a new toks
\let\?\SpecialUsageIndex
\expandafter\newif\csname if@def\endcsname
\newtoks\index@nomainlist
\index@nomainlist{}
\MacrocodeTopsep=2.5pt plus 3pt minus 1pt
\def\@defname{def}
\def\@edefname{edef}
\def\@gdefname{gdef}
\def\@xdefname{xdef}
\def\@letname{let}
\let\main\textbf

% choose macros not to index by definition
\def\DoNotIndexMain{\bgroup
  \catcode`\\=12\relax
  \do@not@index@main}
\def\do@not@index@main#1{\egroup
  \index@nomainlist\expandafter{\the\index@nomainlist#1,}}

% the patch
\reversemarginpar
\@mparswitchfalse
\marginparsep=0.5em
\newbox\@tempboxb
\newbox\macrobox
\marginparwidth=\dimexpr1.5in-2\marginparsep\relax

% macro to put macros in the margin
% we need to \let\par\relax because \marginpar
% contains a transition to h mode and back to v
% mode that will mess up our code line numbering
\def\marginmacro#1\@nil{\begingroup\footnotesize
  \setbox\macrobox\vbox{}\relax
  \setbox\@tempboxa\hbox{\@backslashchar}\relax
  \@tfor\@i:=#1\do
      {\setbox\@tempboxb\hbox{\@i}\relax
        \ifdim\dimexpr\wd\@tempboxa+\wd\@tempboxb\relax
            <\marginparwidth
          \setbox\@tempboxa\hbox{\unhbox\@tempboxa\unhbox\@tempboxb}\else
          \@break@tfor\fi}\relax
  \let\par\relax
  \marginpar{\hb@xt@\marginparwidth{\hfil\unhbox\@tempboxa}}\endgroup}

\def\macro@finish{\macro@namepart
  \if@def
    \@deffalse
    \@expandtwoargs\in@{\macro@namepart}{\the\index@excludelist}\relax
    \ifin@
    \else
      \@expandtwoargs\in@{\macro@namepart}{\the\index@nomainlist}\relax
      \ifin@
        \edef\@tempa{\noexpand\SpecialIndex{\bslash\macro@namepart}}\relax
        \@tempa
      \else
        \edef\@tempa{\noexpand\SpecialMainIndex{\bslash\macro@namepart}}\relax
        \expandafter\marginmacro\macro@namepart\@nil
        \@tempa
      \fi
    \fi
  \else
    \ifx\macro@namepart\@defname
      \@deftrue
    \else
      \ifx\macro@namepart\@edefname
        \@deftrue
      \else
        \ifx\macro@namepart\@letname
          \@deftrue
        \else
          \ifx\macro@namepart\@gdefname
            \@deftrue
          \else
            \ifx\macro@namepart\@xdefname
              \@deftrue
            \fi
          \fi
        \fi
      \fi
    \fi
    \@expandtwoargs\in@{\macro@namepart}{\the\index@excludelist}\relax
    \ifin@
    \else
      \edef\@tempa{\noexpand\SpecialIndex{\bslash\macro@namepart}}\relax
      \@tempa
    \fi
  \fi}

% the other patch (just one change: \parskip\z@ to \parskip 0pt plus 0.2pt)
\def\macro@code{%
   \topsep \MacrocodeTopsep
   \@beginparpenalty0% \predisplaypenalty
   \if@inlabel\leavevmode\fi
   \trivlist \parskip 0pt plus 0.2pt \item[]%
   \macro@font
   \leftskip\@totalleftmargin \advance\leftskip\MacroIndent
   \rightskip\z@ \parindent\z@ \parfillskip\@flushglue
   \blank@linefalse \def\par{\ifblank@line
                             \leavevmode\fi
                             \blank@linetrue\@@par
                             \penalty\interlinepenalty}
   \obeylines
   \let\do\do@noligs \verbatim@nolig@list
   \let\do\@makeother \dospecials
   \global\@newlistfalse
   \global\@minipagefalse
   \ifcodeline@index
     \everypar{\global\advance\c@CodelineNo\@ne
               \llap{\theCodelineNo\ \hskip\@totalleftmargin}%
               \check@module}%
   \else \everypar{\check@module}%
   \fi
   \init@crossref}
%</doc>
% 
% \fi
% 
% \check@checksum
% 
\endinput