# -*- mode: Perl -*-
# /=====================================================================\ #
# |  etoolbox                                                           | #
# | Implementation for LaTeXML                                          | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

RawTeX(<<'EoTeX');
\def\etb@catcodes{\do\&\do\|\do\:\do\-\do\=\do\<\do\>}
\def\do#1{\catcode\number`#1=\the\catcode`#1\relax}
\edef\etb@catcodes{\etb@catcodes}
\let\do\noexpand
\AtEndOfPackage{\etb@catcodes\undef\etb@catcodes}

\catcode`\&=3
\catcode`\|=3
\@makeother\:
\@makeother\-
\@makeother\=
\@makeother\<
\@makeother\>

\protected\def\etb@error{\PackageError{etoolbox}}
\protected\def\etb@warning{\PackageWarning{etoolbox}}
\protected\def\etb@info{\PackageInfo{etoolbox}}
\newcount\etb@tempcnta
EoTeX

DefMacro('\newrobustcmd OptionalMatch:* DefToken [Number][]{}', sub {
    my ($stomach, $star, $cs, $nargs, $opt, $body) = @_;
    if (!isDefinable($cs)) {
      Info('ignore', $cs, $stomach,
        "Ignoring redefinition (\\newcommand) of '" . ToString($cs) . "'")
        unless LookupValue(ToString($cs) . ':locked'); }
    else {
      DefMacroI($cs, convertLaTeXArgs($nargs, $opt), $body, protected => 1, long => 1); }
    return Tokens(); });

DefMacro('\renewrobustcmd OptionalMatch:* DefToken [Number][]{}', sub {
    my ($stomach, $star, $cs, $nargs, $opt, $body) = @_;
    DefMacroI($cs, convertLaTeXArgs($nargs, $opt), $body, protected => 1, long => 1);
    return Tokens(); });

DefMacro('\providerobustcmd OptionalMatch:* DefToken [Number][]{}', sub {
    my ($stomach, $star, $cs, $nargs, $opt, $body) = @_;
    if (isDefinable($cs)) {
      DefMacroI($cs, convertLaTeXArgs($nargs, $opt), $body, protected => 1, long => 1); }
    return Tokens(); });

RawTeX(<<'EoTeX');

% {<csname>}

\newrobustcmd*{\csshow}[1]{%
  \begingroup\expandafter\endgroup
  \expandafter\show\csname#1\endcsname}

% {<csname>}

\newcommand*{\csmeaning}[1]{%
  \ifcsname #1\endcsname
    \expandafter\meaning\csname #1\endcsname
  \else
    \detokenize{undefined}%
  \fi}

% {<cstoken>}{<true>}{<false>}

\newcommand{\ifdef}[1]{%
  \ifdefined#1%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<cstoken>}{<true>}{<false>}

\newcommand{\ifundef}[1]{%
  \ifdefined#1%
    \ifx#1\relax
      \expandafter\expandafter
      \expandafter\@firstoftwo
    \else
      \expandafter\expandafter
      \expandafter\@secondoftwo
    \fi
  \else
    \expandafter\@firstoftwo
  \fi}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsdef}[1]{%
  \ifcsname#1\endcsname
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsundef}[1]{%
  \ifcsname#1\endcsname
    \expandafter\ifx\csname#1\endcsname\relax
      \expandafter\expandafter
      \expandafter\@firstoftwo
    \else
      \expandafter\expandafter
      \expandafter\@secondoftwo
    \fi
  \else
    \expandafter\@firstoftwo
  \fi}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdefmacro}{}
\long\edef\ifdefmacro#1{%
  \noexpand\expandafter\noexpand\etb@ifdefmacro
  \noexpand\meaning#1\detokenize{macro}:&}
