diff options
Diffstat (limited to 'macros/latex/contrib/catoptions/tex/catoptions.sty')
-rw-r--r-- | macros/latex/contrib/catoptions/tex/catoptions.sty | 6331 |
1 files changed, 6331 insertions, 0 deletions
diff --git a/macros/latex/contrib/catoptions/tex/catoptions.sty b/macros/latex/contrib/catoptions/tex/catoptions.sty new file mode 100644 index 0000000000..cc9336c44f --- /dev/null +++ b/macros/latex/contrib/catoptions/tex/catoptions.sty @@ -0,0 +1,6331 @@ +%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% +% This is 'catoptions' package, version 0.2.7h, 2014/08/29. % +% % +% The catoptions package changes LaTeX package loading internals % +% so that all subsequently loaded packages can rely on having % +% normal catcodes in effect. The package also contains some useful % +% facilities unconnected with catcodes. In particular, it contains % +% options processing facilities that have the familiar and simple % +% syntax of LaTeX's legacy options parsing mechanism, but with % +% improved robustness in terms of option value default, preservation % +% of braces in option values, and parsing of expandable package % +% and class option values. Also, the package contains some API. % +% % +% The catcode facilities of the package are an extension of the % +% 'pcatcode' package by Michael J. Downes and David M. Jones. % +% % +% This package and accompanying files may be distributed and/or % +% modified under the conditions of the LaTeX Project Public License, % +% either version 1.3 of this license or any later version. % +% % +% The LPPL maintenance status of this software is 'author-maintained'. % +% % +% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). % +%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% + +\begingroup +\chardef\%\catcode37\catcode37 14\relax\expandafter\iffalse\string\ +\fi\let\e\endlinechar\chardef\E\e\e13\chardef\n\catcode\e\catcode\e5% +\chardef\s\catcode32 \catcode32\string=10 +\chardef\=\catcode61 \catcode61\string=12 +\chardef\l=\catcode123 \catcode123=1 +\chardef\r=\catcode125 \catcode125=2 +\chardef\[=\catcode91 \catcode91=12 +\chardef\]=\catcode93 \catcode93=12 +\chardef\^=\catcode94 \catcode94=7 +\chardef\.=\catcode46 \catcode46=12 +\chardef\/=\catcode47 \catcode47=12 +\chardef\~=\catcode126 \catcode126=13 +\chardef\&=\catcode38 \catcode38=4 +\chardef\$=\catcode36 \catcode36=3 +\chardef\_=\catcode95 \catcode95=8 +\chardef\+=\catcode43 \catcode43=12 +\chardef\!=\catcode33 \catcode33=12 +\chardef\'=\catcode39 \catcode39=12 +\chardef\(=\catcode40 \catcode40=12 +\chardef\)=\catcode41 \catcode41=12 +\chardef\*=\catcode42 \catcode42=12 +\chardef\,=\catcode44 \catcode44=12 +\chardef\-=\catcode45 \catcode45=12 +\chardef\:=\catcode58 \catcode58=12 +\chardef\<=\catcode60 \catcode60=12 +\chardef\>=\catcode62 \catcode62=12 +\chardef\`=\catcode96 \catcode96=12 +\edef\x{% + \endgroup + \def\noexpand\cptrestorecatcodes{% + \endlinechar=\number\E \catcode\number\e=\number\n + \catcode32=\number\s \catcode123=\number\l + \catcode125=\number\r \catcode37=\number\% + \catcode61=\number\= \catcode91=\number\[ + \catcode93=\number\] \catcode94=\number\^ + \catcode46=\number\. \catcode47=\number\/ + \catcode126=\number\~ \catcode38=\number\& + \catcode36=\number\$ \catcode95=\number\_ + \catcode43=\number\+ \catcode33=\number\! + \catcode39=\number\' \catcode40=\number\( + \catcode41=\number\) \catcode42=\number\* + \catcode44=\number\, \catcode45=\number\- + \catcode58=\number\: \catcode60=\number\< + \catcode62=\number\> \catcode96=\number\` + }% +} +\x +\catcode37 14\relax\expandafter\iffalse\string\ +\fi\endlinechar13\catcode13 5% +\catcode61\string=12 +\catcode32=10 +\catcode123=1 +\catcode125=2 +\catcode91=12 +\catcode93=12 +\catcode46=12 +\catcode47=12 +\catcode94=7 +\catcode126=13 + +\AtEndOfPackage{% + \newletcsset{% + \csvloop=\csv@@loop, + \csvparse=\csv@@parse, + \kvloop=\kv@@loop, + \kvparse=\kv@@parse, + \kvprocess=\kv@@process, + \tsvloop=\tsv@@loop, + \tsvparse=\tsv@@parse, + \sisoloop=\siso@@loop, + \dofunclist=\cptdofunclist, + \docommalist=\cptdocommalist, + \dosisolist=\cptdosisolist, + \newvariables=\cptnewvariables, + \stripallouterbraces=\cptstripallouterbraces, + \stripouterbraces=\cptstripNouterbraces, + \stripallouterbracesincs=\cptstripallouterbracesincs, + \gobble@to@relax=\cptgobbletorelax, + \cpt@gobbletorelax=\cptgobbletorelax, + \cpt@gobbletorelax@fi@endgroup=\cptbgobbletorelax, + \ifcasse=\cptifcasse, + \docasse=\cptdocasse, + \csvnormalize=\csv@@normalize, + \kvnormalize=\kv@@normalize + }% +} +\edef\cpt@hashchar{\string#} +\begingroup +\catcode`#=13 +\gdef\cpt@activehash{#} +\endgroup +\m@ne=-1 \z@=0pt \p@=1pt +\@ifdefinable\m@one{\newcount\m@one\m@one\m@ne} +\@ifdefinable\z@pt{\newdimen\z@pt\z@pt\z@} +\chardef\active=13 +\NeedsTeXFormat{LaTeX2e}[2011/06/27] +\ProvidesPackage{catoptions} + [2014/08/29 v0.2.7h Securing catcodes and parsing options (AM)] +\ifcase% + \ifx\eTeXversion\cpt@undefined\z@pt\else + \ifnum\eTeXversion<\tw@\z@pt\else\@ne\fi\fi + \PackageError{catoptions}{eTeX not loaded or old version} + {This package requires eTeX version 2 or higher.}% + \expandafter\endinput +\fi +\protected\def\cptloggingall{% + \tracinggroups\@ne\tracingifs\@ne\tracingall\tracingassigns\@ne +} +\let\cpttracingall\cptloggingall +% \ifcsdefinable, \cpt@starorlong, \cpt@testopt, \cptcommanormalize, etc, +% change later on: +\@ifdefinable\ifcsdefinable{\let\ifcsdefinable\@ifdefinable} +\@ifdefinable\cptnewlet\relax +% Don't put '=' after \let#1, in case the caller uses '=': +\protected\def\cptnewlet#1{\ifcsdefinable#1\relax\let#1} +\cptnewlet\cpt@nil\relax +\newcommand*\cpt@nnil{\cpt@nil} +\let\@iden\@firstofone +\def\cptiofii#1#2{#1} +\def\cptiiofii#1#2{#2} +\@ifdefinable\ifforbreak{\newif\ifforbreak} +\cptnewlet\cpt@starorlong\@star@or@long +\cptnewlet\cpt@testopt\@testopt +\cptnewlet\cptcommanormalize\unexpanded +\protected\def\ifnotnilTF#1#2{% + \begingroup + \edef\reserved@a{\cpttrimspace{#1}}% + \def\reserved@b{#2}% + \expandafter\endgroup + \ifx\reserved@a\reserved@b\expandafter\@gobble + \else\expandafter\@iden\fi +} +\newcommand*\defifxTF[2]{% + \begingroup + \edef\reserved@a{\cpttrimspace{#1}}% + \expandafter\endgroup\ifx#2\reserved@a + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\newcommand*\cpt@for@nil{\cpt@for@nil} +% Simple, 1-dimensional comma loop. \forbreak can be used to break +% out of the loop. \do may appear in #1; so we can't use \do as the delimiter: +\protected\def\cptfor#1\dofor#2{% + \def\cpt@fordo##1,{\cpt@for@a,\cpt@fordo{##1}{#2}}% + \edef\reserved@a{\cptcommanormalize{#1}}% + \forbreakfalse + \expandafter\cpt@fordo\reserved@a,\cpt@for@nil,% +} +% Simple, 1-dimensional tsv loop: +\protected\def\cpttfor#1\dofor#2{% + \def\cpt@tfordo##1{\cpt@for@a{}\cpt@tfordo{##1}{#2}}% + \forbreakfalse\cpt@tfordo#1\cpt@for@nil +} +\protected\def\cpt@for@a#1#2#3#4{% + \edef\reserved@a{\unexpanded{#3}}% + \ifx\reserved@a\cpt@for@nil\expandafter\@gobble\else + \expandafter\@iden\fi{% + \ifforbreak\expandafter\cptiofii\else\expandafter\cptiiofii\fi + {\def\reserved@a##1\cpt@for@nil#1{}\reserved@a}{#4#2}% + }% +} +% \foreachmeer{<list>}<processor> +% Expandable comma loop. The \noexpand before #1 is required when #1 +% begins with a command. <processor> must be pre-defined by the user: +\newcommand*\foreachmeer[2]{% + \expandafter\cpt@foreachmeer@a\romannumeral + -`\q\cptcommanormalize{\noexpand#1},\cpt@nnil,\meer@nil{#2}% +} +\def\cpt@foreachmeer@a#1,#2\meer@nil#3{% + \expandafter\ifx\cpt@car#1\car@nil\cpt@nnil + \expandafter\cptiofii\else\expandafter\cptiiofii\fi + {}{#3{#1}\cpt@foreachmeer@a#2\meer@nil{#3}}% +} +% Unique \chardef'd token: +\ifcsdefinable\cptchardef{% + \protected\def\cptchardef#1#2 {% + \ifcsdefinable#1{% + \def\reserved@a##1=##2\@nil{##2 }% + \chardef#1\reserved@a=#2\@nil + }% + }% +} +\newcommand\cptswap[2]{#2#1} +\newcommand\cptswapbracefirst[2]{#2{#1}} +\newcommand\cptswapbracesecond[2]{{#2}#1} +\newcommand\cptswapbraceboth[2]{{#2}{#1}} +\cptswap{ }{\let\cptsptoken= } +\def\@space{ } +\@namedef{cptgobblespace} {} +\@ifdefinable\@gobblespace{\let\@gobblespace\cptgobblespace} +% \cptnewbools[<pref>]{a,b} +\newcommand*\cptnewbools[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname if#1##1\endcsname + {\expandafter\newif\csname if#1##1\endcsname}% + }% +} +\cptnewbools[cpt@]{st,pl,pm,cl,verbose} +% \cptnewcounts[<pref>]{a,b} +\newcommand*\cptnewcounts[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname#1##1\endcsname + {\expandafter\newcount\csname#1##1\endcsname}% + }% +} +% \cptnewcounters[<pref>]{a,b}[<master>] +\newcommand*\cptnewcounters{\cpt@testopt\cpt@newcounters{}} +\def\cpt@newcounters[#1]#2{% + \cpt@testopt{\cpt@newc@unters{#1}{#2}}{}% +} +\def\cpt@newc@unters#1#2[#3]{% + \cptfor#2\dofor{% + \ifcat&\detokenize{#3}&\relax + \newcounter{#1##1}% + \else + \newcounter{#1##1}[#3]% + \fi + }% +} +\newcommand*\cptnewdimens[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname#1##1\endcsname + {\expandafter\newdimen\csname#1##1\endcsname}% + }% +} +\newcommand*\cpt@quark{\@gobble\cpt@quark} +\newcommand\ifxTF[2]{% + \ifblankTF{#1}{% + \ifblankTF{#2}\cptiofii\cptiiofii + }{% + \ifblankTF{#2}\cptiiofii{% + \expandafter\ifblankTF\expandafter{\@gobble#1}{% + \expandafter\ifblankTF\expandafter{\@gobble#2}{% + \ifx#1#2\expandafter\cptiofii\else\expandafter\cptiiofii\fi + }{% + \cpt@notonetokenerr{#2}% + }% + }{% + \cpt@notonetokenerr{#1}% + }% + }% + }% +} +\newcommand\ifxFT[2]{\ifxTF{#1}{#2}\cptiiofii\cptiofii} +\def\cpt@ifcseq@#1#2\cpt@ifcseq@nil{\expandafter#1} +\newcommand\ifcseqTF[2]{% + \csname @\expandafter\expandafter\expandafter + \ifx\cpt@ifcseq@#1\batchmode\cpt@ifcseq@nil\cpt@car#2\noboundary\car@nil + first\else second\fi oftwo\endcsname +} +\newcommand\ifcseqFT[2]{\ifcseqTF{#1}{#2}\cptiiofii\cptiofii} +\newcommand*\ifxcseqTF[2]{% + \ifcseqTF{#1}{#2}{% + \cptiofii + }{% + \expandafter\cptswapbracefirst\expandafter{#1}% + {\expandafter\ifstrcmpTF\expandafter{#2}}% + \cptiofii\cptiiofii + }% +} +\newcommand\ifnullTF[1]{% + \ifcat$\detokenize{#1}$\expandafter\@firstoftwo + \else\expandafter\@secondoftwo\fi +} +\newcommand\ifnullFT[1]{\ifnullTF{#1}\cptiiofii\cptiofii} +\newcommand\ifblankTF[1]{% + \expandafter\ifnullTF\expandafter{\@gobble#1.}% +} +\newcommand\ifblankFT[1]{\ifblankTF{#1}\cptiiofii\cptiofii} +\let\then\iffalse +\let\dolacus\iffalse +\@ifdefinable\iflacus\relax +\long\def\iflacus#1\dolacus{% + \ifcat$\detokenize\expandafter{\@gobble#1.}$% +} +\newcommand\ifbracedTF[3]{% + \romannumeral\expandafter\@secondoftwo\expandafter{\expandafter + {\string#1.}\expandafter\cptiofii\expandafter{\iffalse}\fi + 0 #2}{0 #3}% +} +\newcommand\ifbracedFT[1]{\ifbracedTF{#1}\cptiiofii\cptiofii} +\newcommand\ifleadspaceTF[3]{% + \romannumeral\csname + @\ifnullTF{#1}{second}{\iffalse{\fi\cpt@ifleadspace.#1 }}% + oftwo\endcsname{0 #2}{0 #3}% +} +\long\def\cpt@ifleadspace#1 {% + \expandafter\ifnullTF\expandafter{\@gobble#1}{first}{second}% + \expandafter\@gobble\expandafter{\iffalse}\fi +} +\newcommand\iftrailspaceTF[1]{% + \romannumeral-`\q + \csname @\expandafter\@firstofone\expandafter{% + \romannumeral\expandafter + \cpt@iftrailspace\expandafter{\cpt@removetospace.#1 }% + }% +} +\newcommand\cpt@iftrailspace[1]{% + \ifnullTF{#1}{% + \expandafter\cptiiofii\cptiofii + }{% + \ifleadspaceTF{#1}{% + \expandafter\ifnullTF\expandafter{\@gobblespace#1}{% + \expandafter\@firstoftwo\@firstoftwo + }{% + \@secondoftwo + }% + }{% + \@secondoftwo + }% + }{% + {0 first}{0 second}oftwo\endcsname + }{% + \expandafter\cpt@iftrailspace\expandafter{\cpt@removetospace.#1}% + }% +} + +\ifxTF\pdfstrcmp\cpt@undefined{% + \RequirePackage{pdftexcmds}% + \ifxTF\pdf@strcmp\cpt@undefined{% + \cpt@err{Neither \string\pdfstrcmp nor \string\pdf@strcmp exists}\@ehc + }{% + \let\cpt@pdfstrcmp\pdf@strcmp + }% +}{% + \let\cpt@pdfstrcmp\pdfstrcmp +} +\long\def\cptifstreq#1#2\then{% + \ifnum\cpt@pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=\z@pt +} +\newcommand\ifstrcmpTF[2]{% + \usename{@\ifnum\cpt@pdfstrcmp{\detokenize{#1}}% + {\detokenize{#2}}=0first\else second\fi oftwo}% +} +\newcommand\ifstrcmpFT[2]{\ifstrcmpTF{#1}{#2}\cptiiofii\cptiofii} +\newcommand*\cpt@def@[3]{% + \ifcsdefinable#3\relax + \ifcat$\detokenize{#2}$\else\protected\fi + \l@ngrel@x\csname#1def\endcsname#3% +} +\ifcsdefinable\robust@def{% + \protected\def\robust@def{\cpt@starorlong{\cpt@def@{}{p}}}% +} +\robust@def*\new@def{\cpt@starorlong{\cpt@def@{}{}}} +\robust@def*\new@gdef{\cpt@starorlong{\cpt@def@{g}{}}} +\robust@def*\robust@gdef{\cpt@starorlong{\cpt@def@{g}{p}}} +\robust@def*\new@edef{\cpt@starorlong{\cpt@def@{e}{}}} +\robust@def*\robust@edef{\cpt@starorlong{\cpt@def@{e}{p}}} +\robust@def*\new@xdef{\cpt@starorlong{\cpt@def@{x}{}}} +\robust@def*\robust@xdef{\cpt@starorlong{\cpt@def@{x}{p}}} +\robust@def*\renew@def{\cpt@starorlong{\cpt@redef@{}}} +\robust@def*\robust@redef{\cpt@starorlong{\cpt@redef@{p}}} +\robust@def*\cpt@redef@#1#2{% + \@ifundefined{\expandafter\@gobble\string#2}{}{% + \ifcpt@verbose + \@latex@info{Command '\string#2' redefined}% + \fi + }% + \ifcat$\detokenize{#1}$\else\protected\fi + \l@ngrel@x\def#2% +} +\new@def*\cpt@checkoptprefix{\@iden} +\robust@def*\provide@def{% + \cpt@testst{\cpt@testcl{\cpt@providedef\relax}}% +} +\robust@def*\providerobust@def{% + \cpt@testst{\cpt@testcl{\cpt@providedef\protected}}% +} +\robust@def*\cpt@providedef#1#2{% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ifdefTF#2{% + \ifcpt@verbose + \cpt@info{Command '\string#2' already defined: + \MsgBrk not redefined}% + \fi + \def\reserved@a{\undefcs\reserved@b}% + }{% + \def\reserved@a{% + \ifcpt@cl\global\fi\let#2\reserved@b + \undefcs\reserved@b + }% + }% + \afterassignment\reserved@a + \ifcpt@st\else\long\fi + #1\def\reserved@b +} +\new@def*\MsgBrk{\MessageBreak} +\new@def*\commentBegin{% + \begingroup + \catcode`\{=12 + \catcode`\}=12 + \catcode`\#=12 + \cpt@commentblock +} +\new@def\cpt@commentblock#1\commentEnd{\endgroup} +\robust@def*\cptnormalcatcodes{% + \endlinechar13 + \catcode33=12\catcode34=12\catcode35=6\catcode36=3\catcode37=14 + \catcode38=4\catcode39=12\catcode40=12\catcode41=12\catcode42=12 + \catcode43=12\catcode44=12\catcode45=12\catcode46=12\catcode47=12 + \catcode58=12\catcode59=12\catcode60=12\catcode61=12\catcode62=12 + \catcode63=12\catcode91=12\catcode92=0\catcode93=12\catcode94=7 + \catcode95=8\catcode96=12\catcode123=1\catcode124=12\catcode125=2 + \catcode126=13\catcode32=10\catcode13=5\catcode9=10\catcode10=12 +} + +\begingroup +\let\s\string +\escapechar\m@one +\new@xdef*\cpt@oth@rchars{% + \s\!\s\"\s\$\s\&\s\'\s\(\s\)\s\*\s+\s\,\s\-\s\.\s\/\s\:% + \s\;\s\<\s\=\s\>\s\?\s\[\s\]\s\^\s\_\s\`\s\|\s\~% + %% left out: \s\\\s\%\s\{\s\}\s\# +} +\new@xdef*\cpt@otherchars{% + \cpt@oth@rchars\s\\\s\%\s\{\s\}\s\#% +} +\endgroup + +\new@def*\cpt@spcatcodestack{} +\robust@def*\cpt@sppushcatcodes{% + \edef\cpt@spcatcodestack{% + \catcode\number`\ =\the\catcode`\ % + \catcode\number`\^^I=\the\catcode`\^^I + \catcode\number\endlinechar=\the\catcode`\ + \endlinechar=\the\endlinechar + {\cpt@spcatcodestack}% + }% +} +\robust@def*\BeginOverlookWhiteSpace{% + \cptpushnumber\cpt@overlooknr + \ifnum\cpt@overlooknr>\@ne + \cpt@err{There is an unclosed + \string\BeginOverlookWhiteSpace}\@ehc + \fi + \cpt@sppushcatcodes + \catcode`\ =9\relax + \catcode`\^^I=9\relax + \endlinechar\m@one +} +\robust@def*\EndOverlookWhiteSpace{% + \def\reserved@a##1##{##1\xdef\cpt@spcatcodestack}% + \expandafter\reserved@a\cpt@spcatcodestack + \undefcs\cpt@overlooknr +} +\robust@def*\BeginOverlookEndline{% + \cptpushnumber\cpt@overlookendlinenr + \ifnum\cpt@overlookendlinenr>\@ne + \cpt@err{There is an unclosed + \string\BeginOverlookEndline}\@ehc + \fi + \cptchardef\cpt@savendlinechar=\number\endlinechar + \endlinechar\m@one +} +\robust@def*\EndOverlookEndline{% + \endlinechar\cpt@savendlinechar + \undefcs\cpt@overlookendlinenr +} +\new@def*\cpt@catcodestack{} +\robust@def*\cptpushcatcodes{% + \begingroup + \def\x##1{% + \ifx##1\@nnil\else + \catcode\number`##1=\the\catcode`##1\relax + \expandafter\x + \fi + }% + \xdef\cpt@catcodestack{% + \expandafter\x\cpt@otherchars\ \ + \^^I\^^J\@nnil{\cpt@catcodestack}% + }% + \endgroup +} +\cptpushcatcodes +\cptnormalcatcodes +\robust@def*\cptpopcatcodes{% + \begingroup + \def\x##1##{\endgroup##1\xdef\cpt@catcodestack}% + \expandafter\x\cpt@catcodestack +} +\@ifdefinable\currentcatcodesubset\relax +\robust@def*\GetCurrentCatcodeSubset{% + \begingroup + \def\x##1{% + \ifx##1\@nnil\else + \@space(\string##1\@firstofone{:\number\catcode`##1})% + \expandafter\x + \fi + }% + \edef\x{% + \def\noexpand\currentcatcodesubset{% + \x\^^I\^^J\^^L\^^M\ \!\"\#\$\%\&% + \'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\}\|\~\@nnil + }% + }% + \expandafter\endgroup\x +} +\new@def*\cpt@lq{`} +\robust@def*\cpt@setupsafeactivesedef{% + \let\cpt@setupsafeactivesedef\relax + \begingroup + \cpttfor!"$&'()*+,-./:;<=>?[]^_`|~\dofor{% + \catcode\cpt@lq##1\string=\active + }% + \everyeof{\noexpand}% + \xdef\cpt@safeactives{\unexpanded\expandafter{\cpt@activehash}% + \scantokens{\unexpanded{!"$&'()*+,-./:;<=>?[]^_`|~}}}% + \gdef\cptsafeactivesedef##1##2{% + \begingroup + \expandafter\cpttfor\cpt@safeactives\dofor{% + \ifnum\catcode\cpt@lq####1\string=\active + \edef####1{\string####1}% + \fi + }% + \cptexpandsecond\endgroup + {\edef\noexpand##1{\noexpand\unexpanded{##2}}}% + }% + \endgroup +} +\newcommand*\neededfutureletchars{} +\newcommand*\declarefutureletset[2][fl@]{% + \xdef\cpt@fletprefix{\cpttrimspaces{#1}}% + \cptexpandargonce{\cptfiltermergecsv[,]\cpt@fletprefixes} + \cpt@fletprefix\nofilter + \ifblankTF{#2}{% + \def\neededfutureletchars{}% + }{% + \def\neededfutureletchars{#2}% + \cpt@sttrue\cpt@csvnormalize[,]\neededfutureletchars + \oifstrcmpFT\neededfutureletchars{all}{}{% + \def\neededfutureletchars{}% + \def\cpt@tempa##1\@##2\@{% + \ifx##1\end\else + \cptguaddtolist\neededfutureletchars{##1}% + \expandafter\cpt@tempa + \fi + }% + \expandafter\cpt@tempa\cpt@futureletchars\end\@\@ + }% + }% + \globalize\neededfutureletchars + \globalize\cpt@fletprefixes +} + +\begingroup +\cptrestorecatcodes +\begingroup +\catcode`\3="3 \catcode`\4="4 \catcode`\7="7 \catcode`\8="8 +\catcode`\A="A \catcode`\B="B \catcode`\C="C \catcode`\D="D +\robust@gdef*\cpt@flet@a#1#2{% + \begingroup + \edef\cpt@tempa{\noexpandcsn{\cpt@fletprefix#1}}% + \edef\cpt@tempb{\noexpandcsn{if\cpt@fletprefix#1}}% + \oifinset@sp@TF,\cpt@tempa\cptfutureletmacros{}{% + \xdef\cptfutureletmacros{% + \ifcsnullTF\cptfutureletmacros{}% + {\expandcsonce\cptfutureletmacros,}% + \expandcsonce\cpt@tempa,\expandcsonce\cpt@tempb + }% + }% + \def\siso@do##1{\lccode`##1=`#2}% + \siso@@loop{034678BCD}% + \ifnum\catcode`#2=\active + \def\do##1{\noexpand\do\noexpand##1\noexpand}% + \lowercase{% + \xdef\cpt@activecharacters{% + \cpt@activecharacters + \do#2D% + }% + }% + \fi + \xdef\cpt@tempa{% + \let\noexpand\cpt@tempa\noexpand\cpt@undefined + \gletcs\expandcsonce\cpt@tempa= % + }% + \aftergroup\cpt@tempa + \lowercase{% + \expandafter\endgroup + \ifcase\numexpr\catcode`#2\relax + 0\or \bgroup\or \egroup\or 3\or 4\or 5\or 6\or 7\or + 8\or 9\or \@sptoken\or B\or C\else D\fi + }% +} +\endgroup +\robust@gdef*\cpt@futureletchars{% + space\@\ \@ exclam\@\!\@ dblquote\@\"\@ hash\@\#\@ dollar\@\$\@ + ampersand\@\&\@ rquote\@\'\@ lparen\@\(\@ rparen\@\)\@ star\@\*\@ + plus\@\+\@ comma\@\,\@ hyphen\@\-\@ period\@\.\@ slash\@\/\@ + colon\@\:\@ semicolon\@\;\@ less\@\<\@ equal\@\=\@ greater\@\>\@ + question\@\?\@ lbracket\@\[\@ rbracket\@\]\@ hat\@\^\@ + underscore\@\_\@ lquote\@\`\@ lbrace\@\{\@ vert\@\|\@ rbrace\@\}\@ + tilde\@\~\@ bslash\@\\\@ +} +\robust@gdef*\cptfutureletsetup{% + \gdef\cpt@activecharacters{}% + \gdef\cptfutureletmacros{}% + \def\cpt@flet@b##1\@##2\@{% + \expandafter\ifxTF\cpt@car##1\car@nil\end{}{% + \oifinset@sp@FT,{##1}\neededfutureletchars{}{% + \cpt@flet@a{##1}{##2}% + }% + \cpt@flet@b + }% + }% + \def\csv@do##1{% + \gundefcsn{##1\curropt}% + \gundefcsn{if##1\curropt}% + }% + \def\cpt@fletundef##1\@##2\@{% + \ifxTF##1\end{}{% + \def\curropt{##1}% + \csv@@parse*[,]\cpt@fletprefixes + \cpt@fletundef + }% + }% + \def\cpt@fletdef##1\@##2\@{% + \expandafter\ifxTF\cpt@car##1\car@nil\end{}{% + \oifinset@sp@FT,{##1}\neededfutureletchars{}{% + \csn@xdef{if\cpt@fletprefix##1}####1{% + \noexpand\usename{@\noexpand\ifx + \noexpandcsn{\cpt@fletprefix##1}% + ####1\unexpanded{\@empty first\else second\fi oftwo}% + }% + }% + }% + \cpt@fletdef + }% + }% + \expandafter\cpt@fletundef\cpt@futureletchars\end\@\@ + \expandafter\cpt@fletdef\cpt@futureletchars\end\@\@ + \expandafter\cpt@flet@b\cpt@futureletchars\end\@\@ +} + +% We can't use \AtBeginDocument here in place of \BeforeStartOfDocument. +% See <http://tex.stackexchange.com/questions/146391/catoptions +% -destroys-french-active-characters-and>. +\AtEndOfPackage{\BeforeStartOfDocument{\cptrestorecatcodes}} + +\robust@gdef*\futureletresetactives{% + \begingroup + \defpass\cpt@tempa##1{\endgroup + \def\do####1####2{\let####1=##1####2}% + }{ }% + \cpt@activecharacters + \let\do\relax +} +\endgroup + +\robust@def*\UseNormalCatcodes{% + \ifdocstartedTF{% + \cpt@err + {\noexpand\UseNormalCatcodes is a preamble command} + {Preamble command in document body.}% + }{}% + \RecoverAtRequirePackage\UseNormalCatcodes + \let\UseNormalCatcodes\relax + \cptpushcatcodes + \cptnormalcatcodes + \ifcseqTF\@currname\@empty{% + \BeforeStartOfDocument{\cptpopcatcodes}% + }{% + \AfterEndOfStyleFile{\cptpopcatcodes}% + }% +} +\new@def*\cptgetcatcode#1{% + \number + \ifcat\noexpand#1\bgroup1\else + \ifcat\noexpand#1\egroup2\else + \ifcat\noexpand#1$3\else %$ + \ifcat\noexpand#1&4\else + \ifcat\noexpand#1##6\else + \ifcat\noexpand#1^7\else + \ifcat\noexpand#1_8\else + \ifcat\noexpand#1\@sptoken10\else + \ifcat\noexpand#1a11\else + \ifcat\noexpand#1!12\else + \ifcat\noexpand#1\noexpand~13\else + -1\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi +} + +\robust@def\cpt@ifnextchar#1#2#3{% + \begingroup + \let\reserved@a=#1% + \toks@{\endgroup#2}% + \toks1{\endgroup#3}% + \global\futurelet\@let@token\cpt@ifnext +} +\robust@def*\cpt@ifnext{% + \ifx\@let@token\@sptoken + \toks2{\cpt@ifn@xt}% + \else + \ifx\@let@token\reserved@a + \toks2\expandafter{\the\toks@}% + \else + \toks2\expandafter{\the\toks1}% + \fi + \fi + \the\toks2 +} +\@namedef{cpt@ifn@xt} {\global\futurelet\@let@token\cpt@ifnext} +\newcommand\ifnextcharTF[3]{% + \begingroup + \cpt@ifnextchar\relax + {\cpt@ifnextcharacter{#1}{#2}{#3}}% + {\cpt@ifnextcharacter{#1}{#2}{#3}}% +} +\new@def\cpt@ifnextcharacter#1#2#3{% + \ifcase + \ifcat\noexpand\@let@token\bgroup 1\fi + \ifcat\noexpand\@let@token\egroup 1\fi + 0\let\next\cpt@ifn@xtcharacter + \else + \def\next{\endgroup\cpt@ifnextchar}% + \fi + \next{#1}{#2}{#3}% +} +\new@def\cpt@ifn@xtcharacter#1#2#3#4{% + \escapechar92\relax + \edef\x{\cpt@ifn@xtch@racter{#1}\cpt@ifn@xtch@racter{#4}}% + \expandafter\endgroup\csname @\expandafter + \ifx\x first\else second\fi oftwo\endcsname + {#2}{#3}#4% +} +% Must be expandable: +\new@def\cpt@ifn@xtch@racter#1{% + \expandafter\cpt@ifn@xtch@r@cter\string#1\relax\noboundary{#1}% +} +\new@def\cpt@ifn@xtch@r@cter#1#2\noboundary#3{% + \ifx\relax#2#1\else\noexpand#3\fi +} +\robust@redef\cpt@ifstar#1{\ifnextcharTF*{\@firstoftwo{#1}}} +\robust@redef*\cpt@starorlong#1{% + \cpt@ifstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}% +} +\new@def*\ifsecondisnnilTF#1{% + \expandafter\expandafter\expandafter\cpt@ifsecondisnnil + \expandafter\string\noexpand#1\cpt@nnil\cpt@nil +} +\new@def*\cpt@ifsecondisnnil#1#2\cpt@nil{% + \expandafter\ifcseqTF\cpt@car#2\car@nil\cpt@nnil +} +\new@def\aftercsname#1#2{% + \expandafter\cptswap\expandafter{\csname#2\endcsname}{#1}% +} +\new@def\xaftercsname#1#2{% + \expandafter\expandafter\expandafter + \cptswap\expandafter\expandafter + \expandafter{\csname#2\endcsname}{#1}% +} +\new@def\xaftercsnamebrace#1#2{% + \expandafter\expandafter\expandafter + \cptswapbracefirst\expandafter + \expandafter\expandafter{\csname#2\endcsname}{#1}% +} +%% For internal use; #1 must be one token: +\new@def*\simpleexpandarg#1#2{\expandafter#1\expandafter{#2}} +\cptnewlet\s@expandarg\simpleexpandarg +%%-- + +\new@def*\cptexpandnext#1#2{% + \expandafter\cptswap\expandafter{#2}{#1}% +} +\new@def*\cptbexpandnext#1#2{% + \expandafter\expandafter\expandafter\cptswap + \expandafter\expandafter\expandafter{#2}{#1}% +} +\new@def*\cptexpandbracenext#1#2{% + \expandafter\cptswapbracefirst\expandafter{#2}{#1}% +} +\cptnewlet\cptexpandbrnext\cptexpandbracenext +\new@def*\cptexpandsome#1\expandthis#2#3\expandstop{% + \cptexpandnext{#1}{#2}#3% +} +\new@def*\cptexpandbracesome#1\expandthis#2#3\expandstop{% + \cptexpandbracenext{#1}{#2}#3% +} +\new@def\cptremovescape#1{% + \ifblankTF{#1}{}{\expandafter\@gobble\string#1}% +} +\new@def\cptgobblescape#1{% + \ifblankTF{#1}{}{% + \ifnum\escapechar>\@cclv\else + \ifnum\escapechar<\z@pt\else + \expandafter\expandafter + \csname @gobble\ifnum\escapechar=\@xxxii @space\fi + \cptthreexp\endcsname + \fi + \fi + \string#1% + }% +} +\robust@def*\defpass#1#2#{\afterassignment#1\long\def#1#2} +\robust@def*\edefpass#1#2#{\afterassignment#1\long\edef#1#2} +\new@def\uselivecs#1{% + \ifdefTF{#1}{#1}{\cpt@notdeferr{#1}}% +} +\new@def*\usecsifdef#1{\ifdefTF#1{#1}{}} +\new@def*\expandonceifmacroelsenil#1{% + \ifmacroTF{#1}{% + \ifexpandableTF{#1}{% + \expandcsonce{#1}% + }{% + \unexpanded{#1}% + }% + }{}% +} +\new@def\usename#1{\csname#1\endcsname}% long! +\new@def\usecsn#1{% + \ifcsname#1\endcsname\expandafter\@iden\else + \expandafter\@gobble\fi{\usename{#1}}% +} +% \usecsnifdef is stronger than \usecsn: +\new@def*\usecsnifdef#1{\ifcsndefTF{#1}{\usename{#1}}{}} +\new@def\uselivecsn#1{% + \ifcsndefTF{#1}{% + \usename{#1}% + }{% + \cpt@err{Command '\@backslashchar#1' undefined}\@ehc + }% +} +\new@def\ifcondTF#1\fi{\csname @#1first\else second\fi oftwo\endcsname} +\new@def\ifcondFT#1\fi{\ifcondTF#1\fi} +\new@def*\ifcsnameTF#1{% + \ifblankTF{#1}\@secondoftwo{% + \usename{@\ifcsname#1\endcsname first\else second\fi oftwo}% + }% +} +\new@def*\ifcsnameFT#1{\ifcsnameTF{#1}\cptiiofii\cptiofii} +\new@def*\ifnamedefTF#1{% + \ifcsnameTF{#1}{% + \usename{@\expandafter\ifx\csname#1\endcsname\relax + second\else first\fi oftwo}% + }{% + \@secondoftwo + }% +} +\robust@def*\cpt@notdefinable{% + \@latex@error + {Command '\@backslashchar\undefinablecs' already exists}% + {Command '\@backslashchar\undefinablecs' already defined, + \MsgBrk or name '\@backslashchar\@qend\undefinablecs' illegal.} +} +\robust@def*\ifchoicefoundTF\endgroup{% + \expandafter\endgroup\ifcpt@choicefd + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +\robust@def*\cpt@oneoftwo#1\endgroup{% + \let\@firstoftwo\relax + \let\@secondoftwo\relax + \cptpassexpanded{% + \endgroup + \ifcase#1\relax + \ifdefboolTF{cpt@choicefd}\cptiofii\cptiiofii + \or + \ifdefboolTF{cpt@choicefd}\cptiiofii\cptiofii + \else + \cpt@err{Invalid number '#1'}\noexpand\@ehc + \fi + }% +} +\robust@def*\cpt@ifseeparameter#1#{% + \xifinsetTF + {\detokenize{macro parameter character}} + {\meaning\@let@token}% +} +% \cptcommanormalize is cheap but is restricted to comma lists only. +% Also, it isn't meant for parsing keyval lists. See \kv@@normalize +% and \kv@@parse: +\begingroup +\uccode`\~=`\,% +\uppercase{\endgroup + \def\cptcommanormalize#1{% + \unexpanded\expandafter{\romannumeral-`\q + \cpt@activecomma,#1,~\cpt@nil}% + }% + \def\cpt@activecomma#1~#2\cpt@nil{% + \ifblankTF{#2} + {\cpt@spacecomma#1 ,\cpt@nil}{\cpt@activecomma#1,#2\cpt@nil}% + }% +} +\def\cpt@spacecomma#1 ,#2\cpt@nil{% + \ifblankTF{#2} + {\cpt@commaspace#1, \cpt@nil}{\cpt@spacecomma#1,#2\cpt@nil}% +} +\def\cpt@commaspace#1, #2\cpt@nil{% + \ifblankTF{#2} + {\cpt@doublecomma#1,,\cpt@nil}{\cpt@commaspace#1,#2\cpt@nil}% +} +\def\cpt@doublecomma#1,,#2\cpt@nil{% + \ifblankTF{#2} + {\ifblankTF{#1}{}{\expandafter\noexpand\@gobble#1}} + {\cpt@doublecomma#1,#2\cpt@nil}% +} +\cptnewcounts{cpt@csvdepth} +\cptnewbools{loopbreak} +\ifcsdefinable\loopbreak{\let\loopbreak\loopbreaktrue} +\robust@def*\cpt@notdeferr#1{% + \@latex@error{Command '\detokenize{#1}' isn't defined} + {I expected '\detokenize{#1}' to be defined.}% +} +\robust@def*\cpt@isdeferr#1{% + \@latex@error{Command '\detokenize{#1}' is already defined} + {I expected '\detokenize{#1}' to be undefined.}% +} +\robust@def*\cpt@notcserr#1{% + \@latex@error{Token '\detokenize{#1}' not a macro + \MsgBrk or is currently undefined} + {I expected '\detokenize{#1}' to be defined.}% +} +\robust@def*\cpt@iscserr#1{% + \@latex@error{Token '\detokenize{#1}' is a macro: + \MsgBrk not currently undefined} + {I didn't expect '\detokenize{#1}' to be defined.}% +} +\robust@def*\cpt@notescapederr#1{% + \@latex@error{Token '\detokenize{#1}' not escaped + \MsgBrk or is an active character}{I expected + the first token of\MsgBrk'\detokenize{#1}' to be + escape character.}% +} +\robust@def*\cpt@isescapederr#1{% + \@latex@error{Token '\detokenize{#1}' is escaped}{% + I didn't expect the first character of '\detokenize{#1}' + \MsgBrk to be the escape character.}% +} +\robust@def*\cpt@notbracederr#1{% + \@latex@error{Token '\detokenize{#1}' isn't braced} + {I expected '\detokenize{#1}' to be braced.}% +} +\robust@def*\cpt@isbracederr#1{% + \@latex@error{Token '\detokenize{#1}' is braced} + {I didn't expect '\detokenize{#1}' to be braced.}% +} +\robust@def*\cpt@notonetokenerr#1{% + \@latex@error{'\detokenize{#1}' is not one token} + {I expected '\detokenize{#1}' to be one token.}% +} +\robust@def*\cpt@isonetokenerr#1{% + \@latex@error{'\detokenize{#1}' is one token} + {I didn't expect '\detokenize{#1}' to be one token.}% +} +\robust@def*\cpt@notblankerr#1{% + \@latex@error{'\detokenize{#1}' is not blank or empty} + {I expected '\detokenize{#1}' to be blank.}% +} +\robust@def*\cpt@isblankerr#1{% + \@latex@error + {Blank/empty token for command '\detokenize{#1}'} + {I didn't expect a blank argument/token here.}% +} +\robust@def*\cpt@notexpandableerr#1{% + \@latex@error{'\detokenize{#1}' is not expandable + \MsgBrk or is undefined} + {I expected '\detokenize{#1}' to be expandable.}% +} +\robust@def*\cpt@toodeep#1#2{% + \@latex@error{Command '\detokenize{#1}' nested too deeply} + {Command '\detokenize{#1}' nested beyond level '#2'.}% +} + +\begingroup +\catcode`\&=7 +\robust@gdef*\cpt@getmacroprefix#1{% + \begingroup + \edef\cpt@tempa##1{\def##1####1\detokenize{macro}:####2&}% + \cpt@tempa\@ifmacro{% + \def\macroprefix{##1}% + \usename{@\ifblankTF{##2}{second}{first}oftwo}% + }% + \edef\cpt@tempb##1{##1\detokenize{macro}:&}% + \cpt@tempb{\expandafter\@ifmacro\meaning#1}{% + \@testtrue + }{% + \@testfalse\def\macroprefix{}% + }% + \cpteveryscan + \cptpassexpanded{% + \endgroup + \ifcsemptyTF\macroprefix\@iden{\noexpand\scantokens}% + {\def\noexpand\macroprefix{\macroprefix}\relax}% + }% +} +\new@gdef*\cpt@getprefix#1>#2&{#1} +\robust@gdef*\ifprotectedTF#1{% + \begingroup + \edef\cpt@tempa##1{\def##1####1\string\protected####2&}% + \cpt@tempa\cpt@tempa{% + \aftercsname\endgroup{@\ifblankTF{##2}{second}{first}oftwo}% + }% + \edef\cpt@tempb##1{% + ##1\expandafter\cpt@getprefix\meaning#1&\string\protected&% + }% + \cpt@tempb\cpt@tempa +} +\endgroup + +% We need the equivalent of '\protected\let' and we want to be able to +% do \shelllet\x=\y: +\robust@def*\shelllet#1{\cpt@ifeql{\cpt@shelllet{#1}}{\cpt@shelllet{#1}}} +\robust@def*\cpt@shelllet#1#2{% + \ifblankTF{#2}{% + \cpt@isblankerr\shelllet + }{% + \expandafter\ifblankTF\expandafter{\@gobble#2}{% + \ifcsdefinable#1{% + % Here we must use \let and not \def (for immediate inheritance): + \ifprotectedTF#2{\let#1=#2}{% + \ifcsndefinable{shell@\cptremovescape#1}{% + \letcsntocs{shell@\cptremovescape#1}=#2% + \protected\edef#1{\cptmakecs{shell@\cptremovescape#1}}% + }% + }% + }% + }{% + \cpt@notonetokenerr{#2}% + }% + }% +} +\robust@def\showruntime#1\runtime{% + \pdfresettimer#1% + \message{Run time: \the\pdfelapsedtime}% +} +\new@def*\ifdocstartedTF{\ifdefTF\cpt@docstarted\cptiofii\cptiiofii} + +\long\def\@gobblethree#1#2#3{} +\long\def\@firstofthree#1#2#3{#1} +\long\def\@secondofthree#1#2#3{#2} +\long\def\@thirdofthree#1#2#3{#3} +\new@def\cptalloftwo#1#2{#1#2} +\new@def*\cptrmstop{0 } +\ifcsdefinable\cptrm{\let\cptrm\romannumeral} +\new@def\cpt@car#1#2\car@nil{#1} +\new@def\cpt@cdr#1#2\cdr@nil{#2} +\ifcsdefinable\cpt@relax{\let\cpt@relax\relax} +% This is needed to define phantom environments: +\newcommand*\phantom@env{\relax} +\new@def\cptgobbletorelax#1\cpt@relax{} +\new@def\cptbgobbletorelax\fi#1\cpt@relax{\fi\endgroup} +\new@def\cpt@removetonnil#1\cpt@nnil{} +\new@def\cpt@catchtonnil#1\cpt@nnil{#1} +\new@def\cpt@removetodot#1.{} +\new@def\cpt@catchtodot#1.{#1} +\new@def\cpt@removetospace#1 {} +\ifcsdefinable\csvbreak{\let\csvbreak\relax} +\new@def*\cpt@csvbreak{\csvbreak} +\ifcsdefinable\csvpause{\let\csvpause\relax} +\new@def*\cpt@csvpause{\csvpause} +\ifcsdefinable\tsvbreak{\let\tsvbreak\relax} +\new@def*\cpt@tsvbreak{\tsvbreak} +\new@def*\ifcsvbreakTF#1{% + \edef\reserved@a{\unexpanded{#1}}% + \ifcseqTF\reserved@a\cpt@csvbreak +} +\ifcsdefinable\cptdoremainder{\let\cptdoremainder\@gobble} +% #1: sentinel; #2: parser +\robust@def*\gobble@to@sentinel#1#2{% + \defpass\reserved@a##1#1#2{\cptdoremainder{##1}}% +} +\new@def*\cptthreexp{\expandafter\expandafter\expandafter} +\new@def*\cptsevenxp{% + \expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter +} +\robust@def\cptlocalxp#1{\begingroup\cptthreexp\endgroup#1} +\new@def*\cptzapspaces#1{% + \def\cptzapspaces##1{\romannumeral\cpt@zapspaces.##1#1\zap@nil}% +} +\cptzapspaces{ } +\long\def\cpt@zapspaces#1 #2\zap@nil{% + \ifblankTF{#2}{% + \expandafter\cptrmstop\@gobble#1% + }{% + \expandafter\cpt@zapspaces\expandafter.\@gobble#1#2\zap@nil + }% +} +\new@def*\cptdotimes#1{% + \ifblankTF{#1}{% + \ifdefboolTF{cpt@useempty}{\cpt@dotimes{m}}\@gobble + }{% + \expandafter\cpt@dotimes\expandafter + {\romannumeral\number#1000}% + }% +} +\new@def*\cpt@dotimes#1#2{% + \ifnullTF{#1}{}{% + #2\relax + \expandafter\ifnullTF\expandafter{\@gobble#1}{}{% + \expandafter\cpt@dotimes\expandafter{\@gobble#1}{#2}% + }% + }% +} +\new@def*\cptexpandtimes#1{% + \expandafter\cpt@expandtimes\expandafter + {\romannumeral\number#1000}% +} +\new@def*\cpt@expandtimes#1#2{% + \ifnullTF{#1}{% + \unexpanded{#2}% + }{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% + \unexpanded\expandafter{#2}% + }{% + \expandafter\cptswapbracefirst\expandafter{#2}% + {\expandafter\cpt@expandtimes\expandafter{\@gobble#1}}% + }% + }% +} +\new@def*\normal@reverse#1{\cpt@normalreverse{}#1\@nnil} +\long\def\cpt@normalreverse#1#2{% + \expandafter\ifxTF\cpt@car#2\car@nil\@nnil{% + \ifdefboolTF{@test}\@iden\unexpanded{#1}% + }{% + \cpt@normalreverse{#2#1}% + }% +} +\new@def*\robust@reverse@testbrace#1{% + \ifnum\cpt@pdfstrcmp{\detokenize\expandafter{\@gobble#1.}}{}=\z@pt + \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi + {% + \ifnum\cpt@pdfstrcmp{\expandafter\@car\detokenize{#1}\@nil}% + \cpt@leftbracechar=\z@pt + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + }{% + \@secondoftwo + }% +} +\new@def*\robust@reverse#1{\cpt@robustreverse{}.#1\@nnil} +\long\def\cpt@robustreverse#1#2\@nnil{% + \cpt@r@bustreverse{#1}% + {\expandafter\robust@reverse@testbrace\expandafter{\@gobble#2}}#2\@nnil +} +\long\def\cpt@r@bustreverse#1#2.#3{% + \expandafter\ifxTF\cpt@car#3\car@nil\@nnil{% + \ifdefboolTF{@test}\@iden\unexpanded{#1}% + }{% + #2{\cpt@robustreverse{{#3}#1}}{\cpt@robustreverse{#3#1}}.% + }% +} +\robust@def*\ifcommandsdefinable#1{% + \@testopt{\cpt@ifcmdsdefinable#1}\relax +} +\def\cpt@ifcmdsdefinable#1[#2]{% + \edef\reserved@e{\unexpanded{#2}}% + \begingroup + \@tempswafalse + \cptfor #1\dofor{% + \if\expandafter\@car\string##1x\@nil\@backslashchar + \@tempswafalse + \ifcsdefinable##1\@tempswatrue + \else + \cpt@notescapederr{##1}% + \fi + \if@tempswa\else\loopbreak\fi + }% + \if@tempswa + \aftergroup\reserved@e + \fi + \endgroup +} +\ifcommandsdefinable{\cpttrimspace,\cpttrimspaces}\relax +\long\def\cpttrimspaces#1{\cpt@trimspaces@a\relax{#1}} +\begingroup +\catcode`\&=7\catcode`\$=7 +\long\gdef\cpt@trimspaces@a#1#2{\cpt@trimspaces@b.#1$.#2& &} +\long\gdef\cpt@trimspaces@b#1$#2 &{\cpt@trimspaces@c#1$#2&} +\long\gdef\cpt@trimspaces@c#1$#2{% + \cpt@trimspaces@d\ifstrcmpTF{#2}{#1}{% + \unexpanded\expandafter{\@gobble#1}% + }{% + \cpt@trimspaces@d\cpt@trimspaces@a{#2}{#2}% + }% +} +\long\gdef\cpt@trimspaces@d#1#2{% + \expandafter\cpt@trimspaces@e\expandafter#1\expandafter{% + \unexpanded\expandafter + {\romannumeral-`\q\expandafter\noexpand\@gobble#2}% + }% +} +\long\gdef\cpt@trimspaces@e#1#2#3{% + \expandafter#1\expandafter{\@gobble#3}{#2}% +} +\long\gdef\cpttrimspace#1{\cpt@trimspace@a.#1& &} +\long\gdef\cpt@trimspace@a#1 &{\cpt@trimspace@b#1&} +\long\gdef\cpt@trimspace@b#1{% + \unexpanded\expandafter{% + \romannumeral0% + \expandafter\ifleadspaceTF\expandafter{\@gobble#1}{% + \@gobble#1% + }{% + \expandafter\@space\@gobble#1% + }% + }% +} +\endgroup +\robust@def\trim@@spaces#1#2{\edef#2{\cpttrimspaces{#1}}} +\robust@def\trim@@space#1#2{\edef#2{\cpttrimspace{#1}}} +\robust@def*\despacecontent#1{% + \edef#1{\simpleexpandarg\cpttrimspace{#1}}% +} +\robust@def\cptusesimpletrimspaces{% + \let\cptcurrtrimspaces\cpttrimspace +} +\cptusesimpletrimspaces +\let\cptusesimpletrimspace\cptusesimpletrimspaces +\robust@def\cptusehardtrimspaces{% + \let\cptcurrtrimspaces\cpttrimspaces +} +\let\cptusehardtrimspace\cptusehardtrimspaces +% It is more efficient to use \csv@@normalize in place +% of \cptdespacecsvlist. Also, \csv@@normalize allows parsers +% to be made innocent. But the following is needed in some +% instances (eg, where we don't want to sanitize the parser): +\robust@def*\cptdespacecsvlist{\cpt@teststopt\cpt@despacecsvlist,} +% #1: arbitrary parser +% * -> #2 is a <listcmd>, otherwise a <list> +\robust@def*\cpt@despacecsvlist[#1]#2{% + \cpt@stchoose{cpt@st}{#2}\cpt@tempa\cpt@despacecsvlist + \ifcsnullTF\cpt@tempa{}{% + \def\cpt@rsvda{}% + \UseEmptyEntry + \def\csv@do##1{% + \edef\cpt@tempa{\cpttrimspaces{##1}}% + \cptoaddtolist[#1]\cpt@rsvda\cpt@tempa + }% + \csv@@loop*[#1]\cpt@tempa + \ifdefboolFT{cpt@st}{}{\let#2=\cpt@rsvda}% + }% +} +% \cptnewvariables{<type>}[<prf>]{<variables>}[<state/value>] +% If <type> is 'toks', <state/value> is the content of the +% new token register. +% Valid <types> are 'if, toks, dimen, count, tog, switch'. +% Boxes can't be initialized by this command. +\robust@def*\cptnewvariables#1{\cpt@testopt{\cpt@newvariables{#1}}{}} +\robust@def*\cpt@newvariables#1[#2]#3{% + \edef\reserved@a{\noexpand\cpt@testopt{% + \cpt@newv@riables{\cpttrimspace{#1}}{\cpttrimspace{#2}}{#3}% + }{}}% + \reserved@a +} +\robust@def*\cpt@newv@riables#1#2#3[#4]{% + \def\cpt@rsvda##1{% + \ifblankTF{#4}{\def\cpt@tempc{##1}}{\def\cpt@tempc{#4}}% + }% + \edef\cpt@tempb{\ifstrcmpTF{#1}{if}{if}{}}% + \cptfor#3\dofor{% + \ifblankTF{##1}\cptgobbletorelax\relax + \ifnamedefTF{\cpt@tempb#2##1}{% + \edef\undefinablecs{\cpt@tempb#2##1}% + \ifstrcmpTF{#1}{tog}{}{\cpt@notdefinable}% + }{% + \ifstrcmpTF{#1}{tog}{% + \@tempswatrue + \ifnamedefTF{cpt@tog@#2##1}{% + \cpt@err{Toggle '#2##1' already defined}\@ehc + }{% + \lowercase{% + \ifstrcmpTF{#4}{true}{% + \let\cpt@togstate\@firstoftwo + }{% + \ifstrcmpTF{#4}{false}{% + \let\cpt@togstate\@secondoftwo + }{% + \ifblankTF{#4}{% + \let\cpt@togstate\@secondoftwo + }{% + \@latex@error{Invalid toggle value '#4'}\@ehc + }% + }% + }% + }% + \expandafter\let\csname + cpt@tog@#2##1\endcsname\cpt@togstate + }% + }{% + \@tempswatrue + % Declare the new switch: + \ifstrcmpTF{#1}{switch}{% + \lowercase{% + \ifstrcmpTF{#4}{true}{% + \def\reserved@a{00}% + }{% + \ifstrcmpTF{#4}{false}{% + \def\reserved@a{01}% + }{% + \ifblankTF{#4}{% + \def\reserved@a{01}% + }{% + \@latex@error{Invalid switch value '#4'}\@ehc + }% + }% + }% + }% + \expandafter\let\csname#2##1\endcsname\reserved@a + }{% + \@tempswafalse + % Declare the new variable: + \csname new#1\expandafter\endcsname\csname + \cpt@tempb#2##1\endcsname + % Initialize the new variable: + \ifstrcmpTF{#1}{if}{% + \cpt@rsvda{false}% + \csname#2##1\cpt@tempc\endcsname + }{% + \ifstrcmpTF{#1}{toks}{% + \cpt@rsvda{}% + \csname#2##1\endcsname\expandafter{\cpt@tempc}% + }{% + % It is dangerous to initialize boxes here: + % horizontal and vertical boxes are incompatible. + \ifstrcmpTF{#1}{box}{}{% + \ifstrcmpTF{#1}{count}{% + \cpt@rsvda\z@pt + \csname#2##1\endcsname=\cpt@tempc\relax + }{% + \ifstrcmpTF{#1}{dimen}{% + \cpt@rsvda\z@pt + \csname#2##1\endcsname=\cpt@tempc\relax + }{% + \ifstrcmpTF{#1}{skip}{% + \cpt@rsvda{\z@pt plus \z@pt minus \z@pt}% + \csname#2##1\endcsname=\cpt@tempc\relax + }{% + \ifstrcmpTF{#1}{write}{}{% + \ifstrcmpTF{#1}{read}{}{% + \cpt@unknownnewvar{#1}% + }% + }% + }% + }% + }% + }% + }% + }% + }% + }% + }% + \cpt@relax + }% +} +\def\cpt@unknownnewvar#1{% + \if@tempswa\else + \begingroup + \def\x##1{Maybe you meant '##1'.}% + \cpt@err{Unknown variable type '#1'}{% + \ifstrcmpTF{#1}{dim}{\x{dimen}}{% + \ifstrcmpTF{#1}{token}{\x{toks}}{% + \ifstrcmpTF{#1}{tok}{\x{toks}}{% + \ifstrcmpTF{#1}{toggle}{\x{tog}}{% + \ifstrcmpTF{#1}{sw}{\x{switch}}{% + No variable of type '#1'. + }% + }% + }% + }% + }% + }% + \endgroup + \fi +} + +\cptnewvariables{if}[cpt@]{usepox,optfd,noval,igopt,inpox,olddx, + in,check,choicefd,useempty,swa}[false] + +% st -> I saw star +% pl -> I saw plus +% pm -> I saw prime +% cl -> I saw exclamation mark +% verbose -> log information (package option) +% usepox -> use \XDeclareOption and \XProcessOptions for +% \DeclareOption and \ProcessOptions (package option) +% igopt -> ignore option +% optfd -> option found +% inpox -> we're in \XProcessOptions +% olddx -> we're in \DeclareOption and not in \XDeclareOption +% in -> for use in \cpt@in +% check,sw -> generic booleans ('check' for short intervals; +% 'sw' for longer intervals) +% choicefd -> generic (choice found) +% loopbreak -> terminate loop +% useempty -> use empty entry (in loops) +% +\cptnewvariables{tog}{biboolopts}[false] +\cptnewvariables{count}[cpt@]{optdepth,cnta}[\z@pt] +\new@def*\UseEmptyEntry{\global\cpt@useemptytrue} +\new@def*\DiscardEmptyEntry{\global\cpt@useemptyfalse} +\new@def\oifnullTF#1{\expandafter\ifnullTF\expandafter{#1}} +\new@def\oifnullFT#1{\expandafter\ifnullFT\expandafter{#1}} +\new@def\xifnullTF#1{\cptexpandarg\ifnullTF{#1}} +\new@def\xifnullFT#1{\cptexpandarg\ifnullFT{#1}} +\new@def\oifblankTF#1{\expandafter\ifblankTF\expandafter{#1}} +\new@def\oifblankFT#1{\expandafter\ifblankFT\expandafter{#1}} +\new@def\xifblankTF#1{\cptexpandarg\ifblankTF{#1}} +\new@def\xifblankFT#1{\xifblankTF{#1}\cptiiofii\cptiofii} +\new@def*\ifdefTF#1{% + \ifblankTF{#1}\@secondoftwo{% + \usename{@\ifx#1\cpt@undefined second\else + \ifx#1\relax second\else first\fi\fi oftwo}% + }% +} +\new@def*\ifdefFT#1{\ifdefTF{#1}\cptiiofii\cptiofii} +\new@def*\oifdefTF#1{\expandafter\ifdefTF\expandafter{#1}} +\new@def*\oifdefFT#1{\expandafter\ifdefFT\expandafter{#1}} +\new@def*\xifdefTF#1{\cptexpandarg\ifdefTF{#1}} +\new@def*\xifdefFT#1{\cptexpandarg\ifdefFT{#1}} +\new@def*\ifcsndefTF#1{% + \ifblankTF{#1}{% + \expandafter\@secondoftwo\@gobble + }{% + \ifcsname#1\endcsname + \expandafter\@firstofone + \else + \cptthreexp\@secondoftwo\expandafter\@gobble + \fi + }{% + \aftercsname\ifdefTF{#1}% + }% +} +\new@def*\ifcsndefFT#1{\ifcsndefTF{#1}\cptiiofii\cptiofii} +\new@def*\oifcsndefTF#1{\expandafter\ifcsndefTF\expandafter{#1}} +\new@def*\oifcsndefFT#1{\expandafter\ifcsndefFT\expandafter{#1}} +\new@def*\xifcsndefTF#1{\cptexpandarg\ifcsndefTF{#1}} +\new@def*\xifcsndefFT#1{\cptexpandarg\ifcsndefFT{#1}} +\robust@redef*\ifcsdefinable#1#2{% + \ifblankTF{#1}{% + \cpt@isblankerr\ifcsdefinable + }{% + \edef\undefinablecs{\cptgobblescape#1}% + \ifdefTF{#1}\cpt@notdefinable{% + \ifcsndefTF{end\undefinablecs}\cpt@notdefinable{#2}% + }% + }% +} +\ifcsdefinable\@ifcsdefinable{\let\@ifcsdefinable\ifcsdefinable} +\robust@def\rc@ifcsdefinable#1#2{\let\ifcsdefinable\@ifcsdefinable#2} +\robust@def*\ifcsndefinable#1{\cptlocalxp\aftercsname\ifcsdefinable{#1}} +\robust@def*\ifdefinableTF#1{% + \ifblankTF{#1}{% + \cpt@isblankerr\ifdefinableTF + \@secondoftwo + }{% + \ifdefTF{#1}\@secondoftwo{% + \ifcsndefTF{end\cptgobblescape#1}\cptiiofii\cptiofii + }% + }% +} +\robust@def*\ltxmsg@warn{\@latex@warning@no@line} +\robust@def*\ltxmsg@info{\@latex@info@no@line} +\robust@def*\ltxmsg@err{\@latex@error} +\robust@redef\cpt@testopt#1#2{\ifnextcharTF[{#1}{#1[{#2}]}} + +% Eg, \def\csa{\cpt@testcharopt\csb<{default}>} +% \def\csb<#1>{...} +\robust@def*\cpt@testcharopt#1#2#3#4{\ifnextcharTF#2{#1}{#1#2{#3}#4}} + +% Expandable \@testopt: +% Eg, \def\macroa#1{\cpt@xtestopt{#1}\macrob{Mr.}} +% \def\macrob[#1]#2{#1 #2} +% \edef\testa{\macroa{John Johnson}} +% \edef\testb{\macroa[Dr.]{Haiki Heiki}} +\new@def*\cpt@xtestopt#1#2#3{% + \cpt@xifbrack#1\\[\\{#2#1}{#2[{#3}]{#1}}% +} +\new@def*\cpt@xifbrack#1[#2\\#3#{\ifblankTF{#1#2}} +% Eg, \def\macroa{\cpt@newxtestopt\macrob{Mr.}} +% \def\macrob[#1]#2{#1 #2} +% \edef\testa{\expandafter\macroa\activespace{John Johnson}} +% \edef\testb{\macroa[Dr.]{Haiki Heiki}} +\new@def*\cpt@newxtestopt#1#2#3{% + % #3 will be a space only if that space is active. But + % \ifstrcmpTF will detokenize that space before comparison. + \ifstrcmpTF{ }{#3}{% + \cpt@newxtestopt#1{#2}% + }{% + \ifstrcmpTF{#3}{[}{% + #1[% + }{% + \ifntypeTF{#3}{% + #1[#2]#3% + }{% + #1[#2]{#3}% + }% + }% + }% +} +\robust@def*\cpt@ifbrack#1#2{\ifnextcharTF[{#1}{#2}} +\robust@def\cpt@testpnopt#1#2{\ifnextcharTF({#1}{#1({#2})}} +\robust@def\cpt@testltopt#1#2{\ifnextcharTF<{#1}{#1<{#2}>}} +\robust@def\cpt@ifplus#1{\ifnextcharTF+{\@firstoftwo{#1}}} +\robust@def\cpt@ifclam#1{\ifnextcharTF!{\@firstoftwo{#1}}} +\robust@def\cpt@ifprime#1{\ifnextcharTF'{\@firstoftwo{#1}}} +\robust@def\cpt@ifeql#1{\ifnextcharTF={\@firstoftwo{#1}}} +\robust@def\cpt@testst#1{\cpt@ifstar{\cpt@sttrue#1}{\cpt@stfalse#1}} +\robust@def\cpt@testpl#1{\cpt@ifplus{\cpt@pltrue#1}{\cpt@plfalse#1}} +\robust@def\cpt@testpm#1{\cpt@ifprime{\cpt@pmtrue#1}{\cpt@pmfalse#1}} +\robust@def\cpt@testcl#1{\cpt@ifclam{\cpt@cltrue#1}{\cpt@clfalse#1}} +\robust@def\cpt@teststpl#1{\cpt@testst{\cpt@testpl{#1}}} +\robust@def\cpt@teststpm#1{\cpt@testst{\cpt@testpm{#1}}} +\robust@def\cpt@teststopt#1#2{\cpt@testst{\cpt@testopt{#1}{#2}}} +\robust@def*\newletcs#1{% + \begingroup + \def\cpt@tempa{\relax}% + \cpt@ifeql{\cpt@newletcs{#1}}{\cpt@newletcs{#1}}% +} +\robust@def*\gnewletcs#1{% + \begingroup + \def\cpt@tempa{\global}% + \cpt@ifeql{\cpt@newletcs{#1}}{\cpt@newletcs{#1}}% +} +\robust@def*\cpt@newletcs#1{% + \ifcsdefinable{#1}{% + \expandafter\endgroup\cpt@tempa\let#1= % + }% +} +\robust@def*\gletcs{\global\let} +\robust@def*\fulllet{\@testtrue\cpt@fulllet} +\robust@def*\fullnewlet{\@testfalse\cpt@fulllet} +\robust@def*\cpt@fulllet#1#2{% + \trim@@space{#1}\cpt@tempa + \trim@@space{#2}\cpt@tempb + \cpt@fullleterr\cpt@tempa\cpt@tempb + \csname\if@test let\else newletcs\fi + \cptthreexp\endcsname\expandafter\cpt@tempa\cpt@tempb + \oifdefFT\cpt@tempb{}{% + \ifcsndefTF{\expandafter\string\cpt@tempb}{% + \letcsntocsn{\expandafter\string\cpt@tempa} + {\expandafter\string\cpt@tempb}% + }{% + \ifcsndefFT{\expandafter\cptgobblescape\cpt@tempb\@space}{}{% + \letcsntocsn{\expandafter\cptgobblescape\cpt@tempa\@space} + {\expandafter\cptgobblescape\cpt@tempb\@space}% + \ifcsndefFT{\expandafter\string\cpt@tempb\@space}{}{% + \letcsntocsn{\expandafter\string\cpt@tempa\@space} + {\expandafter\string\cpt@tempb\@space}% + }% + }% + }% + }% +} +\new@def*\cpt@fullleterr#1#2{% + \simpleexpandarg\ifntypeTF{#1}{% + \simpleexpandarg\ifntypeTF{#2}{}{% + \cpt@notonetokenerr{#2}% + }% + }{% + \cpt@notonetokenerr{#1}% + }% +} +\robust@def*\letcsset{% + \@tempswafalse + \cpt@ifstar + {\let\dolet\ltsfulllet\cpt@newletcsset}% + {\let\dolet\let\cpt@newletcsset}% +} +% Eg, \newletcsset{\a\b,\x\y} +\robust@def*\newletcsset{% + \@tempswatrue + \cpt@ifstar + {\let\dolet\ltsfulllet\cpt@newletcsset}% + {\let\dolet\let\cpt@newletcsset}% +} +\robust@def*\cpt@newletcsset#1{% + \def\cpt@tempa##1##2\cpt@nil{% + \cpt@tempb##1=##2\cpt@nil + }% + \def\cpt@tempb##1=##2\cpt@nil{% + \ifblankFT{##2}{}{% + \cpt@err{The partner of command '\string##1' is void}\@ehc + }% + \if@tempswa + \ifdefTF{##1}{% + \ifx##1##2\else\cpt@isdeferr{##1}\fi + }{% + \dolet##1=##2% + }% + \else + \dolet##1=##2% + \fi + }% + \cptfor#1\dofor{% + \ifinsetTF{=}{##1}{% + \cpt@tempb##1\cpt@nil + }{% + \cpt@tempa##1\cpt@nil + }% + }% + \undefcs\dolet +} +\robust@def*\cptletmanytocs#1#2{\cptfor#1\dofor{\let##1= #2}} +\robust@def*\fullletmanytocs#1#2{\cptfor#1\dofor{\fulllet{##1}{#2}}} +\robust@def*\begintoksgroup{\begingroup\toks@{}} +\robust@def*\endtoksgroup{\expandafter\endgroup\the\toks@} + +\begingroup +\catcode`\&=7 +\new@gdef*\ifcounterTF#1{% + \ifcseqTF#1\count{% + \@secondoftwo + }{% + \expandafter\cpt@ifcounter@a\meaning#1:&% + }% +} +\edef\cpt@ifcounter@a#1#2{% + \gdef#1##1:##2&{#2##1\string\count&}% + \gdef#2##1\string\count##2&{\noexpand\ifblankTF{##1}}% +} +\cpt@ifcounter@a\cpt@ifcounter@a\cpt@ifcounter@b +% Similar to \ifcounterTF. Don't call this \ifdimTF: +\new@gdef*\ifdimenTF#1{% + \ifcseqTF#1\dimen{% + \@secondoftwo + }{% + \expandafter\cpt@ifdimen@a\meaning#1:&% + }% +} +\edef\cpt@ifdimen@a#1#2{% + \gdef#1##1:##2&{#2##1\string\dimen&}% + \gdef#2##1\string\dimen##2&{\noexpand\ifblankTF{##1}}% +} +\cpt@ifdimen@a\cpt@ifdimen@a\cpt@ifdimen@b +\endgroup + +% Argument #1 can be an arbitrary number (\countdef'd or otherwise). +% Pushing is done globally. +\robust@def*\cptpushnumber#1{% + \ifntypeTF{#1}{% + \ifdefTF{#1}{% + \ifcounterTF#1{% + \global\advance#1\@ne + }{% + \xdef#1{\the\numexpr#1+1}% + }% + }{% + \gdef#1{\@ne}% + }% + }{% + \cpt@notonetokenerr{#1}% + }% +} +\robust@def*\cptpopnumber#1{% + \ifntypeTF{#1}{% + \ifdefTF{#1}{% + \ifnumcmpTF#1=\z@pt{% + \cpt@err{Counter or number '\string#1' is already 0}\@ehc + }{% + \ifcounterTF#1{% + \global\advance#1\m@one + }{% + \xdef#1{\the\numexpr#1-1}% + }% + }% + }{% + \cpt@err{Counter or number '\string#1' is undefined}\@ehc + }% + }{% + \cpt@notonetokenerr{#1}% + }% +} +% #1: calling/base function to push +% #2: comma-separated state list (subsidiary functions) to push +% #3: arbitrary number +\robust@def*\cptpushfunctions#1#2#3{% + \begingroup + \def\reserved@a##1##2\push@nil{% + \ifx\cptpushfunctions##2% + \cptpushnumber#3% + \else + \cpt@notonetokenerr{#3}% + \fi + }% + \reserved@a#3\cptpushfunctions\push@nil + \toks@{}\@temptokena{}\escapechar-1\relax + \let\xp\expandcsonce + \edef\cpt@stack{\string#1@cpt@stack}% + \ifcsndefTF\cpt@stack{}{\csn@def\cpt@stack{}}% + % #2 comes with \\ behind each macro to be pushed. + \def\\##1{% + \edef\cpt@tempa{\noexpandcsn{\string##1@cpt@\cptrm#3}}% + \cptexpanded{% + \toks@{\the\toks@\let\xp\cpt@tempa\noexpand##1}% + \@temptokena{\the\@temptokena\let\noexpand##1\xp\cpt@tempa + \undefcs\xp\cpt@tempa}% + }% + }% + #2% + \csn@xdef\cpt@stack{% + \the\@temptokena\noexpand\cpt@nil{\expandcsnonce\cpt@stack}% + }% + \expandafter\endgroup\the\toks@ +} + +% #1: calling/base function to pop +% #2: depth counter +\robust@def*\cptpopfunctions#1#2{% + \ifdefTF{#2}{% + \ifnum#2=\z@pt + \cpt@err{Number '\string#2' is currently '0'}\@ehc + \fi + }{% + \cpt@err{Can't pop functions with unknown + \MsgBrk number \string#2}\@ehc + }% + \edef\cpt@stack{\cptremovescape{#1}@cpt@stack}% + \ifcsndefTF\cpt@stack{% + \edef\reserved@a{\expandcsnonce\cpt@stack}% + \def\reserved@b##1\cpt@nil{##1\csn@gdef\cpt@stack}% + \expandafter\reserved@b\reserved@a + }{% + \cpt@err{Unknown stack for function \string#1}\@ehc + \@gobble + }% + \cptpopnumber{#2}% +} +\cptchardef\cpt@optionstacklimit=4\relax +% #1: calling (base) function +% #2: state list (a macro) +% #3: state counter +\robust@def*\cpt@pushstate#1#2#3{% + \ifnum#3>\cpt@optionstacklimit\relax + \@latex@error{Current option/key state is being pushed + \MsgBrk beyond level '\cpt@optionstacklimit'. I suspect infinite + \MsgBrk re-entrance. If this isn't the case, please + \MsgBrk set package option 'option-stack-limit' or + 'key-stack-limit' to the required value in + \MsgBrk\noexpand\documentclass + }\@ehc + \fi + \cptexpandargonce{\cptpushfunctions#1}{#2}{#3}% +} +% #1: calling/base function +% #2: state counter +\robust@def*\cpt@popstate#1#2{\cptpopfunctions{#1}{#2}} +\robust@def*\cpt@stchoose#1#2#3#4{% + \ifdefboolTF{#1}{% + \ifmacroTF{#2}{% + \let#3=#2% + }{% + \cpt@err{Bad arguments to macro '\detokenize{#4}'. + \MsgBrk Token '\detokenize{#2}' not a macro + \MsgBrk but '\@backslashchar if#1' is true}\@ehc + }% + }{% + \edef#3{\unexpanded{#2}}% + }% +} +\robust@def*\cptdelimitcs#1#2{% + \begingroup + \def\cpt@tempb##1{% + \edef\cpt@tempa####1{% + \def####1########1\detokenize{macro:}########2% + ->########3\cpt@nil{% + ########1\def\string\cpt@tempa########2% + \ifblankTF{##1}{}{\string##1}{########3}% + }% + \edef####1{####1\meaning#1\cpt@nil}% + }% + \cpt@tempa\cpt@tempa + }% + \cpt@tempb{}% + \cpteveryscan + \scantokens\expandafter{\cpt@tempa}\relax + \ifcseqTF#1\cpt@tempa{% + \cpt@tempb{#2}% + \scantokens\expandafter{\cpt@tempa}\relax + }{% + \cpt@err{Your command \noexpand#1 isn't scannable. + \MsgBrk I needed to delimit its last parameter text}\@ehc + }% + % Because of parameters, \postgroupdef can't be used here: + \gletcs#1\cpt@tempa + \endgroup +} +% First provide \def\do<params>{<defn>} +% \cptdofunclist[<parser>]{<list>} +% \cptdofunclist*[<parser>]{<listcmd>} +% The command expects \do, which can be multi-parametered. +% Parameters of \do are delimited internally, relieving the user +% of this need. Calling \cptdofunclist is equivalent to defining +% a multi-parametered \do within \csv@do: +\robust@def*\cptdofunclist{% + \cptpushnumber\dofunclistdepth + \begingroup + \edef\sav@do{\cptmakecs{sav@do@\cptrm\dofunclistdepth}}% + \expandafter\let\sav@do\do + \expandafter\cptdelimitcs\sav@do\cpt@nil + \toks@{\def\csv@do##1}% + \toks1\expandafter{\expandafter\expandafter\sav@do + \cptrm\ifbracedTF{##1}{0{##1}}{0 ##1}\cpt@nil}% + \expandafter\expandafter\expandafter\endgroup\expandafter + \the\expandafter\toks@\expandafter{\the\toks1}% + \csv@@parse +} +\robust@def*\cptdocommalist{\cpt@testst\cpt@docommalist} +\robust@def*\cpt@docommalist#1#2{% + \def\csv@do##1{#2}% + \cptexpanded{\csv@@parse\ifcpt@st*\fi}{#1}% +} +\robust@def*\csv@@loop{\cpt@listparse{01}{01}} +\robust@def*\csv@@parse{\cpt@listparse{00}{01}} +\robust@def*\kv@@loop{\cpt@listparse{01}{00}} +\robust@def*\kv@@parse{\cpt@listparse{00}{00}} +\new@def*\cpt@listparse#1#2{% + \def\cpt@nmlz{#1}\def\cpt@inkv{#2}% + \cpt@teststopt\cpt@listp@rse,% +} +\newletcs\cpt@csvnil\relax +\new@def*\cpt@csvnnil{\cpt@csvnil} +\newcommand*\cpt@listp@rse[2][,]{% + \cpt@stchoose{cpt@st}{#2}\cpt@csvarg\cpt@listparse + % \cpt@nmlz and \cpt@inkv are used before the commencement + % of the loop: no need to include them in the state list. + % \cpt@loopcbk is meant for callbacks with hash characters. + % It can be defined outside \csv@do or \kv@do and called within + % \csv@do or \kv@do. + \cptpushfunctions\cpt@listparse{% + \\\cpt@listdo\\\curr@do\\\cpt@loopcbk + \\\ifcpt@useempty\\\ifloopbreak\\\cptdoremainder + }\cpt@csvdepth + \letcstocsn\curr@do{\if\cpt@inkv kv\else csv\fi @do}% + \ifdefTF\curr@do{}{% + \cpt@err{'\string\csv@do' or '\string\kv@do' is undefined}\@ehc + }% + \def\cpt@listdo##1#1{% + \edef\cpt@csvarg{\expandcsonce{\@gobble##1}}% + \ifcseqTF\cpt@csvarg\cpt@csvnnil{}{% + \ifcseqTF\cpt@csvarg\cpt@csvbreak{% + \loopbreaktrue + }{% + \ifcsemptyTF\cpt@csvarg{% + \ifboolFT{cpt@useempty}{}{\curr@do{}\relax}% + }{% + \s@expandarg\curr@do\cpt@csvarg\relax + }% + }% + \ifdefboolTF{loopbreak} + {\gobble@to@sentinel\cpt@csvnil#1}{\cpt@listdo.}% + }% + }% + \ifswitchFT{cpt@nmlz}{}{% + \ifcsemptyTF\cpt@csvarg{}{% + \cpt@sttrue + \usename{cpt@\ifswitchTF{cpt@inkv}{kv}{csv}normalize}% + [#1]\cpt@csvarg + }% + }% + \loopbreakfalse + \expandafter\cpt@listdo\expandafter.\cpt@csvarg#1\cpt@csvnil#1% + \cptpopfunctions\cpt@listparse\cpt@csvdepth + \ifnum\cpt@csvdepth=\z@pt + % So that these functions are defined before the loop is called: + \undefcs\csv@do\undefcs\kv@do\undefcs\dofunclistdepth + \fi +} +% #1=keyval list, #2=processor +\robust@def*\kv@@process#1#2{% + \cptpushfunctions\kv@@process{\\\kv@do\\\ifloopbreak\\#2}\cpt@csvdepth + \def\kv@do##1,{% + \defifxTF{##1}\cpt@nnil{}{% + \def\reserved@a####1={% + \edef\key@name{\unexpanded{####1}}% + \def\reserved@a########1=########2\cpt@nil{% + \edef\key@value{\expandcsonce{\@gobble########1}}% + \ifx\key@value\cpt@rej + \cpt@novaltrue\def\key@value{}% + \else + \cpt@novalfalse + \fi + \cptexpandtwoargsonce{#2}\key@name\key@value + }% + \reserved@a.% + }% + \reserved@a##1=^?^=\cpt@nil + \ifloopbreak + \def\kv@do####1\cpt@nil,{}% + \fi + \kv@do + }% + }% + \kv@@normalize{#1}% + \expandafter\kv@do\normalized@list,\cpt@nil,% + \cptpopfunctions\kv@@process\cpt@csvdepth +} +\robust@def*\cpt@setupuserdo#1{% + \ifntypeTF{#1}{% + \ifmacroTF{#1}{\let\user@do#1}{\cpt@notcserr{#1}}% + }{% + \cpt@notonetokenerr{#1}% + }% +} +\robust@def*\cpt@setupnextindris#1{% + \def\getnextindris##1#1##2\indris@nil{% + \if\cpt@incsv + \edef\nextindris{\expandcsonce{\@gobble##1}}% + \else + \edef\nextindris{\s@expandarg\cpttrimspace{\@gobble##1}}% + \fi + \letcsntocs{nextindris@\cptrm\indrisdepth}\nextindris + }% +} +\cptnewvariables{if}{lastindris}[false] +\cptnewvariables{count}{indrisdepth}[\z@pt] +\robust@def*\indrisloop{\cpt@teststopt\cpt@indrisloop,} +% #1: parser +% #2: list +% #3: a one-parameter recurrent macro (eg, \def\do#1{*#1*}) +\robust@def*\cpt@indrisloop[#1]#2#3{% + \cptpushfunctions\indrisloop{% + \\\indris@do\\\indrisnr\\\iflastindris\\\ifloopbreak + \\\user@do\\\getnextindris\\\cptdoremainder + }\cpt@csvdepth + \advance\indrisdepth\@ne + \cpt@stchoose{cpt@st}{#2}\cpt@rsvda\indrisloop + \cpt@sttrue\cpt@csvnormalize[#1]\cpt@rsvda + \lastindrisfalse\loopbreakfalse + \chardef\indrisnr\z@pt + \cpt@setupuserdo{#3}% + \cpt@setupnextindris{#1}% + \let\cpt@incsv\cptswtrue + \def\indris@do##1#1##2\indris@nil{% + \s@expandarg\ifcsvbreakTF{\@gobble##1}\loopbreak\relax + \ifdefboolTF{loopbreak}{% + \cptdoremainder{##2}% + }{% + \edef\currindris{\expandcsonce{\@gobble##1}}% + \letcsntocs{currindris@\cptrm\indrisdepth}\currindris + \edef\indrisnr{\the\numexpr\indrisnr+1}% + \getnextindris.##2\indris@nil + \ifcseqTF\nextindris\cpt@nnil{% + \lastindristrue\def\nextindris{}% + \csn@def{nextindris@\cptrm\indrisdepth}{}% + \s@expandarg\user@do\currindris\relax + }{% + \s@expandarg\user@do\currindris\relax + \indris@do.##2\indris@nil + }% + }% + }% + \expandafter\indris@do\expandafter.\cpt@rsvda#1\cpt@nil#1\indris@nil + \cptpopfunctions\indrisloop\cpt@csvdepth + \advance\indrisdepth\m@one +} + +% #1=list, #2=operator/format +% Eg, +% \def\pkg{% +% \ifnextcharTF'% +% {\@firstoftwo{\def\pkgsw{00}\@pkg}} +% {\def\pkgsw{01}\@pkg}% +% } +% \def\@pkg#1{% +% \def\do##1{\textcolor{ForestGreen}{\texttt{##1}}}% +% \cptprintcommalist{#1}\do +% \if\pkgsw\@space package\ifnum\maxindrisnr>\@ne s\fi\fi +% } +\robust@def*\cptprintcommalist{\cpt@testst\cpt@printcommalist} +\robust@def*\cpt@printcommalist#1#2{% + \cpt@stchoose{cpt@st}{#1}\cpt@tempa\cptprintcommalist + \def\print@do##1{% + \ifnum\indrisnr>\@ne + \iflastindris + \edef\maxindrisnr{\number\indrisnr}% + \@space and\@space + \else + ,\@space + \fi + \fi + #2{##1}% + }% + \expandafter\indrisloop\expandafter{\cpt@tempa}\print@do +} +%% Robust, multi-level, general-purpose tsv processor: +\robust@def*\tsv@@loop{% + \let\tsv@inparse\cptswfalse + \cpt@testst\cpt@tsvparse@a +} +\robust@def*\tsv@@parse{% + \let\tsv@inparse\cptswtrue + \cpt@testst\cpt@tsvparse@a +} +\new@def*\cpt@tsvnil{\cpt@tsvnil} +\robust@def\cpt@tsvparse@a#1{% + \cpt@stchoose{cpt@st}{#1}\cpt@tsvarg\cpt@tsvparse@a + % Use \cpt@csvdepth here also, to avoid premature undefining + % of pushed counterparts of \ifcpt@useempty, \ifloopbreak and + % \cptdoremainder by \cptpopfunctions: + \cptpushfunctions\tsv@@parse{% + \\\sav@tsv@do\\\ifcpt@useempty\\\ifloopbreak\\\cptdoremainder + \\\tsv@inparse + }\cpt@csvdepth + \ifdefTF\tsv@do{}{% + \cpt@err{'\string\tsv@do' is undefined}\@ehc + }% + \let\sav@tsv@do\tsv@do + \loopbreakfalse + \expandafter\cpt@tsvparse@b\cpt@tsvarg\cpt@tsvnil + \cptpopfunctions\tsv@@parse\cpt@csvdepth + \ifnum\cpt@csvdepth=\z@pt + \undefcs\tsv@do + \fi +} +\robust@def*\cpt@tsvparse@b{% + \ifdefboolTF{loopbreak}{% + \gobble@to@sentinel\cpt@tsvnil{}% + }{% + \begingroup + \let\bgr@up\bgroup + \let\bgroup\cpt@undefined + % Don't use \ifnextcharTF here: + \cpt@ifnextchar\bgr@up\cpt@tsvparse@c\cpt@tsvparse@c + }% +} +\robust@def\cpt@tsvparse@c#1{% + \ifcseqTF\@let@token\bgr@up{% + \endgroup + \edef\cpt@tsvarg{{\unexpanded{#1}}}% + }{% + \endgroup + \edef\cpt@tsvarg{\usename{cpttrimspace\if\tsv@inparse s\fi}{#1}}% + }% + \ifcseqTF\cpt@tsvarg\cpt@tsvnil{}{% + \ifcseqTF\cpt@tsvarg\cpt@tsvbreak{% + \loopbreak + }{% + \ifcsemptyTF\cpt@tsvarg{% + \ifcpt@useempty\sav@tsv@do{}\relax\fi + }{% + \expandafter\sav@tsv@do\expandafter{\cpt@tsvarg}\relax + }% + }% + \cpt@tsvparse@b + }% +} +% \tsv@@parse does preserve outer braces but sometimes this +% isn't required, necessitating a call to a brace stripper. +% \siso@@loop strips outer braces in its arguments and +% doesn't trim leading and trailing spaces, but can +% be nested to any level: +\newletcs\cpt@sisonil\relax +\new@def*\cpt@sisonnil{\cpt@sisonil} +\robust@def*\siso@@loop{\cpt@testst\cpt@sisoloop} +\robust@def*\cpt@sisoloop#1{% + \cpt@stchoose{cpt@st}{#1}\siso@arg\siso@@loop + % Use \cpt@csvdepth here also, to avoid premature un-defining + % of pushed counterparts of \ifloopbreak: + \cptpushfunctions\siso@@loop{\\\sav@siso@do\\\ifloopbreak}\cpt@csvdepth + \ifdefTF\siso@do{}{\cpt@notdeferr\siso@do}% + \let\sav@siso@do\siso@do + \loopbreakfalse + \expandafter\cpt@sisoloop@a\siso@arg\cpt@sisonil + \cptpopfunctions\siso@@loop\cpt@csvdepth + \ifnum\cpt@csvdepth=\z@pt\undefcs\siso@do\fi +} +\robust@def*\cpt@sisoloop@a#1{% + \edef\siso@arg{\unexpanded{#1}}% + \ifcseqTF\siso@arg\cpt@sisonnil{}{% + \ifdefboolTF{loopbreak}{% + \gobble@to@sentinel\cpt@sisonil{}% + }{% + \sav@siso@do{#1}\relax\cpt@sisoloop@a + }% + }% +} +\robust@def*\cptdosisolist{\cpt@testst\cpt@dosisolist} +\robust@def*\cpt@dosisolist#1#2{% + \def\siso@do##1{#2}% + \cptexpanded{\siso@@loop\ifcpt@st*\fi}{#1}% +} +% +% 1. Any type of parser, argument and delimiter are allowed in \cptforeach. +% 2. It is permissible to use #1, #2, #3, etc, to refer to the elements of +% list in the callback. +% 3. Control sequences can't be used as delimiters in #2. +% 4. Star (*) suffix implies that <list> is a command. +% 6. This can't be used to fill/complete the list before processing. +% See keyreader-for package for that feature. +% +% Example: +% +% \newcount\nr +% \cptforeach[;] \xa/\ya/\za \in a1/b1/c1; a2/b2/c2; a3/b3/c3 \do{% +% \nr\z@pt +% \cptforeach[,] \xs|\ys|\zs \in s1|t1|u1, s2|t2|u2, s3|t3|u3 \do{% +% \advance\nr\@ne +% \ifnum\nr>\@ne\loopbreak\fi +% \edef\cmda####1{#1#2#3*####1*##1##2##3}% +% \edef\cmdb####1{\xa\ya\za*####1*\xs\ys\zs}% +% }% +% } +% +\cptnewcounts[cpt@]{foreachdepth} +\robust@def*\cptforeach{\cpt@teststopt\cpt@foreach,} +\robust@def*\cpt@foreach[#1]#2\in#3\do#4{% + \begingroup + \let\if@foreach@st\ifcpt@st + \global\advance\cpt@foreachdepth\@ne + \@tempcnta\z@pt\def\cpt@tempc{}% + \def\cpt@cmds{}\def\cpt@params{}% + \cpttfor#2\dofor{% + \ifescapedTF{##1}{% + \advance\@tempcnta\@ne + \edef\cpt@cmds{% + \expandcsonce\cpt@cmds + \edef\unexpanded{##1}{% + \noexpand\unexpanded{########\number\@tempcnta}% + }% + }% + \edef\cpt@params{\expandcsonce\cpt@params########\number\@tempcnta}% + \edef\cpt@tempc{\expandcsonce\cpt@tempc\unexpanded{\\##1}}% + }{% + \ifnum\@tempcnta=\z@pt + \cpt@err{First item of \noexpand\cptforeach can't + \MsgBrk be a delimiter}\@ehc + \else + \ifnum\@tempcnta=\@ne + \edef\cpt@subparser{\cpttrimspace{##1}}% + \fi + \edef\cpt@params{\expandcsonce\cpt@params\unexpanded{##1}}% + \fi + }% + }% + \edef\cpt@tempb{\unexpanded{#3}}% + \expandafter\cpt@sttrue\expandafter\cpt@csvnormalize + \expandafter[\cpt@subparser]\cpt@tempb + % Add one extra parameter: + \edef\cpt@params{% + \expandcsonce\cpt@params + \cpt@subparser####\the\numexpr\@tempcnta+1\relax + }% + % Generate extra subparser list for padding: + \@tempcnta\z@pt\def\cpt@tempa{}% + \cptloop + \edef\cpt@tempa{\cpt@tempa\cpt@subparser}% + \advance\@tempcnta\@ne + \ifnum\@tempcnta<8\relax + \cptrepeat + \edef\elt{\noexpandcsn{cpt@foreach@do@\romannumeral\cpt@foreachdepth}}% + \let\cpt@foreach@nil\relax + \cptexpanded{% + \endgroup + \cptpushfunctions\cptforeach{\expandcsonce\cpt@tempc}\cpt@csvdepth + \def\expandcsonce\elt\expandcsonce\cpt@params\cpt@foreach@nil{% + \expandcsonce\cpt@cmds\unexpanded{#4}% + }% + \def\noexpand\csv@do####1{% + \expandcsonce\elt####1\cpt@tempa\cpt@foreach@nil + }% + \csv@@parse\if@foreach@st*\fi[#1]{\expandcsonce\cpt@tempb}% + }% + \cptpopfunctions\cptforeach\cpt@csvdepth + \global\advance\cpt@foreachdepth\m@ne +} + +\robust@def*\cpt@oncurrlevel#1#2{% + \ifdefTF\curr@level{% + \ifnum\curr@level=\z@pt + \cpt@err{'\string\curr@level' is zero}{% + I can't do anything on zero current level.}% + \fi + }{% + \cpt@err{'\string\curr@level' undefined}\@ehc + }% + \cptexpandsecond{#1} + {\noexpandcsn{\cptgobblescape#2@\romannumeral\curr@level}}% +} +% #1: parser +% #2: token list +\new@def*\csliststack#1#2{% + \iflacus#2\dolacus\else + \expandafter\ifnullTF\expandafter{\cptiiofii#2{}}{% + \ifdefTF{#2}{% + \ifx#2\@empty\else\expandcsonce{#2}#1\fi + }{}% + }{% + \unexpanded{#2}#1% + }% + \fi +} +\newletcs\cptliststack\csliststack +\new@def*\csnliststack#1#2{% + \ifblankTF{#1}{% + \expandafter\csliststack\expandafter + {\expandafter}\csname#2\endcsname + }{% + \expandafter\csliststack\expandafter#1\csname#2\endcsname + }% +} +\robust@def*\cptemptify#1{% + \ifblankTF{#1}{}{\let#1\@empty}% +} +\robust@def*\cptgemptify#1{% + \ifblankTF{#1}{}{\global\let#1\@empty}% +} +\robust@def*\genemptify{\cpt@teststcl\cpt@genemptify} +\def\cpt@genemptify#1{% + \ifblankTF{#1}{}{% + \ifcpt@cl\global\fi\ifcpt@st\else\long\fi\def#1{}% + }% +} +\robust@def*\cptemptifycsn{\aftercsname\cptemptify} +\robust@def*\cptgemptifycsn{\global\aftercsname\cptemptify} +\robust@def*\cptemptifycsset{% + \cpt@testst{\cpt@testcl\cpt@emptifycsset}% +} +\robust@def*\cpt@emptifycsset#1{% + \cptfor#1\dofor{% + \ifntypeTF{##1}{% + \ifescapedTF{##1}{% + \ifcpt@cl\global\fi\def##1{}% + }{% + \cpt@notescapederr{##1}% + }% + }{% + \cpt@notonetokenerr{##1}% + }% + }% +} +\robust@def*\cptemptifycsnset{\cpt@testopt\cpt@emptifycsnset{}} +\robust@def*\cpt@emptifycsnset[#1]#2{% + \cptfor#2\dofor{\csn@def{#1##1}{}}% +} +\AtEndOfPackage{% + \AfterStartOfDocument{% + \def\do#1{% + \ifdefTF#1{% + \gdef#1{% + \@latex@error{'\string#1' is a preamble command} + {Move command '\string#1' to document preamble.}% + }% + }{% + \ifx\relax#1\else + \cpt@warn{Undefined command '\unexpanded{#1}': + \MsgBrk appeared in \string\cptonlypreamble}% + \fi + }% + }% + \cpt@preamblecmdhook + \gundefcs\cpt@preamblecmdhook + \gletcs\do\noexpand + }% +} +\new@def*\cpt@preamblecmdhook{} +\robust@def*\cptonlypreamble#1{% + \begingroup + \def\csv@do##1{% + \ifescapedFT{##1}{% + \cpt@notescapederr{##1}% + }{% + \ifntypeTF{##1}{% + \xifinsetTF{\detokenize{\do##1}}% + {\cptoxdetok\cpt@preamblecmdhook}{% + \cpt@warn{Command '\unexpanded{##1}' multiply + \MsgBrk submitted to \string\cptonlypreamble: + ignored}% + }{% + \xdef\cpt@preamblecmdhook{\csliststack{}% + \cpt@preamblecmdhook\unexpanded{\do##1}% + }% + }% + }{% + \cpt@notonetokenerr{##1}% + }% + }% + }% + \csv@@parse[,]{#1}% + \endgroup +} +\new@def*\cpt@newlinespaces{^^J\@spaces\@spaces} +\robust@def*\cptelementcount{\cpt@teststopt\cpt@elemcount,} +\robust@def*\cpt@elemcount[#1]#2{% + \begingroup + \def\cptelemnr{0}% + \edef\reserved@a{\ifcpt@st*\fi}% + \def\csv@do##1{% + \edef\cptelemnr{\the\numexpr\cptelemnr+1}% + }% + \expandafter\csv@@loop\reserved@a[#1]{#2}% + \postgroupdef\cptelemnr\endgroup +} +% Eg, \ifelemcountTF[;](>)[2]{a;b;c}{T}{F}; +% * -> #4 is a macro +\robust@def*\ifelemcountTF{\cpt@teststopt\cpt@ifelemcount@a,} +\robust@def*\cpt@ifelemcount@a[#1]{% + \cpt@testpnopt{\cpt@ifelemcount@b{#1}}=% +} +\robust@def*\cpt@ifelemcount@b#1(#2){% + \cpt@testopt{\cpt@ifelemcount@c{#1}{#2}}1% +} +\robust@def*\cpt@ifelemcount@c#1#2[#3]#4{% + \begingroup + \@tempcnta\z@pt + \edef\reserved@a{\ifcpt@st*\fi}% + \def\csv@do##1{% + \advance\@tempcnta\@ne + }% + \expandafter\csv@@loop\reserved@a[#1]{#4}% + \aftercsname\endgroup{@\ifnum\@tempcnta#2#3 % + first\else second\fi oftwo}% +} +\robust@def*\cptfindduplicates{\cpt@teststopt\cpt@findduplicates,} +\robust@def*\cpt@findduplicates[#1]#2{% + \begingroup + \edef\reserved@a{\ifcpt@st*\fi}% + \edef\parser{\detokenize{#1}}% + \def\cpt@currstack{}\gdef\duplicates{}% + \def\csv@do##1{% + \xifinsetTF{\detokenize{#1##1#1}} + {\parser\cptoxdetok\cpt@currstack\parser}{% + \xdef\duplicates{\csliststack#1\duplicates\unexpanded{##1}}% + }{% + \edef\cpt@currstack{\csliststack#1\cpt@currstack\unexpanded{##1}}% + }% + }% + \expandafter\csv@@parse\reserved@a[#1]{#2}% + \ifcsemptyTF\duplicates + {\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% +} +\new@def*\ifcsnullTF#1{% + \ifblankTF{#1}\@secondoftwo{% + \oifblankTF{\@gobble#1}{% + \ifcseqTF#1\@empty + }{% + \@secondoftwo + }% + }% +} +\new@def*\ifcsnullFT#1{\ifcsnullTF{#1}\cptiiofii\cptiofii} +\new@def*\oifcsnullTF#1{\expandafter\ifcsnullTF\expandafter{#1}} +\new@def*\oifcsnullFT#1{\expandafter\ifcsnullFT\expandafter{#1}} +\new@def\ifcsemptyTF#1{% + \expandafter\ifcseqTF\cpt@car#1\@undefined\car@nil\@empty +} +\new@def*\ifcsnnullTF#1{% + \ifblankTF{#1}{% + \@secondoftwo + }{% + \ifcsndefTF{#1}{% + \expandafter\ifx\csname#1\endcsname\@empty + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + }{% + \@secondoftwo + }% + }% +} +\new@def*\ifcsnnullFT#1{\ifcsnnullTF{#1}\cptiiofii\cptiofii} +\new@def*\ifdefnotnullTF#1{% + \ifdefTF{#1}{% + \ifcsnullTF{#1}\cptiiofii\cptiofii + }{% + \@secondoftwo + }% +} +\new@def*\ifcsndefnotnullTF#1{% + \ifcsndefTF{#1}{% + \ifcsnnullTF{#1}\cptiiofii\cptiofii + }{% + \@secondoftwo + }% +} +\new@def*\expandcsonce#1{\unexpanded\expandafter{#1}} +\new@def*\expandcsnonce#1{\aftercsname\expandcsonce{#1}} +\new@def*\expandcstwice#1{\unexpanded\cptthreexp{#1}} +\new@def*\expandcsntwice#1{\aftercsname\expandcstwice{#1}} +\new@def*\noexpandcsn#1{\expandcsonce{\csname#1\endcsname}} +\newletcs\cptmakecs=\noexpandcsn +\new@def*\cptoxdetok#1{\detokenize\expandafter{#1}} +\new@def*\cpttxdetok#1{\detokenize\cptthreexp{#1}} +\new@def*\cptsxdetok#1{\detokenize\cptsevenxp{#1}} +\robust@def\cptpassexpanded#1{% + \begingroup\protected@edef\x{\endgroup#1}\x +} +\newletcs\cptexpanded=\cptpassexpanded +\robust@def\cptpassunexpanded#1{\begingroup\long\def\x{\endgroup#1}\x} +\robust@def*\cptexpandarg#1#2{\cptpassexpanded{\unexpanded{#1}{#2}}} +\robust@def*\cptexpandargonce#1#2{% + \cptpassexpanded{\unexpanded{#1}{\expandcsonce{#2}}}% +} +\robust@def*\cptexpandsecond#1#2{\cptpassexpanded{\unexpanded{#1}#2}} +\robust@def*\cptexpandsecondonce#1#2{% + \cptpassexpanded{\unexpanded{#1}\expandcsonce{#2}}% +} +\robust@def*\cptexpandsecondarg#1#2#3{% + \cptpassexpanded{\unexpanded{#1#2}{#3}}% +} +\robust@def*\cptexpandsecondargonce#1#2#3{% + \cptpassexpanded{\unexpanded{#1#2}{\expandcsonce{#3}}}% +} +\robust@def*\cptexpandtwoargs#1#2#3{% + \cptpassexpanded{\unexpanded{#1}{#2}{#3}}% +} +\robust@def*\cptexpandtwoargsonce#1#2#3{% + \cptpassexpanded + {\unexpanded{#1}{\expandcsonce{#2}}{\expandcsonce{#3}}}% +} +\robust@def*\StyleFileRCSInfo$#1 #2 #3 #4 #5 #6 #7 #8 ${% + \def\cpt@filedate{#4}% + \def\cpt@fileversion{v#3}% + \def\cpt@filetime{#5}% + \def\cpt@fileauthor{#6\@space#7}% +} +\new@def*\cpt@filedesc{} +\defpass\reserved@a#1{% + \robust@def*\StyleFilePurpose##1{% + \gdef\cpt@filedesc{##1#1(\cpt@fileauthor)}% + }% +}{ } +\new@def*\StyleFileInfo{% + \cpt@filedate\@space\cpt@fileversion\@space\cpt@filedesc +} +\robust@def*\SetStyleFileMessages{% + \begingroup + \catcode`\ =9\catcode`\^^I=9\relax + \edef\cpt@tempa{\expandafter\@carcube\@currname\@nil @}% + \def\cpt@tempb{\@testopt{\expandafter\endgroup + \cpt@SetStyleFileMessages}}% + \expandafter\cpt@tempb\expandafter{\cpt@tempa}% +} +\robust@def*\cpt@SetStyleFileMessages[#1]#2#3#4{% + \begingroup + \def\cpt@tempa##1{\noexpandcsn{##1}}% + \protected\def\cpt@tempb{\global\protected\@namedef}% + \edef\cpt@tempc{\ifx\@currext\@pkgextension Package\else Class\fi}% + \@tempswafalse + \cptfor#2,#3,#4\dofor{% + \ifcsname#1##1\endcsname + \edef\undefinablecs{#1##1}\@tempswatrue\forbreaktrue + \fi + }% + \if@tempswa + \cpt@notdefinable + \else + \cptpassexpanded{% + \cpt@tempb{#1#2}####1{\cpt@tempa{\cpt@tempc Info}% + {\@currname}{####1\noexpand\@gobble}}% + \cpt@tempb{#1#3}####1{\cpt@tempa{\cpt@tempc WarningNoLine}% + {\@currname}{####1}}% + \cpt@tempb{#1#4}####1####2{\cpt@tempa{\cpt@tempc Error}% + {\@currname}{####1}{####2}}% + }% + \fi + \endgroup +} +\SetStyleFileMessages[cpt@]{info}{warn}{err} +\new@def*\ifboolTF#1{% + \ifblankTF{#1}{% + \cpt@err{Empty boolean}\@ehc + }{% + \ifcsndefTF{if#1}{% + \ifdefboolTF{#1}% + }{% + \cpt@err{Boolean '\@backslashchar#1' undefined}\@ehc + }% + }% +} +\new@def*\ifdefboolFT#1{\ifdefboolTF{#1}\cptiiofii\cptiofii} +\new@def*\ifdefboolTF#1{% + \usename{@\usename{if#1}first\else second\fi oftwo}% +} +\new@def*\ifboolFT#1{\ifboolTF{#1}\cptiiofii\cptiofii} +\new@def*\ifgroupboolTF#1{% + \ifboolTF{#1}{\endgroup\cptiofii}{\endgroup\cptiiofii}% +} +\new@def*\ifbooleanTF#1#{% + \ifntypeTF{#1}{% + \ifescapedTF{#1}{% + \ifboolTF{\cptremovescape#1}\cptiofii\cptiiofii + }{% + \cpt@notescapederr + }% + }{% + \cpt@notonetokenerr{#1}% + }% +} +\new@def\cptiterate#1\cptrepeat{\cpt@iterate\@gobble{#1}} +\newletcs\cptloop=\cptiterate +\newletcs\cptrepeat\fi +\new@def\cpt@iterate\@gobble#1{% + #1\relax\expandafter\cpt@iterate\fi\@gobble{#1}% +} +\new@def\cptwhileexpr#1\do#2{% + #1 \cptswap{#2\cptwhileexpr{#1}\do{#2}}\fi +} +\new@def*\cpt@numlt#1<{#1<\numexpr} +\new@def*\cpt@numgt#1>{#1>\numexpr} +\new@def*\cpt@numeq#1={#1=\numexpr} +\new@def*\cpt@dimlt#1<{#1<\dimexpr} +\new@def*\cpt@dimgt#1>{#1>\dimexpr} +\new@def*\cpt@dimeq#1={#1=\dimexpr} +% Don't put \numexpr in the arg #2 when calling \cptwhilenum: +\new@def*\cptwhilenum#1\do#2{% + \ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% + \cpt@removetonnil<=>\cpt@nnil\relax + \cptswap{#2\cptwhilenum{#1}\do{#2}}\fi +} +% Don't put \dimexpr in the arg #2 when calling \cptwhiledim: +\new@def*\cptwhiledim#1\do#2{% + \ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% + \cpt@removetonnil<=>\cpt@nnil\relax + \cptswap{#2\cptwhiledim{#1}\do{#2}}\fi +} +\new@def*\ifnumcmpTF#1#{% + \usename{@\ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% + \cpt@removetonnil<=>\cpt@nnil first\else second\fi oftwo}% +} +\new@def*\ifnumcmpFT#1#{\usename{@\ifnumcmpTF#1{second}{first}oftwo}} +\new@def*\ifdimcmpTF#1#{% + \usename{@\ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% + \cpt@removetonnil<=>\cpt@nnil first\else second\fi oftwo}% +} +\new@def*\ifdimcmpFT#1#{\usename{@\ifdimcmpTF#1{second}{first}oftwo}} +% Define control sequences to check for a token (eg, dash): +% \cpt@defcheck<cs><testtoken>\cpt@nil +\robust@def*\cpt@defcheck#1#2\cpt@nil{% + \new@def*#1##1\cpt@nil{% + \begingroup + \def\cpt@tempa####1#2####2\cpt@nil{\endgroup + \usename{@\ifblankTF{####2}{second}{first}oftwo}% + }% + \cpt@tempa##1#2\cpt@nil + }% +} +\cpt@defcheck\cpt@checkeq=\cpt@nil +%%-- +% Define control sequences to split tokens (eg, at a dash): +% \cpt@defsplit@at<cs><splitter/testtoken>\cpt@nil +\robust@def*\cpt@defsplit@at#1#2\cpt@nil{% + \def#1##1\cpt@nil{% + \begingroup + \def\cpt@tempa####1#2####2\cpt@nil{\endgroup + \def\lpt{####1}\def\rpt{####2}% + }% + \ifinsetTF{#2}{##1}{% + \cpt@tempa##1#2\cpt@nil + }{% + \def\lpt{##1}\def\rpt{}% + }% + }% +} +\cpt@defsplit@at\cpt@split@ateq=\cpt@nil + +% Define a control sequence to check for the presence +% of a suffix in/for another control sequence: +\robust@def\DefSuffixChecker#1#2#3#4{% + \long\gdef#1##1##2##3##4{% + \begintoksgroup + \def\cpt@tempa{% + \ifstrcmpTF{##4}{#2}{% + \ifstrcmpTF{##2##3}{#3#4}{% + \toks@{##1##4##2##3}% + }{% + \ifstrcmpTF{##2##3}{#4#3}{% + \toks@{##1##4##3##2}% + }{% + \ifntypeTF{##2}{% + \ifntypeTF{##3}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2{##3}##4}% + }% + }{% + \ifntypeTF{##3}{% + \toks@{##1{##2}##3##4}% + }{% + \toks@{##1{##2}{##3}##4}% + }% + }% + }% + }% + }{% + \cpt@tempb + }% + }% + \def\cpt@tempb{% + \ifstrcmpTF{##4}{#3}{% + \ifstrcmpTF{##2##3}{#2#4}{% + \toks@{##1##2##4##3}% + }{% + \ifstrcmpTF{##2##3}{#4#2}{% + \toks@{##1##3##4##2}% + }{% + \toks@{##1##2##3##4}% + }% + }% + }{% + \cpt@tempc + }% + }% + \def\cpt@tempc{% + \ifstrcmpTF{##4}{#4}{% + \ifstrcmpTF{##2##3}{#2#3}{% + \toks@{##1##2##3##4}% + }{% + \ifstrcmpTF{##2##3}{#3#2}{% + \toks@{##1##3##2##4}% + }{% + \toks@{##1##2##3##4}% + }% + }% + }{% + \cpt@tempd + }% + }% + \def\cpt@tempd{% + \ifstrcmpTF{##3}{#2}{% + \ifstrcmpTF{##2}{#3}{% + \ifntypeTF{##4}{% + \toks@{##1##3##2##4}% + }{% + \toks@{##1##3##2{##4}}% + }% + }{% + \cpt@tempi + }% + }{% + \cpt@tempe + }% + }% + \def\cpt@tempe{% + \ifstrcmpTF{##3}{#3}{% + \ifstrcmpTF{##2}{#2}{% + \ifntypeTF{##4}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2##3{##4}}% + }% + }{% + \cpt@tempi + }% + }{% + \cpt@tempf + }% + }% + \def\cpt@tempf{% + \ifntypeTF{##4}{\toks1{##4}}{\toks1{{##4}}}% + \cpt@tempg + }% + \def\cpt@tempg{% + \ifntypeTF{##3}{% + \ifntypeTF{##2}{% + \cpt@temph{##1##2##3}% + }{% + \cpt@temph{##1{##2}##3}% + }% + }{% + \ifntypeTF{##2}{% + \cpt@temph{##1##2{##3}}% + }{% + \cpt@temph{##1{##2}{##3}}% + }% + }% + }% + \def\cpt@temph####1{% + \cptexpanded{\toks@{\unexpanded{####1}\the\toks1}}% + }% + \def\cpt@tempi{% + \ifstrcmpTF{##2}{#4}{% + \ifntypeTF{##4}{% + \toks@{##1##3##2##4}% + }{% + \toks@{##1##3##2{##4}}% + }% + }{% + \ifntypeTF{##4}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2##3{##4}}% + }% + }% + }% + \cpt@tempa + \endtoksgroup + }% +} +\DefSuffixChecker\cpt@checkoptprefix{*}{+}{!} +\new@def*\ifnumoddTF#1#{% + \usename{@\ifodd#1\@empty first\else second\fi oftwo}% +} +\new@def*\ifnumoddFT#1#{% + \usename{@\ifnumoddTF#1{second}{first}oftwo}% +} +\newletcs\ifnumevenTF\ifnumoddFT +\robust@def*\cptnumexpr{\cpt@testcl{\cpt@numexpr{num}}} +\robust@def*\cptdimexpr{\cpt@testcl{\cpt@numexpr{dim}}} +\robust@def*\cptglueexpr{\cpt@testcl{\cpt@numexpr{glue}}} +\robust@def*\cptmuexpr{\cpt@testcl{\cpt@numexpr{mu}}} +\new@def*\cpt@numexpr#1#2#3{% + \ifntypeTF{#2}{}{\cpt@notonetokenerr{#2}}% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ifdefTF{#2}{% + \ifcpt@cl\global\fi#2=\usename{#1expr}#3\relax\relax + }{% + \def\reserved@a##1#1##2##3\@nil{% + \usename{new##2}#2\relax + }% + \reserved@a num{count}dim{dimen}glue{skip}mu{muskip}\@nil + \ifcpt@cl\global\fi#2=\usename{#1expr}#3\relax\relax + }% +} +\robust@def*\cptnumdef{\cpt@testcl{\cpt@numdef{num}}} +\robust@def*\cptdimdef{\cpt@testcl{\cpt@numdef{dim}}} +\robust@def*\cptgluedef{\cpt@testcl{\cpt@numdef{glue}}} +\robust@def*\cptmudef{\cpt@testcl{\cpt@numdef{mu}}} +\new@def*\cpt@numdef#1#2#3{% + \ifntypeTF{#2}{}{\cpt@notonetokenerr{#2}}% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ifcpt@cl\global\fi\edef#2{\the\usename{#1expr}#3}% +} +\robust@def*\cptnumadd{\cpt@testcl{\cpt@numadd{num}}} +\robust@def*\cptdimadd{\cpt@testcl{\cpt@numadd{dim}}} +\robust@def*\cptglueadd{\cpt@testcl{\cpt@numadd{glue}}} +\robust@def*\cptmuadd{\cpt@testcl{\cpt@numadd{mu}}} +\new@def*\cpt@numadd#1#2#3{% + \ifntypeTF{#2}{}{\cpt@notonetokenerr{#2}}% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ifdefTF{#2}{% + \ifcpt@cl\global\fi\edef#2{\the\usename{#1expr}#2+#3}% + }{% + \ifcpt@cl\global\fi\edef#2{\the\usename{#1expr}#3}% + }% +} +\robust@def*\csnnumdef{\cpt@testcl{\aftercsname{\cpt@numdef{num}}}} +\robust@def*\csndimdef{\cpt@testcl{\aftercsname{\cpt@numdef{dim}}}} +\robust@def*\csnnumadd{\cpt@testcl{\aftercsname{\cpt@numadd{num}}}} +\robust@def*\csndimadd{\cpt@testcl{\aftercsname{\cpt@numadd{dim}}}} +\new@edef*\cpt@leftbracechar{% + \expandafter\@car\string{\@nil\iffalse}\fi +} +\new@edef*\cpt@rightbracechar{% + \iffalse{\fi\expandafter\@car\string}\@nil +} +\newcommand\xifstrcmpTF[2]{% + \usename{@\ifnum\cpt@pdfstrcmp{#1}{#2}=0first\else + second\fi oftwo}% +} +\new@def\xifstrcmpFT#1#2{\xifstrcmpTF{#1}{#2}\cptiiofii\cptiofii} +\new@def\oifstrcmpTF#1#2{% + \expandafter\cptswapbracefirst\expandafter{#1} + {\expandafter\ifstrcmpTF\expandafter{#2}}% +} +\robust@def\oifstrcmp@sp@TF#1#2{% + \ifntypeTF{#1}{% + \ifexpandableTF{#1}{% + \ifntypeTF{#2}{% + \ifexpandableTF{#2}{% + \oifstrcmpTF{#1}{#2}% + }{% + \cpt@notexpandableerr{#2}% + \@secondoftwo + }% + }{% + \cpt@notonetokenerr{#2}% + \@secondoftwo + }% + }{% + \cpt@notexpandableerr{#1}% + \@secondoftwo + }% + }{% + \cpt@notonetokenerr{#1}% + \@secondoftwo + }% +} +\robust@def\oifstrcmpFT#1#2{% + \oifstrcmpTF{#1}{#2}\cptiiofii\cptiofii +} +% Expandable: +\new@def\ifstreqTF#1#2{% + \expandafter\cptswap\expandafter + {\expandafter{\romannumeral-`\q\cpttrimspaces{#1}}} + {\expandafter\ifstrcmpTF\expandafter + {\romannumeral-`\q\cpttrimspaces{#2}}}% +} +\robust@def\ifstreqFT#1#2{\ifstreqTF{#1}{#2}\cptiiofii\cptiofii} +\robust@def\oifstreqTF#1#2{\cptexpandtwoargsonce\ifstreqTF{#1}{#2}} +\robust@def\oifstreqFT#1#2{\cptexpandtwoargsonce\ifstreqFT{#1}{#2}} +\robust@def\xifstreqTF#1#2{\cptexpandtwoargs\ifstreqTF{#1}{#2}} +\robust@def\xifstreqFT#1#2{\cptexpandtwoargs\ifstreqFT{#1}{#2}} +\new@def*\ifleftbracedTF#1{% + \ifblankTF{#1}{% + \@secondoftwo + }{% + \usename{@\if\expandafter\cpt@car\detokenize{#1}\car@nil + \expandafter\cpt@car\string{\car@nil\ifnum0=`}\fi + first\else second\fi oftwo}% + }% +} +\new@def*\ifdefeqTF#1#2{% + \ifdefTF{#1}{% + \ifdefTF{#2}{% + \usename{@\ifx#1#2first\else second\fi of oftwo}% + }\@secondoftwo + }\@secondoftwo +} +\new@def\ifdefeqFT#1#2{\ifdefeqTF{#1}{#2}\cptiiofii\cptiofii} +\new@def\ifcateqTF#1#{\usename{@\ifcat#1first\else second\fi oftwo}} +% Expand and detokenize before comparison: +\new@def\ifcharcmpTF#1#2{% + \ifntypeTF{#1}{% + \ifntypeTF{#2}{% + \usename{@\if\detokenize\expandafter{\romannumeral\expandafter + \cptswap\expandafter{\romannumeral-`\q#2}{-`\q#1}}% + first\else second\fi oftwo}% + }{% + \cpt@notonetokenerr{#2}\@secondoftwo + }% + }{% + \cpt@notonetokenerr{#1}\@secondoftwo + }% +} +\new@def\ifexpandableTF#1#2#3{% + \romannumeral\ifleftbracedTF{#1}\@secondoftwo{% + \ifblankTF{#1}\@secondoftwo{\expandafter\ifx\noexpand#1#1% + \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}}% + {0 #2}{0 #3}% +} + +% Test if #1 is a single, non-space and non-braced token: +\new@def\ifntypeTF#1{% + \if0\cpt@pdfstrcmp{\detokenize\expandafter{\cptalloftwo#1{}{}}}% + {\detokenize{#1{}}}% + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +\new@def\ifsingletokenTF#1#2#3{% + \romannumeral\ifblankTF{#1}\@secondoftwo{% + \ifbracedTF{#1}\@secondoftwo{% + \ifleadspaceTF{#1}{% + \expandafter\ifblankTF\expandafter{\@gobblespace#1}% + }{% + \expandafter\ifblankTF\expandafter{\@gobble#1}% + }% + \cptiofii\cptiiofii + }% + }{0 #2}{0 #3}% +} +\new@def\ifsingletokenFT#1{\ifntypeTF{#1}\cptiiofii\cptiofii} +% Don't test for \ifleadspaceTF: +\new@def\ifsingleindrisTF#1{% + \romannumeral + \ifblankTF{#1}{% + 0 \cptiiofii + }{% + % Eat one token and take the rest to \cpt@ifsingleindris: + \expandafter + \cpt@ifsingleindris\cpt@cdr#1\cdr@nil\single@nil{#1}% + }% +} +\new@def\cpt@ifsingleindris#1\single@nil#2{% + \ifblankTF{#1}{% + \xifstrcmpTF{\expandafter\cpt@car + \detokenize{#2}x\car@nil}\cpt@leftbracechar + {0 \cptiiofii}{0 \cptiofii}% + }{0 \cptiiofii}% +} +\robust@def*\ifsingledigitTF#1{% + \begingroup + \let\@@nil\relax + \edef\cpt@tempa##1{\def##1####1\detokenize{#1}####2####3\@@nil}% + \cpt@tempa\cpt@tempa{% + \endgroup + \csname @\ifx##20first\else second\fi oftwo\endcsname + }% + \edef\cpt@tempb{00 01 02 03 04 05 06 07 08 09 0\detokenize{#1}}% + \expandafter\cpt@tempa\cpt@tempb\relax\@@nil +} +\new@def*\cpt@parserlist{,;:/|*><=-+"'} +\robust@def*\cpt@checklistparser#1#2{% + \ifmacroTF{#1}{% + \ifcpt@verbose + \cpt@info{Parser '\detokenize{#1}' is a macro}\@ehc + \fi + }{% + \ifntypeTF{#1}{% + \xifinsetTF{\detokenize{#1}}\cpt@parserlist{% + #2% Don't put \relax here! + }{% + \cpt@listparsererr{#1}% + }% + }{% + \cpt@listparsererr{#1}% + }% + }% +} +\robust@def*\cpt@ch@cklistparser#1{% + \ifblankTF{#1}{% + \cpt@listparsererr{#1}% + }{% + % if #1 is a single token: + \ifsecondisnnilTF{#1}{% + \xifinsetTF{\detokenize{#1}}\cpt@parserlist{}{% + \cpt@listparsererr{#1}% + }% + }{% + \cpt@listparsererr{#1}% + }% + }% +} +\robust@def*\cpt@listparsererr#1{% + \cpt@err{Invalid list parser '\detokenize{#1}'}\@ehc +} +\robust@def*\postgroupdef#1\endgroup{% + \cptpassexpanded{\endgroup\cpt@csexit{#1}}% +} +\robust@def*\postgroupcsndef#1\endgroup{% + \aftercsname\postgroupdef{#1}\endgroup +} +% #1: macro; +% #2: arbitrary token (eg, \endgroup): +\robust@def*\cptpassacross#1#2{% + \cptpassexpanded{\unexpanded{#2}\cpt@csexit#1}% +} +\new@def*\cpt@csexit#1{\edef\noexpand#1{\ox@unexpanded{#1}}} +\new@def*\ox@unexpanded#1{\noexpand\unexpanded{\expandcsonce{#1}}} +\robust@def*\cptaftergroup#1{% + \advance\@tempcnta\@ne + \csn@xdef{cpt@aftergroup@\romannumeral\@tempcnta}{% + \gundefcsn{cpt@aftergroup@\romannumeral\@tempcnta}% + \unexpanded\ifblankTF{#1}{}\expandafter{#1}% + }% + \aftercsname\aftergroup{cpt@aftergroup@\romannumeral\@tempcnta}% +} +\robust@def\cptafterassignment#1{% + \begingroup + \advance\@tempcnta\@ne + \csn@xdef{cpt@afterassignment@\romannumeral\@tempcnta}{% + \gundefcsn{cpt@afterassignment@\romannumeral\@tempcnta}% + \unexpanded\ifblankTF{#1}{}\expandafter{#1}% + }% + \aftercsname{\endgroup\afterassignment} + {cpt@afterassignment@\romannumeral\@tempcnta}% +} +\robust@def*\cptexpandmacro#1#2{% + \ifntypeTF{#1}{% + \ifmacroTF{#1}{% + \ifexpandableTF{#1}{% + \simpleexpandarg\cptexpandmacro{#1}#2% + }{% + \edef#2{\unexpanded{#1}}% + }% + }{% + \edef#2{\unexpanded{#1}}% + }% + }{% + \edef#2{\unexpanded{#1}}% + }% +} +% Expandable: +\new@def*\cptexpandcs#1{% + \ifntypeTF{#1}{% + \ifmacroTF{#1}{% + \ifexpandableTF{#1}{% + \simpleexpandarg\cptexpandcs{#1}% + }{% + \noexpand#1% + }% + }{% + \noexpand#1% + }% + }{% + \unexpanded{#1}% + }% +} +% Expandable full expand; strips braces and leading +% spaces, but not trailing spaces: +\begingroup +\catcode`\&=7 +\new@gdef*\cptfullexpand#1{% + \romannumeral\cpt@fullexpand{#1}{}% +} +\new@gdef*\cpt@fullexpand#1{% + \expandafter\cpt@f@llexp@nd\romannumeral\cpt@f@llexpand#1&% +} +\new@gdef*\cpt@f@llexpand#1{% + \ifmacroTF{#1}{% + \ifexpandableTF{#1}{% + \expandafter\cpt@f@llexpand\expandafter{#1}% + }{% + 0 #1% + }% + }{% + 0 #1% + }% +} +\new@gdef*\cpt@f@llexp@nd#1#2{% + \ifblankTF{#2}{0 #3#1}{\cpt@fullexpand{#2}{#3#1}}% +} +\endgroup + +% [<fallback>]{<teststr>}{<{str1}{act1}{str2}{act2}...>} +% Expandable: +\new@def*\cptifstreqcase#1{\cpt@xtestopt{#1}\cpt@ifstreqcase{}} +\new@def\cpt@ifstreqcase[#1]#2#3{% + \expandafter\cptswapbracefirst\expandafter{#2}% + {\cpt@ifstreqc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% +} +\new@def\cpt@ifstreqc@se#1#2#3\cpt@nil#4#5{% + \ifblankTF{#3}{#5}{% + \ifstrcmpTF{#1}{#4}{#2}{% + \cpt@ifstreqc@se#3\cpt@nil{#4}{#5}% + }% + }% +} +% #1: test string (choice) +% #2: nominations and callbacks, eg, {{a}1,{b}2,{ x }3} +% #3: no-match fallback +% Expandable: +\new@def\cptcheckchoice#1#2#3{% + \expandafter\cptswapbracefirst\expandafter + {\romannumeral-`\q\cpttrimspace{#1}} + {\cpt@checkchoice#2,\cpt@mil\cpt@mil,\cpt@nil}{#3}% +} +\new@def\cpt@checkchoice#1#2,#3\cpt@nil#4#5{% + \ifblankTF{#3}{\unexpanded{#5}}{% + \xifstrcmpTF{\cpttrimspace{#1}}{\unexpanded{#4}}{% + \unexpanded{#2}% + }{% + \cpt@checkchoice#3\cpt@nil{#4}{#5}% + }% + }% +} +% Test if <str1>, etc, is in <teststr> +% [<default act>]{<teststr>}{<{str1}{act1}{str2}{act2}...>} +\new@def*\cptifstrpresentcase#1{\cpt@xtestopt{#1}\cpt@ifstrincase{}} +\new@def\cpt@ifstrincase[#1]#2#3{% + \expandafter\cptswapbracefirst\expandafter{#2}% + {\cpt@ifstrinc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% +} +\new@def\cpt@ifstrinc@se#1#2#3\cpt@nil#4#5{% + \ifblankTF{#3}{#5}{% + \ifinsetTF{#1}{#4}{#2}{% + \cpt@ifstrinc@se#3\cpt@nil{#4}{#5}% + }% + }% +} +\new@def\do@else@part\do#1#2\endif{\unexpanded{#1}} +\new@def\all@to@endif#1\endif{\unexpanded{#1}} +\new@def\first@to@endif#1#2\endif{\unexpanded{#1}} +\new@def\gobble@to@endif#1\endif{} +\new@def*\ifcassedimcmpTF#1#2#3{\ifdimcmpTF#1#2{#3}} +\new@def*\ifcassenumcmpTF#1#2#3{\ifnumcmpTF#1#2{#3}} +% Eg, +% \edef\x{% +% \cptifcasse\ifstrcmpTF{teststr} +% {str1}{case1 callback} +% {str2}{case2 callback} +% \ifnone +% no match +% \endif +% } +% \edef\x{% +% \cptifcasse\ifcassenumcmpTF{testnum} +% {=2}{equal to 2} +% {<3}{less than 3} +% {>4}{greater than 4} +% \ifnone +% no match +% \endif +% } +% The comparator command is any test command that yields +% <iofii> or <iiofii> but \ifnumcmpTF can't be used directly. +% Use \ifcassenumcmpTF instead. The user can also define his own +% logical test command and pass it to \cptifcasse, eg, +% \def\test#1#2{\ifinsetTF{#2}{#1}} +\new@def*\cptifcasse#1#2{% + \ifstrcmpTF{#1}\ifnone{% + \all@to@endif + }{% + \ifstrcmpTF{#1}\endif{}{% + \ifstrcmpTF{#2}\ifnone{% + \all@to@endif + }{% + \ifstrcmpTF{#2}\endif{}{\cpt@ifcasse{#1}{#2}}% + }% + }% + }% +} +\new@def*\cpt@ifcasse#1#2#3{% + \ifstrcmpTF{#3}\ifnone{% + \all@to@endif + }{% + \ifstrcmpTF{#3}\endif{}{% + #1{#2}{#3}\first@to@endif{\cpt@ifcasse@i{#1}{#2}}% + }% + }% +} +\new@def*\cpt@ifcasse@i#1#2#3{\cpt@ifcasse{#1}{#2}} + +% Eg, +% \edef\x{% +% \cptdocasse\ifcassedimcmpTF{1pt+2pt+3pt} +% {=2pt}\do{equal to 2pt} +% \elseif +% {<3pt}\do{less than 3pt} +% \elseif +% \do{no match} +% \endif +% } +% \edef\x{% +% \cptdocasse\ifcassenumcmpTF{1+2+3} +% {=2}\do{equal to 2} +% \elseif +% {<3}\do{less than 3} +% \elseif +% \do{no match} +% \endif +% } +% \edef\x{% +% \cptdocasse\ifcassenumcmpTF{5} +% {=2}\do{equal to 2} +% \elseif +% {<3}\do{less than 3} +% \elseif +% {>4}\do{greater than 4} +% \elseif +% \do{no match} +% \endif +% } +% \edef\x{% +% \cptdocasse\ifstrcmpTF{x} +% a\do{\def\y{a}} +% \elseif +% b\do{\def\y{b}} +% \elseif +% \endif +% } +\new@def*\cptdocasse#1#2{% + \ifstrcmpTF{#1}\elseif{% + \gobble@to@endif + }{% + \ifstrcmpTF{#1}\endif{}{% + \ifstrcmpTF{#2}\elseif{% + \gobble@to@endif + }{% + \ifstrcmpTF{#2}\endif{}{\cptdocasse@i{#1}{#2}}% + }% + }% + }% +} +\new@def*\cptdocasse@i#1#2#3{% + \ifstrcmpTF{#3}\elseif{% + \cptdocasse@i{#1}{#2}% + }{% + \ifstrcmpTF{#3}\endif{}{% + \ifstrcmpTF{#3}\do{% + \do@else@part\do + }{% + \cptdocasse@ii{#1}{#2}{#3}% + }% + }% + }% +} +\new@def*\cptdocasse@ii#1#2#3\do#4{% + \ifstrcmpTF{#4}\elseif{% + \cptdocasse@ii{#1}{#2}% + }{% + \ifstrcmpTF{#4}\endif{}{% + #1{#2}{#3}{% + \unexpanded{#4}% + \gobble@to@endif + }{% + \cptdocasse@i{#1}{#2}% + }% + }% + }% +} + +\robust@def\cpt@in#1#2{% + \long\def\in@@##1#1##2\in@@{% + \edef\in@@{\unexpanded{##2}}% + \ifx\in@@\@empty\cpt@infalse\else\cpt@intrue\fi + }% + \in@@#2{\in@@}#1\in@@ +} +\robust@def\cptiffound#1\in#2\then{% + \cptexpandtwoargs\cpt@in{\cpttrimspace{#1}}{\cpttrimspace{#2}}% + \ifcpt@in +} +\robust@def\ifinsetTF#1#2{% + \cpt@in{#1}{#2}% + \usename{@\ifcpt@in first\else second\fi oftwo}% +} +\robust@def\ifinsetFT#1#2{\ifinsetTF{#1}{#2}\cptiiofii\cptiofii} +\robust@def\oifinsetTF#1#2{\cptexpandtwoargsonce\ifinsetTF{#1}{#2}} +\robust@def\oifinsetFT#1#2{\oifinsetTF{#1}{#2}\cptiiofii\cptiofii} +\robust@def\xifinsetTF#1#2{\cptexpandtwoargs\ifinsetTF{#1}{#2}} +\robust@def\xifinsetFT#1#2{\xifinsetTF{#1}{#2}\cptiiofii\cptiofii} +\robust@def\oifinset@sp@TF#1#2#3{% + \begingroup + \edef\parser{\detokenize{#1}}% + \edef\x{{\parser\cptoxdetok{#2}\parser}% + {\parser\ifdefTF{#3}{\cptoxdetok{#3}}{}\parser}}% + \expandafter\endgroup\expandafter\ifinsetTF\x +} +\robust@def\oifinset@sp@FT#1#2#3{% + \oifinset@sp@TF{#1}{#2}{#3}\cptiiofii\cptiofii +} +\robust@def*\cptifpattern#1\in#2{% + \ifntypeTF{#2}{% + \ifdefTF{#2}{% + \ifblankTF{#1}{% + \@secondoftwo + }{% + \xifinsetTF{\detokenize{#1}}{\meaning#2}% + }% + }{% + \@secondoftwo + }% + }{% + \cpt@notonetokenerr{#2}% + }% +} +% \cptaddtolist[<parser>]<\cs>{<newitem>} +% * -> use \protected@(e)xdef. +% uadd -> don't expand <newitem> at all. +% oadd -> expand <newitem> once. +% xadd -> fully expand <newitem>. +% gadd -> add globally. +\robust@def*\cptuaddtolist{\cpt@teststopt{\cpt@addtolist\unexpanded{e}},} +\robust@def*\cptguaddtolist{\cpt@teststopt{\cpt@addtolist\unexpanded{x}},} +\robust@def*\cptoaddtolist{\cpt@teststopt{\cpt@addtolist\expandcsonce{e}},} +\robust@def*\cptgoaddtolist{\cpt@teststopt{\cpt@addtolist\expandcsonce{x}},} +\robust@def*\cptxaddtolist{\cpt@teststopt{\cpt@addtolist\@firstofone{e}},} +\robust@def*\cptgxaddtolist{\cpt@teststopt{\cpt@addtolist\@firstofone{x}},} +\newletcs\cptaddtolist\cptuaddtolist +\newletcs\cptgaddtolist\cptguaddtolist +\robust@def\cpt@addtolist#1#2[#3]#4#5{% + \ifcpt@check\cpt@checklistparser{#3}\relax\fi + \begingroup + \toks@{\endgroup + \ifdefTF#4{% + \ifdefboolTF{cpt@st}{% + \usename{protected@#2def}#4{\csliststack#3#4#1{#5}}% + }{% + \usename{#2def}#4{\csliststack#3#4#1{#5}}% + }% + }{% + \ifdefboolTF{cpt@st}{% + \usename{protected@#2def}#4{#1{#5}}% + }{% + \usename{#2def}#4{#1{#5}}% + }% + }% + }% + \ifblankTF{#5}{% + \ifcpt@useempty\the\toks@\else\endgroup\fi + }{% + \the\toks@ + }% +} +\robust@def*\cptapptomacro{\cpt@testst{\cpt@hooktomacro>}} +\robust@def*\cptpreptomacro{\cpt@testst{\cpt@hooktomacro<}} +\robust@def\cpt@hooktomacro#1#2#3{% + \cpt@getmacroprefix{#2}% + \ifcpt@st\let\reserved@a\expandcsonce\else\let\reserved@a\unexpanded\fi + \ifdefTF{#2}{% + \ifx#1>% + \macroprefix\edef#2{\expandcsonce{#2}\reserved@a{#3}}% + \else + \macroprefix\edef#2{\reserved@a{#3}\expandcsonce{#2}}% + \fi + }{% + \macroprefix\edef#2{\reserved@a{#3}}% + }% +} +% #1 : optional list parser +% #2 : control sequence of main list +% #3 : sublist to remove (not cs) +% #4 : filter/wrapper +\robust@def*\cptfilterremovecsv{% + \begingroup + \let\cpt@inkv\cptswfalse + \let\temp@parse\csv@@parse + \cpt@testopt\cpt@filterremoveelements{,}% +} +\robust@def*\cptfilterremovekv{% + \begingroup + \let\cpt@inkv\cptswtrue + \let\temp@parse\kv@@parse + \cpt@testopt\cpt@filterremoveelements{,}% +} +\robust@def*\cpt@filterremoveelements[#1]#2#3#4{% + \edef\temp@do + {\cptmakecs{\ifxTF\temp@parse\csv@@parse{csv}{kv}@do}}% + \cptdeclarefilter{#4}% + \ifdefTF{#2}{}{\def#2{}}% + \edef\cpt@delete{\unexpanded{#3}}% + \ifcsnullTF\cpt@delete{}{% + \cpt@sttrue + \usename{cpt@\if\cpt@inkv k\else cs\fi vnormalize}[#1]\cpt@delete + }% + \edef\cpt@tempd##1{% + {\detokenize{#1}\noexpand\cptoxdetok{##1}\detokenize{#1}}% + {\detokenize{#1}\cptoxdetok\cpt@delete\detokenize{#1}}% + }% + \def\cpt@tempc{}% + \expandafter\def\temp@do##1{% + \edef\cpt@tempa{\unexpanded{##1}}% + \cpt@usefilter\cpt@tempa\cpt@tempb + % no \oifinset@sp@TF here (see detokenization above): + \expandafter\xifinsetTF\cpt@tempd\cpt@tempb{}{% + \cptuaddtolist[#1]\cpt@tempc{##1}% + }% + }% + \ifcsnullTF#2{}{% + \ifcsnullTF\cpt@delete{}{% + \temp@parse*[#1]#2% + }% + }% + \let#2\cpt@tempc + \postgroupdef#2\endgroup +} +\robust@def*\cptdeclarefilter#1{% + \edef\cpt@usefilter##1##2{% + \ifblankTF{#1}{\let##2=##1}{% + \ifcseqTF#1\relax{\let##2=##1}{% + \ifstrcmpTF{#1}\nofilter{\let##2=##1}{% + \unexpanded{#1}{##1}{##2}% + }% + }% + }% + }% +} +% #1 : parser +% #2 : old list (a control sequence) of parser-separated list +% #3 : new update (a non-command list) +% #4 : element-wise filter/wrapper +\newletcs\everymergeitem=\@iden +\robust@def*\cptfiltermergecsv{% + \begingroup + \let\temp@parse\csv@@parse + \cpt@testopt\cpt@filtermergelists{,}% +} +\robust@def*\cptfiltermergekv{% + \begingroup + \let\temp@parse\kv@@parse + \cpt@testopt\cpt@filtermergelists{,}% +} +\robust@def*\cpt@filtermergelists[#1]#2#3#4{% + \edef\temp@do{% + \cptmakecs{\ifcseqTF\temp@parse\csv@@parse{csv}{kv}@do}% + }% + \cptdeclarefilter{#4}% + \ifdefTF{#2}{}{\def#2{}}% + \ifblankTF{#3}{% + \def\cpt@update{}% + }{% + \edef\cpt@update{\unexpanded{#3}}% + }% + \def\cpt@add##1{% + \edef#2{\csliststack#1#2\everymergeitem{\expandcsonce{##1}}}% + }% + \expandafter\def\temp@do##1{% + \cpt@choicefdfalse + \edef\cpt@merge@a{\unexpanded{##1}}% + \cpt@usefilter\cpt@merge@a\cpt@merge@b + \expandafter\def\temp@do####1{% + \edef\cpt@merge@c{\unexpanded{####1}}% + \cpt@usefilter\cpt@merge@c\cpt@merge@d + \cptscancs\cpt@merge@b + \cptscancs\cpt@merge@d + \ifx\cpt@merge@b\cpt@merge@d + \cpt@choicefdtrue\cpt@add\cpt@merge@a + \else + \cpt@add\cpt@merge@c + \fi + }% + \cptexpandargonce{\def#2{}\temp@parse[#1]}#2% + \ifdefboolTF{cpt@choicefd}{}{\cpt@add\cpt@merge@a}% + }% + \ifcsnullTF#2{% + \edef#2{\expandcsonce\cpt@update}% + }{% + \ifcsnullTF\cpt@update{}{% + \temp@parse*[#1]\cpt@update + }% + }% + \postgroupdef#2\endgroup + \let\everymergeitem\@firstofone + % No need to undefine \temp@parse, \temp@do, etc: + % they have been defined in a local group. +} +\cptnewvariables{switch}[cpt@]{fromrepl,fromrem}[false] + +% See also \cptfilterremovecsv: +% #1 : optional list parser +% #2 : listcmd +% #3 : single element to remove +% * -> remove all occurrences of #3 +\robust@def*\cptremoveoneelement{\cpt@teststopt\cpt@removeoneelement,} +\robust@def\cpt@removeoneelement[#1]#2#3{% + \begingroup + \let\ifremovest\ifcpt@st + \edef\pser{\detokenize{#1}}% + \def\cpt@remove@a##1{% + \def\cpt@remove@b####1#1##1#1####2\remove@nil{% + \edef#2{\unexpanded{####1#1####2}}% + \cpt@trimparsers[#1]#2% + }% + \xifinsetTF{\detokenize{#1##1#1}}{\pser\cptoxdetok{#2}\pser}{% + \expandafter\cpt@remove@b\expandafter#1#2#1\remove@nil + % If removing all occurrences: + \ifdefboolTF{removest}{% + \expandafter\cpt@remove@a\expandafter{\cpt@remove@c}% + }{}% + }{}% + }% + \ifdefswitchTF{cpt@fromrem}{% + % We're coming from \cptremoveelements, #3 has been + % trimmed and #2 has already been normalized: + \edef\cpt@remove@c{\unexpanded{#3}}% + }{% + \cpt@sttrue\cpt@csvnormalize[#1]#2% + \edef\cpt@remove@c{\cpttrimspaces{#3}}% + }% + \let\cpt@remove@d#2% + \expandafter\cpt@remove@a\expandafter{\cpt@remove@c}% + \ifdefswitchTF{cpt@fromrem}{}{% + \ifx\cpt@remove@d#2\ifcpt@verbose + \cpt@warn{The list in \noexpand#2 not updated: + \MsgBrk perhaps something was wrong}% + \fi\fi + }% + \postgroupdef#2\endgroup +} +% #1 : optional list parser +% #2 : control sequence of list +% #3 : sublist to remove +\robust@def*\cptremoveelements{\cpt@teststopt\cpt@removeelements,} +\robust@def\cpt@removeelements[#1]#2#3{% + \begingroup + \edef\cpt@resa{\ifcpt@st*\fi}% + \let\cpt@fromrem\cptswtrue + \cpt@sttrue\cpt@csvnormalize[#1]#2% + \long\def\csv@do##1{% + \expandafter\cptremoveoneelement\cpt@resa[#1]#2{##1}% + }% + \csv@@parse[#1]{#3}% + \postgroupdef#2\endgroup +} +% \cptreplaceoneelement[<parser>]{<cs>}{<search>}{<replace>} +% #1: optional list parser +% #2: control sequence of list +% #3: single item to replace +% #4: item to substitute +% * -> replace all occurrences +\robust@def*\cptreplaceoneelement{\cpt@teststopt\cpt@replaceoneelement,} +\robust@def\cpt@replaceoneelement[#1]#2#3#4{% + \begingroup + \let\ifreplst\ifcpt@st + \edef\pser{\detokenize{#1}}% + \def\cpt@replace@a##1{% + \def\cpt@replace@b####1#1##1#1####2\rep@nil{% + \edef#2{\unexpanded{####1#1#4#1####2}}% + \cpt@trimparsers[#1]#2% + }% + \xifinsetTF{\detokenize{#1##1#1}}{\pser\cptoxdetok#2\pser}{% + \expandafter\cpt@replace@b\expandafter#1#2#1\rep@nil + % If replacing all occurrences of #3 in #2: + \ifdefboolTF{replst}{% + \expandafter\cpt@replace@a\expandafter{\cpt@replace@c}% + }{}% + }{}% + }% + \ifdefswitchTF{cpt@fromrepl}{% + % We're coming from \cptreplaceelements, #3 has been + % trimmed and #2 has already been normalized: + \edef\cpt@replace@c{\unexpanded{#3}}% + }{% + \cpt@sttrue\cpt@csvnormalize[#1]#2% + \edef\cpt@replace@c{\cpttrimspaces{#3}}% + }% + \let\cpt@replace@d#2% + \expandafter\cpt@replace@a\expandafter{\cpt@replace@c}% + \ifdefswitchTF{cpt@fromrepl}{}{% + \ifx\cpt@replace@d#2% + \ifcpt@verbose + \cpt@warn{The list in \noexpand#2 not updated: + \MsgBrk something was wrong}% + \fi + \fi + }% + \postgroupdef#2\endgroup +} +% #1: optional list parser +% #2: listcmd +% #3: items to replace +% #4: items to substitute +% * -> replace all occurrences +\robust@def*\cptreplaceelements{\cpt@teststopt\cpt@replaceelements,} +\robust@def\cpt@replaceelements[#1]#2#3#4{% + \begingroup + \edef\cpt@replace@a{\unexpanded{#3}}% + \edef\cpt@replace@b{\unexpanded{#4}}% + \edef\cpt@replace@c{\ifcpt@st*\fi}% + \cptfor#2,\cpt@replace@a,\cpt@replace@b\dofor{% + \cpt@sttrue\cpt@csvnormalize[#1]##1% + }% + \def\cpt@replace@d##1#1##2\noboundary##3#1##4\noboundary{% + \expandafter\cptreplaceoneelement\cpt@replace@c[#1]#2{##1}{##3}% + \ifblankTF{##2}{}{% + \ifblankTF{##4}{}{% + \cpt@replace@d##2\noboundary##4\noboundary + }% + }% + }% + \let\cpt@fromrepl\cptswtrue + \cptexpandsecond\cpt@replace@d{% + \expandcsonce\cpt@replace@a#1\noboundary + \expandcsonce\cpt@replace@b#1\noboundary + }% + \postgroupdef#2\endgroup +} +\robust@def*\csnnewif#1{% + \ifstrcmpTF{#1}{x}{% + \cpt@err{Redefining '\cptmakecs{ifx}'?}\@ehc + }{% + \usename{newif\cptthreexp}\usename{if#1}% + }% +} +\robust@def*\csn@def{\aftercsname\def} +\robust@def*\csn@gdef{\aftercsname\gdef} +\robust@def*\csn@edef{\aftercsname\edef} +\robust@def*\csn@xdef{\aftercsname\xdef} +\robust@def*\csndef{\cpt@starorlong{\cpt@csndef{}{}{}}} +\robust@def*\csnpdef{\cpt@starorlong{\cpt@csndef{}{p}{}}} +\robust@def*\csngdef{\cpt@starorlong{\cpt@csndef{}{}{g}}} +\robust@def*\csnpgdef{\cpt@starorlong{\cpt@csndef{}{p}{g}}} +\robust@def*\csnedef{\cpt@starorlong{\cpt@csndef{}{}{e}}} +\robust@def*\csnpedef{\cpt@starorlong{\cpt@csndef{}{p}{e}}} +\robust@def*\csnxdef{\cpt@starorlong{\cpt@csndef{}{}{x}}} +\robust@def*\csnpxdef{\cpt@starorlong{\cpt@csndef{}{p}{x}}} +\robust@def*\newcsndef{\cpt@starorlong{\cpt@csndef{n}{}{}}} +\robust@def*\newcsnpdef{\cpt@starorlong{\cpt@csndef{n}{p}{}}} +\robust@def*\newcsngdef{\cpt@starorlong{\cpt@csndef{n}{}{g}}} +\robust@def*\newcsnpgdef{\cpt@starorlong{\cpt@csndef{n}{p}{g}}} +\robust@def*\newcsnedef{\cpt@starorlong{\cpt@csndef{n}{}{e}}} +\robust@def*\newcsnpedef{\cpt@starorlong{\cpt@csndef{n}{p}{e}}} +\robust@def*\newcsnxdef{\cpt@starorlong{\cpt@csndef{n}{}{x}}} +\robust@def*\newcsnpxdef{\cpt@starorlong{\cpt@csndef{n}{p}{x}}} +\new@def*\cpt@csndef#1#2#3#4{% + \if#1n\relax + \ifcsndefTF{#4}{% + \def\undefinablecs{#4}\cpt@notdefinable + }{}% + \fi + \if#2p\relax\let\reserved@a\protected\else + \let\reserved@a\relax\fi + \reserved@a\l@ngrel@x\aftercsname\aftercsname{#3def}{#4}% +} +\robust@def*\letcsntocs#1{\cptthreexp\let\usename{#1}} +\robust@def*\gletcsntocs#1{\global\cptthreexp\let\usename{#1}} +\robust@def*\letcstocsn#1#2{% + \begingroup\expandafter\endgroup\expandafter + \let\expandafter#1\csname#2\endcsname +} +\robust@def*\gletcstocsn#1#2{% + \begingroup\expandafter\endgroup\expandafter\global + \expandafter\let\expandafter#1\csname#2\endcsname +} +\robust@def*\letcsntocsn#1#2{% + \begingroup\expandafter\endgroup + \expandafter\let\csname#1\expandafter + \endcsname\csname#2\endcsname +} +\robust@def*\gletcsntocsn#1#2{% + \begingroup\expandafter\endgroup\expandafter + \global\expandafter\let\csname#1\expandafter + \endcsname\csname#2\endcsname +} +\robust@def*\globalize#1{\gletcs#1#1} +\robust@def*\globalizecsn#1{% + \begingroup\expandafter\endgroup\expandafter + \global\expandafter\let\csname#1\expandafter\endcsname + \csname#1\endcsname +} +\robust@def*\undefcs#1{\let#1\cpt@undefined} +\robust@def*\gundefcs{\global\undefcs} +\robust@def*\undefcsn#1{\aftercsname\undefcs{#1}} +\robust@def*\gundefcsn{\global\undefcsn} +\robust@def*\undefcsset{\cpt@testst{\cpt@testcl\cpt@undefcsset}} +\robust@def*\cpt@undefcsset#1{% + \cpt@stchoose{cpt@st}{#1}\cpt@rsvda\undefcsset + \expandafter\cptfor\cpt@rsvda\dofor{% + \ifntypeTF{##1}{% + \ifescapedTF{##1}{% + \ifcpt@cl\global\fi\undefcs##1% + }{% + \cpt@notescapederr{##1}% + }% + }{% + \cpt@notonetokenerr{##1}% + }% + }% +} +% #1: parser, #2: listcmd +% This is one way to preserve braces in #2: +\robust@def*\cpttrimleadparsers#1#2{% + \ifblankTF{#1}{% + \cpt@err{Empty parser in \string\cpttrimleadparsers}\@ehc + }{}% + \begingroup + \ifcat$\detokenize\expandafter\expandafter\expandafter + {\expandafter\@gobble#2.}$\cptbgobbletorelax\fi + \def\reserved@e##1#1{% + \edef\reserved@a{\unexpanded\expandafter{\@gobble##1}}% + \ifx\reserved@a\@empty + \def\next{\reserved@e.}% + \else + \def\@next####1#1\noboundary + {\edef#2{\unexpanded\expandafter{\@gobble####1}}}% + \edef\next{\unexpanded{\@next##1#1}}% + \fi + \next + }% + \expandafter\reserved@e\expandafter.#2#1\noboundary + \postgroupdef#2\endgroup\cpt@relax +} +% #1: parser, #2: list command +\robust@def\cpttrimtrailparsers#1#2{% + \begingroup + \def\cpt@trima{% + \xifinsetTF{\detokenize{#1}\noboundary} + {\cptoxdetok{#2}\noboundary}{% + \def\reserved@a####1#1\noboundary{% + \edef#2{\expandcsonce{\@gobble####1}}% + \cpt@trima + }% + \expandafter\reserved@a\expandafter.#2\noboundary + }{}% + }% + \cpt@trima + \postgroupdef#2\endgroup +} +\robust@def*\cpttrimparsers{\cpt@testopt\cpt@trimparsers,} +\robust@def*\cpt@trimparsers[#1]#2{% + \ifntypeTF{#1}{% + \cpttrimleadparsers{#1}#2% + \cpttrimtrailparsers{#1}#2% + }{% + \cpt@notonetokenerr{#1}% + }% +} +% #1: token on command, #2: test token: +\robust@def\cpt@stripsuffix#1#2{% + \ifblankTF{#2}{% + \cpt@err{Blank test token for \string\cpt@stripsuffix}\@ehc + }{% + \edef\reserved@a{% + \ifblankTF{#1}{}{\ifstrcmpTF{#1}{#2}{}{\unexpanded{#1}}}% + }% + }% +} +% Strip #1 number of outer braces in #2; return result in #3: +\robust@def*\cptstripNouterbraces{\cpt@testopt\cpt@stripouterbraces\@ne} +\newletcs\cptstripnbr\cptstripNouterbraces +\robust@def*\cpt@stripouterbraces[#1]{% + \begingroup + \def\end@def##1##2##3{\postgroupdef##3\endgroup}% + \@tempcnta\z@pt + \catcode`\{=1 + \catcode`\}=2 + \catcode`\#=6 + \cpt@str@pouterbraces{#1}% +} +\robust@def\cpt@str@pouterbraces#1#2#3{% + \advance\@tempcnta\@ne + \edef#3{\unexpanded{#2}}% + \cpt@str@pouterbr@ces#2\strip@nil{#3}{#1}% +} +\robust@def\cpt@str@pouterbr@ces#1\strip@nil#2#3{% + \defifxTF{#1}#2{% + \end@def + }{% + \ifnum\@tempcnta>#3\relax + \expandafter\end@def + \else + \expandafter\cpt@str@pouterbraces + \fi + }% + {#3}{#1}{#2}% +} +\robust@def\cptstripallouterbraces#1#2{% + \edef#2{\unexpanded\cptthreexp{\cpt@stripallouterbraces#1\strip@nil}}% +} +\newletcs\cptstripallbr\cptstripallouterbraces +\robust@def\cptstripallouterbracesincs#1{% + \expandafter\cptstripallouterbraces\expandafter{#1}#1% +} +\newletcs\cptstripallbrincs\cptstripallouterbracesincs +\robust@def\cpt@stripallouterbraces#1\strip@nil{% + \romannumeral\ifbracedTF{#1}{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% + \expandafter\@gobble\cpt@stripallouterbraces#1\strip@nil + }{0 #1}% + }{0 #1}% +} +\robust@def\cpt@starafter#1#2{% + \begingroup + \def\cpt@tempa{#1}% + \def\cpt@tempb##1{#1{#2}}% + \def\cpt@tempc{\futurelet\next\cpt@staract}% + \cpt@tempc +} +\new@def*\cpt@staract{% + \ifcseqTF\@sptoken\next{% + \afterassignment\cpt@tempc\let\next= % + }{% + \cptexpandsecond\endgroup{% + \ifcseqTF*\next{\expandcsonce\cpt@tempb}% + {\expandcsonce\cpt@tempa}% + }% + }% +} +\robust@def*\cptbracearg{\cpt@testopt\cpt@bracearg\@ne} +\robust@def\cpt@bracearg[#1]#2#3{% + \begingroup + \@tempcnta\z@pt + \loop + \edef#3{\unexpanded{{#2}}}% + \advance\@tempcnta\@ne + \ifnum\@tempcnta<#1\relax + \repeat + \postgroupdef#3\endgroup +} +% Expandable: +\edef\ifmacroTF#1{% + \noexpand\ifblankTF{#1}{% + \noexpand\@secondoftwo + }{% + \noexpand\ifleftbracedTF{#1}{% + \noexpand\@secondoftwo + }{% + \unexpanded{\expandafter\cpt@ifmacro\meaning}% + #1\detokenize{macro}:\cpt@nil + }% + }% +} +\new@def*\ifmacroFT#1{\ifmacroTF{#1}\cptiiofii\cptiofii} +\new@def*\oifmacroTF#1{\simpleexpandarg\ifmacroTF{#1}} +\new@def*\ifcsnmacroTF{\aftercsname\ifmacroTF} +\edef\cpt@ifmacro{% + \def\noexpand\cpt@ifmacro##1\detokenize{macro}:##2\cpt@nil +} +\cpt@ifmacro{\usename{@\ifblankTF{#2}{second}{first}oftwo}} + +\new@def*\csnmeaning#1{\aftercsname\meaning{#1}} +\robust@def*\ifescapedTF#1{% + \begingroup + \escapechar92\relax + \edef\x{\expandafter\cpt@car\string#1x\car@nil}% + \aftercsname\endgroup + {@\ifx\x\@backslashchar first\else second\fi oftwo}% +} +\robust@def*\ifescapedFT#1{\ifescapedTF{#1}\cptiiofii\cptiofii} +% \robustaliascount counts the number of 'robustified' commands. +% It may be used to set a threshold for the no. of allowable +% aliases. \cptrobustify avoids \scantokens, because some commands +% aren't scannable: +\cptchardef\maxrobustalias50 +\robust@def*\cptrobustify#1{% + \def\csv@do##1{% + \ifescapedTF{##1}{% + \ifdefTF{##1}{% + \cptpushnumber\robustaliascount + \ifnum\robustaliascount<\maxrobustalias\relax + \ifcsndefTF{robbase@\cptgobblescape##1}{% + \cpt@warn{Command '\string##1' is already robust: + \MsgBrk not made robust again}% + }{% + \letcsntocs{robbase@\cptgobblescape##1}##1% + \protected\edef##1{\cptmakecs{robbase@\cptgobblescape##1}}% + }% + \else + \cpt@err{Maximum number '\number\maxrobustalias' of + robust command aliases exceeded:\MsgBrk + You can set \noexpand\maxrobustalias higher}\@ehc + \fi + }{% + \cpt@notdeferr{##1}% + }% + }{% + \cpt@notescapederr{##1}% + }% + }% + \csv@@parse[,]{#1}% +} +\robust@def*\leftaddtocs{% + \let\cpt@def\edef\let\swap\cptswap\cpt@addtocs +} +\robust@def*\gleftaddtocs{% + \let\cpt@def\xdef\let\swap\cptswap\cpt@addtocs +} +\robust@def*\rightaddtocs{% + \let\cpt@def\edef\let\swap\cptalloftwo\cpt@addtocs +} +\robust@def*\grightaddtocs{% + \let\cpt@def\xdef\let\swap\cptalloftwo\cpt@addtocs +} +\robust@def*\rightaddtocsn{\aftercsname\rightaddtocs} +\robust@def*\grightaddtocsn{\aftercsname\grightaddtocs} +\robust@def*\leftaddtocsn{\aftercsname\leftaddtocs} +\robust@def*\gleftaddtocsn{\aftercsname\gleftaddtocs} +\robust@def\cpt@addtocs#1#2{% + \ifntypeTF{#1}{% + \ifescapedTF{#1}{% + \ifdefTF#1{% + \cpt@getmacroprefix{#1}% + \macroprefix\cpt@def + #1{\swap{\expandcsonce{#1}}{\unexpanded{#2}}}% + }{% + \cpt@def#1{\unexpanded{#2}}% + }% + }{% + \cpt@notescapederr{#1}% + }% + }{% + \cpt@notonetokenerr{#1}% + }% + \undefcs\cpt@def\undefcs\swap +} +\robust@def*\cpteveryscan{% + \everyeof{\noexpand}% + \endlinechar\m@one + \makeatletter + \catcode`\ =10 + \catcode`\\\z@pt + \catcode`\{\@ne + \catcode`\}\tw@ +} +% #1 must be a non-parametered macro: +\robust@def*\cptscancs#1{% + \begingroup + \edef#1{\long\def\string#1{\cptoxdetok{#1}}}% + \cpteveryscan + \scantokens\expandafter{#1}\relax + \postgroupdef#1\endgroup +} +\newletcs\cptscantokens\cptscancs +\begingroup + \lccode`\A =`\@ % + \lccode`\B =`\@ % + \catcode`\A = 8 % + \catcode`\B = 3 % +\lowercase{\endgroup\def\cpt@rescan@marker{AB}} +\robust@def*\cptrescan{\cpt@rescan@a\def} +\robust@def*\cptgrescan{\cpt@rescan@a\gdef} +% #1 = \def or \gdef +% #2 = command to receive the re-scanned stuff +% #3 = arbitrary code to execute before \scantokens +% #4 = stuff to rescan +\robust@def*\cpt@rescan@a#1#2#3#4{% + \begingroup + \everyeof\expandafter{\cpt@rescan@marker\noexpand}% + \endlinechar\m@one\newlinechar\m@one + #3% + \cptexpanded{\endgroup + #1\noexpand#2{% + \expandafter\cpt@rescan@b\expandafter\@empty + \scantokens\expandafter{#4}% + }% + }% +} +\edefpass\reserved@a{% + % The \expandafter here is to get rid of \@empty: + \def\noexpand\cpt@rescan@b##1\cpt@rescan@marker{% + \noexpand\unexpanded\noexpand\expandafter{##1}% + }% +} +\robust@def*\cpt@lowercasecs#1{% + \ifmacroTF{#1}{% + \cptexpandarg\lowercase{\def\noexpand#1{#1}}% + }{% + \cpt@notcserr{#1}% + }% +} +\robust@def*\cptprovidecount#1{% + \ifescapedTF{#1}{% + \ifdefTF{#1}{% + \ifcounterTF{#1}{}{% + \cpt@warn{Command '\noexpand#1' is already + \MsgBrk defined but not a counter}% + }% + }{% + \newcount#1% + }% + }{% + \cpt@notescapederr{#1}% + }% +} +\robust@def*\cptprovidedimen#1{% + \ifescapedTF{#1}{% + \ifdefTF{#1}{% + \ifdimenTF{#1}{}{% + \cpt@warn{Command '\noexpand#1' is already + \MsgBrk defined but not a dimension}% + }% + }{% + \newdimen#1% + }% + }{% + \cpt@notescapederr{#1}% + }% +} +\robust@def*\newtog#1{\cpt@testopt{\cpt@newtog{#1}}{false}} +\new@def*\cpt@newtog#1[#2]{% + \ifinsetTF{,}{#1}{% + \cpt@err{Command \noexpand\newtog doesn't accept list} + {Please submit only one toggle to \noexpand\newtog. + \MsgBrk You can use \noexpand\cptnewvariables + for multiple toggles.}% + }{}% + \ifcsndefTF{cpt@tog@#1}{% + \cpt@err{Toggle '#1' already defined}% + {Please provide a new toggle.}% + }{}% + \cpt@gettogstate{#2}% + \letcsntocs{cpt@tog@#1}\cpt@togstate +} +\robust@def*\providetog#1{% + \ifcsndefTF{cpt@tog@#1}{}{% + \letcsntocs{cpt@tog@#1}\@secondoftwo + }% +} +\robust@def*\cpt@gettogstate#1{% + \lowercase{% + \xifstrcmpTF{#1}{true}{% + \let\cpt@togstate\@firstoftwo + }{% + \xifstrcmpTF{#1}{false}{% + \let\cpt@togstate\@secondoftwo + }{% + \cpt@err{Invalid toggle value '#1'}% + {Valid toggle values are 'true' and 'false'.}% + }% + }% + }% +} +\robust@def*\cpt@notogerr#1{% + \cpt@err{Toggle switch '#1' is undefined}\@ehc +} +\robust@def*\settogtrue#1{% + \ifcsndefTF{cpt@tog@#1}{% + \letcsntocs{cpt@tog@#1}\@firstoftwo + }{% + \cpt@notogerr{#1}% + }% +} +\newletcs\togtrue=\settogtrue +\robust@def*\settogfalse#1{% + \ifcsndefTF{cpt@tog@#1}{% + \letcsntocs{cpt@tog@#1}\@secondoftwo + }{% + \cpt@notogerr{#1}% + }% +} +\newletcs\togfalse=\settogfalse +\robust@def*\settog#1#2{% + \ifcsndefTF{cpt@tog@#1}{% + \cpt@gettogstate{#2}% + \letcsntocs{cpt@tog@#1}\cpt@togstate + }{% + \cpt@notogerr{#1}% + }% +} +\robust@def*\undeftog#1{% + \ifcsndefTF{cpt@tog@#1}{% + \letcsntocs{cpt@tog@#1}\cpt@undefined + }{% + \cpt@info{Null instruction to undefine unknown toggle '#1'}% + }% +} +\new@def*\iftogTF#1{% + \ifcsndefTF{cpt@tog@#1}{% + \usename{cpt@tog@#1}% + }{% + \cpt@notogerr{#1}\@gobbletwo + }% +} +\new@def*\iftogFT#1{\iftogTF{#1}\cptiiofii\cptiofii} +\new@def*\cptswtrue{00} +\new@def*\cptswfalse{01} +\def\reserved@a#1{% + \new@def*\negatesw##1{% + 0\ifcase##11#1\or\expandafter1\else\expandafter0\fi + }% + \new@def*\bothswtrue##1##2{% + 0\ifcase##1##2#1\expandafter0\else\expandafter1\fi + }% + \new@def*\oneswtrue##1##2{% + 0\ifnum##1##2<101#1\expandafter0\else\expandafter1\fi + }% +} +\reserved@a{ } +% Convert bool value (true or false) to switch value (00 or 01): +\robust@def*\booltoswitch#1#2{% + \begingroup + \def\reserved@a##1#1##2##3\@nil{% + \def#2{##2}% + \ifx#2\@nnil + \cpt@err{Bad boolean value '#1' can't be + \MsgBrk converted to switch value}\@ehc + \fi + }% + \reserved@a true{00}false{01}#1{\@nil}\@nil + \postgroupdef#2\endgroup +} +% Expandable: +\new@def*\bbooltoswitch#1{% + \expandafter\ifstrcmpTF\expandafter + {\romannumeral-`\q\expandafter\cpttrimspace + \expandafter{\romannumeral-`\q#1}}{true}{00}{01}% +} + +\robust@def*\cptnewswitch#1{\cpt@testopt{\cpt@newswitch#1}{false}} +\robust@def*\cpt@newswitch#1[#2]{% + \ifinsetTF{,}{#1}{% + \cpt@err{Command \noexpand\cptnewswitch doesn't accept list} + {Please submit only one switch to \string\cptnewswitch.}% + }{}% + \xifinsetTF{,#1,}{,if,x,switch,tog,togg,bool,test,}{% + \cpt@err{Invalid switch name '#1'}\@ehc + }{}% + \ifcsndefinable{#1}\relax + \cpt@getswitchstate{#2}% + \letcsntocsn{#1}{cptsw\cpt@switchstate}% +} +\robust@def*\cpt@getswitchstate#1{% + \lowercase{\edef\cpt@tempa{\cpttrimspaces{#1}}}% + \xifinsetTF{,\cpt@tempa,}{,true,false,}{% + \let\cpt@switchstate\cpt@tempa + }{% + \cpt@err{Invalid switch value '#1'} + {Valid switch values are 'true' and 'false'.}% + }% +} +\robust@def*\cpt@noswitcherr#1{% + \cpt@err{Switch '\string#1' is undefined}\@ehc +} +\robust@def*\cptsetswitch#1#2{% + \ifcsndefTF{#1}{% + \cpt@getswitchstate{#2}% + \letcsntocsn{#1}{cptsw\cpt@switchstate}% + }{% + \cpt@noswitcherr{#1}% + }% +} +\robust@def*\cptsetswitchtrue#1{% + \ifcsndefTF{#1}{% + \letcsntocs{#1}\cptswtrue + }{% + \cpt@noswitcherr{#1}% + }% +} +\newletcs\cptswitchtrue\cptsetswitchtrue +\robust@def*\cptsetswitchfalse#1{% + \ifcsndefTF{#1}{% + \letcsntocs{#1}\cptswfalse + }{% + \cpt@noswitcherr{#1}% + }% +} +\newletcs\cptswitchfalse\cptsetswitchfalse +\new@def*\ifdefswitchTF#1{% + \ifcsndefFT{#1}{% + \cpt@err{Switch '#1' is not defined}\@ehc + \@gobbletwo + }{% + \if\usename{#1}\expandafter\cptiofii\else\expandafter\cptiiofii\fi + }% +} +\new@def*\ifdefswitchFT#1{\ifdefswitchTF{#1}\cptiiofii\cptiofii} +\new@def*\ifswitchTF#1{% + \if\usename{#1}\expandafter\cptiofii\else\expandafter\cptiiofii\fi +} +\new@def*\ifswitchFT#1{\ifswitchTF{#1}\cptiiofii\cptiofii} +\new@def*\thebool@normal#1{\ifboolTF{#1}{true}{false}} +\new@def*\thebool@reverse#1{\ifboolTF{#1}{false}{true}} +\cptnewcounts[cpt@]{exprcnt} +\robust@def*\ifexprTF#1{% + \begingroup + \let\cpt@expr@neg\cptswfalse + \cpt@exprcnt\z@pt + \cpt@expr@beg + \cpt@expr@bgroup#1(\expr@nil + \cpt@expr@end + \cpt@expr@eval +} +\robust@def*\cpt@expr@beg{% + \begingroup + \let\cpt@expr@neg\cptswfalse + \cpt@exprcnt\z@pt +} +\robust@def*\cpt@expr@end{% + \cpt@expr@eval\cpt@expr@true\cpt@expr@false +} +\robust@def*\cpt@expr@eval{% + \aftercsname\endgroup + {@\ifnum\cpt@exprcnt<\z@pt second\else first\fi oftwo}% +} +\robust@def*\cpt@expr@true{% + \advance\cpt@exprcnt\if\cpt@expr@neg\m@one\else\z@pt\fi + \let\cpt@expr@neg\cptswfalse +} +\robust@def*\cpt@expr@false{% + \advance\cpt@exprcnt\if\cpt@expr@neg\z@pt\else\m@one\fi + \let\cpt@expr@neg\cptswfalse +} +\robust@def\cpt@expr@bgroup#1(#2\expr@nil{% + \cpt@expr@egroup#1)\expr@nil + \ifblankTF{#2}{}{% + \cpt@expr@beg + \cpt@expr@bgroup#2\expr@nil + }% +} +\robust@def\cpt@expr@egroup#1)#2\expr@nil{% + \cpt@expr@and#1and\expr@nil + \ifblankTF{#2}{}{% + \cpt@expr@end + \cpt@expr@egroup#2\expr@nil + }% +} +\robust@def\cpt@expr@and#1and#2\expr@nil{% + \cpt@expr@or#1or\expr@nil + \ifblankTF{#2}{}{% + \cpt@exprcnt\ifnum\cpt@exprcnt<\z@pt\m@one\else\z@pt\fi + \cpt@expr@and#2\expr@nil + }% +} +\robust@def\cpt@expr@or#1or#2\expr@nil{% + \cpt@expr@not#1not\expr@nil + \ifblankTF{#2}{}{% + \cpt@exprcnt\ifnum\cpt@exprcnt<\z@pt\z@pt\else\@ne\fi + \cpt@expr@or#2\expr@nil + }% +} +\robust@def\cpt@expr@not#1not#2\expr@nil{% + \cpt@expr@tog#1tog\expr@nil + \ifblankTF{#2}{}{% + \let\cpt@expr@neg\cptswtrue + \cpt@expr@not#2\expr@nil + }% +} +\robust@def\cpt@expr@tog#1tog#2\expr@nil{% + \cpt@expr@bool#1bool\expr@nil + \ifblankTF{#2}{}{\cpt@expr@tog@a#2\expr@nil}% +} +\robust@def\cpt@expr@tog@a#1#2\expr@nil{% + \edef\reserved@a{\cpttrimspaces{#1}}% + \ifcsndefTF{cpt@tog@\reserved@a}{% + \usename{cpt@tog@\reserved@a}\cpt@expr@true\cpt@expr@false + }{% + \cpt@err{Invalid test expression: + \MsgBrk toggle '\reserved@a' is undefined}\@ehc + \cpt@expr@false + }% + \cpt@expr@tog#2\expr@nil +} +\robust@def\cpt@expr@bool#1bool#2\expr@nil{% + \cpt@expr@switch#1switch\expr@nil + \ifblankTF{#2}{}{\cpt@expr@bool@a#2\expr@nil}% +} +\robust@def\cpt@expr@bool@a#1#2\expr@nil{% + \edef\reserved@a{\cpttrimspaces{#1}}% + \ifcsndefTF{if\reserved@a}{% + \ifdefboolTF\reserved@a\cpt@expr@true\cpt@expr@false + }{% + \cpt@err{Invalid test expression: + \MsgBrk boolean '\reserved@a' is undefined}\@ehc + \cpt@expr@false + }% + \cpt@expr@bool#2\expr@nil +} +\robust@def\cpt@expr@switch#1switch#2\expr@nil{% + \cpt@expr@test#1test\expr@nil + \ifblankTF{#2}{}{\cpt@expr@switch@a#2\expr@nil}% +} +\robust@def\cpt@expr@switch@a#1#2\expr@nil{% + \edef\reserved@a{\cpttrimspaces{#1}}% + \ifcsndefTF\reserved@a{% + \ifswitchTF\reserved@a\cpt@expr@true\cpt@expr@false + }{% + \cpt@err{Invalid test expression: + \MsgBrk switch '\reserved@a' is undefined}\@ehc + \cpt@expr@false + }% + \cpt@expr@switch#2\expr@nil +} +\robust@def\cpt@expr@test#1test#2\expr@nil{% + \ifblankTF{#1}{}{% + \cpt@err{Invalid piece in test expression: + \MsgBrk'\detokenize{#1}'}\@ehc + }% + \ifblankTF{#2}{}{% + \cpt@expr@test@a#2\expr@nil + }% +} +\robust@def\cpt@expr@test@a#1#2\expr@nil{% + \ignorespaces#1\cpt@expr@true\cpt@expr@false + \cpt@expr@test#2\expr@nil +} + +\robust@def*\cptifonepresentTF#1#2{% + \begingroup + \cpt@choicefdfalse + \def\siso@do##1{% + \ifinsetTF{##1}{#2}{% + \cpt@choicefdtrue\loopbreak + }{}% + }% + \siso@@loop{#1}% + \expandafter\endgroup\ifcpt@choicefd + \expandafter\cptiofii\else\expandafter\cptiiofii\fi +} +% #1: listcmd +% #2: comparator: < (ascending) or > (descending) +% Eg, \def\x{13251{8/2}} \cptnumbersort\x> +\robust@def*\cptnumbersort#1#2{% + \begingroup + \let\numcmp\ifnumcmpTF + \cpt@sortlist{#1}{#2}% +} +% Eg, \def\x{13251{4456789201.12}} \cptbignumbersort\x> +\robust@def*\cptbignumbersort#1#2{% + \begingroup + \ifcsndefTF{ver@fp.sty}{% + \def\reserved@a##1#2##2##3\cpt@nil{% + \def\numcmp####1#2####2####{% + \usename{FPif##2}{####1}{####2}% + \expandafter\cptiofii\else\expandafter\cptiiofii\fi + }% + }% + \reserved@a={eq}>{gt}<{lt}\cpt@nil + }{% + \cpt@err{'fp' package not loaded} + {You need to first load 'fp' package before + \MsgBrk calling \string\cptbignumbersort.}% + }% + % If #1 contains expressions, evaluate them first before + % sorting the results: + \cptexpandarg{\cptifonepresentTF{/*-+}}{\cptoxdetok{#1}}{% + \def\siso@do##1{% + \FPeval\resulta{clip(##1)}% + \edef#1{#1{\resulta}}% + }% + \cptexpandarg{\def#1{}\siso@@loop}{#1}% + }{}% + \cpt@sortlist{#1}{#2}% +} +% Eg, \def\x{ab{west}cdea{east}} \cptalphasort\x< +\robust@def*\cptalphasort#1#2{% + \begingroup + \def\numcmp##1#2##2##{% + \ifnum\cpt@pdfstrcmp{##1}{##2}#2\z@pt + \expandafter\cptiofii\else\expandafter\cptiiofii\fi + }% + \cpt@sortlist{#1}{#2}% +} +\robust@def*\cpt@sortlist#1#2{% + \def\sortedlist{}% + \cpt@sortlist@a{#1}{#2}% + \edefpass#1{\endgroup\def\noexpand#1{\sortedlist}}% +} +\new@def*\cpt@sortwrapper#1{{#1}} +\robust@def*\cpt@sortlist@a#1#2{% + % Get the largest/smallest number and return: + \def\do##1{% + \def\smaller@bigger{}% + \defpass\do####1{% + \defifxTF{####1}\@nnil{% + % Store the largest/smallest number: + \edef\sortedlist{\sortedlist\cpt@sortwrapper{##1}}% + \ifcsemptyTF\smaller@bigger{}{% + \let#1=\smaller@bigger + \cpt@sortlist@a#1#2% + }% + }{% + \numcmp####1#2##1{% + \cpt@sortlist@b{#1}{#2}{{####1}{##1}}.% + }{% + \edef\smaller@bigger{\smaller@bigger{####1}}% + \do + }% + }% + }% + }% + \expandafter\do#1\@nil +} +\robust@def*\cpt@sortlist@b#1#2#3#4\@nil{% + % \@gobble is for gobbling the dot: + \edef#1{#3\smaller@bigger\@gobble#4}% + \cpt@sortlist@a{#1}{#2}% +} +\robust@def*\BeforeProcessOptions{% + \ifcsndefTF{\@currname @\@currext @beginprocessopt}{% + \cpt@warn{\noexpand\BeforeProcessOptions wrongly located}% + \@gobble + }{% + \aftercsname\grightaddtocs{\@currname @\@currext + @beforeprocessopt}% + }% +} +\robust@def*\AfterProcessOptions{% + \ifcsndefTF{\@currname @\@currext @endprocessopt}{% + \@firstofone + }{% + \aftercsname\grightaddtocs{\@currname @\@currext + @afterprocessopt}% + }% +} +\robust@def*\BeforeStartOfDocument{\grightaddtocs\cpt@beforestartdoc} +\new@def*\cpt@beforestartdoc{} +\gleftaddtocs\document{% + \endgroup + \let\BeforeStartOfDocument\@firstofone + \cpt@beforestartdoc + \let\BeforeStartOfDocument\@notprerr + \gundefcs\cpt@beforestartdoc + \gdef\cpt@docstarted{}% + \begingroup +} +\robust@def*\AfterStartOfDocument{\grightaddtocs\cpt@afterstartdoc} +\new@def*\cpt@afterstartdoc{} +\robust@def*\AfterAfterStartOfDocument#1{% + \AtBeginDocument{% + \grightaddtocs\cpt@afterafterstartdoc{#1}% + }% +} +\new@def*\cpt@afterafterstartdoc{} +\grightaddtocs\document{% + \let\AfterStartOfDocument\@firstofone + \cpt@afterstartdoc + \let\AfterStartOfDocument\@notprerr + \gundefcs\cpt@afterstartdoc + \cpt@afterafterstartdoc + \let\AfterAfterStartOfDocument\@notprerr + \gundefcs\cpt@afterafterstartdoc + \ignorespaces +} +\gleftaddtocs\@popfilename{% + \ifcsnameFT{\@currname.\@currext-cpt@hook}{}{% + \usename{\@currname.\@currext-cpt@hook}% + \gundefcsn{\@currname.\@currext-cpt@hook}% + }% +} +% \loadifnotloaded{<package>}[<date>] +\robust@def*\loadifnotloaded#1{% + \cpt@testopt{\cpt@ifpkgnotloaded{#1}}{}% +} +\robust@def*\cpt@ifpkgnotloaded#1[#2]{% + \@ifpackageloaded{#1}{% + \@ifpackagelater{#1}{#2}{}{% + \ltxmsg@err{Loaded version of #1 package is not current}\@ehc + }% + }{% + \RequirePackage{#1}[#2]% + }% +} +% If package has been loaded with <options>. +% \ifpackagewithoptionsTF{<package>}{<options>}{<true>}{<false>} +\robust@def*\ifpackagewithoptionsTF{\cpt@ifoptions\@pkgextension} +\robust@def*\ifclasswithoptionsTF{\cpt@ifoptions\@clsextension} +\robust@def*\cpt@ifoptions#1#2{% + \cptexpandarg\cpt@ifopti@ns{\cpt@optionlist{#2.#1}}% +} +\robust@def*\cpt@ifopti@ns#1#2{% + \begingroup + \edef\temp@optlist{\unexpanded{#1}}% + \cpt@sttrue\cpt@kvnormalize[,]\temp@optlist + \cpt@choicefdtrue + \def\checkopts{% + \def\kv@do####1{% + \oifinset@sp@TF,{####1}\temp@optlist + {}{\cpt@choicefdfalse\loopbreak}% + }% + \kv@@parse{#2}% + }% + \ifblankTF{#2}{% + \ifcsemptyTF\temp@optlist{}{% + \cpt@choicefdfalse + }% + }{% + \ifcsemptyTF\temp@optlist{% + \cpt@choicefdfalse + }{% + \checkopts + }% + }% + \ifdefboolTF{cpt@choicefd} + {\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% +} +% #1=package, #2=options +\robust@def*\cptcheckoptionclash#1#2{% + \begingroup + \edef\cpt@rsvda{\detokenize\expandafter + {\romannumeral-`\q\cpt@optionlist{#1.\@pkgextension}}}% + \@tempswafalse + \ifblankTF{#2}{% + \ifcsnullTF\cpt@rsvda{}\@tempswatrue + }{% + \ifcsnullTF\cpt@rsvda{% + \@tempswatrue + }{% + \def\kv@do####1{% + \xifinsetTF{,\detokenize{####1},}{,\cpt@rsvda,}{}{% + \@tempswatrue\loopbreak + }% + }% + \kv@@parse[,]{#2}% + }% + }% + \expandafter\endgroup + \if@tempswa + \cpt@err{Option clash for package ##1.\@pkgextension}\@ehc + \expandafter\@gobble + \fi +} +% If package was later loaded (before begin-document). +% \ifpackageloadedlaterTF{<package>}{<true>}{<false>} +\robust@def*\ifpackageloadedlaterTF{\cpt@ifpkgloadedlater\@pkgextension} +\robust@def*\ifclassloadedlaterTF{\cpt@ifpkgloadedlater\@clsextension} +\robust@def*\cpt@ifpkgloadedlater#1#2#3#4{% + \begingroup + \edef\elt{\ifx#1\@pkgextension package\else class\fi}% + \usename{@if\elt loaded}{#2}{% + \endgroup + \ifcpt@verbose + \cpt@info{\@cls@pkg\@space '#2' has been loaded}% + \fi + }{% + \def\elt##1##2{% + \ifcpt@verbose + \cpt@info{\@cls@pkg\@space '#2' was##1 loaded afterwards}% + \fi + \unexpanded{##2}\relax + }% + \cptexpanded{\endgroup + \AfterStartOfDocument{% + \noexpand\ifcsndefTF{ver@#2.#1}{\elt{}{#3}}{\elt{n't}{#4}}% + }% + }% + }% +} +% \cptloadpackages[<inner-parser><outer-parser>]{% +% pkga<inner>options<inner>date<outer> +% pkgb<inner>options<inner>date<outer> +% } +\robust@def*\cptloadpackages{% + \begingroup + \endlinechar=-1 + \cpt@testopt{\expandafter\endgroup\cpt@loadpackages}{|;}% +} +\robust@def\cpt@loadpackages[#1]#2{% + \begingroup + \toks@{}% + % ##1: inner parser; ##2 outer parser: + \def\cpt@tempa##1##2\cpt@nil{% + \ifblankTF{##2}{% + \cpt@err{No outer parser or something wrong + \MsgBrk while in \string\cptloadpackages}\@ehc + \@gobble + }{% + \ifinsetFT{,}{##1##2}{}{% + \cpt@err{Parser can't be comma (,) in + \string\cptloadpackages}\@ehc + \expandafter\@gobble + }% + }% + % \cpt@lo@dpackages can't be taken outside \cpt@loadpackages: + \def\cpt@lo@dpackages####1##1####2##1####3##1####4\cpt@nil{% + \ifblankTF{####1}{% + \cpt@err{No package name while in \string\cptloadpackages}\@ehc + \@gobble + }{}% + \ifblankTF{####2}{% + \def\cpt@rsvda{}% + }{% + \cptstripallouterbraces{####2}\cpt@rsvda + }% + \@ifpackageloaded{####1}{% + % Check if package was previously loaded with options: + \edef\cpt@rsvdb{\detokenize\expandafter + {\romannumeral-`\q\cpt@optionlist{####1.\@pkgextension}}}% + \@tempswafalse + \ifcsnullTF\cpt@rsvda{% + \ifcsnullTF\cpt@rsvdb{}\@tempswatrue + }{% + \ifcsnullTF\cpt@rsvdb{% + \@tempswatrue + }{% + \def\kv@do########1{% + \xifinsetTF{,\detokenize{########1},}{,\cpt@rsvdb,}{}{% + \@tempswatrue\loopbreak + }% + }% + \kv@@parse*[,]\cpt@rsvda + }% + }% + \if@tempswa + \cpt@err{Option clash for package ####1.\@pkgextension}\@ehc + \expandafter\@gobble + \fi + }{% + \cptexpanded{% + \toks@{\the\toks@ + \ifcseqTF\documentclass\@twoclasseserror + {\noexpand\usepackage}{\noexpand\RequirePackage}% + [\expandcsonce\cpt@rsvda]{####1}[####3]% + }% + }% + }% + }% + \def\csv@do####1{% + \cpt@lo@dpackages####1##1##1##1##1\cpt@nil + }% + \cpt@useemptyfalse + \csv@@parse[##2]{#2}% + }% + \cpt@tempa#1\cpt@nil + \expandafter\endgroup\the\toks@ +} +% Eg, +% \cptrequirepackages{% +% pkga|options|date; pkgb|options|date; etc. +% } +\robust@def*\cptrequirepackages#1{% + \begintoksgroup + \let\RequirePackage\relax + \def\cpt@requirepackage##1|##2|##3|##4\@nil{% + \edef\cpt@tempa{\cpttrimspaces{##1}}% + \edef\cpt@tempb{\cpttrimspaces{##2}}% + \edef\cpt@tempc{\cpttrimspaces{##3}}% + \@ifpackageloaded{\cpt@tempa}{% + \xifstrcmpTF\cpt@tempc{^?^}{}{% + \@ifpackagelater\cpt@tempa\cpt@tempc{% + \cptexpandbracenext\cptstripallouterbraces\cpt@tempb\cpt@tempb + \cptexpandsecond\cptcheckoptionclash + {{\expandcsonce\cpt@tempa}{\expandcsonce\cpt@tempb}}% + }{% + \addto@hook\toks@{\@latex@error{Loaded version of + '\cpt@tempa' package is not current}\@ehc}% + }% + }% + }{% + \xifstrcmpTF\cpt@tempb{^?^}{% + \xifstrcmpTF\cpt@tempc{^?^}{% + \addto@hook\toks@{\RequirePackage{\cpt@tempa}}% + }{% + \addto@hook\toks@{\RequirePackage{\cpt@tempa}[\cpt@tempc]}% + }% + }{% + \xifstrcmpTF\cpt@tempc{^?^}{% + \addto@hook\toks@{\RequirePackage[\cpt@tempb]{\cpt@tempa}}% + }{% + \addto@hook\toks@ + {\RequirePackage[\cpt@tempb]{\cpt@tempa}[\cpt@tempc]}% + }% + }% + }% + }% + \def\csv@do##1{% + \cpt@requirepackage##1|^?^|^?^|\@nil + }% + \csv@@parse[;]{#1}% + \endtoksgroup +} +% #1=base, #2=modules to be load +\robust@def*\cptloadmodules#1#2{% + \begintoksgroup + \def\clash@list{}% + \def\do##1##2{% + \ifcpt@noval + \def\curr@optlist{}% + \else + \cptstripallouterbraces{##2}\curr@optlist + \fi + \@ifpackageloaded{##1}{% + % Check option clash: + \cptexpandarg{\cpt@ifoptions{sty}{##1}}{\expandcsonce\curr@optlist}{}{% + \ifx\curr@optlist\@empty + \cptuaddtolist\clash@list{##1}% + \else + \cptuaddtolist\clash@list{##1=##2}% + \fi + }% + }{% + \cptexpanded{\toks@{\the\toks@ + \noexpand\RequirePackage[\expandcsonce\curr@optlist]{% + \ifblankTF{#1}{}{#1-}##1% + }}% + }% + }% + }% + \kv@@process{#2}\do + \ifx\clash@list\@empty + \expandafter\endtoksgroup + \else + \cptexpanded{\endgroup + \cpt@err{Option clash for module(s): + \noexpand\unexpanded{\expandcsonce\clash@list}}}\@ehc + \fi +} +\robust@def*\AfterEndOfStyleFile{% + \begingroup + \def\cpt@tempa{\endgroup + \expandafter\grightaddtocs + \csname\@currname.\@currext-cpt@hook\endcsname + }% + \ifcsnullTF\@currname{% + \endgroup\@gobble + }{% + \cpt@tempa + }% +} +\robust@def*\ifinstylefileTF{\ifcsemptyTF\@currname\cptiiofii\cptiofii} +\robust@def*\cpt@pushhash{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \cpt@push@hash +} +\robust@def\cpt@push@hash#1#2{% + \xifinsetTF\cpt@hashchar{\detokenize{#1}}{% + \edef\x##1{##1\detokenize{#1}\cpt@hashchar\cpt@nil}% + \edef\y##1{\def##1####1\cpt@hashchar####2\cpt@nil}% + \y\y{% + \ifblankTF{##2}{% + \toks@\expandafter{\the\toks@##1}% + }{% + \cptpassexpanded + {\toks@{\the\toks@##1\cpt@hashchar\cpt@hashchar}}% + \y##2\cpt@nil + }% + }% + \x{\toks@{}\y}% + }{% + \toks@\expandafter{\detokenize{#1}}% + }% + \edef#2{\the\toks@}% + \postgroupdef#2\endgroup +} +\robust@def*\cpt@pophash{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \cpt@pop@hash +} +\robust@def\cpt@pop@hash#1#2{% + \xifinsetTF{\detokenize{##}}{\detokenize{#1}}{% + \edef\x##1{##1\detokenize{#1##}\cpt@nil}% + \edef\y##1{\def##1####1\detokenize{##}####2\cpt@nil}% + \y\y{% + \ifblankTF{##2}{% + \toks@\expandafter{\the\toks@##1}% + }{% + \cptexpanded{\toks@{\the\toks@##1\cpt@hashchar}}% + \y##2\cpt@nil + }% + }% + \x{\toks@{}\y}% + }{% + \toks@\expandafter{\detokenize{#1}}% + }% + \edef#2{\the\toks@}% + \postgroupdef#2\endgroup +} +% * -> #2 is a listcmd, else it is a list: +\robust@def*\csv@@normalize{\cpt@teststopt\cpt@csvnormalize,} +\robust@def\cpt@csvnormalize[#1]#2{% + \let\cpt@inkv\cptswfalse + \cpt@normalizelist{#1}{#2}% +} +\robust@def*\kv@@normalize{\cpt@teststopt\cpt@kvnormalize,} +\robust@def\cpt@kvnormalize[#1]#2{% + \let\cpt@inkv\cptswtrue + \cpt@normalizelist{#1}{#2}% +} +\ifcsdefinable\normalized@list\relax + +\begingroup +\catcode`\^=3 +\robust@gdef\cpt@normalizelist#1#2{% + \begingroup + \let\if@nmlzst\ifcpt@st + \cpt@stchoose{cpt@st}{#2}\reserved@e\cpt@normalizelist + \ifx\reserved@e\@empty + \def\normalized@list{}% + \cptbgobbletorelax + \fi + % It is absolutely necessary to check parser here, since this + % normalizer doesn't take multiple parsers at once: + \cpt@ch@cklistparser{#1}% + \expandafter\SetupParserNormalizer\string#1% + \toks@\expandafter{\expandafter#1\reserved@e#1}% + \nmlz@activeparser + \expandafter\nmlz@spaceletter\string#1% + \expandafter\nmlz@letterspace\string#1% + \expandafter\nmlz@doubleletter\string#1% + \ifswitchFT{cpt@inkv}{}{% + \nmlz@activeequal + \nmlz@spaceletter=% + \nmlz@letterspace=% + % We put '^?' at the end of #1 to preserve any trailing '='. + % This can happen if a key has an empty value. + \toks@\expandafter{\the\toks@^?}% + \nmlz@doubleletter=% + \cpt@commaequalerr + \def\reserved@a##1^?##2\nmlz@nil{\toks@{##1##2}}% + \expandafter\reserved@a\the\toks@\nmlz@nil + }% + \edef\normalized@list{\the\toks@}% + \cpttrimleadparsers#1\normalized@list + \cptexpanded{\endgroup + \ifdefboolTF{@nmlzst}{% + \edef\noexpand#2{\ox@unexpanded\normalized@list}% + }{% + \cpt@csexit\normalized@list + }% + }% + \cpt@relax +} +\endgroup + +\new@def*\SetupParserNormalizer#1{% + \begingroup + \uccode`\~=`#1% + \uppercase{\endgroup + \def\nmlz@activeparser{% + \def\cpt@tempa####1~####2\nmlz@nil{% + \ifblankTF{####2}{% + \toks@{####1}% + }{% + \cpt@tempa####1#1####2\nmlz@nil + }% + }% + \toks@\expandafter{\expandafter}\expandafter + \cpt@tempa\the\toks@~\nmlz@nil + }% + }% +} +\begingroup +\catcode`\==12 +\uccode`\~=`\=% +\uppercase{\endgroup + \def\nmlz@activeequal{% + \def\cpt@tempa##1~##2\nmlz@nil{% + \ifblankTF{##2} + {\toks@{##1}}{\cpt@tempa##1=##2\nmlz@nil}% + }% + \toks@\expandafter{\expandafter}\expandafter + \cpt@tempa\the\toks@~\nmlz@nil + }% +} +\def\nmlz@doubleletter#1{% + \def\cpt@tempa##1#1#1##2\nmlz@nil{% + \ifblankTF{##2} + {\toks@{##1}}{\cpt@tempa##1#1##2\nmlz@nil}% + }% + \expandafter\cpt@tempa\the\toks@#1#1\nmlz@nil +} +\defpass\cpt@tempa#1{% + \def\nmlz@spaceletter##1{% + \def\cpt@tempa####1#1##1####2\nmlz@nil{% + \ifblankTF{####2} + {\toks@{####1}}{\cpt@tempa####1##1####2\nmlz@nil}% + }% + \expandafter\cpt@tempa\the\toks@#1##1\nmlz@nil + }% + \def\nmlz@letterspace##1{% + \def\cpt@tempa####1##1#1####2\nmlz@nil{% + \ifblankTF{####2} + {\toks@{####1}}{\cpt@tempa####1##1####2\nmlz@nil}% + }% + \expandafter\cpt@tempa\the\toks@##1#1\nmlz@nil + }% +}{ } +\robust@def*\cpt@commaequalerr{% + \def\cpt@tempa##1,=##2\nmlz@nil{% + \ifblankTF{##2}{}{% + \cpt@err{There is 'comma' next to 'equal' (,=) in + \MsgBrk your key-value list}\@ehc + }% + }% + \expandafter\cpt@tempa\the\toks@,=\nmlz@nil +} +% Double parser normalizer. This is for normalizing lists +% like {x|| y|||| z}, where the parser is double bar ||: +\new@def*\SetupDoubleParserNormalizer#1{% + \begingroup + \uccode`\~=`#1% + \uppercase{\endgroup + \def\cptnormalizedoubleparser##1{% + \unexpanded\expandafter{\romannumeral-`\q + \nmlz@activedoubleparser#1#1##1#1#1~~\nmlz@nil}% + }% + \def\nmlz@activedoubleparser##1~~##2\nmlz@nil{% + \ifblankTF{##2} + {\nmlz@spacedoubleparser##1 #1#1\nmlz@nil} + {\nmlz@activedoubleparser##1#1#1##2\nmlz@nil}% + }% + }% + \def\nmlz@spacedoubleparser##1 #1#1##2\nmlz@nil{% + \ifblankTF{##2} + {\nmlz@doubleparserspace##1#1#1 \nmlz@nil} + {\nmlz@spacedoubleparser##1#1#1##2\nmlz@nil}% + }% + \def\nmlz@doubleparserspace##1#1#1 ##2\nmlz@nil{% + \ifblankTF{##2} + {\nmlz@fourparser##1#1#1#1#1\nmlz@nil} + {\nmlz@doubleparserspace##1#1#1##2\nmlz@nil}% + }% + \def\nmlz@fourparser##1#1#1#1#1##2\nmlz@nil{% + \ifblankTF{##2} + {\ifblankTF{##1}{}{\@gobbletwo##1}} + {\nmlz@fourparser##1#1#1##2\nmlz@nil}% + }% +} +% This is for normalizing lists like {x\\ y\\\\ z}, where \\ is +% a control sequence: +\robust@def*\SetupSpecialParserNormalizer#1{% + \def\cptspecialnormalize##1{% + \unexpanded\expandafter{\romannumeral-`\q + \spnmlz@spaceparser##1 #1\nmlz@nil}% + }% + \def\spnmlz@spaceparser##1 #1##2\nmlz@nil{% + \ifblankTF{##2} + {\spnmlz@parserspace##1#1 \nmlz@nil} + {\spnmlz@spaceparser##1#1##2\nmlz@nil}% + }% + \def\spnmlz@parserspace##1#1 ##2\nmlz@nil{% + \ifblankTF{##2} + {\spnmlz@doubleparser##1#1#1\nmlz@nil} + {\spnmlz@parserspace##1#1##2\nmlz@nil}% + }% + \def\spnmlz@doubleparser##1#1#1##2\nmlz@nil{% + \ifblankTF{##2}{##1} + {\spnmlz@doubleparser##1#1##2\nmlz@nil}% + }% +} +% See file 'commands-with-different-meaning-in-environment' for examples: +\robust@def*\AtBeginColony#1{\grightaddtocsn{atbegin@#1@colonyhook}} +\robust@def*\AtEndColony#1{\grightaddtocsn{atend@#1@colonyhook}} +\new@def*\colonyarg#1{\@nameuse{colony@arg@\romannumeral#1}} +\robust@def*\newcolony{\cpt@starorlong\new@colony} +\def\new@colony#1{\cpt@testopt{\newcolony@a#1}0} +\def\newcolony@a#1[#2]{% + \cpt@ifbrack{\newcolony@b{#1}{#2}}{\newcolony@c{#1}{[#2]}}% +} +\def\newcolony@b#1#2[#3]{\newcolony@c{#1}{[#2][{#3}]}} +\robust@def*\renewcolony{\cpt@starorlong\renew@colony} +\def\renew@colony#1{% + \ifcsndefTF{#1}{}{\cpt@err{Environment '#1' is undefined}\@ehc}% + \expandafter\let\csname#1\endcsname\relax + \expandafter\let\csname end#1\endcsname\relax + \new@colony{#1}% +} +\long\def\newcolony@c#1#2#3#4{% + \ifcsndefTF{#1}{}{\letcsntocsn{#1}{end#1}}% + \def\reserved@a[##1]##2\@nil{% + \chardef\@tempa\z@pt + \loop\ifnum\@tempa<##1\relax + \edef\@tempa{\the\numexpr\@tempa+1}% + \cptexpandarg{\rightaddtocs\@tempb}{% + \csn@edef{colony@arg@\romannumeral\@tempa}% + {\noexpand\unexpanded{################\number\@tempa}}% + }% + \repeat + }% + \reserved@a#2\@nil + \cptexpandbracenext{\aftercsname\new@command{#1}#2}{% + \@tempb + \@nameuse{atbegin@#1@colonyhook}% + \@nameuse{#1@env@defs}#3% + }% + \l@ngrel@x\csn@def{end#1}{% + #4\@nameuse{atend@#1@colonyhook}% + }% +} +% #1 = environment name; #2 = command +\robust@def*\newcolonycmd{\cpt@testst\new@colonycmd} +\robust@def\new@colonycmd#1#2{% + \aftercsname\rightaddtocs{#1@env@defs}{\colonyletcs{#1}{#2}}% + \cptexpanded{\noexpand\newcommand\ifcpt@st*\fi + \noexpandcsn{#1@\cptgobblescape#2}}% +} +\def\colonyletcs#1#2{\letcstocsn{#2}{#1@\cptgobblescape#2}} + +\robust@def*\cptcheckbool#1#2#3{% + \lowercase{% + \edef\cpt@resa{\s@expandarg\cpttrimspaces{\cptrm-`\q#1}}% + }% + \xifinsetTF{,\cpt@resa,}{,true,false,}{% + #3\relax + }{% + \@latex@error{Invalid value '#1' for '#2'}\@ehc + }% +} +\robust@def*\cptcheckswitch#1#2{% + \edef\cpt@resa{\s@expandarg\cpttrimspaces{\cptrm-`\q#1}}% + \xifinsetTF{,\cpt@resa,}{,00,01,}{% + #2\relax + }{% + \@latex@error{Invalid switch value '#1'}\@ehc + }% +} +\robust@def*\RecoverAtRequirePackage#1{% + \ifblankFT{#1}{}{% + \cpt@isblankerr\RecoverAtRequirePackage + }% + \begingroup + \cptfor#1\dofor{% + \ifescapedTF{##1}{% + \ifdefTF{##1}{}{% + % If the argument was undefined, then it couldn't be + % executed later: + \cpt@notdeferr{##1}% + \@gobble + }% + }{% + \cpt@notescapederr{##1}% + \@gobble + }% + \ifcsndefTF{cpt@atpush@\cptremovescape##1}{}{% + \gletcsntocs{cpt@atpush@\cptremovescape##1}##1% + \edef\cpt@tempa{% + \gletcs\unexpanded{##1}=% + \noexpandcsn{cpt@atpush@\cptremovescape##1}% + }% + \xifinsetTF{\cptoxdetok\cpt@tempa}{\cptoxdetok\@pushfilename}{}{% + \xdef\@pushfilename{% + \expandcsonce\cpt@tempa\expandcsonce\@pushfilename + }% + }% + }% + }% + \endgroup +} +\let\cpt@documentclass\cpt@undefined +\robust@def*\cpt@getdocumentclass{% + \def\csv@do##1{% + \filename@parse{##1}% + \ifx\filename@ext\@clsextension + \ifcsndefFT{opt@\filename@area\filename@base.% + \filename@ext}{}{% + \xdef\cpt@documentclass{% + \filename@area\filename@base.\filename@ext + }% + }% + \fi + \ifx\cpt@documentclass\cpt@undefined\else\loopbreak\fi + }% + \csv@@parse*\@filelist + \ifdefTF\cpt@documentclass{}{% + \ifcpt@verbose + \@latex@info@no@line{'catoptions' package loaded before + \string\documentclass: \MsgBrk no problem}% + \fi + }% +} +\cptpassunexpanded{% + \ifxTF\@filelist\relax{}{% + \ifxTF\@filelist\@gobble{}{% + \ifxTF\@filelist\@empty\relax\cpt@getdocumentclass + }% + }% + \ifxTF\cpt@documentclass\cpt@undefined{% + \let\cpt@classoptionslist\@empty + }{% + \ifxTF\@classoptionslist\relax{}{% + \ifxTF\@classoptionslist\@empty{}{% + \cpt@sttrue\cpt@kvnormalize[,]\@classoptionslist + }% + }% + \let\cpt@classoptionslist\@classoptionslist + \def\@fileswith@ptions##1[##2]##3{% + \edef\cpt@tempa{\cptcommanormalize{##3}}% + \cptfor xkeyval,kvoptions,ltxkeys\dofor{% + \xifinsetFT{,####1,}{,\cpt@tempa,}{}{% + \let\@classoptionslist\cpt@classoptionslist + \forbreaktrue + }% + }% + \cpt@ifbrack{\@fileswith@pti@ns##1[##2]##3}% + {\@fileswith@pti@ns##1[##2]##3[]}% + }% + \def\csv@do##1{% + \ifinsetTF{=}{##1}{}{% + \cptguaddtolist\@classoptionslist{##1}% + }% + }% + \expandafter\def\expandafter\@classoptionslist\expandafter + {\expandafter}\expandafter\csv@@loop\expandafter + {\@classoptionslist}% + }% +} +\robust@def*\cpt@testfam#1{% + \ifnextcharTF<{#1}{#1<\@currname.\@currext>}% +} +\robust@def*\cpt@badoptionerr#1{% + \expandafter\ifescapedTF\expandafter{#1}{% + \cpt@isescapederr{#1}% + }{% + \expandafter\ifmacroFT\expandafter{#1}{}{% + \cpt@err{Macro as option name '\expandcsonce{#1}'}\@ehc + }% + }% +} +\robust@def*\XDeclareOption{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@ifstar + {\cpt@testfam\cpt@define@default@ds}% + {\cpt@testfam\cpt@declareoption}% +} +\robust@def*\XDeclareDefaultCallback{\XDeclareOption*} +\robust@def*\cpt@declareoption<#1>#2{% + \trim@@space{#1}\cpt@currfam + \trim@@space{#2}\cpt@curropt + \cpt@badoptionerr\cpt@curropt + \cptexpandarg\cpt@testopt + {\cpt@d@clareoption{\cpt@currfam}{\cpt@curropt}}{}% +} +\robust@def\cpt@d@clareoption#1#2[#3]#4{% + \cpt@d@cl@reoption{#1}{#2}{#3}% + \ifdefboolTF{cpt@olddx}{% + % xcolor.sty uses a unique definition of callback: + \xifstrcmpTF{\@currname.\@currext}{xcolor.sty}{% + \csn@xdef{#1@ds@#2}{% + \unexpanded{\edef\XC@@opt{\XC@@opt#2,}#4}% + }% + }{% + \csn@xdef{#1@ds@#2}{\unexpanded{#4}}% + }% + }{% + \begingroup + \long\def\cpt@tempa##1{\endgroup + \csn@gdef{#1@ds@#2}####1{##1}% + }% + \cpt@tempa{#4}% + }% + \cpt@olddxfalse +} +\robust@def*\XDeclareOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@ifstar{% + \cpt@err{Command \noexpand\XDeclareOptions has no + star form}\@ehc + }{% + \cpt@testfam\cpt@declareoptions + }% +} +\robust@def*\cpt@declareoptions<#1>#2{% + \cpt@testopt{\cpt@d@clareoptions{#1}{#2}}{}% +} +\robust@def\cpt@d@clareoptions#1#2[#3]#4{% + \trim@@space{#1}\cpt@currfam + \def\csv@do##1{% + \cpt@badoptionerr{##1}% + \s@expandarg\cpt@d@clareoption\cpt@currfam{##1}[#3]{#4}% + }% + \csv@@parse[,]{#2}% +} + +\robust@def*\XInvalidOptionHandler{% + \cpt@testfam\cpt@invalidoptionhandler +} +\robust@def*\cpt@invalidoptionhandler<#1>#2{% + \def\cpt@currfams{#1}% + \def\csv@do##1{% + \ifcsndefTF{##1@invalidoptionerr}{% + \cpt@err{Invalid option handler already defined + \MsgBrk for family '##1'}{% + Second invalid option handler for family '##1'? + }% + }{% + % The error message will replace key macro, hence + % it needs a parameter: + \csn@gdef{##1@invalidoptionerr}####1{#2####1}% + }% + }% + \csv@@parse*[,]\cpt@currfams +} +\robust@def*\XDeclareInvalidOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@ifstar{% + \cpt@err{Invalid star suffix for command + \MsgBrk\string\XDeclareInvalidOption}\@ehc + }{% + \cpt@testfam\cpt@declarenulloptions + }% +} +\newletcs\XDeclareInvalidOption\XDeclareInvalidOptions +\robust@def*\cpt@declarenulloptions<#1>#2{% + \def\cpt@currfams{#1}% + \def\cpt@curropts{#2}% + \def\csv@do##1{\cpt@d@clarenulloptions{##1}}% + \csv@@parse*[,]\cpt@currfams + \cpt@olddxfalse +} +\robust@def*\cpt@d@clarenulloptions#1{% + \def\csv@do##1{% + \ifcsndefTF{#1@ds@##1}{% + \cpt@err{Option '##1' of family '#1' + \MsgBrk is already defined}\@ehc + }{% + \cpt@badoptionerr{##1}% + \cpt@d@cl@reoption{#1}{##1}{}% + \ifcsndefTF{#1@invalidoptionerr}{% + \gletcsntocsn{#1@ds@##1}{#1@invalidoptionerr}% + }{% + \begingroup + \def\cpt@temp@err{% + \cpt@err{Option '##1' of family '#1' + \MsgBrk is invalid or null}{% + Invalid option '##1' of family '#1'.}% + }% + \ifdefboolTF{cpt@olddx}{% + \csn@xdef{#1@ds@##1}{\cpt@temp@err}% + }{% + \csn@xdef{#1@ds@##1}####1{\cpt@temp@err}% + }% + \endgroup + }% + }% + }% + \csv@@parse*[,]\cpt@curropts +} +\robust@def*\XDeclareCommandOption{% + \let\@fileswith@pti@ns\@badrequireerror + \let\cmdoption\cptswtrue + \cpt@testfam\cpt@declarecmdoption +} +\robust@def*\XDeclareCommandOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \let\cmdoption\cptswtrue + \cpt@testfam\cpt@declarecmdoptions +} +\robust@def*\XDeclareBooleanOption{% + \let\@fileswith@pti@ns\@badrequireerror + \let\cmdoption\cptswfalse + \cpt@testfam\cpt@declarecmdoption +} +\robust@def*\XDeclareBooleanOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \let\cmdoption\cptswfalse + \cpt@testfam\cpt@declarecmdoptions +} +\robust@def*\cpt@declarecmdoption<#1>#2{% + \trim@@space{#1}\cpt@currfam + \trim@@space{#2}\cpt@curropt + \cpt@badoptionerr\cpt@curropt + \cptexpandarg\cpt@testopt + {\cpt@d@clarecmdoption{\cpt@currfam}{\cpt@curropt}}{}% +} +\robust@def\cpt@d@clarecmdoption#1#2[#3]{% + \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@recmdoption + {#1}{#2}{#3}}}{\if\cmdoption cmd\fi\@currname @}% +} +\robust@def\cpt@d@cl@recmdoption#1#2#3(#4)#5{% + \cpt@d@cl@reoption{#1}{#2}{#3}% + \if\cmdoption + \def\cpt@rsvda{\csn@def{#4#2}{####1}}% + \else + \csnnewif{#4#2}% + \def\cpt@rsvda{% + \cptcheckbool{####1}{option #2}{\usename{#4#2\cpt@resa}}% + }% + \fi + \long\def\cpt@rsvdb##1{% + \csn@gdef{#1@ds@#2}####1{##1\relax}% + }% + \expandafter\cpt@rsvdb\expandafter{\cpt@rsvda#5}% +} +\robust@def*\cpt@declarecmdoptions<#1>#2{% + \cpt@testopt{\cpt@d@clarecmdoptions{#1}{#2}}{}% +} +\robust@def\cpt@d@clarecmdoptions#1#2[#3]{% + \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@recmdoptions + {#1}{#2}{#3}}}{\if\cmdoption cmd\fi\@currname @}% +} +\robust@def\cpt@d@cl@recmdoptions#1#2#3(#4)#5{% + \trim@@spaces{#1}\cpt@currfam + \begintoksgroup + \toks1{{#3}(#4){#5}}% + \def\csv@do##1{% + \cpt@badoptionerr{##1}% + \cptexpanded{% + \toks@{\the\toks@\relax + \cpt@d@cl@recmdoption{\cpt@currfam}{##1}\the\toks1 + }% + }% + }% + \csv@@parse[,]{#2}% + \endtoksgroup +} +\robust@def*\XDeclareBiBooleanOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \let\cmdoption\cptswfalse + \cpt@testfam\cpt@declarebibooloptions +} +\cptnewlet\XDeclareBibooleanOptions\XDeclareBiBooleanOptions +\robust@def*\cpt@declarebibooloptions<#1>#2{% + \begingroup + \@tempcnta\z@pt + \def\csv@do##1{% + \advance\@tempcnta\@ne + }% + \csv@@loop[,]{#2}% + \ifnum\@tempcnta>\tw@ + \cpt@err{Biboolean options '#2' more than 2}\@ehc + \aftergroup\@gobble + \else + \ifnum\@tempcnta<\tw@ + \cpt@err{Biboolean options '#2' less than 2}\@ehc + \aftergroup\@gobble + \fi + \fi + \endgroup + \cpt@testopt{\cpt@d@clarebibooloptions{#1}{#2}}{}% +} +\robust@def\cpt@d@clarebibooloptions#1#2[#3]{% + \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@rebibooloptions + {#1}{#2}{#3}}}{\@currname @}% +} +\robust@def\cpt@d@cl@rebibooloptions#1#2#3(#4)#5#6{% + \edef\cpt@currfam{\cpttrimspaces{#1}}% + \def\cpt@curropts{#2}% + \cpt@sttrue\cpt@csvnormalize[,]\cpt@curropts + \def\cpt@tempa##1,##2\cpt@nil##3{% + \cpt@newv@riables{tog}{##3@}{##1,##2}[false]% + \def\cpt@tempa####1####2{% + \cpt@d@cl@rebib@oloptions{##1}{##2}{#3}{#4}{##3}{####1}% + \cpt@d@cl@rebib@oloptions{##2}{##1}{#3}{#4}{##3}{####2}% + }% + }% + \cptexpandsecond\cpt@tempa{\cpt@curropts\cpt@nil{\cpt@currfam}}% + \cpt@tempa{#5}{#6}% +} +% #1: primary option name +% #2: secondary option name +% #3: default value +% #4: macro prefix +% #5: current family +% #6: callback for primary option +\robust@def\cpt@d@cl@rebib@oloptions#1#2#3#4#5#6{% + \cpt@d@cl@recmdoption{#5}{#1}{#3}(#4){% + #6\relax + % If called by sister, don't call back: + \iftogTF{#5@#1}{}{% + \settogtrue{#5@#2}% + \settogtrue{biboolopts}% + \cptexpandarg{\XExecuteOptions<#5>}{#2=\thebool@reverse{#4#1}}% + \settogfalse{biboolopts}% + \settogfalse{#5@#2}% + }% + }% +} +\robust@def*\XDeclareSwitchOption{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@testfam\cpt@declareswoption +} +\robust@def*\XDeclareSwitchOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@testfam\cpt@declareswoptions +} +\robust@def*\cpt@declareswoption<#1>#2{% + \trim@@space{#1}\cpt@currfam + \trim@@space{#2}\cpt@curropt + \cpt@badoptionerr\cpt@curropt + \cptexpandarg\cpt@testopt + {\cpt@d@clareswoption{\cpt@currfam}{\cpt@curropt}}{}% +} +\robust@def*\cpt@d@clareswoption#1#2[#3]{% + \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@reswoption + {#1}{#2}{#3}}}{\@currname @}% +} +\robust@def*\cpt@d@cl@reswoption#1#2#3(#4)#5{% + \cpt@d@cl@reoption{#1}{#2}{#3}% + \def\cpt@rsvda{% + \cptcheckbool{####1}{#2}{% + \letcsntocsn{#4#2}{cptsw\cpt@resa}% + }% + }% + \long\def\cpt@rsvdb##1{% + \csn@gdef{#1@ds@#2}####1{##1\relax}% + }% + \expandafter\cpt@rsvdb\expandafter{\cpt@rsvda#5}% +} +\robust@def*\cpt@declareswoptions<#1>#2{% + \cpt@testopt{\cpt@d@clareswoptions{#1}{#2}}{}% +} +\robust@def\cpt@d@clareswoptions#1#2[#3]{% + \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@reswoptions + {#1}{#2}{#3}}}{\@currname @}% +} +\robust@def\cpt@d@cl@reswoptions#1#2#3(#4)#5{% + \trim@@spaces{#1}\cpt@currfam + \begingroup + \toks@{{#3}(#4){#5}}% + \toks1{}% + \def\csv@do##1{% + \cpt@badoptionerr{##1}% + \cptexpanded{% + \toks1{\the\toks1\relax + \cpt@d@cl@reswoption{\cpt@currfam}{##1}\the\toks@ + }% + }% + }% + \csv@@parse[,]{#2}% + \expandafter\endgroup\the\toks1 +} +\robust@def\cpt@d@cl@reoption#1#2#3{% + \ifcsndefTF{#1@declaredoptions}{% + \xifinsetTF{,\cptoxdetok{#2},}{,\cpt@getdeclaredoptions{#1},}{% + \cpt@warn{Option '#2' multiply defined\MsgBrk in + family '#1'\MsgBrk (in \@cls@pkg\@space'\@currname')% + }% + }{% + \aftercsname{\cptoaddtolist*}{#1@declaredoptions}{#2}% + }% + }{% + \csn@xdef{#1@declaredoptions}{\expandcsonce{#2}}% + }% + \csn@xdef{#1@ds@#2@default}{% + \noexpandcsn{#1@ds@#2}{\unexpanded{#3}}% + }% +} +\robust@def*\XDisableOptions{% + \cpt@testst{% + \let\ifcpt@swa\ifcpt@st + \cpt@testfam\cpt@disableoption + }% +} +\robust@def*\XDisableOptionsAtBeginDocument{\XDisableOptions*} +\robust@def*\cpt@disableoption<#1>#2{% + \def\cpt@currfams{#1}% + \def\cpt@curropts{#2}% + \def\csv@do##1{% + \cpt@dis@bleoption{##1}% + }% + \csv@@parse*[,]\cpt@currfams +} +\robust@def*\cpt@dis@bleoption#1{% + \def\csv@do##1{% + \ifcsndefFT{#1@ds@##1}{% + \cpt@info{Option '##1' of family '#1'\MsgBrk + is undeclared: not disabled} + }{% + \cptpassexpanded{% + \ifcpt@swa\noexpand\AtBeginDocument{\fi + \cptfiltermergekv[,]% + \noexpandcsn{#1@disabledoptions}{##1}% + \noexpand\nofilter + \noexpand\undefcsn{#1@ds@##1@default}% + \csn@gdef{#1@ds@##1}{% + \noexpand\@latex@error{% + Key '##1' of families '#1' is disabled + }{% + Key '##1' of family '#1'\MsgBrk + has been disabled. You can't set or reset\MsgBrk + it at this late stage. Perhaps you should\MsgBrk + have set it earlier in \string\documentclass\MsgBrk + or \string\usepackage + }% + }% + \ifcpt@swa}\fi + }% + }% + }% + \csv@@parse*[,]\cpt@curropts +} +\robust@def*\XLogDisabledOptions{% + \ifnextcharTF<\cpt@disabledoptionlist + \cpt@dis@bledoptionlist +} +\robust@def*\cpt@disabledoptionlist<#1>{% + \cpt@dis@bledoptionlist{#1}% +} +\robust@def*\cpt@dis@bledoptionlist#1{% + \def\cpt@disable@a##1{% + \ifcsndefTF{##1@disabledoptions}{% + \cpt@info{Disabled options of family '##1': + ^^J\expandcsnonce{##1@disabledoptions}}% + }{% + \cpt@info{No disabled options in family '##1' + \MsgBrk at this point\ifcsnullTF\@currname{} + {:\@space You can try the command + \MsgBrk\noexpand\XLogDisabledOptions again, after + \MsgBrk begin document}}% + }% + }% + \def\cpt@disable@b##1##2{% + \cpt@err{Command \noexpand\XLogDisabledOptions issued + \MsgBrk in document but family name contains + \MsgBrk ##1 extension \string##2, + \MsgBrk a preamble command}\@ehc + }% + \def\csv@do##1{% + \ifcsnullFT\@currname{% + \cpt@disable@a{##1}% + }{% + \ifinsetTF\@pkgextension{##1}{% + \cpt@disable@b{package}\@pkgextension + }{% + \ifinsetTF\@clsextension{##1}{% + \cpt@disable@b{class}\@clsextension + }{% + \cpt@disable@a{##1}% + }% + }% + }% + }% + \ifblankTF{#1}{}{\csv@@parse{#1}}% + \undefcs\cpt@disable@a\undefcs\cpt@disable@b +} +\robust@def*\ifoptdisabledTF{% + \cpt@swatrue\cpt@testfam\cpt@ifoptdisabled +} +\robust@def*\ifoptdisabledFT{% + \cpt@swafalse\cpt@testfam\cpt@ifoptdisabled +} +\robust@def*\cpt@ifoptdisabled<#1>#2{% + \def\cpt@currfams{#1}% + \cpt@choicefdfalse + \def\csv@do##1{% + \cpt@ifoptdis@bled{##1}{#2}% + }% + \csv@@parse*[,]\cpt@currfams + \ifdefboolTF{cpt@swa}\ifdefboolTF\ifdefboolFT{cpt@choicefd}% +} +\robust@def*\cpt@ifoptdis@bled#1#2{% + \ifcsndefFT{#1@disabledoptions}{}{% + \xifinsetFT{,#2,}{,\expandcsnonce{#1@disabledoptions},}{}{% + \loopbreak\cpt@choicefdtrue + }% + }% +} +\robust@def*\ifoptdefTF{% + \cpt@swatrue\cpt@testfam\cpt@ifoptdef +} +\robust@def*\ifoptdefFT{% + \cpt@swafalse\cpt@testfam\cpt@ifoptdef +} +\robust@def*\cpt@ifoptdef<#1>#2{% + \def\cpt@currfams{#1}% + \cpt@choicefdfalse + % may break out of loop: + \def\csv@do##1{% + \cpt@ifoptd@f{##1}{#2}% + }% + \csv@@parse*[,]\cpt@currfams + \ifdefboolTF{cpt@swa}\ifdefboolTF\ifdefboolFT{cpt@choicefd}% +} +\robust@def*\cpt@ifoptd@f#1#2{% + \ifcsndefFT{#1@ds@#2}{}{% + \cpt@choicefdtrue\loopbreak + }% +} +\new@def*\cpt@getdeclaredoptions#1{% + \ifcsndefFT{#1@declaredoptions}{}{% + \ifcsnnullTF{#1@declaredoptions}{}{% + \detokenize\cptsevenxp{\usename{#1@declaredoptions}}% + }% + }% +} +\robust@def*\XUnknownOptionHandler{% + \cpt@testfam\cpt@unknownoptionhandler +} +\robust@def*\cpt@unknownoptionhandler<#1>{% + \cpt@testopt{\cpt@unkn@wnoptionhandler#1}{}% +} +\robust@def*\cpt@unkn@wnoptionhandler#1[#2]#3{% + \def\cpt@currfams{#1}% + \edef\reserved@e##1{% + \csn@def{##1@default@ds}####1####2####3{\unexpanded{#3}}% + }% + \def\csv@do##1{% + \ifcsndefFT{##1@default@ds}{}{% + \ifcpt@verbose + \cpt@warn{Unknown option handler for family + \MsgBrk '##1' replaced}% + \fi + }% + \reserved@e{##1}% + \csn@def{##1@default@na}{#2}% + }% + \csv@@parse*[,]\cpt@currfams +} +\robust@def*\cpt@define@default@ds<#1>#2{% + \csn@def{#1@default@ds}##1##2##3{#2}% + \AtEndOfPackage{% + \let\cpt@define@default@ds\rsv@cpt@define@default@ds + }% + \protected\def\cpt@define@default@ds<##1>##2{% + \cpt@err{'\string\XDeclareOption*' multiply defined in + \MsgBrk\@cls@pkg\space'\@currname'}{Multiple star + variant of \noexpand\XDeclareOption in + \@cls@pkg\@space'\@currname'.}% + }% +} +\newletcs\rsv@cpt@define@default@ds\cpt@define@default@ds +% In case a \RequirePackage comes up before end of package: +\RecoverAtRequirePackage\cpt@define@default@ds + +\new@def*\cpt@optionlist#1{% + \ifcsndefFT{opt@#1}{}{\unexpanded\cptsevenxp{\usename{opt@#1}}}% +} +% Use \kv@@parse and \csv@@parse for all options processing +% because there might be the need to break out of the loop +% prematurely. +\newletcs\cpt@processedoptions\@empty + +\robust@def*\XProcessOptions{% + \csn@def{\@currname @\@currext @beginprocessopt}{}% + \letcstocsn\reserved@a{\@currname @\@currext @beforeprocessopt}% + \letcsntocs{\@currname @\@currext @beforeprocessopt}\relax + \ifdefTF\reserved@a\reserved@a\relax + \cpt@inpoxtrue + \let\@fileswith@pti@ns\@badrequireerror + \edef\cpt@testname{\@currname.\@currext}% + \ifx\cpt@testname\cpt@documentclass + \let\@unusedoptionlist\cpt@classoptionslist + \fi + \edef\cpt@classoptions{% + \ifx\cpt@testname\cpt@documentclass\else + \expandcsonce\cpt@classoptionslist\fi + }% + \edef\@curroptions{\cpt@optionlist{\@currname.\@currext}}% + \ifcsnullTF\@curroptions{} + {\cpt@sttrue\cpt@kvnormalize[,]\@curroptions}% + \cpt@testst{\cpt@testfam\cpt@processoptions}% +} +\robust@def*\cpt@processoptions<#1>{% + \ifdefboolTF{cpt@st}{% + \cpt@testopt{\cpt@xprocessoptions#1}{}% + }{% + \cpt@testopt{\cpt@yprocessoptions#1}{}% + }% +} +\robust@def*\cpt@yprocessoptions#1[#2]{% + \ifblankTF{#2}{% + \def\cpt@currna{}% + }{% + \edef\cpt@currna{\cptcommanormalize{#2}}% + }% + \def\csv@do##1{% + \cpt@ypr@cessoptions{##1}% + }% + \csv@@parse{#1}% + \cpt@pr@cessoptions{#1}% + \cpt@pr@cessopti@ns +} +\robust@def*\cpt@ypr@cessoptions#1{% + \def\cpt@currfam{#1}% + \def\kv@do##1{% + \edef\CurrentOption{\unexpanded{##1}}% + \ifcsnullTF\CurrentOption{}{% + \cpt@findoption@a + \ifdefboolFT{cpt@optfd}{}{% + \ifcsndefFT{#1@ds@\cpt@curropt}{}{% + \ifcsnullTF\cpt@currna{% + \cpt@igoptfalse + }{% + \oifinset@sp@TF,\cpt@curropt\cpt@currna{% + \cpt@igopttrue + }{% + \cpt@igoptfalse + }% + }% + \cpt@useoption + }% + }% + }% + }% + \ifxTF\cpt@classoptions\@empty{}{% + \ifcsndefFT{#1@declaredoptions}{}{% + \ifcsnnullTF{#1@declaredoptions}{}{% + \aftercsname{\kv@@parse*}{#1@declaredoptions}% + }% + }% + }% +} +\robust@def*\cpt@xprocessoptions#1[#2]{% + \ifblankTF{#2}{% + \def\cpt@currna{}% + }{% + \edef\cpt@currna{\cptcommanormalize{#2}}% + }% + \def\csv@do##1{% + \cpt@xpr@cessoptions{##1}% + }% + \csv@@parse{#1}% + \cpt@pr@cessoptions{#1}% + \cpt@pr@cessopti@ns +} +\robust@def*\cpt@xpr@cessoptions#1{% + \def\cpt@currfam{#1}% + \edef\DeclaredOptions{\cpt@getdeclaredoptions\cpt@currfam}% + \def\kv@do##1{% + \edef\CurrentOption{\unexpanded{##1}}% + \ifcsnullTF\CurrentOption{}{% + \cpt@findoption@b + \oifinset@sp@FT,\cpt@curropt\DeclaredOptions{}{% + \ifcsndefFT{#1@ds@\cpt@curropt}{}{% + \ifcsnullTF\cpt@currna{% + \cpt@igoptfalse + }{% + \oifinset@sp@TF,\cpt@curropt\cpt@currna{% + \cpt@igopttrue + }{% + \cpt@igoptfalse + }% + }% + \cpt@useoption + }% + }% + }% + }% + \ifcsnullTF\cpt@classoptions{} + {\kv@@parse*[,]\cpt@classoptions}% +} +\robust@def*\cpt@pr@cessoptions#1{% + \def\kv@do##1{% + \edef\CurrentOption{\unexpanded{##1}}% + \ifcsnullTF\CurrentOption{}{% + \cpt@findoption@b + \def\csv@do####1{% + \def\cpt@currfam{####1}% + \ifcsndefTF{\cpt@currfam @ds@\cpt@curropt}{% + \ifcsnullTF\cpt@currna{% + \cpt@igoptfalse + }{% + \oifinset@sp@TF,\cpt@curropt\cpt@currna{% + \cpt@igopttrue + }{% + \cpt@igoptfalse + }% + }% + \cpt@useoption + }{% + \oifinset@sp@TF,\cpt@curropt\XExternalOptions{% + \ifindefaultdsTF{\PassOptionsToClass}{% + \cpt@use@default@ds + }{% + \ifindefaultdsFT{\PassOptionsToPackage}{}{% + \cpt@use@default@ds + }% + }% + }{% + \cpt@addto@undef@opts + \cpt@use@default@ds + }% + }% + }% + \csv@@loop[,]{#1}% + }% + }% + \ifcsnullTF\@curroptions{}{\kv@@parse*[,]\@curroptions}% +} +\robust@def*\cpt@pr@cessopti@ns{% + \let\CurrentOption\@empty + \undefcs\cpt@classoptions + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \cpt@olddxfalse + \AtEndOfPackage{\let\@unprocessedoptions\relax}% + \letcstocsn\reserved@a{\@currname @\@currext @afterprocessopt}% + \letcsntocs{\@currname @\@currext @afterprocessopt}\relax + \ifdefTF\reserved@a\reserved@a\relax + \csn@def{\@currname @\@currext @endprocessopt}{}% +} +\robust@def*\ifindefaultdsTF{% + \begingroup + \def\reserved@e{\cptiofii\cptiiofii}% + \cpt@ifin@default@ds +} +\robust@def*\ifindefaultdsFT{% + \begingroup + \def\reserved@e{\cptiiofii\cptiofii}% + \cpt@ifin@default@ds +} +\robust@def*\cpt@ifin@default@ds#1{% + \let\xp\expandcsonce + \edef\cpt@ds@a{% + {\xp\cpt@currfam}{\xp\cpt@curropt}{\xp\cpt@currval}% + }% + \edef\cpt@ds@b{\cptmakecs{\cpt@currfam @default@ds}}% + \edef\cpt@ds@c{% + \unexpanded\cptsevenxp{\expandafter\cpt@ds@b\cpt@ds@a}% + }% + \cptexpanded{% + \endgroup + \cpt@csexit\cpt@ds@a\cpt@csexit\cpt@ds@b\cpt@csexit\cpt@ds@c + \ifinsetTF{\detokenize{#1}}{\cptoxdetok\cpt@ds@c}% + \xp\reserved@e + }% +} +\robust@def*\cpt@use@default@ds{% + \begingroup + \let\xp\expandcsonce + \ifcsndefTF{\cpt@currfam @default@na}{}{% + \csn@def{\cpt@currfam @default@na}{}% + }% + \toks@{\default@ds}% + \ifcsndefFT{\cpt@currfam @default@ds}{}{% + \edef\cpt@tempa{\expandcsnonce{\cpt@currfam @default@na}}% + \oifinset@sp@TF,\cpt@curropt\cpt@tempa{}{% + \ifindefaultdsFT{define/.code=}{% + \toks@\expandafter{\cpt@ds@c}% + }{% + \ifindefaultdsFT{/.end}{% + \cpt@err{I can't find '/.end' in^^J'\cptoxdetok\cpt@ds@c}\@ehc + }{% + \cptexpandmacro\cpt@currval\curr@val + \despacecontent\curr@val + \def\cpt@tempb{\XDeclareBooleanOption}% + \let\cmd\@empty + \oifstrcmpTF{true}\curr@val{}{% + \oifstrcmpTF{false}\curr@val{}{% + \def\cpt@tempb{\XDeclareCommandOption}% + \def\cmd{cmd}% + }% + }% + \def\cpt@tempa##1define/.code=##2/.end##3\cpt@nil{% + \cptexpanded{\toks@{% + \unexpanded{##1##3}% + \cpt@tempb<\cpt@currfam>{\cpt@curropt}[\xp\curr@val]% + (\cmd\@currname @){\unexpanded{##2}}% + \XExecuteOptions<\cpt@currfam>{\cpt@curropt=\xp\curr@val}% + }}% + }% + \expandafter\cpt@tempa\cpt@ds@c\cpt@nil + }% + }% + }% + }% + \expandafter\endgroup\the\toks@ +} +\robust@def*\XExecuteOptions{% + \cpt@inpoxfalse + \cpt@testfam\cpt@executeoptions +} +\robust@def*\cpt@executeoptions<#1>#2{% + \cpt@testopt{\cpt@ex@cuteoptions{#1}{#2}}{}% +} +\robust@def*\cpt@ex@cuteoptions#1#2[#3]{% + \def\cpt@currna{#3}% + \ifcsnullTF\cpt@currna{}{% + \cpt@sttrue\cpt@csvnormalize[,]\cpt@currna + }% + \edef\cpt@curroptvals{\unexpanded{#2}}% + \ifcsnullTF\cpt@curroptvals{}{% + \cpt@sttrue\cpt@kvnormalize[,]\cpt@curroptvals + }% + \def\csv@do##1{% + \cpt@ex@cuteopti@ns{##1}% + }% + \csv@@parse[,]{#1}% + \cpt@olddxfalse + \undefcs\ExecutedOptions + \undefcs\cpt@execwarnlist +} +\robust@def*\cpt@ex@cuteopti@ns#1{% + \def\cpt@currfam{#1}% + \ifnum\cpt@optdepth=\z@pt + \csn@def{\cpt@currfam @executedoptions}{}% + \csn@def{\cpt@currfam @exec@warnlist}{}% + \fi + \edef\DeclaredOptions{\cpt@getdeclaredoptions\cpt@currfam}% + \def\kv@do##1{% + \edef\CurrentOption{\unexpanded{##1}}% + \ifcsnullTF\CurrentOption{}{% + \cpt@findoption@b + \edef\ExecutedOptions{% + \expandcsnonce{\cpt@currfam @executedoptions}% + }% + \edef\cpt@execwarnlist{% + \expandcsnonce{\cpt@currfam @exec@warnlist}% + }% + \oifinset@sp@TF,\cpt@curropt\cpt@currna{}{% + \cpt@igoptfalse + \oifinset@sp@TF,\cpt@curropt\DeclaredOptions{% + \oifinset@sp@TF,\cpt@curropt\ExecutedOptions{% + \oifinset@sp@TF,\cpt@curropt\cpt@execwarnlist{}{% + \iftogTF{biboolopts}{}{% + \ifcpt@verbose + \cpt@info{Option '\cpt@curropt' of family + '\cpt@currfam'\MsgBrk multiply submitted to + \string\XExecuteOptions:\MsgBrk re-executed}% + \fi + }% + \aftercsname{\cptgoaddtolist} + {\cpt@currfam @exec@warnlist}\cpt@curropt + }% + }{% + \aftercsname{\cptgoaddtolist} + {\cpt@currfam @executedoptions}\cpt@curropt + }% + \cpt@useoption + }{% + \cpt@addto@undecl@opts + }% + }% + }% + }% + \kv@@loop*[,]\cpt@curroptvals +} +% Alias keys must always come from the parent's family: +\robust@def*\XExecuteAliasOption#1{% + \cpt@testopt{\cpt@executealiasoption#1}{}% +} +\robust@def*\cpt@executealiasoption#1[#2]{% + \edef\reserved@a{\ifblankTF{#2} + {\expandcsonce\cpt@currval}{\unexpanded{#2}}}% + \cpt@inpoxfalse + \cptexpandsecond\cpt@executeoptions + {<\cpt@currfam>{#1=\expandcsonce\reserved@a}}\relax +} +% \OptionFound is always the option with its current value, +% while \CurrentOption may have no value (as in +% \cpt@ypr@cessoptions, the only function calling +% \cpt@findoption@a): +\robust@def\cpt@findoption@a{% + \cpt@optfdfalse + \def\kv@do##1{% + \ifblankTF{##1}{}{% + \xifinsetTF{=}{\detokenize{##1}}{% + \cpt@splitoption##1=\opt@split@nil + }{% + \edef\cpt@curropt{\unexpanded{##1}}% + \let\cpt@currval\@empty + }% + \ifx\cpt@curropt\CurrentOption + \cpt@optfdtrue\loopbreak + \edef\OptionFound{\unexpanded{##1}}% + \else + \let\cpt@curropt\@empty + \let\OptionFound\@empty + \fi + }% + }% + % This loop may break prematurely: + \kv@@loop*[,]\cpt@classoptions +} +\robust@def\cpt@findoption@b{% + % Here \CurrentOption may have a value: + \let\OptionFound\CurrentOption + \xifinsetTF{=}{\cptoxdetok\CurrentOption}{% + \expandafter\cpt@splitoption\CurrentOption=\opt@split@nil + \let\CurrentOption\cpt@curropt + }{% + \let\cpt@curropt\CurrentOption + \let\cpt@currval\@empty + }% +} +\robust@def\cpt@splitoption#1=#2\opt@split@nil{% + \def\cpt@curropt{#1}% + \ifinsetTF{=\opt@split@nil}{#2\opt@split@nil}{% + \begingroup + \defpass\cpt@tempa##1=##2\opt@split@nil{\endgroup + \edef\cpt@currval{\unexpanded\expandafter{\@gobble##1}}% + }% + .#2\opt@split@nil + }{% + \edef\cpt@currval{\unexpanded{#2}}% + }% +} +\robust@def*\cpt@useoption{% + \ifdefboolFT{cpt@inpox}{}{% + \oifinset@sp@TF,\OptionFound\cpt@processedoptions{}{% + \cptgoaddtolist\cpt@processedoptions\OptionFound + }% + \oifinset@sp@TF,\CurrentOption\cpt@processedoptions{}{% + \cptgoaddtolist\cpt@processedoptions\CurrentOption + }% + \ifcsnullTF\OptionFound{}{\cpt@removecurroption\OptionFound}% + \ifcseqTF\OptionFound\CurrentOption{}{% + \cpt@removecurroption\CurrentOption + }% + }% + \ifdefboolTF{cpt@igopt}{}{% + % Don't attempt to catch undefined options here: + \ifcsndefFT{\cpt@currfam @ds@\cpt@curropt}{}{% + \ifdefboolTF{cpt@olddx}{% + \usename{\cpt@currfam @ds@\cpt@curropt}% + }{% + \ifcsnullTF\cpt@currval{% + \cptthreexp\cpt@usedefault + \csname\cpt@currfam @ds@\cpt@curropt + @default\endcsname\cpt@nil + }{% + \cpt@useoption@a + }% + }% + }% + }% +} +\robust@def*\cpt@useoption@a{% + \cpt@pushstate\XExecuteOptions\cpt@optionstate\cpt@optdepth + \cptexpandargonce{\usename{\cpt@currfam @ds@\cpt@curropt}}% + \cpt@currval\relax + \cpt@popstate\XExecuteOptions\cpt@optdepth +} +% Only 'article', 'report', 'memoir' options have been added +% to \XExternalOptions. Other external options (eg, those of +% script and KOMA-Script classes) haven't been added. +\new@def*\XExternalOptions{% + 10pt,11pt,12pt,14pt,17pt,20pt,25pt,30pt,36pt,48pt,60pt,% + a0paper,a1paper,a2paper,a3paper,a4paper,a6paper,% + b0paper,b1paper,b2paper,b3paper,b4paper,b5paper,b6paper,% + letterpaper,legalpaper,executivepaper,landscape,oneside,% + twoside,draft,final,titlepage,notitlepage,onecolumn,% + twocolumn,leqno,fleqn,openbib,openright,openleft,openany,% + article,ms,showtrims,oldfontcommands,extrafontsizes,noetex% +} +\robust@def*\AddToExternalOptions#1{% + \cptfiltermergecsv[,]\XExternalOptions{#1}\nofilter +} +\robust@def*\RemoveFromExternalOptions#1{% + \cptfilterremovecsv[,]\XExternalOptions{#1}\nofilter +} +\robust@def*\cpt@addto@undecl@opts{% + \edef\everymergeitem##1{\@space##1}% + \cptexpandarg{\cptfiltermergekv[;]\cpt@undeclaredopts}% + {\cpt@currfam,\cpt@curropt,\expandcsonce\cpt@currval}\nofilter +} +\robust@def*\cpt@addto@undef@opts{% + \edef\everymergeitem##1{\@space##1}% + \oifinset@sp@TF,\cpt@curropt\XExternalOptions{}{% + \cptexpandarg{\cptfiltermergekv[;]\cpt@undefinedopts}% + {\cpt@currfam,\cpt@curropt,\expandcsonce\cpt@currval}\nofilter + }% +} +\AfterStartOfDocument{\AtEndDocument{% + % \cpt@undeclaredopts from \XExecuteOptions: + \ifdefFT\cpt@undeclaredopts{}{% + \ifcsnullTF\cpt@undeclaredopts{}{% + \despacecontent\cpt@undeclaredopts + \cpt@warn{% + Undeclared options found in \string\XExecuteOptions + \MsgBrk (family,option,value): + ^^J\expandcsonce\cpt@undeclaredopts + }% + }% + }% + % \cpt@undefinedopts from \XProcessOptions: + \ifdefFT\cpt@undefinedopts{}{% + \ifcsnullTF\cpt@undefinedopts{}{% + \despacecontent\cpt@undefinedopts + \cpt@warn{% + Undefined options + \MsgBrk[Family, Option, Value]: + \MsgBrk\expandcsonce\cpt@undefinedopts. + \MsgBrk Default action already taken in each case + }% + }% + }% +}} +\robust@def*\cpt@usedefault#1#2\cpt@nil{% + \ifmacroTF{#1}{% + \edef\cpt@tempa{\cptremovescape#1}% + }{% + \cpt@notcserr{#1}% + }% + \edef\cpt@tempb{\cpt@currfam @ds@\cpt@curropt}% + \@onelevel@sanitize\cpt@tempb + \ifcseqTF\cpt@tempa\cpt@tempb{% + \begingroup + \csn@def{\cpt@currfam @ds@\cpt@curropt}##1{% + \toks@{\def\cpt@currval{##1}}% + }% + \usename{\cpt@currfam @ds@\cpt@curropt @default}% + \expandafter\endgroup\the\toks@ + \cpt@useoption@a + }{% + \cpt@warn{Non-standard default function for option + '\expandcsonce\cpt@curropt':\MsgBrk Executed anyway}% + \cpt@pushstate\XExecuteOptions\cpt@optionstate\cpt@optdepth + \usename{\cpt@currfam @ds@\cpt@curropt @default}\relax + \cpt@popstate\XExecuteOptions\cpt@optdepth + }% +} +\robust@def*\cpt@optionstate{% + \\\cpt@currfams\\\cpt@curroptvals\\\cpt@currfam\\\cpt@currna + \\\cpt@curropt\\\cpt@currval\\\CurrentOption\\\OptionFound + \\\ifcpt@inpox\\\ifcpt@optfd\\\ifcpt@igopt\\\DeclaredOptions + \\\ExecutedOptions +} +\robust@def*\cpt@removecurroption#1{% + \cptexpandargonce{\cptfilterremovekv[,]% + \@unusedoptionlist}{#1}\nofilter +} +% Remove processed options from \@unusedoptionlist: +\robust@def*\cpt@optioncleanup#1{% + \ifmacroTF{#1}{}{\cpt@notcserr{#1}}% + \BeforeStartOfDocument{% + \ifdefFT#1{}{% + \ifcsnullTF#1{}{% + \ifcsnullTF\@unusedoptionlist{}{% + \def\csv@do##1{% + \xifinsetTF{,\detokenize{##1},}% + {,\cptoxdetok\@unusedoptionlist,}{% + \cpt@removecurroption{##1}% + }% + }% + \csv@@parse*[,]#1% + }% + }% + }% + \globalize\@unusedoptionlist + \def#1{}% + }% +} +\BeforeStartOfDocument{% + \cpt@optioncleanup\cpt@processedoptions +} +\robust@redef*\@fileswith@pti@ns#1[#2]#3[#4]{% + \begingroup + \edef\fileopts{\unexpanded{#2}}% + \ifcsnullTF\fileopts{}{\cpt@sttrue\cpt@kvnormalize[,]\fileopts}% + \def\fileswithopts##1##2{% + \noexpand\@onefilewithoptions{##1}% + [\expandcsonce\fileopts]\unexpanded{[#4]##2}% + }% + \def\file@withopts##1{\cptpassexpanded{\toks@{##1}}}% + \toks@{}% + \ifcseqTF#1\@clsextension{% + \ifx\@classoptionslist\relax + \xdef\@classoptionslist{\expandcsonce\fileopts}% + \file@withopts{\fileswithopts{#3}{#1\@documentclasshook}}% + \else + \file@withopts{\fileswithopts{#3}{#1}}% + \fi + }{% + \edef\cpt@tempa{\cptzapspaces{#3}}% + \DiscardEmptyEntry + \def\csv@do##1{% + \file@withopts{\the\toks@\fileswithopts{##1}\@pkgextension}% + }% + \csv@@loop*\cpt@tempa + }% + \expandafter\endgroup\the\toks@ +} +\robust@redef*\@onefilewithoptions#1[#2][#3]#4{% + \@pushfilename + \xdef\@currname{#1}% + \global\let\@currext#4% + \letcsntocs{\@currname.\@currext-h@@k}\@empty + \let\CurrentOption\@empty + \@reset@ptions + \makeatletter + \defpass\reserved@a{% + \@ifl@aded\@currext{#1}{% + \cpt@ifoptions\@currext{#1}{#2}{}{% + \edef\reserved@e{\cpt@optionlist{#1.\@currext}}% + \@onelevel@sanitize\reserved@e + \despacecontent\reserved@e + \ltxmsg@err{Option clash for \@cls@pkg\@space #1}{% + The package '#1' has already been loaded + with \ifx\reserved@e\@empty no options.\MsgBrk\else + options:\MsgBrk\@space\@space[\reserved@e].\fi\MsgBrk + There has now been an attempt to load it with + \iflacus#2\dolacus no options\else options + \MsgBrk\@space\@space[\unexpanded{#2}]\fi. + \MsgBrk Adding the global options:\MsgBrk + \@space\@space'\ifx\reserved@e\@empty\else + \reserved@e\ifblankTF{#2}{}{,}\fi\unexpanded{#2}'\MsgBrk + to your \noexpand\documentclass declaration may fix this. + }% + }% + }{% + \@pass@ptions\@currext{#2}{#1}% + \gletcsntocs{ver@\@currname.\@currext}\@empty + \InputIfFileExists{\@currname.\@currext}{}{% + \@missingfileerror\@currname\@currext + }% + \let\@unprocessedoptions\@@unprocessedoptions + \usename{\@currname.\@currext-h@@k}% + \undefcsn{\@currname.\@currext-h@@k}% + \@unprocessedoptions + }% + \def\cpt@tempa####1 v####2 ####3\@nil####4{% + \edef####4{'####1\ifblankTF{####2}{}{ v####2}'}% + }% + \cpt@tempa#3 v \@nil\cpt@tempb + \cptthreexp\cpt@tempa\csname ver@#1.\@currext + \expandafter\endcsname\@space v \@nil\cpt@tempc + \@ifl@ter\@currext{#1}{#3}{}{% + \cptexpandarg\AtEndDocument{% + \ltxmsg@warn{% + You requested,\on@line, version\MsgBrk + \cpt@tempb\@space of \@cls@pkg\@space #1,\MsgBrk + but only version \cpt@tempc\MsgBrk is available + }% + }% + }% + \ifx\@currext + \@clsextension\let\LoadClass\@twoloadclasserror + \fi + \@popfilename + \@reset@ptions + }% +} +\robust@def*\cpt@removevalues#1{% + \cptdocommalist{#1}{\cpt@rem@vevalues{##1}}% +} +\robust@def*\cpt@rem@vevalues#1{% + \ifcseqTF#1\@empty\cptgobbletorelax\relax + \xifinsetTF{=}{\cptoxdetok{#1}}{}\cptgobbletorelax + \begingroup + \def\cpt@resa{}% + \def\cpt@resb##1=##2\cpt@nil{% + \edef\cpt@resa{\csliststack,\cpt@resa\unexpanded{##1}}% + }% + \def\kv@do##1{\cpt@resb##1=\cpt@nil}% + \kv@@parse*{#1}% + \let#1\cpt@resa + \postgroupdef#1\endgroup + \cpt@relax +} +\robust@redef*\ExecuteOptions#1{% + \cptpushfunctions\ExecuteOptions{\\\CurrentOption}\cpt@optdepth + \edef\CurrentOption{\unexpanded{#1}}% + \cpt@sttrue\cpt@kvnormalize[,]\CurrentOption + \cpt@removevalues\CurrentOption + \def\csv@do##1{% + \def\CurrentOption{##1}% + \csname ds@##1\endcsname + }% + \csv@@parse*\CurrentOption + \cptpopfunctions\ExecuteOptions\cpt@optdepth +} +\robust@redef\@pass@ptions#1#2#3{% + \begingroup + \ifntypeTF{#2}{% + \ifmacroTF{#2}{% + \let\@expand\expandcsonce + }{% + \let\@expand\unexpanded + }% + }{% + \let\@expand\unexpanded + }% + \ifcsndefTF{opt@#3.#1}{% + \ifblankTF{#2}{}{% + \cptexpandarg{\cptexpandsecond{\cptfiltermergekv[,]}% + {\cptmakecs{opt@#3.#1}}}{\@expand{#2}}{}% + }% + }{% + \csn@edef{opt@#3.#1}{\@expand{#2}}% + }% + \globalizecsn{opt@#3.#1}% + \endgroup +} +\robust@redef*\OptionNotUsed{% + \ifxTF\@currext\@clsextension{% + \cptexpandargonce{\cptfiltermergekv[,]% + \@unusedoptionlist}\CurrentOption\nofilter + }{}% +} +\robust@redef*\@use@ption{% + \oifinset@sp@FT,\CurrentOption\@unusedoptionlist{}{% + \cptexpandargonce{\cptfilterremovekv[,]% + \@unusedoptionlist}\CurrentOption\nofilter + }% + \csname ds@\CurrentOption\endcsname +} +\let\@@fileswith@pti@ns\@fileswith@pti@ns +\robust@redef*\ProcessOptions{% + \cptpushfunctions\ProcessOptions{\\\CurrentOption}\cpt@optdepth + \cpt@sttrue\cpt@csvnormalize[,]\@declaredoptions + \cpt@sttrue\cpt@kvnormalize[,]\@classoptionslist + \edef\@curroptions{\cpt@optionlist{\@currname.\@currext}}% + \cpt@sttrue\cpt@kvnormalize[,]\@curroptions + \cpt@removevalues{\@classoptionslist,\@curroptions}% + \let\ds@\@empty + \cpt@ifstar\@xprocess@ptions\@process@ptions +} +\robust@redef*\@process@ptions{% + \edef\@curr@ptions{% + \ifx\@currext\@clsextension\else\expandcsonce + \@classoptionslist,\fi\expandcsonce\@curroptions + }% + \def\csv@do##1{% + \def\CurrentOption{##1}% + \oifinset@sp@TF,\CurrentOption\@curr@ptions{% + \@use@ption + \letcsntocs{ds@##1}\@empty + }{}% + }% + \csv@@parse*\@declaredoptions + \@process@pti@ns +} +\robust@redef*\@xprocess@ptions{% + \ifcseqTF\@currext\@clsextension{}{% + \def\csv@do##1{% + \def\CurrentOption{##1}% + \oifinset@sp@TF,\CurrentOption\@declaredoptions{% + \@use@ption + \letcsntocs{ds@##1}\@empty + }{}% + }% + \csv@@parse*\@classoptionslist + }% + \@process@pti@ns +} +\robust@redef*\@process@pti@ns{% + \def\csv@do##1{% + \def\CurrentOption{##1}% + \ifcsndefTF{ds@##1}\@use@ption{\@use@ption\default@ds}% + }% + \csv@@parse*\@curroptions + \expandafter\cptfor\@declaredoptions\dofor{% + \letcsntocs{ds@##1}\relax + }% + \cptpopfunctions\ProcessOptions\cpt@optdepth + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \AtEndOfPackage{\let\@unprocessedoptions\relax}% +} +% If catoptions is loaded before \documentclass, it will +% automatically use \XDeclareOption, etc. At \documentclass, +% if usepox is false, the package will revert to \DeclareOption, +% etc: +\cptpassunexpanded{% + \begingroup + \def\cpt@tempa{\endgroup + \gnewletcs\cpt@kernelDeclareOption\DeclareOption + \gnewletcs\cpt@kernelProcessOptions\ProcessOptions + \gnewletcs\cpt@kernelExecuteOptions\ExecuteOptions + \gdef\DeclareOption{\cpt@olddxtrue\XDeclareOption}% + \gdef\ProcessOptions{\cpt@olddxtrue\XProcessOptions}% + \gdef\ExecuteOptions{\cpt@olddxtrue\XExecuteOptions}% + \AtEndOfPackage{% + \ifcpt@usepox\else + \def\documentclass{% + \let\documentclass\@twoclasseserror + \if@compatibility\else + \def\usepackage{% + \gletcs\DeclareOption\cpt@kernelDeclareOption + \gletcs\ProcessOptions\cpt@kernelProcessOptions + \gletcs\ExecuteOptions\cpt@kernelExecuteOptions + \cpt@olddxfalse + \RequirePackage + }% + \fi + \@fileswithoptions\@clsextension + }% + \fi + }% + }% + \ifdefTF\cpt@documentclass\endgroup\cpt@tempa +} + +\cptonlypreamble{% + \cptonlypreamble,\cpt@getdocumentclass,\cptloadpackages, + \ifpackagewithoptionsTF,\ifclasswithoptionsTF,\cpt@ifoptions, + \cptpushcatcodes,\cptpopcatcodes,\UseNormalCatcodes, + \StyleFilePurpose,\StyleFileInfo, + \AfterEndOfStyleFile,\StyleFileRCSInfo,\SetStyleFileMessages, + \XDeclareOption,\XDeclareOptions,\XDeclareCommandOption, + \XDeclareCommandOptions,\XDeclareBooleanOption, + \XDeclareBooleanOptions,\XDeclareBiBooleanOptions, + \XDeclareSwitchOption,\XDeclareSwitchOptions, + \XProcessOptions,\XExecuteOptions,\XExecuteAliasOption, + \cpt@processedoptions,\cpt@optionlist,\cpt@findoption@a, + \cpt@findoption@b,\cpt@processoptions,\cpt@xprocessoptions, + \cpt@yprocessoptions,\cpt@pr@cessoptions,\BeforeStartOfDocument, + \AfterStartOfDocument,\XInvalidOptionHandler,\XDeclareInvalidOption, + \XDeclareInvalidOptions,\XUnknownOptionHandler,\XExternalOptions, + \AfterProcessOptions,\BeforeProcessOptions,\loadifnotloaded +} +\XDeclareBiBooleanOptions{verbose,silent}[true](cpt@){}{} +\XDeclareBiBooleanOptions{draft,final}[true](cpt@){}{} +\XDeclareCommandOptions{% + option-stack-limit,optionstacklimit,key-stack-limit,% + keystacklimit,key-depth-limit,keydepthlimit% +}[4](cpt@){% + \xdef\cpt@optionstacklimit{\number#1}% +} +\XDeclareBooleanOption{usepox}[true](cpt@){% + \ifcpt@usepox + \AtEndOfPackage{% + \gdef\DeclareOption{\cpt@olddxtrue\XDeclareOption}% + \gdef\ProcessOptions{\cpt@olddxtrue\XProcessOptions}% + \gdef\ExecuteOptions{\cpt@olddxtrue\XExecuteOptions}% + }% + \fi +} +\XDisableOptions*{draft,final} +\XDeclareOption*{\cpt@warn{Unknown option '\CurrentOption' ignored}} +\XExecuteOptions{% + verbose=false,usepox=true,optionstacklimit=4% +}\relax +\XProcessOptions*\relax + +\cptpopcatcodes +\cptrestorecatcodes +\declarefutureletset[fl@]{lbracket,star,rquote} + +\endinput + +%% End of file catoptions.sty %% |