# -*- 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> #_# | #
# \=========================================================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 '" . Stringify($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%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#1#2}
{\ifx%
\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\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;