\edef\etb@ifdefmacro{%
  \def\noexpand\etb@ifdefmacro##1\detokenize{macro}:##2&}
\etb@ifdefmacro{\notblank{#2}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsmacro}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefmacro\csname#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdefprefix}[1]{%
  \ifdefmacro{#1}
    {\etb@ifdefprefix{#1}}
    {\@secondoftwo}}
\long\edef\etb@ifdefprefix#1{%
  \noexpand\expandafter\noexpand\etb@ifdefprefix@i
  \noexpand\meaning#1\detokenize{macro}:&}
\edef\etb@ifdefprefix@i{%
  \def\noexpand\etb@ifdefprefix@i##1\detokenize{macro}:##2&}
\etb@ifdefprefix@i{\notblank{#1}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsprefix}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefprefix\csname#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdefparam}{}
\long\edef\ifdefparam#1{%
  \noexpand\expandafter\noexpand\etb@ifdefparam
  \noexpand\meaning#1\detokenize{macro}:->&}
\edef\etb@ifdefparam{%
  \def\noexpand\etb@ifdefparam##1\detokenize{macro}:##2->##3&}
\etb@ifdefparam{\notblank{#2}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsparam}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefparam\csname#1\endcsname}
    {\@secondoftwo}}


EoTeX

# If we want to allow raw interpretation, we need to define the discrepant macros *before*
# we load the native package, since they are used within it extensively.
# Hence we need to lock them, to avoid the native redefinition.

DefMacro('\ifdefprotected DefToken {} {}', sub {
    my ($gullet, $cs, $true, $false) = @_;
    my $definition = LookupMeaning($cs);
    if (!$definition || !$definition->isExpandable) {
      # Undefined, or not an expandable definition, therefore not protected
      return $false;
    }
    my $expansion = ToString($definition->getExpansion);
    # We are getting into hot water here - etoolbox considers macros with an expansion prefixde by
    # "\protected" to be protected -- but latexml does not use that mechanism consistently.
    # In fact, the opposite is true - the recommended approach is to add a "protected => 1" flag
    # to the binding definition.
    if (($definition && $definition->isProtected) || $expansion =~ /^\\protected/) {
      return $true;
    } else {
      return $false;
    }
}, protected => 1);

RawTeX(<<'EoTeX');
% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsprotected}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefprotected\csname#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true}{<false>}

\newrobustcmd{\ifdefltxprotect}[1]{%
  \begingroup
  \edef\etb@resrvda{\string#1}%
  \def\etb@resrvdb{#1}%
  \edef\etb@resrvdb{\expandafter\strip@prefix\meaning\etb@resrvdb}%
  \edef\etb@resrvda{%
    % latexml does not implement x@protect for DeclareRobustCommand, skip
    %\ifx\etb@resrvda\etb@resrvdb
    %  \noexpand\x@protect
    %  \noexpand#1%
    %\fi
    \noexpand\protect\expandafter\noexpand
    \csname\expandafter\@gobble\string#1 \endcsname}%
  \expandafter\endgroup\ifx#1\etb@resrvda
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<csname>}{<true>}{<false>}

\newrobustcmd*{\ifcsltxprotect}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefltxprotect\csname#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true>}{<false>}

\newcommand{\ifdefempty}[1]{%
  \ifundef{#1}
    {\@secondoftwo}
    {\ifdefmacro{#1}
       {\ifdefparam{#1}
	  {\@secondoftwo}
	  {\etb@ifdefempty{#1}}}
       {\@secondoftwo}}}

\def\etb@ifdefempty#1{%
  \expandafter\expandafter
  \expandafter\ifblank
  \expandafter\expandafter
  \expandafter{%
  \expandafter\strip@prefix\meaning#1}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsempty}[1]{%
  \ifcsundef{#1}
    {\@secondoftwo}
    {\expandafter\ifdefparam\csname#1\endcsname
       {\@secondoftwo}
       {\expandafter\etb@ifdefempty\csname#1\endcsname}}}

% {<cstoken>}{<true>}{<false>}

\newcommand{\ifdefvoid}[1]{%
  \ifundef{#1}
    {\@firstoftwo}
    {\ifdefmacro{#1}
       {\ifdefparam{#1}
	  {\@secondoftwo}
	  {\etb@ifdefempty{#1}}}
       {\@secondoftwo}}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsvoid}[1]{%
  \ifcsundef{#1}
    {\@firstoftwo}
    {\expandafter\ifdefparam\csname#1\endcsname
       {\@secondoftwo}
       {\expandafter\etb@ifdefempty\csname#1\endcsname}}}

% {<cstoken1>}{<cstoken2>}{<true>}{<false>}

\newcommand{\ifdefequal}[2]{%
  \ifundef{#1}
    {\@secondoftwo}
    {\ifundef{#2}
       {\@secondoftwo}
       {\ifx#1#2%
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi}}}

% {<csname1>}{<csname2>}{<true>}{<false>}

\newcommand*{\ifcsequal}[2]{%
  \ifcsundef{#1}
    {\@secondoftwo}
    {\ifcsundef{#2}
       {\@secondoftwo}
       {\expandafter\ifx
        \csname#1\expandafter\endcsname
        \csname#2\endcsname
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi}}}

% {<cstoken1>}{<cstoken2>}{<true>}{<false>}

\newrobustcmd{\ifdefstrequal}[2]{%
  \ifdefmacro{#1}
    {\ifdefmacro{#2}
       {\begingroup
	\edef\etb@tempa{\expandafter\strip@prefix\meaning#1}%
	\edef\etb@tempb{\expandafter\strip@prefix\meaning#2}%
	\ifx\etb@tempa\etb@tempb
	  \aftergroup\@firstoftwo
	\else
	  \aftergroup\@secondoftwo
	\fi
	\endgroup}
       {\@secondoftwo}}
    {\@secondoftwo}}

% {<csname1>}{<csname2>}{<true>}{<false>}

\newcommand*{\ifcsstrequal}[2]{%
  \ifcsundef{#1}
    {\@secondoftwo}
    {\ifcsundef{#2}
       {\@secondoftwo}
       {\expandafter\ifdefstrequal
        \csname#1\expandafter\endcsname
	\csname#2\endcsname}}}

% {<cstoken>}{<string>}{<true>}{<false>}

\newrobustcmd{\ifdefstring}[2]{%
  \ifdefmacro{#1}
    {\begingroup
     \edef\etb@tempa{\expandafter\strip@prefix\meaning#1}%
     \edef\etb@tempb{\detokenize{#2}}%
     \ifx\etb@tempa\etb@tempb
       \aftergroup\@firstoftwo
     \else
       \aftergroup\@secondoftwo
     \fi
     \endgroup}
    {\@secondoftwo}}

% {<csname>}{<string>}{<true>}{<false>}

\newrobustcmd{\ifcsstring}[2]{%
  \ifcsundef{#1}
    {\@secondoftwo}
    {\expandafter\ifdefstring\csname#1\endcsname{#2}}}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdefcounter}[1]{\etb@ifcounter#1&}
\long\def\etb@ifcounter#1#2&{%
  \ifx\count#1%
    \expandafter\@secondoftwo
  \else
    \expandafter\etb@ifcounter@i\meaning#1:%
  \fi}
\edef\etb@ifcounter@i#1:#2\fi{\noexpand\fi
  \noexpand\etb@ifcounter@ii#1\string\count&}
\edef\etb@ifcounter@ii{%
  \def\noexpand\etb@ifcounter@ii##1\string\count##2&}
\etb@ifcounter@ii{\ifblank{#1}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcscounter}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefcounter\csname#1\endcsname}
    {\@secondoftwo}}

% {<name>}{<true>}{<false>}

\newcommand*{\ifltxcounter}[1]{%
  \ifcsdef{c@#1}
    {\expandafter\ifdefcounter\csname c@#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdeflength}[1]{\etb@iflength#1&}
\long\def\etb@iflength#1#2&{%
  \ifx\skip#1%
    \expandafter\@secondoftwo
  \else
    \expandafter\etb@iflength@i\meaning#1:%
  \fi}
\edef\etb@iflength@i#1:#2\fi{\noexpand\fi
  \noexpand\etb@iflength@ii#1\string\skip&}
\edef\etb@iflength@ii{%
  \def\noexpand\etb@iflength@ii##1\string\skip##2&}
\etb@iflength@ii{\ifblank{#1}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcslength}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdeflength\csname#1\endcsname}
    {\@secondoftwo}}

% {<cstoken>}{<true}{<false>}

\newcommand{\ifdefdimen}[1]{\etb@ifdimen#1&}
\long\def\etb@ifdimen#1#2&{%
  \ifx\dimen#1%
    \expandafter\@secondoftwo
  \else
    \expandafter\etb@ifdimen@i\meaning#1:%
  \fi}
\edef\etb@ifdimen@i#1:#2\fi{\noexpand\fi
  \noexpand\etb@ifdimen@ii#1\string\dimen&}
\edef\etb@ifdimen@ii{%
  \def\noexpand\etb@ifdimen@ii##1\string\dimen##2&}
\etb@ifdimen@ii{\ifblank{#1}}

% {<csname>}{<true>}{<false>}

\newcommand*{\ifcsdimen}[1]{%
  \ifcsdef{#1}
    {\expandafter\ifdefdimen\csname#1\endcsname}
    {\@secondoftwo}}

% {<string1>}{<string2>}{<true>}{<false>}

\newrobustcmd{\ifstrequal}[2]{%
  \begingroup
  \edef\etb@tempa{\detokenize{#1}}%
  \edef\etb@tempb{\detokenize{#2}}%
  \ifx\etb@tempa\etb@tempb
    \aftergroup\@firstoftwo
  \else
    \aftergroup\@secondoftwo
  \fi
  \endgroup}

% {<string>}{<true>}{<false>}

\newcommand{\ifstrempty}[1]{%
  \expandafter\ifx\expandafter&\detokenize{#1}&%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<string>}{<true>}{<false>}

\newcommand{\ifblank}[1]{% from expl3
  \expandafter\ifx\expandafter\relax\detokenize\expandafter{\@gobble#1?}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

\newcommand{\notblank}[1]{%
  \expandafter\ifx\expandafter\relax\detokenize\expandafter{\@gobble#1?}\relax
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi}

% {<numexpr>}{<comp>}{<numexpr>}{<true>}{<false>}

\newcommand*{\ifnumcomp}[3]{%
  \ifnum\numexpr#1\relax#2\numexpr#3\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<numexpr>}{<numexpr>}{<true>}{<false>}

\newcommand*{\ifnumequal}[1]{%
  \ifnumcomp{#1}=}

\newcommand*{\ifnumgreater}[1]{%
  \ifnumcomp{#1}>}

\newcommand*{\ifnumless}[1]{%
  \ifnumcomp{#1}<}

% {<numexpr>}{<true>}{<false>}

\newcommand*{\ifnumodd}[1]{%
  \ifodd\numexpr#1\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<dimexpr>}{<comp>}{<dimexpr>}{<true>}{<false>}

\newcommand*{\ifdimcomp}[3]{%
  \ifdim\dimexpr#1\relax#2\dimexpr#3\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

% {<dimexpr>}{<dimexpr>}{<true>}{<false>}

\newcommand*{\ifdimequal}[1]{%
  \ifdimcomp{#1}=}

\newcommand*{\ifdimgreater}[1]{%
  \ifdimcomp{#1}>}

\newcommand*{\ifdimless}[1]{%
  \ifdimcomp{#1}<}

% {<expr>}{<true>}{<false>}

\newcommand{\ifboolexpe}[1]{%
  \etb@be@beg\etb@be@bgroup#1(&\etb@be@end}

\let\etb@be@true\@empty
\def\etb@be@false{-\@ne}

\def\etb@be@beg{%
  \ifnum\numexpr\z@\ifnum\numexpr\z@}

\def\etb@be@end{%
  <\z@
    \expandafter\etb@be@false
  \fi
  <\z@
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi}

\long\def\etb@be@bgroup#1(#2&{%
  \etb@be@egroup#1)&%
  \ifblank{#2}
    {}
    {\etb@be@beg
     \etb@be@bgroup#2&}}

\long\def\etb@be@egroup#1)#2&{%
  \etb@be@and#1and&%
  \ifblank{#2}
    {}
    {\etb@be@end\etb@be@true\etb@be@false
     \etb@be@egroup#2&}}

\long\def\etb@be@and#1and#2&{%
  \etb@be@or#1or&%
  \ifblank{#2}
    {}
    {<\z@
       \expandafter\@firstofone
     \else
       \expandafter\@gobble
     \fi
     {=\z@\fi\ifnum\numexpr\m@ne}%
     \ifnum\numexpr\z@
     \etb@be@and#2&}}

\long\def\etb@be@or#1or#2&{%
  \etb@be@not#1not&%
  \ifblank{#2}
    {}
    {<\z@
       \expandafter\@secondoftwo
     \else
       \expandafter\@firstoftwo
     \fi
     {=\z@\fi\ifnum\numexpr\z@
      \ifnum\numexpr\@ne}
     {=\z@\fi\ifnum\numexpr\z@
      \ifnum\numexpr\z@}%
     \etb@be@or#2&}}

\long\def\etb@be@not#1not#2&{%
  \etb@be@togl#1togl&%
  \ifblank{#2}
    {}
    {>\z@
       \expandafter\@firstoftwo
     \else
       \expandafter\@secondoftwo
     \fi
     {\unless\ifnum\numexpr\m@ne}
     {\unless\ifnum\numexpr\z@}%
     \etb@be@not#2&}}

\long\def\etb@be@togl#1togl#2&{%
  \etb@be@bool#1bool&%
  \ifblank{#2}
    {}
    {\etb@be@togl@i#2&}}

\long\def\etb@be@togl@i#1#2&{%
  \ifcsdef{etb@tgl@#1}
    {\csname etb@tgl@#1\endcsname\etb@be@true\etb@be@false}
    {\etb@be@err{Toggle '#1' undefined}{}}%
  \etb@be@togl#2&}

\long\def\etb@be@bool#1bool#2&{%
  \etb@be@test#1test&%
  \ifblank{#2}
    {}
    {\etb@be@bool@i#2&}}

\long\def\etb@be@bool@i#1#2&{%
  \ifcsundef{if#1}
    {\etb@be@err{Boolean '#1' undefined}{}}
    {\csname if#1\endcsname
     \else
       \etb@be@false
     \fi}%
  \etb@be@bool#2&}

\long\def\etb@be@test#1test#2&{%
  \ifblank{#1}
    {}
    {\etb@be@err{The invalid part is: '\detokenize{#1}'}{}}%
  \ifblank{#2}
    {}
    {\etb@be@test@i#2&}}

\long\def\etb@be@test@i#1#2&{%
  #1\etb@be@true\etb@be@false
  \etb@be@test#2&}

\long\def\etb@be@err#1#2{%
  \expandafter\ifnum\the\numexpr
    \expandafter\ifnum\the\currentiftype=-3
      \expandafter\thr@@
    \else
      \expandafter\currentiftype
    \fi
  =\thr@@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {=\z@\fi
   \etb@be@err{#1}{#2\ifnum\numexpr\m@ne}}
  {\etb@err@expr{#1}#2}}

% {<expr>}{<true>}{<false>}

\newrobustcmd{\ifboolexpr}[1]{\etb@boolexpr{#1}}

\long\def\etb@boolexpr#1{%
  \begingroup
  \let\etb@br@neg\@firstoftwo
  \etb@tempcnta\z@
  \etb@br@beg
  \etb@br@bgroup#1(&%
  \etb@br@end
  \etb@br@eval}

\def\etb@br@beg{%
  \begingroup
  \let\etb@br@neg\@firstoftwo
  \etb@tempcnta\z@}

\def\etb@br@end{%
  \etb@br@eval\etb@br@true\etb@br@false}

\def\etb@br@eval{%
  \ifnum\etb@tempcnta<\z@
    \aftergroup\@secondoftwo
  \else
    \aftergroup\@firstoftwo
  \fi
  \endgroup}

\def\etb@br@true{%
  \advance\etb@tempcnta\etb@br@neg\z@\m@ne
  \let\etb@br@neg\@firstoftwo}

\def\etb@br@false{%
  \advance\etb@tempcnta\etb@br@neg\m@ne\z@
  \let\etb@br@neg\@firstoftwo}

\long\def\etb@br@bgroup#1(#2&{%
  \etb@br@egroup#1)&%
  \ifblank{#2}
    {}
    {\etb@br@beg
     \etb@br@bgroup#2&}}

\long\def\etb@br@egroup#1)#2&{%
  \etb@br@and#1and&%
  \ifblank{#2}
    {}
    {\etb@br@end
     \etb@br@egroup#2&}}

\long\def\etb@br@and#1and#2&{%
  \etb@br@or#1or&%
  \ifblank{#2}
    {}
    {\ifnum\etb@tempcnta<\z@
       \etb@tempcnta\m@ne
     \else
       \etb@tempcnta\z@
     \fi
     \etb@br@and#2&}}

\long\def\etb@br@or#1or#2&{%
  \etb@br@not#1not&%
  \ifblank{#2}
    {}
    {\ifnum\etb@tempcnta<\z@
       \etb@tempcnta\z@
     \else
       \etb@tempcnta\@ne
     \fi
     \etb@br@or#2&}}

\long\def\etb@br@not#1not#2&{%
  \etb@br@togl#1togl&%
  \ifblank{#2}
    {}
    {\let\etb@br@neg\@secondoftwo
     \etb@br@not#2&}}

\long\def\etb@br@togl#1togl#2&{%
  \etb@br@bool#1bool&%
  \ifblank{#2}
    {}
    {\etb@br@togl@i#2&}}

\long\def\etb@br@togl@i#1#2&{%
  \ifcsdef{etb@tgl@#1}
    {\csname etb@tgl@#1\endcsname\etb@br@true\etb@br@false}
    {\etb@err@expr{Toggle '#1' undefined}\etb@br@false}%
  \etb@br@togl#2&}

\long\def\etb@br@bool#1bool#2&{%
  \etb@br@test#1test&%
  \ifblank{#2}
    {}
    {\etb@br@bool@i#2&}}

\long\def\etb@br@bool@i#1#2&{%
  \ifcsundef{if#1}
    {\etb@err@expr{Boolean '#1' undefined}\etb@br@false}
    {\csname if#1\endcsname
       \etb@br@true
     \else
       \etb@br@false
     \fi}%
  \etb@br@bool#2&}

\long\def\etb@br@test#1test#2&{%
  \ifblank{#1}
    {}
    {\etb@err@expr{The invalid part is: '\detokenize{#1}'}}%
  \ifblank{#2}
    {}
    {\etb@br@test@i#2&}}

\long\def\etb@br@test@i#1#2&{%
  \ignorespaces#1\etb@br@true\etb@br@false
  \etb@br@test#2&}

\long\def\etb@err@expr#1{%
  \etb@error
    {Invalid boolean expression}
    {#1.}}

% {<expr>}{<code>}

\newrobustcmd{\whileboolexpr}[2]{%
  \etb@boolexpr{#1}{#2\whileboolexpr{#1}{#2}}{}}

% {<expr>}{<code>}

\newrobustcmd{\unlessboolexpr}[2]{%
  \etb@boolexpr{#1}{}{#2\unlessboolexpr{#1}{#2}}}

% {<cstoken>}

\newcommand{\expandonce}[1]{%
  \unexpanded\expandafter{#1}}

% {<csname>}

\newcommand*{\csexpandonce}[1]{%
  \expandafter\expandonce\csname#1\endcsname}

% {<code>}

\newcommand*{\protecting}{}
\def\protecting#{%
  \ifx\protect\@typeset@protect
    \etb@protecting\@firstofone
  \fi
  \ifx\protect\@unexpandable@protect
    \etb@protecting\etb@unexpandable
  \fi
  \ifx\protect\noexpand
    \etb@protecting\unexpanded
  \fi
  \ifx\protect\string
    \etb@protecting\detokenize
  \fi
  \relax\@firstofone}

\def\etb@protecting#1#2\relax\@firstofone{\fi#1}
\long\def\etb@unexpandable#1{\unexpanded{\protecting{#1}}}

% {<csname>}

\newrobustcmd*{\csdef}[1]{\expandafter\def\csname#1\endcsname}
\newrobustcmd*{\csedef}[1]{\expandafter\edef\csname#1\endcsname}
\newrobustcmd*{\csgdef}[1]{\expandafter\gdef\csname#1\endcsname}
\newrobustcmd*{\csxdef}[1]{\expandafter\xdef\csname#1\endcsname}
\newrobustcmd*{\protected@csedef}{\etb@protected\csedef}
\newrobustcmd*{\protected@csxdef}{\etb@protected\csxdef}

\def\etb@protected{%
  \let\@@protect\protect
  \let\protect\@unexpandable@protect
  \afterassignment\restore@protect}

% {<csname>}{<cstoken>}

\newrobustcmd{\cslet}[2]{%
  \expandafter\let\csname#1\endcsname#2}

% {<cstoken>}{<csname>}

\newrobustcmd{\letcs}[2]{%
  \ifcsdef{#2}
    {\expandafter\let\expandafter#1\csname#2\endcsname}
    {\undef#1}}

% {<csname>}{<csname>}

\newrobustcmd*{\csletcs}[2]{%
  \ifcsdef{#2}
    {\expandafter\let
     \csname#1\expandafter\endcsname
     \csname#2\endcsname}
    {\csundef{#1}}}

% {<csname>}

\newcommand*{\csuse}[1]{%
  \ifcsname#1\endcsname
    \csname#1\expandafter\endcsname
  \fi}

% {<cstoken>}

\newrobustcmd{\undef}[1]{\let#1\etb@undefined}

% {<csname>}

\newrobustcmd*{\csundef}[1]{\cslet{#1}\etb@undefined}
\newrobustcmd*{\csgundef}[1]{\global\cslet{#1}\etb@undefined}

% {<cstoken>}{<code>}

\newrobustcmd{\appto}[2]{%
  \ifundef{#1}
    {\edef#1{\unexpanded{#2}}}
    {\edef#1{\expandonce#1\unexpanded{#2}}}}
\newrobustcmd{\eappto}[2]{%
  \ifundef{#1}
    {\edef#1{#2}}
    {\edef#1{\expandonce#1#2}}}
\newrobustcmd{\gappto}[2]{%
  \ifundef{#1}
    {\xdef#1{\unexpanded{#2}}}
    {\xdef#1{\expandonce#1\unexpanded{#2}}}}
\newrobustcmd{\xappto}[2]{%
  \ifundef{#1}
    {\xdef#1{#2}}
    {\xdef#1{\expandonce#1#2}}}

\newrobustcmd*{\protected@eappto}{\etb@protected\eappto}
\newrobustcmd*{\protected@xappto}{\etb@protected\xappto}

% {<cstoken>}{<code>}

\newrobustcmd{\preto}[2]{%
  \ifundef{#1}
    {\edef#1{\unexpanded{#2}}}
    {\edef#1{\unexpanded{#2}\expandonce#1}}}
\newrobustcmd{\epreto}[2]{%
  \ifundef{#1}
    {\edef#1{#2}}
    {\edef#1{#2\expandonce#1}}}
\newrobustcmd{\gpreto}[2]{%
  \ifundef{#1}
    {\xdef#1{\unexpanded{#2}}}
    {\xdef#1{\unexpanded{#2}\expandonce#1}}}
\newrobustcmd{\xpreto}[2]{%
  \ifundef{#1}
    {\xdef#1{#2}}
    {\xdef#1{#2\expandonce#1}}}

\newrobustcmd*{\protected@epreto}{\etb@protected\epreto}
\newrobustcmd*{\protected@xpreto}{\etb@protected\xpreto}

% {<csname>}{<code>}

\newrobustcmd*{\csappto}[1]{\expandafter\appto\csname#1\endcsname}
\newrobustcmd*{\cseappto}[1]{\expandafter\eappto\csname#1\endcsname}
\newrobustcmd*{\csgappto}[1]{\expandafter\gappto\csname#1\endcsname}
\newrobustcmd*{\csxappto}[1]{\expandafter\xappto\csname#1\endcsname}
\newrobustcmd*{\protected@cseappto}{\etb@protected\cseappto}
\newrobustcmd*{\protected@csxappto}{\etb@protected\csxappto}

% {<csname>}{<code>}

\newrobustcmd*{\cspreto}[1]{\expandafter\preto\csname#1\endcsname}
\newrobustcmd*{\csepreto}[1]{\expandafter\epreto\csname#1\endcsname}
\newrobustcmd*{\csgpreto}[1]{\expandafter\gpreto\csname#1\endcsname}
\newrobustcmd*{\csxpreto}[1]{\expandafter\xpreto\csname#1\endcsname}
\newrobustcmd*{\protected@csepreto}{\etb@protected\csepreto}
\newrobustcmd*{\protected@csxpreto}{\etb@protected\csxpreto}

% {<cstoken>}{<numexpr>}

\newrobustcmd*{\numdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \edef#1{\the\numexpr#2}}
\newrobustcmd*{\numgdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \xdef#1{\the\numexpr#2}}

% {<csname>}{<numexpr>}

\newrobustcmd*{\csnumdef}[1]{%
  \expandafter\numdef\csname#1\endcsname}
\newrobustcmd*{\csnumgdef}[1]{%
  \expandafter\numgdef\csname#1\endcsname}

% {<cstoken>}{<dimexpr>}

\newrobustcmd*{\dimdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \edef#1{\the\dimexpr#2}}
\newrobustcmd*{\dimgdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \xdef#1{\the\dimexpr#2}}

% {<csname>}{<dimexpr>}

\newrobustcmd*{\csdimdef}[1]{%
  \expandafter\dimdef\csname#1\endcsname}
\newrobustcmd*{\csdimgdef}[1]{%
  \expandafter\dimgdef\csname#1\endcsname}

% {<cstoken>}{<glueexpr>}

\newrobustcmd*{\gluedef}[2]{%
  \ifundef#1{\let#1\z@skip}{}%
  \edef#1{\the\glueexpr#2}}
\newrobustcmd*{\gluegdef}[2]{%
  \ifundef#1{\let#1\z@skip}{}%
  \xdef#1{\the\glueexpr#2}}

% {<csname>}{<glueexpr>}

\newrobustcmd*{\csgluedef}[1]{%
  \expandafter\gluedef\csname#1\endcsname}
\newrobustcmd*{\csgluegdef}[1]{%
  \expandafter\gluegdef\csname#1\endcsname}

% {<cstoken>}{<muexpr>}

\newrobustcmd*{\mudef}[2]{%
  \ifundef#1{\def#1{0mu}}{}%
  \edef#1{\the\muexpr#2}}
\newrobustcmd*{\mugdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \xdef#1{\the\muexpr#2}}

% {<csname>}{<muexpr>}

\newrobustcmd*{\csmudef}[1]{%
  \expandafter\mudef\csname#1\endcsname}
\newrobustcmd*{\csmugdef}[1]{%
  \expandafter\mugdef\csname#1\endcsname}

% {<counter>}{<numexpr>}

\newrobustcmd*{\defcounter}[2]{%
  \ifcsundef{c@#1}
    {\etb@noglobal\@nocounterr{#1}}%
    {\csname c@#1\endcsname\numexpr#2\relax}}

% {<length>}{<glueexpr>}

\newrobustcmd*{\deflength}[2]{%
  \ifundef{#1}
    {\etb@noglobal\etb@err@nolen{#1}}%
    {#1\glueexpr#2\relax}}

\protected\def\etb@err@nolen#1{%
  \etb@error{Length '\string#1' undefined}\@eha}

% {<name>}

\newrobustcmd*{\newbool}[1]{%
  \expandafter\@ifdefinable\csname if#1\endcsname{%
    \expandafter\newif\csname if#1\endcsname}}

% {<name>}

\newrobustcmd*{\providebool}[1]{%
  \ifcsundef{if#1}
    {\expandafter\newif\csname if#1\endcsname}
    {\begingroup
     \edef\@tempa{\expandafter\meaning\csname if#1\endcsname}%
     \ifx\@tempa\etb@isfalse
     \else
       \ifx\@tempa\etb@istrue
       \else
         \etb@error{\@backslashchar if#1 not a boolean}\@eha
       \fi
     \fi
     \endgroup}}

% {<name>}{<true>|<false>}

\newrobustcmd*{\setbool}[2]{%
  \ifcsundef{if#1}
    {\etb@noglobal\etb@err@nobool{#1}}
    {\ifcsundef{#1#2}
       {\etb@noglobal\etb@err@boolval{#2}}
       {\csname#1#2\endcsname}}}

% {<name>}

\newrobustcmd*{\booltrue}[1]{%
  \ifcsundef{if#1}
    {\etb@noglobal\etb@err@nobool{#1}}
    {\csname#1true\endcsname}}

% {<name>}

\newrobustcmd*{\boolfalse}[1]{%
  \ifcsundef{if#1}
    {\etb@noglobal\etb@err@nobool{#1}}
    {\csname#1false\endcsname}}

\edef\etb@istrue{\meaning\iftrue}
\edef\etb@isfalse{\meaning\iffalse}
\protected\def\etb@noglobal{\let\relax\relax}

% {<name>}{<true}{<false>}

\newcommand*{\ifbool}[1]{%
  \ifcsundef{if#1}
    {\etb@err@nobool{#1}\@gobbletwo}
    {\csname if#1\endcsname
       \expandafter\@firstoftwo
     \else
       \expandafter\@secondoftwo
     \fi}}

% {<name>}{<not true}{<not false>}

\newcommand*{\notbool}[1]{%
  \ifcsundef{if#1}
    {\etb@err@nobool{#1}\@gobbletwo}
    {\csname if#1\endcsname
       \expandafter\@secondoftwo
     \else
       \expandafter\@firstoftwo
     \fi}}

\protected\def\etb@err@nobool#1{%
  \etb@error{Boolean '\@backslashchar if#1' undefined}\@eha}

\def\etb@err@boolval#1{%
  \etb@error
    {Invalid boolean value '#1'}
    {Valid boolean values are 'true' and 'false'.}}

% {<name>}

\newrobustcmd*{\newtoggle}[1]{%
  \ifcsdef{etb@tgl@#1}
    {\etb@error{Toggle '#1' already defined}\@eha}
    {\cslet{etb@tgl@#1}\@secondoftwo}}

% {<name>}

\newrobustcmd*{\providetoggle}[1]{%
  \ifcsdef{etb@tgl@#1}
    {}
    {\cslet{etb@tgl@#1}\@secondoftwo}}

% {<name>}{<true>|<false>}

\newrobustcmd*{\settoggle}[2]{%
  \ifcsdef{etb@tgl@#1}
    {\ifcsdef{etb@toggle#2}
       {\csletcs{etb@tgl@#1}{etb@toggle#2}}
       {\etb@noglobal\etb@err@boolval{#2}}}
    {\etb@noglobal\etb@err@notoggle{#1}}}

% {<name>}

\newrobustcmd*{\toggletrue}[1]{%
  \ifcsdef{etb@tgl@#1}
    {\cslet{etb@tgl@#1}\etb@toggletrue}
    {\etb@noglobal\etb@err@notoggle{#1}}}

% {<name>}

\newrobustcmd*{\togglefalse}[1]{%
  \ifcsdef{etb@tgl@#1}
    {\cslet{etb@tgl@#1}\etb@togglefalse}
    {\etb@noglobal\etb@err@notoggle{#1}}}

\let\etb@toggletrue\@firstoftwo
\let\etb@togglefalse\@secondoftwo

% {<name>}{<true}{<false>}

\newcommand*{\iftoggle}[1]{%
  \ifcsdef{etb@tgl@#1}
    {\csname etb@tgl@#1\endcsname}
    {\etb@err@notoggle{#1}\@gobbletwo}}

% {<name>}{<not true}{<not false>}

\newcommand*{\nottoggle}[1]{%
  \ifcsdef{etb@tgl@#1}
    {\csname etb@tgl@#1\endcsname\@secondoftwo\@firstoftwo}
    {\etb@err@notoggle{#1}\@gobbletwo}}

\protected\def\etb@err@notoggle#1{%
  \etb@error{Toggle '#1' undefined}\@eha}

% {<cstoken>}{<true}{<false>}

\protected\def\etb@ifscanable#1{%
  \begingroup
  \edef\etb@resrvda{%
    \def\noexpand\etb@resrvda####1\detokenize{macro}:####2->####3&{%
      ####1\def\string\etb@resrvda####2{####3}}%
    \edef\noexpand\etb@resrvda{\noexpand\etb@resrvda\meaning#1&}}%
  \etb@resrvda
  \makeatletter
  \endlinechar\m@ne
  \newlinechar\m@ne
  \scantokens\expandafter{\etb@resrvda}%
  \expandafter\endgroup\ifx#1\etb@resrvda
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

EoTeX

# STOPGAP! Because a lot of LaTeXML definitions are realized via Perl subroutines,
# the "\meaning#1" tests in the native definition of this macro would return CODE(...) strings
# that makes the test always fail.
#
# An observation from studying etoolbox.sty is that this macro is both internal (not meant for authors),
# and is only used as a error-handling guard for \patchcmd and similar, i.e. it returns the "true"
# case in all intended correct uses. Hence:
DefMacro('\etb@ifpattern DefToken {}', '\begingroup\@firstoftwo', protected => 1);

RawTeX(<<'EoTeX');
% {<string>}{<true}{<false>}

\protected\long\def\etb@ifhashcheck#1{%
  \begingroup
  \edef\etb@resrvda{\detokenize{#1}}%
  \expandafter\endgroup
  \expandafter\etb@ifhashcheck@i\meaning\etb@resrvda&}

\edef\etb@ifhashcheck@i#1&{%
  \noexpand\expandafter
  \noexpand\etb@ifhashcheck@ii
  \noexpand\strip@prefix#1\string#\string#&}

\edef\etb@ifhashcheck@ii{%
  \def\noexpand\etb@ifhashcheck@ii##1\string#\string###2&}
\etb@ifhashcheck@ii{\ifblank{#2}}

% {<cstoken>}

\newrobustcmd*{\robustify}[1]{%
  \ifundef{#1}
    {\etb@error{\string#1 undefined}\@eha}
    {\ifdefmacro{#1}
       {\ifdefltxprotect{#1}
          {\letcs\etb@resrvda{\expandafter\@gobble\string#1 }%
           \@tempswatrue}
          {\let\etb@resrvda#1%
           \@tempswafalse}%
        \ifdefparam\etb@resrvda
          {\etb@ifscanable\etb@resrvda
             {\etb@robustify\etb@resrvda
              \let#1\etb@resrvda}
             {\etb@error{Failed to robustify \string#1}
                {The command is special and cannot be
                 handled by \string\robustify.}%
              \@tempswafalse}}
          {\protected\edef#1{\expandonce\etb@resrvda}}%
        \if@tempswa
          \csundef{\expandafter\@gobble\string#1 }%
        \fi
        \undef\etb@resrvda}
       {\etb@error{\string#1 not a macro}\@eha}}}

\def\etb@robustify#1{%
  \begingroup
  \edef\etb@resrvdb{%
    \def\noexpand\etb@resrvdb####1\detokenize{macro}:####2->####3&{%
      \protected####1\def\string#1\space####2{####3}}%
    \edef\noexpand\etb@resrvdb{%
      \noexpand\etb@resrvdb\meaning#1&}}%
  \etb@resrvdb
  \etb@patchcmd@scantoks\etb@resrvdb}

%  {<cstoken>}{<search>}{<true}{<false>}
% *{<cstoken>}{<true}{<false>}

\newrobustcmd{\ifpatchable}{%
  \etb@dbg@trce\ifpatchable
  \begingroup
  \@makeother\#%
  \@ifstar\etb@ifpatchable@i\etb@ifpatchable}

\long\def\etb@ifpatchable#1#2{%
  \endgroup
  \etb@dbg@init#1%
  \ifundef{#1}
    {\etb@dbg@fail{def}\@secondoftwo}
    {\etb@dbg@info{def}%
     \ifdefmacro{#1}
       {\etb@dbg@info{mac}%
        \etb@ifscanable{#1}
          {\etb@ifhashcheck{#2}
             {\etb@dbg@info{tok}%
              \etb@ifpattern#1{#2}
                 {\etb@dbg@info{pat}%
                  \etb@dbg@info{pos}\@firstoftwo}
                 {\etb@dbg@fail{pat}\@secondoftwo}}
             {\etb@dbg@fail{hsh}\@secondoftwo}}
          {\etb@dbg@fail{tok}\@secondoftwo}}
       {\etb@dbg@fail{mac}\@secondoftwo}}}

\long\def\etb@ifpatchable@i#1{%
  \endgroup
  \etb@dbg@init#1%
  \ifundef{#1}
    {\etb@dbg@fail{def}\@secondoftwo}
    {\etb@dbg@info{def}%
     \ifdefmacro{#1}
       {\etb@dbg@info{mac}%
        \ifdefparam{#1}
          {\etb@dbg@info{prm}%
           \etb@ifscanable{#1}
             {\etb@dbg@info{tok}%
              \etb@dbg@info{pos}\@firstoftwo}
             {\etb@dbg@fail{tok}\@secondoftwo}}
          {\etb@dbg@info{prl}%
           \ifdefprotected{#1}
             {\etb@dbg@info{pro}}
             {}%
           \etb@dbg@info{pos}\@firstoftwo}}
       {\etb@dbg@fail{mac}\@secondoftwo}}}

EoTeX

# Need to be able to examine a Macro's replacement for a match (and then replace)
# we can only do this for token expansions, and should return failure for all else.
DefMacro('\patchcmd [] DefToken {}{}{}{}', sub {
    my ($gullet, $prefix, $cs, $search, $replace, $success, $failure) = @_;
    my $definition = LookupMeaning($cs);
    if ($definition && $definition->isExpandable) {
      my $expansion = $definition->getExpansion;
      if (ref $expansion eq 'CODE') {
        Info('unexpected', 'patchcmd', $gullet, "Patchcmd is not supported on LaTeXML-native definitions, will not patch " . ToString($cs));
        return $failure;
      }
      my $string        = ToString($expansion);
      my $search_string = ToString($search);
      # All characters are meant to be matched as literal, avoid regex interpretation
      $search_string = quotemeta($search_string);
      my $search_regex = qr/$search_string/;
      if ($string =~ $search_regex) {
        # Should the token substitution happen on the actual data structure?
        # string replacement is a quick&dirty way out...
        my $replace_string = ToString($replace);
        $string =~ s/$search_regex/$replace_string/;
        # New definition in local scope
        $STATE->installDefinition(LaTeXML::Core::Definition::Expandable->new($cs, $definition->getParameters, $string));
        return $success;
      } else {
        return $failure;
      }
    } else {
      Info('unexpected', 'patchcmd', $gullet, "Patchcmd is not supported on non-expandable definitions, will not patch " . ToString($cs));
      return $failure;
} }, protected => 1);

RawTeX(<<'EoTeX');
\newcommand{\etb@patchcmd}[4][########1]{%
  \etb@ifpatchable#2{#3}
    {\etb@dbg@succ{ret}%
     \begingroup
     \edef\etb@resrvda{%
       \def\noexpand\etb@resrvda####1\detokenize{macro:}####2->####3&{%
         #1\def\string\etb@resrvda\space####2{\noexpand\etb@resrvdb####3&}}%
       \def\noexpand\etb@resrvdb####1\detokenize{#3}####2&{%
         ####1\detokenize{#4}####2}%
       \edef\noexpand\etb@resrvda{%
         \noexpand\etb@resrvda\meaning#2&}}%
     \etb@resrvda
     \etb@patchcmd@scantoks\etb@resrvda
     \let#2\etb@resrvda
     \undef\etb@resrvda
     \@firstoftwo}%
    {\@secondoftwo}}

\def\etb@patchcmd@scantoks#1{%
  \edef\etb@resrvda{\endgroup
    \endlinechar\m@ne
    \unexpanded{\makeatletter\scantokens}{#1}%
    \endlinechar\the\endlinechar\relax
    \catcode\number`\@=\the\catcode`\@\relax}%
  \etb@resrvda}

% {<cstoken>}{<code>}{<success>}{<failure>}

\newrobustcmd*{\apptocmd}{%
  \etb@dbg@trce\apptocmd
  \begingroup
  \@makeother\#%
  \etb@hooktocmd\etb@append}

\newrobustcmd*{\pretocmd}{%
  \etb@dbg@trce\pretocmd
  \begingroup
  \@makeother\#%
  \etb@hooktocmd\etb@prepend}

\long\def\etb@hooktocmd#1#2#3{%
  \endgroup
  \etb@dbg@init#2%
  \ifundef{#2}
    {\etb@dbg@fail{def}\@secondoftwo}
    {\etb@dbg@info{def}%
     \ifdefmacro{#2}
       {\etb@dbg@info{mac}%
        \ifdefparam{#2}
          {\etb@dbg@info{prm}%
           \etb@ifscanable{#2}
             {\etb@ifhashcheck{#3}
                {\etb@dbg@info{tok}%
                 \etb@dbg@succ{ret}%
                 \etb@hooktocmd@i#1#2{#3}%
                 \@firstoftwo}
                {\etb@dbg@fail{hsh}\@secondoftwo}}
             {\etb@dbg@fail{tok}\@secondoftwo}}
          {\etb@dbg@info{prl}%
           \ifdefprotected{#2}
             {\etb@dbg@info{pro}%
              \etb@dbg@succ{red}%
              \protected}
             {\etb@dbg@succ{red}}%
           \edef#2{#1{\expandonce#2}{\unexpanded{#3}}}%
           \@firstoftwo}}
       {\etb@dbg@fail{mac}\@secondoftwo}}}

\long\def\etb@hooktocmd@i#1#2#3{%
  \begingroup
  \edef\etb@resrvda{%
    \def\noexpand\etb@resrvda####1\detokenize{macro}:####2->####3&{%
      ####1\def\string\etb@resrvda\space####2{#1{####3}{\detokenize{#3}}}}%
    \edef\noexpand\etb@resrvda{%
      \noexpand\etb@resrvda\meaning#2&}}%
  \etb@resrvda
  \etb@patchcmd@scantoks\etb@resrvda
  \let#2\etb@resrvda
  \undef\etb@resrvda}

\long\def\etb@append#1#2{#1#2}
\long\def\etb@prepend#1#2{#2#1}

\newrobustcmd*{\tracingpatches}{%
  \etb@info{Enabling tracing}%
  \input{etoolbox.def}%
  \global\let\tracingpatches\relax}
\@onlypreamble\tracingpatches

\let\etb@dbg@trce\@gobble
\let\etb@dbg@init\@gobble
\let\etb@dbg@info\@gobble
\let\etb@dbg@succ\@gobble
\let\etb@dbg@fail\@gobble

% {<numeral>}

\newcommand{\rmntonum}[1]{%
  \ifblank{#1}
    {}
    {\expandafter\etb@rti@end\number\numexpr
     \expandafter\etb@rti@prs\detokenize{#1}&\relax}}

\def\etb@rti@prs#1#2{%
  \ifx&#1%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#1#2}
  {\ifx&#2%
     \expandafter\@firstoftwo
   \else
     \expandafter\@secondoftwo
   \fi
   {\etb@rti@chk#1+\etb@rti@num#1#2}
   {\etb@rti@chk#1\etb@rti@chk#2%
    \ifnum\etb@rti@num#1<\etb@rti@num#2 %
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    {+\etb@rti@num#2-\etb@rti@num#1\etb@rti@prs}
    {+\etb@rti@num#1\etb@rti@prs#2}}}}

\def\etb@rti@chk#1{%
  \ifcsname etb@rmn@#1\endcsname
  \else
    \expandafter\etb@rti@brk
  \fi}

\def\etb@rti@brk#1&{+\z@&-1}
\def\etb@rti@end#1&#2\relax{\ifblank{#2}{#1}{#2}}
\def\etb@rti@num#1{\csname etb@rmn@#1\endcsname}

\chardef\etb@rmn@i=1
\chardef\etb@rmn@I=1
\chardef\etb@rmn@v=5
\chardef\etb@rmn@V=5
\chardef\etb@rmn@x=10
\chardef\etb@rmn@X=10
\chardef\etb@rmn@l=50
\chardef\etb@rmn@L=50
\chardef\etb@rmn@c=100
\chardef\etb@rmn@C=100
\mathchardef\etb@rmn@d=500
\mathchardef\etb@rmn@D=500
\mathchardef\etb@rmn@m=1000
\mathchardef\etb@rmn@M=1000

% {<numeral>}{<true>}{<false>}

\newcommand{\ifrmnum}[1]{%
  \ifblank{#1}
    {\@secondoftwo}
    {\expandafter\etb@ifr@prs\detokenize{#1}\relax}}

\def\etb@ifr@prs#1{%
  \ifx\relax#1%
    \expandafter\@firstoftwo
  \else
    \ifcsname etb@rmn@#1\endcsname
      \expandafter\expandafter
      \expandafter\etb@ifr@prs
    \else
      \expandafter\expandafter
      \expandafter\etb@ifr@brk
    \fi
  \fi}

\def\etb@ifr@brk#1\relax{\@secondoftwo}

% <*>{<command>}{<separator>}

\newrobustcmd*{\DeclareListParser}{%
  \@ifstar
    {\etb@defparser\etb@defparser@arg}
    {\etb@defparser\etb@defparser@do}}

\def\etb@defparser#1#2#3{%
  \@ifdefinable#2{#1{#2}{#3}}}

\def\etb@defparser@do#1#2{%
  \ifblank{#2}{\long\def#1##1{%
    \etb@lst@@notoken@do##1\etb@lst@q@end&}}
    {\etb@defparser@do@aux{#1}{#2}}}

\def\etb@defparser@do@aux#1#2{%
  \begingroup
  \edef\@tempa{\endgroup
    \long\def\noexpand#1####1{%
      \expandafter\noexpand
      \csname etb@lst@\expandafter\@gobble\string#1\endcsname
      \noexpand\@nil####1\noexpand#2\noexpand\etb@lst@q@end\noexpand#2&}%
    \long\csdef{etb@lst@\expandafter\@gobble\string#1}%
      ####1\noexpand#2{%
      \noexpand\expandafter\noexpand\ifx\noexpand\expandafter
      \noexpand\etb@lst@q@end\noexpand\@gobble####1\noexpand\@empty
        \noexpand\expandafter\noexpand\@firstoftwo
      \noexpand\else
        \noexpand\expandafter\noexpand\@secondoftwo
      \noexpand\fi
        {\noexpand\listbreak}
        {\noexpand\etb@listitem\noexpand\do{####1}%
         \expandafter\noexpand
         \csname etb@lst@\expandafter\@gobble\string#1\endcsname
	 \noexpand\@nil}}}%
  \@tempa}

\long\def\etb@lst@@notoken@do#1{%
  \ifx\etb@lst@q@end#1\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {\listbreak}
    {\do{#1}%
    \etb@lst@@notoken@do}}

\def\etb@lst@q@end{\etb@lst@q@end}

\def\etb@defparser@arg#1#2{%
  \ifblank{#2}{\long\def#1##1##2{%
    \etb@lst@@notoken@arg{##1}##2\etb@lst@q@end&}}
    {\etb@defparser@arg@aux{#1}{#2}}}

\def\etb@defparser@arg@aux#1#2{%
  \begingroup
  \edef\@tempa{\endgroup
    \long\def\noexpand#1####1####2{%
      \expandafter\noexpand
      \csname etb@lst@\expandafter\@gobble\string#1\endcsname
      {####1}\noexpand\@nil####2\noexpand#2\noexpand\etb@lst@q@end\noexpand#2&}%
    \long\csdef{etb@lst@\expandafter\@gobble\string#1}####1####2\noexpand#2{%
      \noexpand\expandafter\noexpand\ifx\noexpand\expandafter
      \noexpand\etb@lst@q@end\noexpand\@gobble####2\noexpand\@empty
        \noexpand\expandafter\noexpand\@firstoftwo
      \noexpand\else
        \noexpand\expandafter\noexpand\@secondoftwo
      \noexpand\fi
        {\noexpand\listbreak}
        {\noexpand\etb@listitem{####1}{####2}%
         \expandafter\noexpand
         \csname etb@lst@\expandafter\@gobble\string#1\endcsname
	        {####1}\noexpand\@nil}}}%
  \@tempa}

\long\def\etb@lst@@notoken@arg#1#2{%
  \ifx\etb@lst@q@end#2\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {\listbreak}
    {#1{#2}%
    \etb@lst@@notoken@arg{#1}}}

\long\def\etb@listitem#1#2{%
  \expandafter\ifblank\expandafter{\@gobble#2}
    {}
    {\expandafter\etb@listitem@i
     \expandafter{\@secondoftwo#2}{#1}}}
\long\def\etb@listitem@i#1#2{#2{#1}}

\newcommand*{\listbreak}{}
\long\def\listbreak#1&{}

% {<item1>,<item2>,...} => \do{<item1>}\do{<item2>}...

\DeclareListParser{\docsvlist}{,}

% {<handler>}{<item1>,<item2>,...} => <handler>{<item1>}<handler>{<item2>}...

\DeclareListParser*{\forcsvlist}{,}

% {<listmacro>}{<string>}

\newrobustcmd{\listadd}[2]{%
  \ifblank{#2}{}{\appto#1{#2|}}}
\newrobustcmd{\listeadd}[2]{%
  \begingroup
  \edef\etb@tempa{\endgroup\noexpand\ifblank{#2}}%
  \etb@tempa{}{\eappto#1{#2|}}}
\newrobustcmd{\listgadd}[2]{%
  \ifblank{#2}{}{\gappto#1{#2|}}}
\newrobustcmd{\listxadd}[2]{%
  \begingroup
  \edef\etb@tempa{\endgroup\noexpand\ifblank{#2}}%
  \etb@tempa{}{\xappto#1{#2|}}}

% {<listcsname>}{<string>}

\newrobustcmd{\listcsadd}[1]{%
  \expandafter\listadd\csname#1\endcsname}
\newrobustcmd{\listcseadd}[1]{%
  \expandafter\listeadd\csname#1\endcsname}
\newrobustcmd{\listcsgadd}[1]{%
  \expandafter\listgadd\csname#1\endcsname}
\newrobustcmd{\listcsxadd}[1]{%
  \expandafter\listxadd\csname#1\endcsname}

% {<listmacro>}{<string>}

\newrobustcmd{\listremove}[2]{%
  \etb@listremove{#1}{#2}\def}
\newrobustcmd{\listgremove}[2]{%
  \etb@listremove{#1}{#2}\gdef}

\protected\long\def\etb@listremove#1#2#3{%
  \ifblank{#2}
    {}
    {\ifinlist{#2}{#1}{%
     \begingroup
     \def\etb@tempa##1|#2|##2&{\endgroup
       \expandafter#3\expandafter#1\expandafter{\@gobble##1|##2}}%
    \expandafter\etb@tempa\expandafter|#1&}{}}%
}

% {<listcsname>}{<string>}

\newrobustcmd{\listcsremove}[1]{%
  \expandafter\listremove\csname#1\endcsname}
\newrobustcmd{\listcsgremove}[1]{%
  \expandafter\listgremove\csname#1\endcsname}

% {<string>}{<listmacro>}{<true>}{<false>}

\newrobustcmd{\ifinlist}[2]{%
  \begingroup
  \def\etb@tempa##1|#1|##2&{\endgroup
    \ifblank{##2}\@secondoftwo\@firstoftwo}%
  \expandafter\etb@tempa\expandafter|#2|#1|&}

\newrobustcmd{\xifinlist}[1]{%
  \begingroup
  \edef\etb@tempa{\endgroup\ifinlist{#1}}%
  \etb@tempa}

% {<string>}{<listcsname>}{<true>}{<false>}

\newrobustcmd{\ifinlistcs}[2]{%
  \expandafter\etb@ifinlistcs@i\csname #2\endcsname{#1}}
\long\def\etb@ifinlistcs@i#1#2{\ifinlist{#2}{#1}}

\newrobustcmd{\xifinlistcs}[1]{%
  \begingroup
  \edef\etb@tempa{\endgroup\ifinlistcs{#1}}%
  \etb@tempa}

% {<handler>}{<listmacro>} => <handler>{<item1>}<handler>{<item2>}...

\newcommand*{\forlistloop}[2]{%
  \expandafter\etb@forlistloop\expandafter{#2}{#1}}

\long\def\etb@forlistloop#1#2{\etb@forlistloop@i{#2}#1|\etb@lst@q@end|&}

\long\def\etb@forlistloop@i#1#2|{%
  \ifx\etb@lst@q@end#2\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {\listbreak}
    {\ifblank{#2}
      {}
      {#1{#2}}%
      \etb@forlistloop@i{#1}}}

% {<handler>}{<listcsname>} => <handler>{<item1>}<handler>{<item2>}...

\newcommand*{\forlistcsloop}[2]{%
  \expandafter\expandafter\expandafter\etb@forlistloop
  \expandafter\expandafter\expandafter{\csname#2\endcsname}{#1}}

% {<listmacro>} => \do{<item1>}\do{<item2>}...

\newcommand*{\dolistloop}{\forlistloop\do}

% {<listcsname>} => \do{<item1>}\do{<item2>}...

\newcommand*{\dolistcsloop}{\forlistcsloop\do}

EoTeX
# #======================================================================
# # 2.5 Additional Document Hooks
# # \AfterPreamble
# # \AtEndPreamble
# # \AfterEndPreamble
# # \AfterEndDocument
DefMacro('\AfterPreamble{}', sub {
    if (LookupValue('inPreamble')) {
      PushValue('@at@begin@document', $_[1]->unlist);
      return; }
    else {
      return $_[1]; } });
DefMacro('\AtEndPreamble{}', sub {
    PushValue('@document@preamble@atend', $_[1]->unlist); });
DefMacro('\AfterEndPreamble{}', sub {
    PushValue('@document@preamble@afterend', $_[1]->unlist); });
DefMacro('\AfterEndDocument{}', sub {
    PushValue('@after@end@document', $_[1]->unlist); });

RawTeX(<<'EoTeX');
\AtEndDocument{\let\AfterEndPreamble\@gobble}
EoTeX
# #======================================================================
# # 2.6 Environment Hooks

DefMacro('\AtBeginEnvironment{}{}', sub {
    PushValue('@environment@' . ToString($_[1]) . '@atbegin', $_[2]->unlist); });
DefMacro('\AtEndEnvironment{}{}', sub {
    PushValue('@environment@' . ToString($_[1]) . '@atend', $_[2]->unlist); });
DefMacro('\BeforeBeginEnvironment{}{}', sub {
    PushValue('@environment@' . ToString($_[1]) . '@beforebegin', $_[2]->unlist); });
DefMacro('\AfterEndEnvironment{}{}', sub {
    PushValue('@environment@' . ToString($_[1]) . '@afterend', $_[2]->unlist); });

#**********************************************************************
1;
