summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/catoptions
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/catoptions
Initial commit
Diffstat (limited to 'macros/latex/contrib/catoptions')
-rw-r--r--macros/latex/contrib/catoptions/README47
-rw-r--r--macros/latex/contrib/catoptions/doc/catoptions-guide.cfg83
-rw-r--r--macros/latex/contrib/catoptions/doc/catoptions-guide.tex1108
-rw-r--r--macros/latex/contrib/catoptions/tex/catoptions.sty6331
4 files changed, 7569 insertions, 0 deletions
diff --git a/macros/latex/contrib/catoptions/README b/macros/latex/contrib/catoptions/README
new file mode 100644
index 0000000000..2efc44bd00
--- /dev/null
+++ b/macros/latex/contrib/catoptions/README
@@ -0,0 +1,47 @@
+This is the README file for the 'catoptions' package.
+
+VERSION
+
+Version 0.2.7h, 2014/08/29
+
+LOCATION ON CTAN
+
+macros/latex/contrib/catoptions
+
+SUMMARY
+
+The 'catoptions' package changes package loading internals so
+that all subsequently loaded packages can rely on normal/standard
+catcodes of all ASCII characters. The package defines canonical
+control sequences to represent all the visible ASCII characters.
+It also provides robust options parsing mechanisms, in addition
+to many TeX programming tools.
+
+LICENSE
+
+The 'catoptions' package 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 latest
+version of this license is in http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+The LPPL maintenance status of this software is 'author-maintained'.
+
+This software is provided 'as it is', without warranty of any kind,
+either expressed or implied, including, but not limited to, the
+implied warranties of merchantability and fitness for a particular
+purpose.
+
+AUTHOR
+
+Ahmed Musa
+
+RELATED PACKAGES
+
+The catcode section of the 'catoptions' package is an extension of
+the 'pcatcode' package by Michael J. Downes and David M. Jones.
+
+
+
+
diff --git a/macros/latex/contrib/catoptions/doc/catoptions-guide.cfg b/macros/latex/contrib/catoptions/doc/catoptions-guide.cfg
new file mode 100644
index 0000000000..a34684ab06
--- /dev/null
+++ b/macros/latex/contrib/catoptions/doc/catoptions-guide.cfg
@@ -0,0 +1,83 @@
+\ProvidesFile{catoptions-guide.cfg}%
+ [2012/11/17 v0.2.7f Configuration file for catoptions-guide.tex (AM)]
+
+\cptloadpackages{%
+ xwatermark|printwatermark;
+ array;
+ colortbl;
+ ltablex;
+}
+\keepXColumns
+
+\fancypagenos[%
+ showonpageone = false,
+ showpagenumbers = true,
+ showheadrule = true,
+ showfootrule = false,
+ yposition = -.42\paperheight,
+ xposition = 0,
+ scale = 1,
+ angle = 0,
+ left-header = The \textcolor{macrocolor}{catoptions} package,
+ style = \textsc{Page~\thepage~of~\pageref{xwmlastpage}},
+ right-header = \ttcl{black}{\today}
+]
+
+\amltxoptions{%
+ geometryoptions = {left=3cm,right=3cm,top=2.5cm,%
+ bottom=2.5cm,includeheadfoot},
+ reviewdocument = false,
+ parindent = false,
+ toc = false,
+ frontpagestyle = empty,
+ pretitleskip = 0ex,
+ posttitleskip = 1ex,
+ presuptitleskip = 15ex,
+ postsuptitleskip = 0ex,
+ presubtitleskip = 0ex,
+ postsubtitleskip = -\baselineskip,
+ loadnatbib = {numbers,sort&compress},
+ cmdcolor = xmagenta1,
+ stylecolor = xgreen1,
+ speccolor = teal,
+ sectionheadcolor = blue
+}
+\def\otherchars{\quoted{other} characters\sspace}
+\ltsnewletcs*\sectionbreak\medbreak
+\AtBeginDocument{\renewdef*\thefootnote{\fnsymbol{footnote}}}
+
+\newwatermark
+[page=1,fontfamily=phv,fontsize=11pt,fontseries=m,textalign=center,
+ coordunit=pc,textwidth=\hsize,textangle=0,textscale=1.8,textxpos=0,
+ textypos=32.5]{\xwmfadingtext[textcolor=blue,boxcolor=red,
+ scale=1.8,height=1.5ex,letterwidth=7.8mm]{catoptions}\\[1ex]%
+ \ttcl{blue}{\resizebox{.5\width}{!}{Setting up
+ {\tt\string\futurelet} characters, securing catcodes,
+ and parsing options}}%
+}
+
+\newwatermark
+[page=1,fontfamily=phv,fontsize=10pt,fontseries=m,color=black,textalign=center,
+ coordunit=pc,textwidth=\hsize,textangle=0,textscale=1,textxpos=0,textypos=24]{%
+ \ltscitation[author={Michael J. Downes, 1958--2003},textcolor=black,leftmargin=0em,
+ fonttype=\small]{%
+ The \pkgg'{pcatcode} functionality would work best if it were built into the
+ \usecsn{latex2e} kernel, but it cannot be usefully added to the kernel now without
+ adversely affecting document compatibility across different systems. This package
+ therefore modifies one or two of the low-level package-loading functions defined
+ by the kernel. Theoretically speaking, the \pkgg'{pcatcode} itself has to guard against
+ the
+ kind of catcode problems that it is intended to circumvent. If you would like a
+ nice little \texnician's exercise, try your hand, before looking at the code of the
+ \pkgg'{pcatcode}, at the task that I set for myself: find the minimal set of catcode
+ assumptions that one has to make before attempting to establish normalcy, where normalcy is
+ defined as the state at the end of the \latex kernel, just before the last
+ \hx{\makeatother}. This is the state that may normally be expected at the
+ beginning of a \hx{\documentclass} file, if the \latex format file does not
+ have any extensions (\eg, \pkgm{babel}) compiled in.
+ }%
+}
+
+\endinput
+
+%%% End of file catoptions-guide.cfg %%%
diff --git a/macros/latex/contrib/catoptions/doc/catoptions-guide.tex b/macros/latex/contrib/catoptions/doc/catoptions-guide.tex
new file mode 100644
index 0000000000..e286601ac9
--- /dev/null
+++ b/macros/latex/contrib/catoptions/doc/catoptions-guide.tex
@@ -0,0 +1,1108 @@
+\documentclass[
+ use-a4-paper,
+ use-10pt-font,
+ final-version,
+ use-UK-English,
+ fancy-section-headings,
+ frame-section-numbers,
+ para-abstract-style,
+ input-config-file,
+ no-hyperref-messages
+]{amltxdoc}
+
+\hfuzz1pt
+\makeatletter
+\WrapQuotes
+\def\xdecs{\fx{\XDeclareOption}\Redstar\sspace}
+\makeindex
+\let\footnote\ltsfootnote
+
+\begin{document}
+
+\begin{frontmatter}
+\title{The \texttt{\color{blue}catoptions} Package\titleref{t1,t2}}
+\titlenotes[t1,t2]{%
+ The package is available at \url{\titleurltext}.\sep
+ This manual doesn't, as yet, explain all the currently available features and commands of
+ the \pkg'{catoptions}. This manual continues to evolve.
+}
+\version{0.2.7g}
+\titleurl{http://mirror.ctan.org/macros/latex/contrib/catoptions/}
+\author{Ahmed Musa \Email{amusa22@gmail.com}\\Preston, Lancashire, UK}
+
+\def\abstractname{\textsf{Summary}}
+\begin{abstract}
+ \small
+ The \pkg'{catoptions} provides several extensions to the \pkgm'{pcatcode}. Apart from the tools related to setting up, preserving and restoring category codes, it includes many \texorlatex programming tools and even new list and options processing interfaces. It modifies the \latex kernel's options parsing mechanism to forestall premature expansion of options and values (in the manner of the \pkg'{xkvltxp,kvoptions-patch}), so that the \pkg'{catoptions} may be loaded even before \hx{\documentclass}. In fact, the package is meant to be loaded on top of other packages, so as to exploit its catcode preserving scheme. Among other reasons, this necessitated the development of the options parsing scheme of this package. Only the catcode and options parsing facilities are treated in this manual; the application programming interfaces will be covered in the documentation of the \pkg'{ltxtools}. The machinery of the \pkg'{catoptions} adds no cost to the simple syntax of \LaTeX's native options parser. Users who are already familiar with \LaTeX's legacy options processing don't necessarily have to invest the time that is essential in learning the extensive machinery of existing key-value and option parsers. Existing packages don't have to be modified to use the features of the \pkg'{catoptions}. The \pkg'{catoptions}, while maintaining simplicity, does not strip off even one level of outer braces in parsing package options and in list processing. It robustly normalizes key-values and options prior to parsing. The options parsing scheme of the \pkg'{catoptions} has been tried as a replacement parser on the \pkgg{article} class and on many packages, including \pkg'{hyperref, cleveref, natbib} without difficulties. Packages that redefine \latex's native options processing internals may not work properly with \pkg'{catoptions}. I know that \pkg'{xcolor} redefines \hx{\@declareoption} and the \pkg'{catoptions} has taken that fact into account, but there may be other packages that modify \latex's options processing internals that I am not aware of.
+\end{abstract}
+
+\let\licensename\relax
+\begin{license}
+ \small
+\xwmcolorbox[textalign=justified, outerframecolor=blue, innerframecolor=orange,
+ width=.985\hsize]{%
+ This work (\ie, all the files in the \pkg'{catoptions} bundle) may be distributed and/or modified under the conditions of the \lppl, either version~1.3 of this license or any later version.
+ The \lppl maintenance status of this software is \quoted{author-maintained}. This software is provided \quoted{as it is}, without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose.
+ \endgraf
+ \centerline{\makered{\CopyrightYear}}\vspace{-.8\baselineskip}\relax
+}
+\end{license}
+\end{frontmatter}
+
+\begin{xwmshade}[fillcolor=white,framecolor=orange,framerule=1pt,framesep=2pt,
+ width=1.0\hsize]\tableofcontents
+\end{xwmshade}
+
+
+\docsection(sec:motivation){Motivation}
+
+\lletter{M}{y motivation} for turning to the \pkgg'{pcatcode} was to save myself the trouble of declaring category codes at the beginning of my packages. After spending some time on the \pkgg'{pcatcode}, I discovered I had learnt enough to make changes and additions to some of its macros and functionality. After completing the catcode stuff in the \pkg'{catoptions}, I wanted to pass options to the package. If the package is to be loaded on top of other packages, as intended, then its options parsing scheme should be independent of other packages. But realizing the trouble with passing expandable option values to packages and classes via the \latex kernel's scheme, I decided to implement modifications to the kernel's options parser. Apart from the problem of premature expansion of options and values by the \latex kernel, outer curly braces in option values are lost during parsing. Indeed, the kernel's option parsing scheme doesn't recognize option values indicated with the equality sign.
+
+
+\docsection(sec:packageloading){Loading the package}
+
+\ltsnewfootnote{1}{%
+ The user interfaces of \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} are similar to those of \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} but they aren't the same. See \sref{sec:options-parse}.
+}
+The \pkg'{catoptions} can be loaded in class and style files and in documents (before or after \hx{\documentclass}) with the options described in \sref{sec:pkg-options}. If the package is loaded before \hx{\documentclass}, it will, by default, use the options parser of the package in place of \latex's options parsing scheme (namely, the more robust commands \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} in place of \latex's native commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions})\usefootnote{1}. In that case, the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} are aliased to \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions}, respectively. The latter set of commands do immediately recognize that they have to deal with option functions that are based on the kernel's syntax and semantics. This allows expandable options and option values (together with options with spaces in their names) to be passed via \hx{\documentclass}---if \pkg{catoptions} is loaded before \hx{\documentclass}. This also implies that existing packages can use the options parsing scheme of \pkg'{catoptions} without modifying the packages.
+
+However, if after loading \pkg'{catoptions} before \hx{\documentclass} the user still wants to use the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions}, the package option \fx{usepox} (see \sref{sec:pkg-options}) can be toggled to \texttt{false}. In this case, option values can't be passed via \hx{\documentclass}. More precisely, option values passed via \hx{\documentclass} are stripped off internally by \pkg{catoptions} so that they may be processed by \hx{\ProcessOptions}.
+
+
+\docsection(sec:pkg-options)<Package options>{Package options}
+
+\lletter{T}{he} \pkg'{catoptions} has the options shown in \sref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to enter information onto the log file when some events happen (\eg, when commands are redefined by means of, say, the command \fx{\robust@redef}, which has the same syntax with \tex's legacy \hx{\def}; and when an option from the same family is multiply submitted to, say, \fx{\XExecuteOptions}). This option may be used in the future to provide debugging features for the package.
+
+\extrarowheight=2pt
+\arrayrulecolor{yellow}
+\begin{tabularx}{\linewidth}{|m{3cm}|m{2.5cm}|X|}
+\caption{Package options\xwmlabel{tab:pkgoptions}}\\\hline
+\rowcolor{pink}
+\bfseries Option&\bfseries Default&\bfseries Meaning\\\hline
+\endfirsthead
+\hline
+\multicolumn{3}{|l|}{\emph{Continued from last page}}\\\hline
+\bfseries Option&\bfseries Default&\bfseries Meaning\\\hline
+\endhead
+\multicolumn{3}{|r|}{\emph{Continued on next page}}\\\hline
+\endfoot
+\hline
+\endlastfoot
+\fx{verbose} & \hx{false} & The global boolean switch that determines if information should be logged for some tasks in the package.\\\hline
+\fx{usepox} & \hx{true} & The boolean switch that determines if the options parser of \pkgg{catoptions} should be used for all options processing of packages loaded after \hx{\documentclass} even if those packages are based on \usecsn{latex2e}'s native options processing scheme.\\\hline
+\end{tabularx}
+
+As noted in \sref{sec:packageloading}, if the \pkg'{catoptions} is loaded before \hx{\documentclass} it will invariably use the options processing mechanism of the package. In that case (of the package being loaded before \hx{\documentclass}), the option \fxim{usepox} directs the package to use the \pkg{catoptions}'s options processing scheme for all the packages loaded after \hx{\documentclass}, instead of \latex's native options parsing procedures. This allows \pkg{catoptions}'s options parsing scheme to be used for existing packages loaded after \hx{\documentclass} without modifying the packages.
+
+Assuming that the options \quotedtt{textstyle} and \quotedtt{name} belong to an existing package (say, \quotedtt{mypackage}) to be loaded later, then the following example demonstrates one feature of the \pkg'{catoptions}, in the case in which the package is loaded before \hx{\documentclass}:
+
+\start{example}[Loading catoptions before \documentclass]
+\RequirePackage[verbose, usepox]{catoptions}
+\documentclass[textstyle=\ttfamily,name={Mr X\"avier Sanchez},a4paper,
+ draft,10pt]{article}
+\usepackage{mypackage}
+\finish{example}
+\fxim*{\RequirePackage,\usepackage,\documentclass}
+
+If the \pkg'{catoptions} wasn't loaded before \hx{\documentclass} then the above example would fail, because \latex's option parser can't handle options with values (much less values with expandable tokens).
+
+
+\docsection(sec:saving-catcodes){Saving and restituting category codes}
+
+There are the following user commands for saving and returning category codes of \quoted{other} characters to their previous states:
+
+\start+{newmacro}[]
+\cptnormalcatcodes
+\cptpushcatcodes
+\cptpopcatcodes
+\UseNormalCatcodes
+\GetCurrentCatcodeSubset
+\cptfutureletsetup
+\finish{newmacro}
+\fxim*{\UseNormalCatcodes,\cptpushcatcodes,\cptpopcatcodes,
+\cptnormalcatcodes,\cptfutureletsetup,\GetCurrentCatcodeSubset}
+
+The command \fx{\cptnormalcatcodes} simply resets the category codes of all \otherchars together with those of the space character and \fx{\^^I} and \fx{\^^J} to their standard values. The \hx{\endlinechar} is also reset to its normal value by this command. The command \fx{\cptpushcatcodes} pushes the current category codes for restitution later with \fx{\cptpopcatcodes}.
+
+The command \fx{\UseNormalCatcodes} works only in packages and does more than one thing: it calls \fx{\cptpushcatcodes} (to save the prevailing category codes) and then \fx{\cptnormalcatcodes} (to enforce the standard category codes). At the end of the class file or package, it automatically issues \fx{\cptpopcatcodes} to recover all the category codes earlier pushed. The command \fx{\UseNormalCatcodes} can conveniently be issued at the start of the package and the developer can be assured of access to the standard category codes of all \otherchars together with those of the space character and \fx{\^^I} and \fx{\^^J}. It should be called only once in a package: subsequent calls within the same package will have no effect.
+
+After issuing the command \fx{\GetCurrentCatcodeSubset}, you can do
+
+\start{example}[\currentcatcodesubset]
+\show\currentcatcodesubset
+\finish{example}
+\fxim*{\currentcatcodesubset}
+
+to see the current catcode setup. The command \fx{\cptfutureletsetup} is described in \sref{sec:future-letting}.
+
+\start{example}[\UseNormalCatcodes]
+\ProvidesPackage{mypackage}[2011/01/16 v0.01]
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\RequirePackage[verbose, usepox]{catoptions}
+\UseNormalCatcodes
+|com(At the end of `mypackage' all the category codes pushed by)
+|com(\UseNormalCatcodes will automatically be popped.)
+\finish{example}
+\dummyfxi*{\UseNormalCatcodes}
+
+
+\docsection(sec:future-letting){Future-letting of \headquoted{other} characters}
+
+The command \fx{\cptfutureletsetup} defines canonical control sequences to represent the following characters:
+
+$$\vbox{%
+ \def\newvrule{%
+ \ifnum\@tempcnta<\@vpt
+ \global\@tempcnta\numexpr\@tempcnta+1\relax
+ \textcolor{blue}{\vrule}%
+ \fi
+ }%
+ \noindent\everycr{\noalign{\global\@tempcnta\z@}}%
+ \@tempcnta\z@\tabskip=1em
+ \halign{%
+ &\strut#\hfil&\hfil\textcolor{red}{\tt#}\hskip.25em\newvrule\cr
+ space&\textvisiblespace& exclam&!&dblquote&"&hash&\#& dollar&\$&
+ ampersand&\&\cr
+ lquote&`& rquote&'& lparen&(& rparen&)& star&$*$& plus&+\cr
+ comma&,& hyphen&-&period&.&slash&/& colon&:& semicolon&;\cr
+ less&<&greater&>&equal&=& question&?& lbracket&[& rbracket&]\cr
+ hat&\char`\^& underscore&\char`\_& bslash&\char`\\&
+ lbrace&\char`\{& rbrace&\char`\}& vert&|\cr
+ tilde&\char`~\cr
+ }%
+}$$
+
+However, for efficiency reasons, the canonical control sequences will be defined for only the characters (or, indeed, their names) appearing in the user-supplied list \fx{\declarefutureletset}, whose syntax is
+
+\start{newmacro}[\declarefutureletset]
+\declarefutureletset[|nang(stub)]{|nang(set)}
+\finish{newmacro}
+
+Here, \ang{set} is a comma-separated list of names from the \quoted{other} characters listed above. The defined commands are prefixed with an optional \ang{stub}, whose default value is \fx{fl@}. The defined commands have the syntaxes
+
+\start'{newmacro}[futurelet characters]
+\|nang(stub)|nang(char)
+\if|nang(stub)|nang(char)
+\finish{newmacro}
+
+For efficiency gains, a call to \fx{\cptfutureletsetup} automatically undefines all the canonical control sequences previously defined with a call to \fx{\cptfutureletsetup}---before the new canonical control sequences are defined.
+
+For instance, with the choices
+
+\start{example}[\declarefutureletset]
+\declarefutureletset[fl@]{space, star, lbracket}
+\cptfutureletsetup
+\finish{example}
+
+we have the following commands on hand for testing after \fx{\futurelet}:
+
+\start+{example}[futurelet commands]
+\fl@space \fl@star \fl@lbracket
+\iffl@space \iffl@star \iffl@lbracket
+\finish{example}
+\aidx*{futurelet commands}
+
+If any of the commands emanating from concatenating \ang{stub} with the name of the character is already defined, an error message is flagged. It should be noted that these commands are available only after issuing the command \fx{\cptfutureletsetup}, which isn't called automatically anywhere by the \pkg'{catoptions}. Normally, at \hx{\AtBeginDocument} the \pkg'{catoptions} calls the command \fx{\cptrestorecatcodes}, without calling \fx{\cptfutureletsetup}. Calling \ffx'{\declarefutureletset, \cptfutureletsetup} is the user's duty.
+
+The commands \ffx'{\declarefutureletset, \cptfutureletsetup} are decoupled to allow the user to call \fx{\declarefutureletset} only once, and perhaps much earlier, before calling the command \fx{\cptfutureletsetup} as often as desired.
+
+An inefficient call of the form
+
+\start{example}[\declarefutureletset]
+\declarefutureletset[fl@]{|R(all)}
+\finish{example}
+
+where \quotedtt{all} means that control sequences should be defined for all the available \quoted{other} characters, will define all the following control sequences whenever \fx{\cptfutureletsetup} is called:
+
+\start+{example}[futurelet commands]
+\fl@space \fl@exclam \fl@dblquote \fl@hash
+\fl@dollar \fl@ampersand \fl@lrquote \fl@lparen
+\fl@rparen \fl@star \fl@plus \fl@comma
+\fl@hyphen \fl@period \fl@slash \fl@colon
+\fl@semicolon \fl@less \fl@equal \fl@greater
+\fl@question \fl@lbracket \fl@rbracket \fl@hat
+\fl@underscore \fl@lquote \fl@lbrace \fl@vert
+\fl@rbrace \fl@tilde \fl@bslash
+
+\iffl@space \iffl@exclam \iffl@dblquote \iffl@hash
+\iffl@dollar \iffl@ampersand \iffl@lrquote \iffl@lparen
+\iffl@rparen \iffl@star \iffl@plus \iffl@comma
+\iffl@hyphen \iffl@period \iffl@slash \iffl@colon
+\iffl@semicolon \iffl@less \iffl@equal \iffl@greater
+\iffl@question \iffl@lbracket \iffl@rbracket \iffl@hat
+\iffl@underscore \iffl@lquote \iffl@lbrace \iffl@vert
+\iffl@rbrace \iffl@tilde \iffl@bslash
+\finish{example}
+\aidxm*{futurelet commands}
+
+This will yield control sequences that may never be needed. While such a facility does exist, using it will be inefficient despite the large capacities of many modern \tex engines.
+
+The use syntaxes for the commands \fnl*'\bs{stub,char} and \fnl*'{\bs if}{stub,char} are as follows:
+
+\start{example}[futurelet characters]
+\futurelet\next\cmd |textbf(|R(*))
+\def\cmd{\ifx\fl@star\next `I saw star'\else `I didn't see star'\fi}
+\def\cmd{\iffl@star\next{`I saw star'}{`I didn't see star'}}
+\finish{example}
+
+Notice that \fx{\ifx\fl@comma\next} is a conventional \tex test, while \fx{\iffl@...} expects two \latex branches (\ffx'{\@firstoftwo,\@secondoftwo}). The commands are meant to be easy to recall and use. If, for example, you are testing for the presence of \fx{\tilde}, you simply do \fx{\iffl@tilde\next{...}{...}}, assuming a \ang{stub} of \fx{fl@}.
+
+After setting up \fx{\futurelet} characters with \fx{\cptfutureletsetup}, you can reset active characters to catcode~13 by \fx{\futureletresetactives}.
+
+
+\docsection(sec:package-prelim){Setting up package preliminaries}
+
+Every package normally requires some preliminary declarations, such as seen below. The commands \ffx'{\StyleFilePurpose, \StyleFileRCSInfo, \StyleFileInfo, \SetStyleFileMessages} are defined by the \pkg'{catoptions}. All of them have intuitive syntaxes, except the command \fx{\SetStyleFileMessages}, whose syntax is explained below.
+
+\start{example}[Package preliminaries]
+\StyleFilePurpose{A collection of useful commands}
+\StyleFileRCSInfo
+$Id: mypackage.sty,v 0.1 2011/01/01 09:00:00 My Name Exp $
+\ProvidesPackage{mypackage}[\StyleFileInfo]
+\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+\SetStyleFileMessages[mypack@]{err}{warn}{info}
+\finish{example}
+
+\start{newmacro}[\SetStyleFileMessages]
+\SetStyleFileMessages[|nang(stub)]{|nang(err)}{|nang(warn)}{|nang(info)}
+\finish{newmacro}
+\fxim*{\SetStyleFileMessages}
+
+Here, \ang{stub} is an optional prefix for the three package messages described below. The default value of \ang{stub} is the first three characters of the package or class name (\hx{\@currname}) concatenated with the \quoted{at} sign \quotedfx{@}. The mandatory arguments \ang{err}, \ang{warn}, and \ang{info} are the suffices for the package error, warning and information messages, respectively.
+
+For instance, with the declaration
+
+\start{example}[\SetStyleFileMessages]
+\SetStyleFileMessages[mypack@]{error}{warning}{info}
+\finish{example}
+
+the following commands are automatically defined by the \pkg'{catoptions}:
+
+\start{example}[\SetStyleFileMessages]
+\mypack@error |tto Error message of two parameters
+\mypack@warning |tto Warning message of one parameter
+\mypack@info |tto Information message of one parameter
+\finish{example}
+
+The commands \ffx'{\mypack@error,\mypack@info} can be used as follows:
+
+\start{example}[\SetStyleFileMessages]
+\ifcptonetokenTF{#1}{%
+ \mypack@info{Correct single argument `\detokenize{#1}': accepted}%
+}{%
+ \mypack@error{Multiple arguments `\detokenize{#1}'}%
+ {Invalid multiple arguments `\detokenize{#1}' rejected}%
+}
+\finish{example}
+
+
+\docsection(sec:options-parse){Options parsing}
+
+The interfaces of the options processing commands are as follows, which, apart from the optional family \ang{fam} and default value \ang{default}, are syntactically similar to the corresponding native \latex commands. The optional family name is useful for defining unique options that stand only a remote chance of being mixed up with options of other families. And the optional default value is handy when the user doesn't supply a value for an option: no errors are produced in this case. Existing packages can be processed with these commands without any modifications to those packages. In fact, we have run many existing packages on the bases of these commands (by letting \latex's \hhx'{\DeclareOption,\ExecuteOptions,\ProcessOptions} to these commands), without encountering difficulties.
+
+
+\docsubsection(sec:ord-options){Ordinary options}
+
+\start{newmacro}[\XDeclareOption]
+\XDeclareOption<|nang(fam)>{|nang(opt)}[|nang(default)]{|nang(fn1)}|label(mac:xdec:a)
+\XDeclareOption|*<|nang(fam)>{|nang(fn2)}|label(mac:xdec:b)
+\finish{newmacro}
+\fxim*{\XDeclareOption}
+
+The \unstform of the macro \fx{\XDeclareOption} declares an option that can be used as a package or class option and executed by \fx{\XExecuteOptions} or \fx{\XProcessOptions}. This macro is similar to the standard \latex macro \hx{\DeclareOption}, but with this command the user can pass a value to the option as well. That value can be accessed by using \fx{#1} or \fx{\cpt@currval} in \ang{fn1}. This will contain \ang{default} when no value has been specified for the option. The default value of the optional argument \ang{default} is empty. This implies that when the user does not assign a value to the option \ang{opt} and when no default value has been defined, no error message will ensue. The optional argument \ang{fam} can be used to specify a unique family for the option. When the argument is not used, the macro will insert the default family name (namely, \fx{\@currname.\@currext}).
+
+\start{example}[\XDeclareOption]
+\ProvidesPackage{mypackage}[\StyleFileInfo]
+\cptnewbool{mybool}
+\XDeclareOption{mybool}[true]{\@nameuse{mybool#1}}
+\XDeclareOption{leftmargin}[.5\hsize]{\setlength\leftmargin{#1}}|xwmlabel(mac:leftmargin)
+\finish{example}
+
+\ltsnewfootnote{2}{%
+ The commands \ffx'{\XDeclareBooleanOption, \XDeclareBooleanOptions, \XDeclareBiBooleanOptions} allow the user to define new boolean options without the need to first initialize the booleans with \hx{\newif} or \fx{\cptnewbool} as seen here.
+}
+
+The user would have noticed the use \fx{\cptnewbool} in the above example\usefootnote{2}. The options \ffx'{mybool,leftmargin} could then be called via any of the following statements:
+
+\start{example}[\XDeclareOption]
+|com(Inside class or package files:)
+\RequirePackage[mybool=true,leftmargin=20pt]{mypackage}
+|com(Inside document file:)
+\usepackage[mybool=false,leftmargin=20pt]{mypackage}
+|com(Via document class:)
+\documentclass[mybool,leftmargin=20pt]{myclass}
+\finish{example}
+
+The \stform of the macro \fx{\XDeclareOption} can be used to process unknown options. It is similar to \latex's \hx{\DeclareOption}\Redstar, but it has additional features. You can deploy \hx{\CurrentOption} within the \ang{fn} of this macro to access the option name and value for which the option is unknown. These values (possibly including an option) could, for example, be passed on to another class or package or could be used as an extra class or package option that, for instance, specifies a style that should be loaded. Moreover, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{fn} to refer to the current family, current option (without its value), and current value, respectively.
+
+\ltsnote This note refers to macro lines \ref{mac:xdec:a} and \ref{mac:xdec:b}. In \fx{\XDeclareOption}, the current option value can be accessed by using \fx{#1} in \ang{fn1}. However, in \xdecs the current family name is accessed as \fx{#1}, the option name is available in \fx{#2}, and the current option value can be accessed with \fx{#3} (all in \ang{fn2}). These differences are important.
+
+
+\docsubsection(sec:external-options){External options}
+
+If no default family handler has been provided by the user (through the macro \xdecs or \fx{\XUnknownOptionHandler}) for the family of an undeclared option, and the option doesn't appear in the list \fx{\XExternalOptions}, then that option will be logged (\ie, entered in the transcript file) as undefined at the end of the document. By default, \fx{\XExternalOptions} contains all \hhx'{article,report,memoir} class options. The user can update the \fx{\XExternalOptions} list by means of the following commands:
+
+\start+{newmacro}[\AddToExternalOptions,\RemoveFromExternalOptions]
+\AddToExternalOptions{|nang(opts)}
+\RemoveFromExternalOptions{|nang(opts)}
+\finish{newmacro}
+\fxim*{\XExternalOptions,\AddToExternalOptions,\RemoveFromExternalOptions}
+
+where \ang{opts} are the comma-separated option names to be added to, or removed from, the list.
+
+\ltsnote Unknown options that appear in \fx{\XExternalOptions} list will not have their \ang{fn1}, \ang{fn2} and \ang{callback} of the default family handler (see \sref{mac:handler}) executed unless they contain one of the commands \hhx'{\PassOptionsToClass, \PassOptionsToPackage}.
+
+\start{newmacro}[\XDeclareOptions]
+\XDeclareOptions<|nang(fam)>{|nang(opts)}[|nang(default)]{|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareOptions}
+
+The command \fx{\XDeclareOptions} is similar to \fx{\XDeclareOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. The command \fx{\XDeclareOptions} can be used to save tokens when it is required to declare a set of options with identical attributes.
+
+
+\docsubsection(sec:cmd-options){Command options}
+
+\start{newmacro}[\XDeclareCommandOption]
+\XDeclareCommandOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareCommandOption}
+
+The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl*'\bs{pref,opt} to hold the user-supplied value of the option. The macro so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} prefixed with the letters \fx{cmd}.
+
+\start{newmacro}[\XDeclareCommandOptions]
+\XDeclareCommandOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareCommandOptions}
+
+The command \fx{\XDeclareCommandOptions} is similar to \fx{\XDeclareCommandOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}.
+
+
+\docsubsection(sec:bool-options){Boolean options}
+
+\start{newmacro}[\XDeclareBooleanOption]
+\XDeclareBooleanOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareBooleanOption}
+
+The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \ang{opt}, also create a boolean \fnl*'{\bs if}{pref,opt}. It will automatically toggle this boolean (to \hx{true} or \hx{false}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a boolean option.
+
+\start{newmacro}[\XDeclareBooleanOptions]
+\XDeclareBooleanOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareBooleanOptions}
+
+The command \fx{\XDeclareBooleanOptions} is similar to \fx{\XDeclareBooleanOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Again, each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}.
+
+
+\docsubsubsection(sec:bibool-options){Biboolean options}
+
+\start{newmacro}[\XDeclareBiBooleanOptions]
+\XDeclareBiBooleanOptions<|A(fam)>{|A(opt1),|A(opt2)}[|A(default)]|(|A(pref)|){|A(fn1)}{|A(fn2)}
+\finish{newmacro}
+\fxim*{\XDeclareBiBooleanOptions}
+
+The command \fx{\XDeclareBiBooleanOptions} declares the two options \ang{opt1} and \ang{opt2} in the comma-separated list of options. Again, each of the two declared options is defined with the same family \ang{fam} and default value \ang{default}, but separate functions \ang{fn1} and \ang{fn2}. A distinguishing characteristic of bi-boolean options is that when one option is \hx{true}, the partner option is automatically turned \hx{false}, and vice versa.
+
+
+\docsubsection(sec:switch-options){Switch options}
+
+\start{newmacro}[\XDeclareSwitchOption]
+\XDeclareSwitchOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareSwitchOption}
+
+In the parlance of the \pkg'{catoptions,ltxtools}, a switch can assume only one of the two possible states: \fx{\cpttrue} (which is defined as \fx{00}) or \fx{\cptfalse} (which is defined as \fx{01}). A switch \fx{\swa} can be tested with \tex's \hx{\if} conditional. For example, we can do \hx{\if}\unskip\fx{\swa...}\hx{\fi}. The \pkg'{catoptions} also provides the commands \ffx'{\ifswitchTF,\ifswitchFT} for testing switches, which can be used as follows:
+
+\start+{newmacro}[\ifswitchTF,\ifswitchFT]
+\ifswitchTF{|nang(switch)}{|nang(true text)}{|nang(false text)}
+\ifswitchFT{|nang(switch)}{|nang(false text)}{|nang(true text)}
+\finish{newmacro}
+\fxim*{\ifswitchTF,\ifswitchFT}
+
+\ltsnewfootnote{4}{%
+ Because of the need to do, \eg, \fx{\let\swa\cpttrue} and \hx{\if}\unskip\fx{\swa} for any given switch \fx{\swa}, switches, unlike toggles, don't have their own separate namespace and it is all too easy to redefine an existing switch.
+}
+Note that here \ang{switch} has no escape character, unless it evaluates to a switch name. So, after defining \fx{\def\swa{00}} we could then do \fx{\ifswitchTF{swa}{true}{false}}. It is somewhat risky to introduce new switches with \hx{\def} or \hx{\let}\usefootnote{4}. It is advisable to always use \fx{\newswitch} instead. It has the syntax
+
+\start{newmacro}[\newswitch]
+\newswitch{|nang(switch)}[|nang(state)]
+\finish{newmacro}
+\fxim*{\newswitch}
+
+Again, note that here \ang{switch} has no escape character, unless it evaluates to a switch name. \ang{state} can be either \hx{true} or \hx{false}.
+
+Switches are cheaper than native booleans since each switch \fx{swa} has one and only one command \fx{\swa}. Each native boolean \fx{boola}, on the other hand, has up to three commands (namely, \ffx'{\ifboola,\boolatrue,\boolafalse}. If you need to declare a large number of native booleans, it is advisable to consider using switches instead.
+
+It is possible to toggle the state of a switch by simply using the commands:
+
+\start+{newmacro}[\setswitchtrue,\setswitchfalse]
+\setswitchtrue{|nang(switch)}
+ |tto |C(if switch) |A(switch) |C(exists, do) \let\switch\cpttrue
+\setswitchfalse{|nang(switch)}
+ |tto |C(if switch) |A(switch) |C(exists, do) \let\switch\cptfalse
+\finish{newmacro}
+\fxim*{\setswitchtrue,\setswitchfalse}
+
+The command \fx{\XDeclareSwitchOption} will, apart from declaring the option \ang{opt}, also create a switch \fnl*'\bs{pref,opt}. It will automatically toggle this switch to \hx{true} (equivalent to \fx{00}) or \hx{false} (equivalent to \fx{01}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is again \quotedfx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a switch option.
+
+\start{newmacro}[\XDeclareSwitchOptions]
+\XDeclareSwitchOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)}
+\finish{newmacro}
+\fxim*{\XDeclareSwitchOptions}
+
+The command \fx{\XDeclareSwitchOptions} is similar to \fx{\XDeclareSwitchOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Again, each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}.
+
+
+\docsubsection(sec:unknown-options){Unknown option handler}
+
+\start{newmacro}[\XUnknownOptionHandler]
+\XUnknownOptionHandler<|nang(fams)>[|nang(na)]{|nang(handler)}
+\finish{newmacro}
+\fxim*{\XUnknownOptionHandler}
+
+\ltsnewfootnote{3}{%
+ Declaring a default handler for each unknown option is, of course, inefficient.
+ We have, therefore, provided provisions for declaring such handers for only families of options.
+}
+The command \fx{\XUnknownOptionHandler} can be used in place of \xdecs to specify default action(s) for options undefined in any family in \ang{fams}\usefootnote{3}. \ang{handler} refers to the default function that should be executed if undeclared options are called from families \ang{fams} by the user. \hx{\CurrentOption} can be deployed within \ang{handler} to access the option name (coupled with its current value) for which the option name is unknown. As mentioned above in the case of \xdecs, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{handler} to access the current family, current option (uncoupled from its current value), and current value, respectively. \ang{na} is the list of options for which \ang{handler} shouldn't apply; for these options, the kernel's unknown option handler (\ie, \hx{\default@ds}) would apply.
+
+If the \ang{handler} contains the special literal form \fx{define/.code=} as in
+
+\start{example}[Unknown option handler]
+|A(fn1) |R(define/.code=)|nang(callback)|R(/.end) |A(fn2)|label(mac:handler)
+\finish{example}
+\fxim*{define/.code}
+
+then each unknown option in families \ang{fams} will be momentarily defined and executed with the option function \ang{callback}. The family of the new option will be \fx{\cpt@currfam} (the prevailing family name); its default value will be \fx{\cpt@currval} (the value specified by the user for the unknown option); and its macro function will be the above-indicated \ang{callback}. Again, you can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{handler} to refer to the current option family, option name, and option value, respectively.
+
+\ltsnote Functions \ang{fn1} and \ang{fn2} on \sref{mac:handler} will be executed for each unknown function in families \ang{fams}, but (unlike \ang{callback}) will not be used in defining unknown options of \ang{fams}.
+
+If the value given for the unknown option is \hx{true} or \hx{false}, the new (\ie, undeclared) option will be defined as a boolean option with macro prefix \quotedfx{\@currname @}; otherwise it will be defined as a command option with macro prefix \quotedfx{cmd\@currname @}. (See the descriptions of the commands \ffx'{\XDeclareCommandOption,\XDeclareBooleanOption} for the meaning of \quoted{macro prefix}.) It should be noted that the token \quoted{define} in the above syntax is not escaped, and that the token \fx{/.end} is mandatory. If \ang{callback} contains these literal forms, they have to be enclosed in curly braces.
+
+The following example, among other things, produces a warning when the user supplies an option that was not previously declared:
+
+\amvzapname
+\start{example}[\XDeclareOption*]
+\XDeclareOption|*<mypackage>{%
+ |com(Unknown options will not be defined automatically here:)
+ \PackageWarningNoLine{mypackage}{Unknown option `\CurrentOption' ignored}%
+ |com(Current option family:)
+ \def\currfamily{#1}%
+ |com(Current option without the given value:)
+ \def\curroption{#2}%
+ |com(User-supplied value of current option:)
+ \def\currvalue{#3}%
+ |com(User defined function:)
+ \def\mymacro##1{\do@a{#2=#3}\do@b{##1}%
+ |com(`\CurrentOption' isn't equivalent to `#2=#3' because non-active)
+ |com(spaces around `#3' would have been removed.)
+}
+\finish{example}
+
+And the following example passes undeclared options to \hx{article} class:
+
+\amvzapname
+\start{example}[\XDeclareOption*]
+\XDeclareOption|*{\PassOptionsToClass{#2=#3}{article}}
+\finish{example}
+
+The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the callback shown.
+
+\start{example}[\XUnknownOptionHandler]
+\XUnknownOptionHandler<mypackage>{%
+ |com(Unknown options will be defined automatically here with the)
+ |com(indicated code:)
+ |R(define/.code=)
+ \def\x##1{##1\relax `option #2 = value #3' in family `#1'}%
+ |R(/.end)
+ |com(The following will be executed for each unknown option of the)
+ |com(given family, but will not be a `callback' for unknown options:)
+ \PackageWarningNoLine{mypackage}{Unknown option `#2' of family
+ `#1' defined on the fly}%
+}
+\finish{example}
+
+
+\docsubsection(sec:invalid-options){Invalid options}
+
+\start+{newmacro}[\XDeclareInvalidOption,\XDeclareInvalidOptions]
+\XDeclareInvalidOption<|nang(fams)>{|nang(opt)}
+\XDeclareInvalidOptions<|nang(fams)>{|nang(opts)}
+\finish{newmacro}
+\fxim*{\XDeclareInvalidOption,\XDeclareInvalidOptions}
+
+The commands \ffx'{\XDeclareInvalidOption,\XDeclareInvalidOptions} declare the given list \ang{opts} as invalid or inadmissible within the specified families \ang{fams}. A user submitting the invalid option will receive the message the option author has specified for the given family via the command \fx{\XInvalidOptionHandler}. Package and class authors don't necessarily have to provide invalid-option handler for each or any family (of their options) via the macro \fx{\XInvalidOptionHandler}: the package provides a default error message for invoked invalid options when the author of the option hasn't defined an invalid-option handler.
+
+\start{newmacro}[\XInvalidOptionHandler]
+\XInvalidOptionHandler<|nang(fams)>{|nang(handler)}
+\finish{newmacro}
+\fxim*{\XInvalidOptionHandler}
+
+The command \fx{\XInvalidOptionHandler} defines, for each family \ang{fam} in \ang{fams}, a one-parameter function, which, when specified, is used to replace the macros of options in the family \ang{fam} when the options appear in \ang{opts} list of \fx{\XDeclareInvalidOptions}.
+
+\start{example}[\XInvalidOptionHandler]
+\XInvalidOptionHandler<fama,famb>{%
+ \@latex@error{Invalid or null option `\CurrentOption'}%
+ {I have encountered an invalid option `\CurrentOption':
+ Your package author has set this option as inadmissible.}%
+}
+\XDeclareInvalidOptions<fama,famb>{opta,optb}
+\finish{example}
+
+
+\docsubsection(sec:exec-options){Executing options}
+
+\start{newmacro}[\XExecuteOptions]
+\XExecuteOptions<|nang(fams)>{|nang(opts)}[|nang(na)]
+\finish{newmacro}
+\fxim*{\XExecuteOptions}
+
+The re-entrant \fx{\XExecuteOptions} macro sets options created by \fx{\XDeclareOption} and is basically a means of setting up the default values of the options. The optional argument \ang{fams} can be used to specify a list of \emph{families} that define the options. When the argument is not used, the macro will insert the default family name (\fx{\@currname.\@currext}). The set \ang{na} is the list of keys to be ignored (\ie, not executed if they appear in \ang{opts}).
+
+This macro will not use the declaration done by \xdecs when undeclared options appear in its argument. Instead, in this case the macro will issue a warning and ignore the option. This differs from the behavior of \latex's \hx{\ExecuteOptions}.
+
+\start{example}[\XExecuteOptions]
+\XExecuteOptions{leftmargin=0pt}
+\finish{example}
+\dummyfxi*{\XExecuteOptions}
+
+This initializes the option \hx{\leftmargin} of \sref{mac:leftmargin} to 0pt.
+
+
+\docsubsection(sec:process-options){Processing options}
+
+\start{newmacro}[\XProcessOptions]
+\XProcessOptions<|nang(fams)>[|nang(na)]
+\XProcessOptions|*<|nang(fams)>[|nang(na)]
+\finish{newmacro}
+\fxim*{\XProcessOptions}
+
+The re-entrant \fx{\XProcessOptions} macro processes the options and values passed by the user to the class or package. The optional argument \ang{fams} can be used to specify the \emph{families} that have been used to define the options. The optional argument \ang{na} can be used to specify options that should be ignored, \ie, not processed. When used in a class file, this macro will ignore unknown options. This allows the user to use global options in the \hx{\documentclass} command which could be claimed by packages loaded later.
+
+The \stform of \fx{\XProcessOptions} works like the \unstform except that the former also copies user input from the \hx{\documentclass} command and processes the options in the order specified by the \hx{\documentclass}. When the user specifies an option in the \hx{\documentclass} which also exists in the local family (or families) of the package calling \fx{\XProcessOptions}\Redstar, the local option will be set as well. In this case, \fx{#1} in \fx{\XDeclareOption} macro will contain the user-value entered in the \hx{\documentclass} (or \fx{\usepackage} or \fx{\RequirePackage}) command for this option. First the global options from \hx{\documentclass} will set local options and afterwards the local options (specified via \hhx'{\usepackage, \RequirePackage, \LoadClass} or similar commands) will set local options, which could overwrite the global options set earlier, depending on how the options sections are organized. The macro \fx{\XProcessOptions}\Redstar reduces to \fx{\XProcessOptions} only when issued from the class which forms the document class for the file at hand (to avoid setting the same options twice), but not for classes loaded later using, for instance, \hx{\LoadClass}. Global options that do not exist in the local families of the package or class calling \fx{\XProcessOptions}\Redstar will be simply ignored or highlighted.
+
+The implementation here differs significantly from the \latex kernel's scheme of carrying out \hx{\ProcessOptions} and \hx{\ProcessOptions}\Redstar. It also deviates from the implementations by other options processing packages. The differences lie mainly in how the local and global options are distinguished and in the order of processing those options. Among other issues, the family structure introduced by the \pkg'{catoptions} (though lightweight) makes the independence between local and global options possible, even if the options from the two categories share the same namespace and are mixed in, say, \hx{\documentclass} command. Also, document classes loaded by \hx{\LoadClass} don't have the same primacy as the first document class. When using \latex kernel's \hx{\ProcessOptions} or \hx{\ProcessOptions}\Redstar, a class file can't copy document class options, even if the class file is loaded by \hx{\LoadClass}. This is not the case with the \pkg'{catoptions}.
+
+\start+{example}[\XDeclareOption,\XExecuteOptions,\XProcessOptions]
+|com(This is a sample class file. We specify a family for the options,)
+|com(instead of using the default family |(testclass.sty|).)
+\ProvidesClass{testclass}[2011/01/15 v1.0 A test class]
+\NeedsTeXFormat{LaTeX2e}
+|com(The following loading of `catoptions' may need to be commented out)
+|com(to avoid option clash with another loading of the package in the document.)
+|makepurple(% \RequirePackage{catoptions})
+\UseNormalCatcodes
+\newif\ifboola
+\XDeclareOption<testclass>{boola}[true]{%
+ \@nameuse{boola#1}%
+ \ifboola\let\eat\@gobble\fi
+}
+\XDeclareOptions<testclass>{opta,optb}[true]{%
+ \def\alloptsfunc##1{\def\tempa{##1}}%
+}
+|com(No need for \newif when declaring boolean options:)
+\XDeclareBooleanOption<testclass>{boolb}[true]|(test@|){%
+ \iftest@boolb
+ \AtEndOfPackage{\gdef\tex{\TeX\xspace}}%
+ \fi
+}
+\XDeclareBiBooleanOptions{draft,final}[true](test@){}{}
+\XDeclareCommandOption<testclass>{color}[blue]|(test@|){%
+ Load `color' package
+}
+|com(Disable option `color' at \AtBeginDocument:)
+\XDisableOption|*<testclass>{color}
+\XDeclareOption<testclass>{align}[left]{%
+ \ifstrcmpTF{#1}{left}{\let\align\raggedright}{%
+ \ifstrcmpTF{#1}{right}{\let\align\raggedleft}{%
+ \ifstrcmpTF{#1}{center}{\let\align\centering}{%
+ \@latex@error{Invalid value `#1' for align}{%
+ You have issued an illegal value `#1' for the variable `align'.
+ }%
+ }%
+ }%
+ }%
+}
+\XDeclareInvalidOption<testclass>{deadoption}
+\XDeclareOption|*<testclass>{\PassOptionsToClass\CurrentOption{article}}
+\XExecuteOptions<testclass>{boola,boolb}
+\XProcessOptions|*<testclass>\relax
+\LoadClass{article}
+\cptloadpackages{%|label(mac:loadpkg)
+ |nang(pkg name)|rv|nang(pkg opts)|rv|nang(pkg date)|R(;)...|R(;)|nang(more packages)
+}
+\endinput
+
+|com(This is a sample document:)
+\RequirePackage[usepox]{catoptions}
+\documentclass[
+ align = right,
+ boola = false,
+ boolb = true,
+ name = {Mr J\"avier Claudioos},
+ a4paper,
+ draft,
+ 10pt
+]{testclass}
+|com(You can call \usepackage{catoptions}, instead of)
+|com(\RequirePackage{catoptions}, after \documentclass, but then the)
+|com(\documentclass option `name={Mr J\"avier Claudioos}' can't be processed.)
+\usepackage{cleveref}
+
+\begin{document}
+ Blackberry bush ... blackberry-lily.
+\end{document}
+\finish{example}
+\fxim*{\cptloadpackages}
+
+
+\docsubsection(sec:before-proc-options){Hook for before and after processing options}
+
+\start{newmacro}[\BeforeProcessOptions,\AfterProcessOptions]
+\BeforeProcessOptions{|nang(code)}
+\AfterProcessOptions{|nang(code)}
+\finish{newmacro}
+\fxim*{\BeforeProcessOptions,\AfterProcessOptions}
+
+The commands \ffx'{\BeforeProcessOptions,\AfterProcessOptions} can be used to process \ang{code} just before and immediately after \fx{\XProcessOptions} has run its course. The command \fx{\AfterProcessOptions} is particularly useful when it is required to optionally load a package, depending on the state of an option in the current package. For obvious reasons, \latex doesn't allow the loading of packages in the options section. The command \fx{\AfterProcessOptions} can be used to load packages after the current package's options have been processed. Here is an example for optionally loading sub-packages at the end of the options section:
+
+\start{example}[\AfterProcessOptions]
+\newif\ifloadsubpackages
+\robust@def*\inputpackage[#1]#2{%
+ \ifloadsubpackages
+ \AfterProcessOptions{\RequirePackage[#1]{#2}}%
+ \fi
+}
+\robust@def*\loadsub#1{%
+ \cptdocommalist{#1}{%
+ \XDeclareOption{##1}{\inputpackage[####1]{##1}}%
+ }%
+}
+\loadsub{subpkg1,subpkg2,subpkg3}
+\finish{example}
+
+%\enlargethispage{2\baselineskip}
+\bigskip
+\docsubsection(sec:ifoptiondef){Testing if an option is defined}
+
+\start{newmacro}[\ifoptdefTF]
+\ifoptdefTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)}
+\ifoptdefFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)}
+\finish{newmacro}
+\fxim*{\ifoptdefTF}
+
+The macro \fx{\ifoptdefTF} returns \ang{true} if option \ang{opt} is undefined in one or more members of \ang{fams}, and \ang{false} otherwise. The command \fx{\ifoptdefFT} reverses the logic of \fx{\ifoptdefTF}.
+
+
+\docsubsection(sec:disable-options){Disabling options}
+
+\start{newmacro}[\XDisableOptions]
+\XDisableOptions<|nang(fams)>{|nang(opts)}
+\XDisableOptions|*<|nang(fams)>{|nang(opts)}
+\finish{newmacro}
+\fxim*{\XDisableOptions}
+
+The command \fx{\XDisableOptions} disables all the options in the list \ang{opts} that can be found in the families \ang{fams}, \ie, it makes the options invalid thereafter. If any of the options in the list \ang{opts} can't be found in the families \ang{fams}, it is simply ignored without warning: since families can be mixed in \ang{fams}, it wouldn't be meaningful issuing several warnings in this case.
+
+The \stform of \fx{\XDisableOptions} delays the invalidation of the \ang{opts} until the invocation of \hx{\begin{document}}. This may be used to bar users of the options from committing the options after the start of document, but not before.
+
+
+\docsubsubsection{Logging disabled options}
+
+\start{newmacro}[\XLogDisabledOptions]
+\XLogDisabledOptions<|nang(fams)>
+\finish{newmacro}
+\fxim*{\XLogDisabledOptions}
+
+The command \fx{\XLogDisabledOptions}, which can be called before and after \hx{\begin{document}}, writes in the current transcript file the options of the families \ang{fams} that have been disabled so far. If no options have been disabled from any of the given families or if the given family does not exist, a message is logged to that effect.
+
+
+\docsubsubsection{Testing if an option is disabled}
+
+\start{newmacro}[\ifoptdisabled]
+\ifoptdisabledTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)}
+\ifoptdisabledFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)}
+\finish{newmacro}
+\fxim*{\ifoptdisabledTF}
+
+The macro \fx{\ifoptdisabledTF} returns \ang{true} if option \ang{opt} has been disabled from one or more members of \ang{fams}, and \ang{false} otherwise. The command \fx{\ifoptdisabledFT} reverses the logic of \fx{\ifoptdisabledTF}.
+
+
+\docsection(sec:normalize)<Normalizing lists>{Normalizing csv and kv lists}
+
+Any arbitrary parser-separated-values (csv) list can be normalized by means of the package command \fx{\csv@@normalize} before processing the list.
+
+\start{newmacro}[\csv@@normalize]
+\csv@@normalize[|nang(parser)]{|nang(list)}
+\csv@@normalize|*[|nang(parser)]|nang(listcmd)
+\finish{newmacro}
+\fxim*{\csv@@normalize}
+
+Here, \ang{list}, which is populated by parser-separated elements, is not expanded before normalization; \ang{listcmd}, on the other hand, is expanded once before normalization. The default value of the optional \ang{parser} is \qcomma. \quoted{Normalization} implies changing the category codes of all the active parsers to their standard values, as well as trimming leading and trailing spaces around the elements of the list and removing consecutive multiple parsers. Thus empty entries that are not enforced by curly braces are removed. The result (\ie, normalized list) is available in the macro \fx{\normalized@list} (in the \unstform case) or \ang{listcmd} (in the \stform case).
+
+\start{example}[\csv@@normalize]
+\begingroup
+\catcode`\;=\active
+\gdef\x{x ; ; {y}; ; z}
+\endgroup
+
+\csv@@normalize*[;]\x
+|com(\show\x)
+\finish{example}
+
+\start{newmacro}[\kv@@normalize]
+\kv@@normalize[|nang(parser)]{|nang(list)}
+\kv@@normalize|*[|nang(parser)]|nang(listcmd)
+\finish{newmacro}
+\fxim*{\kv@@normalize}
+
+The command \fx{\kv@@normalize} normalizes a list of key-value pairs, returning the result in the macro \fx{\normalized@list} (in the \unstform case) or \ang{listcmd} (in the \stform case). Besides dealing with multiple commas and the spaces between entries, in this case the spaces between keys and the equality sign are removed and multiple equality signs are made only one. Moreover, the category codes of the arbitrary parser and the equality sign are made normal/other throughout the list. The command \fx{\kv@@normalize} is meant for options or key-value parsing; it is used in the options processing scheme of \pkg'{catoptions}.
+
+\start{example}[\csv@@normalize]
+\begingroup
+\catcode`\;\string=\active
+\catcode`\=\string=\active
+\gdef\x{x=A ; ; y=={B} ; ; z=C}
+\endgroup
+
+\kv@@normalize*[;]\x
+|com(\show\x)
+\finish{example}
+
+
+\docsection(sec:csvkvparse)<Parsing lists>{Parsing csv and kv lists}
+
+\start+{newmacro}[\csv@@loop,\csv@@parse,\kv@@parse]
+\csv@@loop[|nang(parser)][|nang(list)]
+\csv@@loop|*[|nang(parser)][|nang(listcmd)]
+\csv@@parse[|nang(parser)][|nang(list)]
+\csv@@parse|*[|nang(parser)][|nang(listcmd)]
+\kv@@loop[|nang(parser)][|nang(list)]
+\kv@@loop|*[|nang(parser)][|nang(listcmd)]
+\kv@@parse[|nang(parser)][|nang(list)]
+\kv@@parse|*[|nang(parser)][|nang(listcmd)]
+\finish{newmacro}
+\fxim*{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}
+
+The macros \ffx'{\csv@@parse,\kv@@parse}---and their \stform+---call \ffx'{\csv@@normalize, \kv@@normalize}, respectively. On the other hand, the macros \ffx'{\csv@@loop,\kv@@loop} and their \stform+ don't call \fx{\csv@@normalize} (since not every list will require normalization). This is the only difference between \fx{\csv@@loop} and \fx{\csv@@parse}, and between \fx{\kv@@loop} and \fx{\kv@@parse}. The macros \ffx'{\csv@@loop,\csv@@parse} are meant for general csv-list processing with an arbitrary parser, while the command \ffx'{\kv@@loop,\kv@@parse} are designed for processing key-value lists. These macros loop over a given \ang{parser}-separated \ang{list} and execute the user-defined, one-parameter, commands \ffx'{\csv@do,\kv@do}, respectively, for every item in the list, passing the item as an argument and preserving outer braces. The default value of \ang{parser} is \qcomma. The \stform+ of these commands expand \ang{listcmd} once before commencing the loop.
+
+Here are some points to note about these list processors:
+\begin{enum}
+\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} aren't expandable.
+\item If an item contains \ang{parser}, it must be wrapped in curly braces when using \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, otherwise the elements may be mixed up during parsing. The braces will persist thereafter, but will of course be removed during printing (if the items are printed).
+\item White spaces before and after the list separator are always ignored by the normalizer called by \ffx'{\csv@@parse,\kv@@parse}. If an item contains \ang{parser} or starts with a space, it must, therefore, be wrapped in curly braces before commencing these loops.
+\item Since \ffx'{\csv@@loop,\kv@@loop} don't call the normalizer, they preserve outer/surrounding spaces in the entries. Empty entries in \ang{list} or \ang{listcmd} will be processed by \ffx'{\csv@@loop,\kv@@loop} if the boolean \fx{cpt@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry}, which are based on the boolean \fx{cpt@useempty}, before commencing the iteration. If empty entries are important to the task at hand, then issuing \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} prior to the commencement of the loop is recommended, because a previous call to either \fx{\csv@@loop} or \fx{\kv@@loop} (perhaps by another package) could have set \fx{cpt@useempty} to a state that is no longer valid or desired.
+\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} can be nested to any level and can be mixed.
+\item In the commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, it is always possible to break out of the loop prematurely at any level of nesting, simply by issuing the command \fx{\ltsloopbreak} (see the example below). Breaking an inner loop doesn't affect the continuation of the outer loop, and vice versa; that is, loop breaks are nest-level-dependent.
+\item The user can insert \fx{\csvbreak} as an element in \ang{list} for any of the commands \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse, \dofunclist} with the aim of automatically breaking out of the list processing prematurely (\ie, before the list is exhausted). The tokens \ffx'{\listbreak, \breaklist} are not defined or used by the \pkg'{catoptions}, to avoid name clashes with other packages. The \pkg'{catoptions} instead uses \fx{\csvbreak}, which is an unexpandable token; if it were to be expandable, then experience has shown that a chaotic infinite loop could arise in an expansion context. Breaking out of the loop prematurely on the current nest level doesn't affect the continuation of the loop on the other levels.
+\end{enum}
+
+\start{example}[\csv@@parse]
+\begingroup
+\catcode`\;=\active
+\gdef\x{a ; ; {b}; ; c}
+\endgroup
+
+\@tempcnta\z@
+\def\csv@do#1{%
+ \advance\@tempcnta\@ne
+ \@namedef{x@\romannumeral\@tempcnta}{#1}%
+}
+\csv@@parse*[;]\x
+|com(\show\x@ii)
+
+\def\xa{a , {b} , c}
+\def\xb{x ; y ; {z}}
+\def\csv@do#1{%
+ \pushnumber\nra
+ \csn@edef{arg@\romannumeral\nra}{#1}%
+ \chardef\nrb\z@
+ \def\csv@do##1{%
+ \pushnumber\nrb
+ |com(Breaking the inner loop here doesn't affect the outer loop:)
+ \ifnum\nrb>\@ne|R(\ltsloopbreak)\fi
+ \csn@def{arg@\romannumeral\nra @\romannumeral\nrb}{#1,##1}%
+ }%
+ \csv@@parse*[;]\xb
+}
+\csv@@parse*\xa
+\finish{example}
+
+\start+{example}[Using \csvbreak]
+\cptnewvariables{count}{m@,n@}
+\def\csv@do#1{%
+ \advance\m@\@ne\n@\z@
+ \def\csv@do##1{%
+ \advance\n@\@ne
+ \csn@def{w@\romannumeral\m@ @\romannumeral\n@}{#1,##1}%
+ }%
+ \csv@@parse[;]{ {x} ; {y} ; |R(\csvbreak) ; z }%
+}
+\csv@@parse{ a , {b}, {c} }
+\finish{example}
+\fxim*{\csvbreak}
+
+The following is a pseudocode that depicts the use of \fx{\kv@@parse}:
+
+\start{example}[\kv@@parse]
+\def\kv@do#1{%
+ \def\CurrentOption{#1}%
+ |R(if \CurrentOption is not empty then)
+ Split \CurrentOption into option and value;
+ Search if option exists in \@declaredoptions
+ |R(if option is found then)
+ Execute the option's function
+ |R(else)
+ Report option as unknown
+ |R(fi)
+ |R(fi)
+}
+|com(|fx(\kv@@parse) will normalize |hx(\@classoptions) before parsing it:)
+|R(if there are declared options then)
+ \kv@@parse*\@classoptions
+|R(fi)
+\finish{example}
+
+\start{newmacro}[\dofunclist]
+\def\do|nang(params){|nang(fn)}
+\dofunclist[|nang(parser)]{|nang(list)}
+\dofunclist|*[|nang(parser)]{|nang(listcmd)}
+\finish{newmacro}
+\fxim*{\dofunclist,\do}
+
+The \fx{\dofunclist} command can be used to iterate over a \ang{parser}-separated \ang{list} or \ang{listcmd} and execute the auxiliary command \fx{\do} for every item in the list, passing the item as an argument and preserving outer braces. While the user-defined commands \ffx'{\csv@do,\kv@do} (required by \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}) must be one-parametered, the command \fx{\do} (required by \fx{\dofunclist}) can be multi-parametered. The command \fx{\dofunclist} isn't expandable. \ang{params} are the parameter texts for the command \fx{\do}. White spaces before and after the list separator are always ignored, because the list is first normalized before parsing by \fx{\dofunclist}. If an item contains \ang{parser} or starts with a space, it must be wrapped in curly braces (to preserve the parser or space). The braces may persist thereafter, but will of course be removed during printing (if the items are printed). The default value of \ang{parser} is \qcomma.
+
+Empty entries in \ang{list} will be ignored by the normalizer called by \fx{\dofunclist}. Such empty entries, if needed later, would need to be enclosed in curly braces before commencing the iteration. The \fx{\dofunclist} command, like all the looping macros of this section, can be nested to any level.
+
+\start+{example}[\dofunclist]
+\def\do#1{\item #1}
+\begin{itemize}
+ |com(The following parser |(,|) is superfluous since the default is comma:)
+ \dofunclist[,]{aaaa, bbbb, {cccc, dddd}, eeee}
+\end{itemize}
+
+|com(Let us load many packages compactly here. This is just a simple example of)
+|com(|fx(\dofunclist); you can instead use the more appropriate command)
+|com(|fx(\cptloadpackages) to load packages (see |sref(mac:loadpkg)):)
+\def\do#1.#2[#3]{%
+ \@ifpackageloaded{#1}{%
+ \@ifpackagelater{#1}{#2}{}{%
+ \cpt@warn{Older version of package `#1' was loaded earlier}%
+ }%
+ }{%
+ \let\elt\cpttrimspaces
+ \cptexpandsecond\usepackage{[\elt{#3}]{\elt{#1}}[\elt{#2}]}%
+ }%
+}
+|com(The default parser |(,|) is implied below:)
+\dofunclist{%
+ yfonts.2003/01/08[],
+ pifont.2005/04/12[],
+ helvet.2005/04/12[scaled=0.9],
+ zref.2008/10/01[|R({)user,lastpage|R(})],
+ xcolor.2007/01/21[|R({)table,hyperref|R(})]
+}
+
+|com(An example of nested loops follows. Here outer braces in the)
+|com(elements are preserved:)
+\chardef\m@\z@
+\def\do#1{%
+ \pushnumber\m@
+ \chardef\n@\z@
+ \def\do##1{%
+ \pushnumber\n@
+ \ifnum\n@>\@ne|R(\ltsloopbreak)\fi
+ \csn@def{w@\romannumeral\m@ @\romannumeral\n@}{#1,##1}%
+ }%
+ \dofunclist[;]{x;{y};z}%
+}
+\dofunclist[,]{a,{b},c,d,e}
+\finish{example}
+
+While \fx{\dofunclist} allows the user to define and call multi-parametered \fx{\do} functions, outer curly braces in the \emph{individual} arguments of \fx{\do} may, in some rare cases, be lost in parsing (but only if the number of arguments exceeds one). This possibility depends on how the parameters and arguments of the user-supplied command \fx{\do} are arranged. If preserving braces is essential to the user's need, then he/she might consider using the more robust commands \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse}. It is possible to robustly build a multi-parametered callback in the user-defined commands \ffx'{\csv@do,\kv@do} required by \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse}. In fact, this is what \fx{\dofunclist} does internally.
+
+
+\docsubsection(sec:indris){Looking ahead in csv lists}
+
+Imagine an instance in which, while processing a csv list, you need not only the current item of the list but also the next item. Moreover, you need to know when the last item of the list has been reached, so that, for example, you can do something peculiar with the last item. The \fx{\indrisloop} list processor provides facilities to accomplish these tasks.
+
+\start+{newmacro}[\indrisloop]
+\indrisloop[|nang(parser)]{|nang(list)}|A(fn)
+\indrisloop|*[|nang(parser)]|nang(listcmd)|A(fn)
+\finish{newmacro}
+\fxim*{\indrisloop,\indrisdepth,\currindris,\currindris@i,
+\nextindris,\nextindris@i,\indrisnr,\iflastindris}
+\fxi*{\ifLTS@loopbreak}
+
+The \fx{\indrisloop} command can be used to iterate over a \ang{parser}-separated \ang{list} or \ang{listcmd} and execute the user-supplied one-parameter command \ang{fn} for every item in the list, passing the item as an argument and preserving outer braces.
+
+The \fx{\indrisloop} iterator is of particular interest. The loop provides the macros \ffx'{\indrisdepth, \currindris, \currindris@i, \nextindris, \nextindris@i, \indrisnr, \iflastindris, \ifLTS@loopbreak}, which mean, respectively, the current nested depth/level, the current item on the current level, the current item on an arbitrary level \quotedfx{i}, the next item on the current level, the next item on an arbitrary level \quotedfx{i}, the numerical order of the current item on the current level, the boolean that indicates that the last item of the list has been reached on the current level of nesting, and the boolean that can be used to break the loop prematurely (before the list is exhausted) on any level.
+
+You can do \fx{\iflastindris...\fi} on any level. On any given level, it is possible to break out of the current loop by simply issuing \fx{\ltsloopbreak}. This would not affect the progress of the loops on other levels. When \fx{\iflastindris} is true on a given level \quotedfx{i}, then \ffx'{\nextindris,\nextindris@i} are empty on that level, but not necessarily the macros \ffx'{\currindris,\currindris@i}.
+
+The following provides a simple application of \fx{\indrisloop}, which I posted on \comptexttex in July~2011 in response to a posted question.
+
+\start{example}[\indrisloop]
+\makeatletter
+\robust@def*\andorcomma{%
+ \ifnumcmpTF\indrisnr>\@ne{%
+ \ifboolTF{lastindris}{%
+ \xifstrcmpTF\sav@lastrefsep{and}{ and }{, }%
+ }{, }%
+ }{}%
+}
+\robust@def*\lastrefsep#1{%
+ \ifstrcmpTF{#1}{and}{}{%
+ \ifstrcmpTF{#1}{comma}{}{%
+ \ifstrcmpTF{#1}{,}{}{%
+ \@ltx@err{Invalid argument for \string\lastrefsep}\@ehc
+ }%
+ }%
+ }%
+ \gdef\sav@lastrefsep{#1}%
+}
+\robust@def*\secref{\secref@i{\S}{\S\S}}
+\new@def*\secref@i#1#2#3{%
+ \begingroup
+ \def\reserved{#3}%
+ \csv@@normalize*[,]\reserved
+ \def\do##1{\andorcomma\ref{##1}}%
+ \def\reserved@a##1,##2,##3\@nil{%
+ \ifblankTF{##1}{}{%
+ \ifblankTF{##2}{%
+ #1~\ref{##1}%
+ }{%
+ #2~\indrisloop*\reserved\do
+ }%
+ }%
+ }%
+ \expandafter\reserved@a\reserved,,\@nil
+ \endgroup
+}
+\begin{|R(document)}
+\lastrefsep{and} % or \lastrefsep{comma}
+\section{aaa}\label{sec:aaa}
+\section{bbb}\label{sec:bbb}
+\section{ccc}\label{sec:ccc}
+\section{ddd}
+\noindent\secref{sec:aaa,sec:bbb,sec:ccc}.
+\par\noindent\secref{sec:aaa}
+\end{|R(document)}
+\finish{example}
+
+%\bigskip
+\docsection(sec:tsvparse)<Iterating tokenwise>{Parsing \headquoted{tsv} lists}
+
+\start+{newmacro}[\tsv@@parse,\tsv@@loop]
+\tsv@@loop{|nang(list)}
+\tsv@@loop|*|nang(listcmd)
+\tsv@@parse{|nang(list)}
+\tsv@@parse|*|nang(listcmd)
+\finish{newmacro}
+\fxim*{\tsv@@parse,\tsv@@loop}
+
+The macros \ffx'{\tsv@@loop,\tsv@@parse} loop over \quoted{non-separated} tokens (tsv-list), picking each token as an argument and applying the one-parameter, user-supplied, function \fx{\tsv@do} to it while preserving outer braces in the item. The macros \ffx'{\tsv@@loop, \tsv@@parse} are meant for general tsv-list processing.
+
+The macros \ffx'{\tsv@@loop,\tsv@@parse} (and their \stform+) of course don't call \fx{\csv@@normalize} or \fx{\kv@@normalize}, but instead they trim leading and trailing spaces of individual tokens/entries. The only difference between \fx{\tsv@@loop} and \fx{\tsv@@parse} is that the former calls \fxi{\cpttrimspace}, while the latter calls \fx{\cpttrimspaces}. The expandable function \fxi{\cpttrimspaces} trims all leading and trailing spaces (including chains of implicit spaces) around its argument, while \fx{\cpttrimspace} trims only one leading and one trailing space around its argument. Both \ffx'{\cpttrimspace,\cpttrimspaces} preserve outer braces around their arguments, are expandable, and leave the trimmed token unchanged from its original form. The latter requirement is a condition of Michael Downes.
+
+The starred variants of \ffx'{\tsv@@loop,\tsv@@parse} expand \ang{listcmd} once before commencing the loop.
+
+Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \fx{cpt@useempty} is true. You may thus issue the command \fxi{\UseEmptyEntry} or \fxi{\DiscardEmptyEntry} before commencing the iteration. Both commands \ffx'{\tsv@@loop,\tsv@@parse} can be nested to any level and can be mixed.
+
+In the commands \ffx'{\tsv@loop,\tsv@@parse}, it is always possible to break out of the loop prematurely at any level of nesting by issuing the command \fx{\ltsloopbreak}. Again, breaking an inner loop doesn't affect the continuation of the outer loop, and vice versa. The user can insert \fx{\tsvbreak} as an element in \ang{list} for any of the commands \ffx'{\tsv@@loop, \tsv@@parse} so as to automatically break out of the list processing prematurely (\ie, before the list is exhausted).
+
+\start+{example}[\tsv@@loop,\tsv@@parse]
+\newcount\m
+\newcount\n
+\def\tsv@do#1{%
+ \advance\m\@ne\n\z@
+ \def\tsv@do##1{%
+ \advance\n\@ne
+ \csn@edef{w@\romannumeral\m @\romannumeral\n}{#1,##1}%
+ }%
+ \tsv@@loop{ x {y} |R(\tsvbreak) z }%
+}
+\tsv@@loop{ a {b} {c} }
+\finish{example}
+
+
+\docsection(sec:version-hist){Version history}
+
+The following change history highlights significant changes that affect user utilities and interfaces; mutations of technical nature are not documented in this section. The numbers on the right-hand side of the following lists are section numbers; the \stsign means the subject features in the package but is not reflected anywhere in this user guide.
+
+\begin{versionhist}
+ \begin{version}{0.2.7f}{2012/11/17}
+ \item Bug fix in \fx{\cptonlypreamble}.\vsecref*
+ \end{version}
+ \begin{version}{0.2.7c-e}{2012/10/14}
+ \item Changes in some command names.\vsecref*
+ \end{version}
+ \begin{version}{0.2.7b}{2011/12/17}
+ \item Renamed the user commands \ffx'{\dofunclist, \stripallouterbraces, \stripouterbraces} to \ffx'{\cptdofunclist, \cptstripallouterbraces, \cptstripNouterbraces}, respectively.\vsecref*
+ \end{version}
+ \begin{version}{0.2.7a}{2011/12/07}
+ \item Renamed the user commands \ffx'{\newvariables,\docommalist, \iflacus...\then} to \ffx'{\cptnewvariables,\cptdocommalist, \iflacus...\dolacus}, respectively, to reduce the chances of name clashes with other packages or user code. The old names haven't actually been removed yet, but will disappear in the future.\vsecref*
+ \end{version}
+ \begin{version}{0.2.7}{2011/10/10}
+ \item Introduced the commands \ffx'{\BeforeProcessOptions,\AfterProcessOptions} \vsecref{sec:before-proc-options}
+ \end{version}
+ \begin{version}{0.2.6}{2011/09/10}
+ \item Bug fix in the command \fx{\UseNormalCatcodes} \vsecref{sec:saving-catcodes}
+ \end{version}
+ \begin{version}{0.2.5}{2011/07/20}
+ \item Enlarged the command \fxi{\cptnewvariables} to include \hx{\newwrite} and \fx{\newswitch} \vsecref*
+ \end{version}
+ \begin{version}{0.2.4}{2011/07/04}
+ \item Changes to command \fxi{\cptonlypreamble} \vsecref*
+ \end{version}
+ \begin{version}{0.2c}{2011/06/08}
+ \item Modified syntax for the handler of unknown options \vsecref{sec:options-parse}
+ \end{version}
+
+ \begin{version}{0.2b}{2011/04/02}
+ \item The following commands were introduced \vsecref{sec:options-parse}
+ \start{veritem}
+ \XDeclareInvalidOptions \XUnknownOptionHandler \XDisableOptions
+ \XLogDisabledOptions \ifoptdisabledTF \ifoptdefTF
+ \finish{veritem}
+ \end{version}
+
+ \begin{version}{0.2a}{2011/02/15}
+ \item For efficiency reasons, canonical control sequences for futurelet characters are no longer defined automatically. The user is now responsible for specifying the canonical control sequences that should be defined \vsecref{sec:future-letting}
+ \item The following plural-form commands were introduced \vsecref{sec:options-parse}
+ \start{veritem}
+ \XDeclareOptions \XDeclareCommandOptions
+ \XDeclareBooleanOptions \XDeclareBiBooleanOptions
+ \finish{veritem}
+
+ \end{version}
+ \begin{version}{0.1}{2011/01/25}
+ \item First public release.
+ \end{version}
+
+\end{versionhist}
+
+\newpage
+\ltsindexpreambleformat{\centering}
+\ltsindexpreamble{Index numbers refer to page numbers.}
+\ltsindexcolumns\tw@
+\printindex
+
+\end{document}
+
+\newcount\nr
+\def\alist{a1/b1/c1; a2/b2/c2; a3/b3/c3}
+\trace*
+\cptforeach*[;] \xa/\ya/\za \in \alist \do{%
+ \nr\z@pt
+ \cptforeach[,] \xb|\yb|\zb \in s1|t1|u1, s2|t2|u2, s3|t3|u3 \do{%
+ \advance\nr\@ne
+ \ifnum\nr>\@ne\ltsloopbreak\fi
+ % It is permissible to use #1, #2, #3, ##1, ##2, ##3, etc,
+ % to refer to the elements of each list, but they won't be
+ % despaced as \xa, \ya, \za, etc will be:
+ % \edef\cmda####1{#1#2#3*####1*##1##2##3}%
+ \edef\cmdb####1{\xa\ya\za*####1*\xb\yb\zb}%
+ }%
+}
+
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&#3{%
+ \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&#2{%
+ \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&#3{%
+ \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 %%