summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/keyreader/tex/keyreader.sty
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/keyreader/tex/keyreader.sty
Initial commit
Diffstat (limited to 'macros/latex/contrib/keyreader/tex/keyreader.sty')
-rw-r--r--macros/latex/contrib/keyreader/tex/keyreader.sty1225
1 files changed, 1225 insertions, 0 deletions
diff --git a/macros/latex/contrib/keyreader/tex/keyreader.sty b/macros/latex/contrib/keyreader/tex/keyreader.sty
new file mode 100644
index 0000000000..3b6ad1d7cf
--- /dev/null
+++ b/macros/latex/contrib/keyreader/tex/keyreader.sty
@@ -0,0 +1,1225 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'keyreader.sty', version 0.5b, 2012/11/06. %
+% %
+% 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 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. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\ProvidesPackage{keyreader}
+ [2012/11/06 v0.5b Robust interfaces to xkeyval package (AM)]
+\newdimen\krdz@
+\ifcase
+ \ifx\eTeXversion\@undefined\krdz@\else
+ \ifnum\eTeXversion<\tw@\krdz@\else\@ne\fi\fi
+ \PackageError{keyreader}
+ {eTeX not loaded or old version}
+ {This package requires eTeX version 2 or higher.}%
+ \expandafter\endinput
+\fi
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+\begingroup
+\catcode064 11% @
+\catcode123 01% {
+\catcode125 02% }
+\catcode044 12% ,
+\def\reserved@a{\endgroup
+ \def\do##1,{%
+ \ifx\end##1\else
+ \catcode##1\string=\the\catcode##1 %
+ \expandafter\do
+ \fi
+ }%
+ \edef\krd@restorecodes{\do035,064,123,125,061,059,\end,}%
+}
+\reserved@a
+\catcode035 06% #
+\catcode064 11% @
+\catcode123 01% {
+\catcode125 02% }
+\catcode061 12% =
+\catcode044 12% ,
+\def\do#1=#2,{%
+ \ifx\end#1\else
+ \edef\krd@restorecodes{%
+ \krd@restorecodes
+ \catcode#1=\the\catcode#1 %
+ }%
+ \catcode#1=#2\relax
+ \expandafter\do
+ \fi
+}
+\do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,%
+059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\end=,%
+
+\AtEndOfPackage{%
+ \krdAfterEndPackage{%
+ \krd@restorecodes
+ \let\krd@restorecodes\relax
+ }%
+}
+
+\ifx\XKeyValLoaded\endinput\else
+ \input xkeyval
+\fi
+\let\XKV@doxs\relax
+
+\let\krd@err\@latex@error
+\def\krd@ehd{%
+ There is a problem here. Investigate it before
+ \MessageBreak proceeding. Try typing <return>
+ to proceed.\MessageBreak If that doesn't work,
+ type X <return> to quit.
+}
+\def\@space{ }
+\protected\def\krdnewlet#1{\@ifdefinable{#1}\relax\let#1= }
+\krdnewlet\krd@nil\relax
+\def\krd@nnil{\krd@nil}
+\def\krdswap#1#2{#2#1}
+\def\krd@quark{\@gobble\krd@quark}
+\newcount\krd@csvdepth
+\newif\ifkrd@foreach@break
+\newif\ifkrd@st
+\newif\ifkrdindef
+\long\def\krdifblank#1{%
+ \ifcat$\detokenize\expandafter{\@gobble#1.}$%
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+}
+
+\begingroup
+\catcode`\&=8
+\gdef\krdifledbyspace#1{\krd@ifledbyspace&&#1& \trim@nil}
+\gdef\krd@ifledbyspace&#1& #2\trim@nil{%
+ \krdifblank{#2}\@secondoftwo\@firstoftwo
+}
+\gdef\krdtrimspace#1{\krd@trimspace@a.#1& &}
+\gdef\krd@trimspace@a#1 &{\krd@trimspace@b#1&}
+\gdef\krd@trimspace@b#1&#2{%
+ \krdexpandonce{%
+ \romannumeral-`\q
+ \expandafter\krdifledbyspace\expandafter{\@gobble#1}%
+ {\expandafter\noexpand\@gobble#1}{\expandafter\@space\@gobble#1}%
+ }%
+}
+\endgroup
+
+\def\krdzapspace#1{\krd@zapspace#1 \zap@nil}
+\def\krd@zapspace#1 #2\zap@nil{%
+ \krdifblank{#2}{#1}{%
+ \krd@zapspace#1#2\zap@nil
+ }%
+}
+
+\protected\def\krdAfterEndPackage{%
+ \krdifcsdef{\@currname.\@currext-krd@endpkghook}{}{%
+ \@namedef{\@currname.\@currext-krd@endpkghook}{}%
+ }%
+ \expandafter\g@addto@macro
+ \csname\@currname.\@currext-krd@endpkghook\endcsname
+}
+\xdef\@popfilename{%
+ \unexpanded{%
+ \csname\@currname.\@currext-krd@endpkghook\endcsname
+ \expandafter\let
+ \csname\@currname.\@currext-krd@endpkghook\endcsname
+ \relax
+ }%
+ \unexpanded\expandafter{\@popfilename}%
+}
+\newcommand*\krdifdef[1]{%
+ \krdifblank{#1}\@secondoftwo{%
+ \ifx#1\@undefined
+ \expandafter\@secondoftwo
+ \else
+ \ifx#1\relax
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \else
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \fi
+ \fi
+ }%
+}
+\newcommand*\krdifcsdef[1]{%
+ \krdifblank{#1}{%
+ \expandafter\@secondoftwo\@gobble
+ }{%
+ \ifcsname#1\endcsname
+ \expandafter\@firstofone
+ \else
+ \expandafter\expandafter\expandafter
+ \@secondoftwo\expandafter\@gobble
+ \fi
+ }{%
+ \expandafter\krdifdef\csname#1\endcsname
+ }%
+}
+\def\krd@ifx@quark{\@gobble\krd@ifx@quark}
+\newcommand\krdifx[2]{%
+ \ifx#1#2\krd@ifx@quark
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+}
+\def\krdifbool#1{%
+ \krdifblank{#1}{%
+ \krd@err{No boolean}\krd@ehd
+ }{%
+ \krdifcsdef{if#1}{%
+ \csname @\csname if#1\endcsname
+ first\else second\fi oftwo\endcsname
+ }{%
+ \krd@err{Undefined boolean '#1'}\krd@ehd
+ }%
+ }%
+}
+\def\krd@ifswitch@aux#1#2\krd@nil{%
+ \krdifblank{#2}\@secondoftwo\@firstoftwo
+}
+\def\krdifswitch#1{%
+ \krdifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \expandafter\krd@ifswitch@aux\romannumeral-`\q#1\krd@nil{%
+ \if#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+ }{%
+ \krd@err{Invalid switch '#1'}\krd@ehd
+ }%
+ }%
+}
+\krdifx\pdfstrcmp\@undefined{%
+ \RequirePackage{pdftexcmds}%
+ \krdifx\pdf@strcmp\@undefined{%
+ \krd@err{Neither '\string\pdfstrcmp' nor
+ '\string\pdf@strcmp' exists}\krd@ehd
+ }{%
+ \let\krd@pdfstrcmp\pdf@strcmp
+ }%
+}{%
+ \let\krd@pdfstrcmp\pdfstrcmp
+}
+\newcommand\krdifstrcmp[2]{%
+ \csname @\ifnum\krd@pdfstrcmp{\detokenize{#1}}%
+ {\detokenize{#2}}=0first\else second\fi oftwo\endcsname
+}
+\def\krdifcond#1\fi{%
+ \csname @#1first\else second\fi oftwo\endcsname
+}
+% If we were to use \krdtrimspace for \krdifbraced, then the need
+% for double \romannumeral will cause problems of premature expansion.
+% We need the \romannumeral below to make \krdifbraced expandable:
+\def\krdifbraced#1{%
+ \expandafter\krdswap\expandafter{%
+ \expandafter{\romannumeral-`\q\krd@ifbraced@a{#1}}%
+ }{%
+ \expandafter\krd@ifbraced@d\romannumeral-`\q\krd@ifbraced@a{#1}\krd@nil
+ }%
+}
+\begingroup
+\catcode`\&=7
+\gdef\krd@ifbraced@a#1{\krd@ifbraced@b.#1& &}
+\gdef\krd@ifbraced@b#1 &{\krd@ifbraced@c#1&}
+\gdef\krd@ifbraced@c#1&#2{\expandafter\noexpand\@gobble#1}
+\endgroup
+\def\krd@ifbraced@d#1\krd@nil#2{%
+ \krdifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo
+}
+% \krdstripouterbraces{<nr>}<cmd>
+\protected\def\krdstripouterbraces#1#2{%
+ \begingroup
+ \@tempcnta\krdz@
+ \expandafter\krd@stripouterbraces#2\krd@stripbrace{#2}{#1}%
+}
+\protected\def\krd@stripouterbraces#1\krd@stripbrace#2#3{%
+ \advance\@tempcnta\@ne
+ \krdifcond\ifnum\@tempcnta=#3\fi{%
+ \edef#2{\unexpanded{#1}}%
+ \edef\x{\endgroup\krdaftergr#2}\x
+ }{%
+ \krd@stripouterbraces#1\krd@stripbrace{#2}{#3}%
+ }%
+}
+
+\def\krdoxdetok#1{\detokenize\expandafter{#1}}
+\def\krdusearg#1#2{%
+ \expandafter\krdswap\expandafter{\expandafter{#2}}{#1}%
+}
+\def\krdexpandonce#1{\unexpanded\expandafter{#1}}
+\def\krdnoexpandcs#1{\krdexpandonce{\csname#1\endcsname}}
+\def\krdncsname{\expandafter\noexpand\csname}
+\protected\def\krdexpanded#1{%
+ \begingroup
+ \protected@edef\reserved@a{\endgroup#1}\reserved@a
+}
+\protected\def\krdexpandarg#1#2{\krdexpanded{\unexpanded{#1}{#2}}}
+\protected\def\krdexpandargonce#1#2{%
+ \krdexpanded{\unexpanded{#1}{\krdexpandonce{#2}}}%
+}
+\protected\def\krdexpandsecond#1#2{\krdexpanded{\unexpanded{#1}#2}}
+\protected\def\krdexpandsecondonce#1#2{%
+ \krdexpanded{\unexpanded{#1}\krdexpandonce{#2}}%
+}
+\def\krdaftergr#1{%
+ \edef\noexpand#1{\noexpand\unexpanded{\krdexpandonce{#1}}}%
+}
+\protected\def\krdifescaped#1{%
+ \begingroup
+ \escapechar92\relax
+ \edef\x{\expandafter\@car\string#1x\@nil}%
+ \expandafter\endgroup
+ \csname @\ifx\x\@backslashchar first\else second\fi oftwo\endcsname
+}
+% Eg,
+% \newcount\nr\nr=\tw@
+% \def\do#1{%
+% \let\noexpand#1%
+% \expandafter\noexpand\csname\expandafter\@gobble\string#1@%
+% \romannumeral\nr\endcsname
+% }
+% \edef\x{\krdfor{\cmda,\cmdb}}
+% \show\x -> \let\cmda\cmda@ii \let\cmdb\cmdb@ii
+%
+\def\krdfor#1{\krd@for@a#1,\krd@nnil,\krd@nil}
+\def\krd@for@a#1,#2\krd@nil{%
+ \krdifblank{#1}{%
+ \krd@for@a#2\krd@nil
+ }{%
+ \expandafter\krdifx\@car#1\@nil\krd@nnil
+ {}{\do{#1}\krd@for@a#2\krd@nil}%
+ }%
+}
+% We redefine xkeyval's loops to increase robustness.
+% We can't replace \@nil by \krd@nil here because xkeyval uses \@nil
+% to terminate the loops.
+\protected\long\def\XKV@for@n#1#2#3{%
+ \edef#2{\unexpanded{#1}}%
+ \krdifx#2\@empty{}{%
+ \XKV@f@r#2{#3}#1,\@nil,%
+ }%
+}
+\let\krdcommaloop\XKV@for@n
+\let\krdecommaloop\XKV@for@o
+\protected\long\def\XKV@f@r#1#2#3,{%
+ \edef#1{\unexpanded{#3}}%
+ \krdifx#1\@nnil{}{#2\XKV@f@r#1{#2}}%
+}
+\protected\long\def\XKV@for@eo#1#2#3{%
+ \edef#2{\unexpanded{\XKV@f@r#2{#3}}}%
+ \expandafter#2#1,\@nil,%
+}
+\protected\long\def\XKV@whilist#1#2#3\fi#4{%
+ #3\relax
+ \expandafter\@firstofone
+ \else
+ \expandafter\@gobble
+ \fi
+ {\expandafter\XKV@wh@list#1,\@nil,\@nnil#2#3\fi{#4}{}}%
+}
+\long\def\XKV@wh@list#1,#2\@nnil#3#4\fi#5#6{%
+ \edef#3{\unexpanded{#1}}%
+ \krdifx#3\@nnil{%
+ \def#3{#6}\@gobble
+ }{%
+ #4\relax
+ \expandafter\@firstofone
+ \else
+ \def#3{#6}%
+ \expandafter\@gobble
+ \fi
+ }%
+ {#5\XKV@wh@list#2\@nnil#3#4\fi{#5}{#1}}%
+}
+\protected\def\KV@@sp@def#1#2{\edef#1{\krdtrimspace{#2}}}
+\protected\def\XKV@sp@deflist#1#2{%
+ \edef#1{\unexpanded{#2}}%
+ \krdcsvnormalize#1%
+}
+\protected\def\krd@pushmacros#1#2#3{%
+ \begingroup
+ \global\advance#2\@ne
+ \krdifdef#1{}{\def#1{}}%
+ \def\reserved@a##1{\expandafter\@gobble\string##1@\romannumeral#2}%
+ \def\do##1{\let\noexpand##1\krdnoexpandcs{\reserved@a{##1}}}%
+ \xdef#1{#3{\krdexpandonce#1}}%
+ \def\do##1{\let\krdnoexpandcs{\reserved@a{##1}}\noexpand##1}%
+ \krdexpanded{\endgroup#3}%
+}
+\protected\def\krd@popmacros#1#2{%
+ \begingroup
+ \def\reserved@a##1##{\endgroup##1\gdef#1}%
+ \expandafter\reserved@a#1%
+ \global\advance#2\m@ne
+}
+
+\protected\def\krd@testst#1{\@ifstar{\krd@sttrue#1}{\krd@stfalse#1}}
+
+% \krdforeach[<parser>]
+% {<list>}<\if...>\fi{<ini-code>}{<final-code>}{<reg-code>}
+% \krdforeach*[<parser>]
+% {<listcmd>}<\if...>\fi{<ini-code>}{<final-code>}{<reg-code>}
+%
+% 1. When the conditional <\if...> isn't true, the regular code <reg-code>
+% will be executed for every member of the list.
+% 2. <final-code> will be executed when the conditional <\if...> is true.
+% <ini-code> may be used to first turn <\if...> off before commencing
+% the loop. \ifkrd@foreach@break may be used as the conditional in
+% <\if...>.
+% 3. Both <ini-code> and <final-code> can be empty (ie, {}).
+% 4. Use '#1' in <final-code> and <reg-code> to access the current element
+% of the list.
+%
+\protected\def\krdforeach{\krd@testst{\@testopt\krd@foreach,}}
+\protected\def\krd@foreach[#1]#2#3\fi#4#5#6{%
+ \krd@pushmacros\krd@foreach@stack\krd@csvdepth{%
+ \do\krd@foreach@do\do\krd@foreach@final\do\krd@foreach@regular
+ \do\stopforeach
+ }%
+ \edef\krd@foreach@item{\krdifbool{krd@st}\krdexpandonce\unexpanded{#2}}%
+ \krdcsvnormalize[#1]\krd@foreach@item
+ \def\krd@foreach@final##1{#5}%
+ \def\krd@foreach@regular##1{#6}%
+ \krd@foreach@breakfalse
+ \let\stopforeach\krd@foreach@breaktrue
+ % Initial code:
+ #4\relax
+ \def\krd@foreach@do##1#1##2\krd@nnil{%
+ \edef\krd@foreach@item{\krdexpandonce{\@gobble##1}}%
+ \krdifx\krd@foreach@item\krd@nnil{%
+ \krd@foreach@breakfalse
+ }{%
+ \krdifcond#3\fi{%
+ \expandafter\krd@foreach@final\expandafter{\krd@foreach@item}\relax
+ }{%
+ \expandafter\krd@foreach@regular\expandafter{\krd@foreach@item}\relax
+ \krdifbool{krd@foreach@break}{%
+ \krd@foreach@breakfalse
+ }{%
+ \krd@foreach@do.##2\krd@nnil
+ }%
+ }%
+ }%
+ }%
+ \expandafter\krd@foreach@do\expandafter
+ .\krd@foreach@item#1\krd@nil#1\krd@nnil
+ \krd@popmacros\krd@foreach@stack\krd@csvdepth
+}
+\protected\def\krdaddtolist{\krd@testst{\@testopt{\krd@addtolist{e}},}}
+\protected\def\krdgaddtolist{\krd@testst{\@testopt{\krd@addtolist{x}},}}
+\protected\def\krd@addtolist#1[#2]#3#4{%
+ \@nameuse{#1def}#3{%
+ \krdifdef#3{%
+ \krdifx#3\@empty{}{\krdexpandonce#3#2}%
+ }{}%
+ \krdifbool{krd@st}\krdexpandonce\unexpanded{#4}%
+ }%
+}
+\protected\def\krdcsvnormalize{\@testopt\krd@csvnormalize,}
+\protected\def\krd@csvnormalize[#1]#2{%
+ \begingroup
+ \krd@setupnormalize{#1}%
+ \def\krd@inkv{01}%
+ \edef#2{\expandafter\krd@normalizelist\expandafter{#2}}%
+ \krdexpanded{\endgroup
+ \edef\noexpand#2{\noexpand\unexpanded{\krdexpandonce{#2}}}%
+ }%
+}
+\protected\def\krdkvnormalize#1{%
+ \begingroup
+ \krd@setupnormalize{,}%
+ \def\krd@inkv{00}%
+ \edef#1{\expandafter\krd@normalizelist\expandafter{#1^?^}}%
+ \def\reserved@b##1^?^##2\krd@nil{%
+ \edef#1{\unexpanded{##1##2}}%
+ }%
+ \expandafter\reserved@b#1\krd@nil
+ \krdexpanded{\endgroup
+ \edef\noexpand#1{\noexpand\unexpanded{\krdexpandonce{#1}}}%
+ }%
+}
+\begingroup
+\catcode`\~=13
+\catcode`\!=13
+\protected\gdef\krd@setupnormalize#1{%
+ \begingroup
+ \uccode`\~=`#1%
+ \uccode`\!=`\=%
+ \uppercase{\endgroup
+ \def\krd@normalizelist##1{%
+ \unexpanded\expandafter{\romannumeral-`\q
+ \krd@activeparser#1##1#1~\krd@nil}%
+ }%
+ \def\krd@activeparser##1~##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krdifswitch\krd@inkv{%
+ \krd@activeequal##1!\krd@nil
+ }{%
+ \krd@spaceparser##1 #1\krd@nil
+ }%
+ }{%
+ \krd@activeparser##1#1##2\krd@nil
+ }%
+ }%
+ }%
+ \begingroup
+ \uccode`\~=`\=%
+ \uppercase{\endgroup
+ \def\krd@activeequal##1~##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krd@spaceparser##1 #1\krd@nil
+ }{%
+ \krd@activeequal##1=##2\krd@nil
+ }%
+ }%
+ }%
+ \def\krd@spaceparser##1 #1##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krd@parserspace##1#1 \krd@nil
+ }{%
+ \krd@spaceparser##1#1##2\krd@nil
+ }%
+ }%
+ \def\krd@parserspace##1#1 ##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krdifswitch\krd@inkv{%
+ \krd@spaceequal##1 =\krd@nil
+ }{%
+ \krd@doubleparser##1#1#1\krd@nil
+ }%
+ }{%
+ \krd@parserspace##1#1##2\krd@nil
+ }%
+ }%
+ \def\krd@spaceequal##1 =##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krd@equalspace##1= \krd@nil
+ }{%
+ \krd@spaceequal##1=##2\krd@nil
+ }%
+ }%
+ \def\krd@equalspace##1= ##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krd@doubleparser##1#1#1\krd@nil
+ }{%
+ \krd@equalspace##1=##2\krd@nil
+ }%
+ }%
+ \def\krd@doubleparser##1#1#1##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krdifswitch\krd@inkv{%
+ \krd@doubleequal##1==\krd@nil
+ }{%
+ \krdifblank{##1}{}{%
+ \krd@remleadparser##1\krd@nil
+ }%
+ }%
+ }{%
+ \krd@doubleparser##1#1##2\krd@nil
+ }%
+ }%
+ \def\krd@doubleequal##1==##2\krd@nil{%
+ \krdifblank{##2}{%
+ \krdifblank{##1}{}{%
+ \krd@remleadparser##1\krd@nil
+ }%
+ }{%
+ \krd@doubleequal##1=##2\krd@nil
+ }%
+ }%
+ \def\krd@remleadparser#1##1\krd@nil{\noexpand##1}%
+ \def\krd@parserequalerr##1#1=##2\krd@nil{%
+ \krdifblank{##2}{}{%
+ \krd@err{There is '#1=' in your key-value list}\krd@ehd
+ }%
+ }%
+}
+\endgroup
+\krd@setupnormalize{,}
+
+% Filter class options to remove '=' and option values. Do this
+% retroactively if this package was loaded before \documentclass.
+% The keyreader package can be loaded before \documentclass.
+\protected\def\XKV@filterclassoptions{%
+ \XKV@sgfalse
+ \ifx\@classoptionslist\@undefined\else
+ \ifx\@classoptionslist\relax\else
+ \ifx\@classoptionslist\@empty\else
+ \XKV@sgtrue
+ \fi
+ \fi
+ \fi
+ \ifXKV@sg
+ \let\XKV@filterclassoptions\relax
+ \let\XKV@origclassoptionslist\@classoptionslist
+ \let\XKV@classoptionslist\@classoptionslist
+ \def\@classoptionslist{}%
+ \XKV@for@o\XKV@classoptionslist\XKV@tempa{%
+ \@expandtwoargs\in@{=}{\krdoxdetok\XKV@tempa}%
+ \ifin@\else
+ \edef\@classoptionslist{%
+ \@classoptionslist\ifx\@classoptionslist\@empty\else,\fi
+ \unexpanded\expandafter{\XKV@tempa}%
+ }%
+ \fi
+ }%
+ \fi
+}
+\def\XKV@getdocumentclass{%
+ \let\XKV@documentclass\@undefined
+ \XKV@sgfalse
+ \ifdefined\@filelist
+ \ifx\@filelist\@gobble\else
+ \ifx\@filelist\relax\else
+ \ifx\@filelist\@empty\else
+ \XKV@sgtrue
+ \fi
+ \fi
+ \fi
+ \fi
+ \ifXKV@sg
+ \def\XKV@tempb{00}%
+ \XKV@whilist\@filelist\XKV@tempa\if\XKV@tempb\fi{%
+ \filename@parse\XKV@tempa
+ \ifx\filename@ext\@clsextension
+ \edef\XKV@tempa{\filename@area\filename@base.\filename@ext}%
+ \XKV@ifundefined{opt@\XKV@tempa}{}{%
+ \let\XKV@documentclass\XKV@tempa
+ \def\XKV@tempb{01}%
+ }%
+ \fi
+ }%
+ \fi
+}
+\XKV@getdocumentclass
+\ifdefined\XKV@documentclass
+ \XKV@filterclassoptions
+\else
+ \let\XKV@documentclass\@empty
+ \let\XKV@classoptionslist\@empty
+ \xdef\@popfilename{%
+ \unexpanded\expandafter{\@popfilename}%
+ \noexpand\XKV@filterclassoptions
+ }%
+\fi
+
+% Redefine \XKV@define@key to heed a complaint about the grabbing
+% of the callback:
+\protected\def\XKV@define@key#1{%
+ \@ifnextchar[{%
+ \XKV@d@fine@k@y{#1}%
+ }{%
+ \begingroup
+ \toks1{\endgroup\@namedef{\XKV@header#1}####1}%
+ \def\reserved@a{\the\toks\expandafter1\expandafter{\the\toks0}}%
+ \afterassignment\reserved@a\toks0=%
+ }%
+}
+\def\XKV@d@fine@k@y#1[#2]#3{%
+ \XKV@define@default{#1}{#2}%
+ \expandafter\def\csname\XKV@header#1\endcsname##1{#3}%
+}
+% When the key value has doubled hash characters, xkeyval's
+% definition of \XKV@define@cmdkey fails:
+\def\XKV@define@cmdkey#1#2[#3]#4{%
+ \ifXKV@st\XKV@define@default{#2}{#3}\fi
+ \def\XKV@tempa{\expandafter\def\csname\XKV@header#2\endcsname####1}%
+ \begingroup\expandafter\endgroup\expandafter\XKV@tempa\expandafter
+ {\expandafter\edef\csname#1#2\endcsname{\unexpanded{##1}}#4}%
+}
+% Allow macro prefix (default: mp@) for choice keys:
+\protected\def\define@choicekey{%
+ \XKV@testopta{\XKV@testoptb
+ {\@testopt\XKV@define@choicekey{choice\XKV@header}}}%
+}
+\def\XKV@define@choicekey[#1]#2{%
+ \edef\XKV@macropf{\krdtrimspace{#1}\krdtrimspace{#2}}%
+ \@testopt{\XKV@d@fine@choicekey{#2}}{}%
+}
+\def\XKV@d@fine@choicekey#1[#2]#3{%
+ \XKV@tempa@toks{#2}%
+ \XKV@sp@deflist\XKV@tempa{#3}%
+ \XKV@toks\expandafter{\XKV@tempa}%
+ \@ifnextchar[{\XKV@d@fine@ch@icekey{#1}}{\XKV@d@fine@ch@ic@key{#1}}%
+}
+\def\XKV@d@fine@ch@icekey#1[#2]{%
+ \edef\krd@default{\krdtrimspace{#2}}%
+ % Choice keys shouldn't have braced values:
+ \krdstripouterbraces{2}\krd@default
+ \krdexpanded{%
+ \noexpand\XKV@define@default{#1}{\krdexpandonce\krd@default}%
+ }%
+ \XKV@d@fine@ch@ic@key{#1}%
+}
+\def\XKV@d@fine@ch@ic@key#1{%
+ \edef\reserved@a{\krdnoexpandcs{\XKV@header#1}}%
+ \krdifbool{XKV@pl}{%
+ \expandafter\XKV@d@f@ne@ch@ic@k@y\reserved@a
+ }{%
+ \expandafter\XKV@d@f@ne@ch@ic@key\reserved@a
+ }%
+}
+\def\XKV@d@f@ne@ch@ic@key#1#2{\XKV@d@f@n@@ch@ic@k@y#1{{#2}}}
+\def\XKV@d@f@ne@ch@ic@k@y#1#2#3{\XKV@d@f@n@@ch@ic@k@y#1{{#2}{#3}}}
+\def\XKV@d@f@n@@ch@ic@k@y#1#2{%
+ \edef#1##1{%
+ \edef\krdnoexpandcs{\XKV@macropf}{\noexpand\unexpanded{##1}}%
+ \ifXKV@st\noexpand\XKV@sttrue\else\noexpand\XKV@stfalse\fi
+ \ifXKV@pl\noexpand\XKV@pltrue\else\noexpand\XKV@plfalse\fi
+ \noexpand\XKV@checkchoice[\the\XKV@tempa@toks]{##1}{\the\XKV@toks}%
+ }%
+ \def\XKV@tempa{\def#1####1}%
+ \expandafter\XKV@tempa\expandafter{#1{##1}#2}%
+}
+\protected\def\XKV@checksanitizea#1#2{%
+ \XKV@ch@cksanitize{#1}#2=%
+ \ifin@\else\XKV@ch@cksanitize{#1}#2,\fi
+ \krdifbool{in@}{\krdkvnormalize#2}{}%
+}
+\protected\def\XKV@checksanitizeb#1#2{%
+ \XKV@ch@cksanitize{#1}#2,%
+ \krdifbool{in@}{\krdcsvnormalize[,]#2}{}%
+}
+% Don't apply the new schemes to \setkeys, because old calls to
+% \setkeys will now discover that braces are preserved. This may
+% break their codes:
+\protected\def\krdsetkeys{\XKV@testopta{\XKV@testoptc\krd@setkeys}}
+\protected\def\krd@setkeys[#1]#2{%
+ \edef\krd@na{\unexpanded{#1}}%
+ \krdifx\krd@na\@empty{}{\krdcsvnormalize\krd@na}%
+ \edef\XKV@resb{\unexpanded{#2}}%
+ \krdkvnormalize\XKV@resb
+ \let\XKV@naa\@empty
+ \XKV@for@o\XKV@resb\XKV@tempa{%
+ \expandafter\XKV@g@tkeyname\XKV@tempa=\@nil\XKV@tempa
+ \XKV@addtolist@x\XKV@naa\XKV@tempa
+ }%
+ \ifnum\XKV@depth=\krdz@\let\XKV@rm\@empty\fi
+ \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{preseth}%
+ \krdexpandsecond\krd@s@tkeys
+ {{\krdexpandonce\XKV@resb}{\krdexpandonce\krd@na}}%
+ \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{presett}%
+ \let\CurrentOption\@empty
+}
+\protected\def\krd@s@tkeys#1#2{%
+ \edef\key@list{\unexpanded{#1}}%
+ \krdkvnormalize\key@list
+ \edef\XKV@na{\unexpanded{#2}}%
+ \krdifx\XKV@na\@empty{}{\krdcsvnormalize\XKV@na}%
+ \def\krd@s@tkeys@a##1={%
+ \def\reserved@a####1=####2\@nil{%
+ \edef\reserved@a{\expandafter\krdtrimspace\expandafter{\@gobble####1}}%
+ \krdifx\reserved@a\@empty{%
+ \expandafter\krd@s@tk@ys##1==\@nil
+ }{%
+ \expandafter\krdifbraced\expandafter{\reserved@a}{%
+ \edef\CurrentOption{%
+ \unexpanded{##1}={{\krdexpandonce\reserved@a}}%
+ }%
+ }{%
+ \edef\CurrentOption{\unexpanded{##1}=\krdexpandonce\reserved@a}%
+ }%
+ \expandafter\krd@s@tk@ys\CurrentOption==\@nil
+ }%
+ }%
+ \reserved@a.%
+ }%
+ \XKV@for@o\key@list\CurrentOption{%
+ \expandafter\krd@s@tkeys@a\CurrentOption==\@nil
+ }%
+}
+% I found that \XKV@s@tk@ys is responsible for the inability of
+% xkeyval's \setkeys to handle unbalanced conditionals. So
+% we redefine it here, but only for \krdsetkeys:
+\protected\def\krd@s@tk@ys#1=#2=#3\@nil{%
+ \XKV@g@tkeyname#1=\@nil\XKV@tkey
+ \krdexpandargonce{\KV@@sp@def\XKV@tkey}\XKV@tkey
+ \krdifx\XKV@tkey\@empty{%
+ \krdifblank{#2}{}{%
+ \krd@err{No key specified for value
+ \MessageBreak '\the\XKV@toks'}\krd@ehd
+ }%
+ }{%
+ \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}%
+ \krdifbool{in@}{}{%
+ \XKV@knftrue
+ \KV@@sp@def\XKV@tempa{#2}%
+ \krdifbool{XKV@preset}{%
+ \XKV@s@tk@ys@{#3}%
+ }{%
+ \krdifbool{XKV@pl}{%
+ \XKV@for@eo\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \XKV@s@tk@ys@{#3}%
+ }%
+ }{%
+ \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{%
+ \XKV@makehd\XKV@tfam
+ \XKV@s@tk@ys@{#3}%
+ }%
+ }%
+ }%
+ \krdifbool{XKV@knf}{%
+ \krdifbool{XKV@inpox}{%
+ \krdifx\XKV@doxs\relax{%
+ \ifx\@currext\@clsextension\else
+ \let\CurrentOption\XKV@tkey\@unknownoptionerror
+ \fi
+ }{%
+ \XKV@doxs
+ }%
+ }{%
+ \krdifbool{XKV@st}{%
+ \XKV@addtolist@o\XKV@rm\CurrentOption
+ }{%
+ \krd@err{Key '\XKV@tkey' is undefined in
+ families \MessageBreak '\XKV@fams'}\krd@ehd
+ }%
+ }%
+ }{%
+ \krdifbool{XKV@inpox}{%
+ \krdifx\XKV@testclass\XKV@documentclass{%
+ \expandafter\XKV@useoption\expandafter{\CurrentOption}%
+ }{}%
+ }{}%
+ }%
+ }%
+ }%
+}
+% When the key default value has doubled hash characters,
+% xkeyval's definition of \XKV@default fails:
+\protected\def\XKV@default#1#2\@nil{%
+ \edef\XKV@tempa{\expandafter\@gobble\string#1}%
+ \edef\XKV@tempb{\XKV@header\XKV@tkey}%
+ \@onelevel@sanitize\XKV@tempb
+ \krdifx\XKV@tempa\XKV@tempb{%
+ \begingroup
+ \@namedef{\XKV@header\XKV@tkey}##1{%
+ \toks@{\edef\XKV@tempa{\unexpanded{##1}}}%
+ }%
+ \csname\XKV@header\XKV@tkey @default\endcsname
+ \expandafter\endgroup\the\toks@
+ \krdifcsdef{XKV@\XKV@header save}{%
+ \expandafter\XKV@testsavekey\csname XKV@\XKV@header
+ save\endcsname\XKV@tkey
+ }{}%
+ \ifXKV@rkv
+ \ifXKV@sg\expandafter\global\fi
+ \expandafter\let
+ \csname XKV@\XKV@header\XKV@tkey @value\endcsname\XKV@tempa
+ \fi
+ \expandafter\XKV@replacepointers\expandafter{\XKV@tempa}%
+ \XKV@srstate{@\romannumeral\XKV@depth}{}%
+ \expandafter#1\expandafter{\XKV@tempa}\relax
+ \XKV@srstate{}{@\romannumeral\XKV@depth}%
+ }{%
+ \XKV@srstate{@\romannumeral\XKV@depth}{}%
+ \csname\XKV@header\XKV@tkey @default\endcsname\relax
+ \XKV@srstate{}{@\romannumeral\XKV@depth}%
+ }%
+}
+\protected\def\XKV@replacepointers#1{%
+ \let\XKV@tempa\@empty
+ \let\XKV@resa\@empty
+ \XKV@r@placepointers#1\usevalue\@nil
+}
+\def\XKV@r@placepointers#1\usevalue#2{%
+ \XKV@addtomacro@n\XKV@tempa{#1}%
+ \edef\XKV@tempb{\unexpanded{#2}}%
+ \ifx\XKV@tempb\@nnil\else\XKV@afterfi
+ \XKV@ifundefined{XKV@\XKV@header#2@value}{%
+ \krd@err{No value has been recorded for key
+ \MessageBreak '#2'; pointer not replaced}\krd@ehd
+ \XKV@r@placepointers
+ }{%
+ \@expandtwoargs\in@{,\detokenize{#2},}{,\krdoxdetok\XKV@resa,}%
+ \ifin@\XKV@afterelsefi
+ \krd@err{Possible back linking of pointers;
+ \MessageBreak pointer replacement terminated}\krd@ehd
+ \else\XKV@afterfi
+ \XKV@addtolist@x\XKV@resa{#2}%
+ \expandafter\expandafter\expandafter\XKV@r@placepointers
+ \csname XKV@\XKV@header#2@value\endcsname
+ \fi
+ }%
+ \fi
+}
+\protected\def\krdsetrmkeys{\XKV@testopta{\XKV@testoptc\krd@setrmkeys}}
+\protected\def\krd@setrmkeys[#1]{%
+ \krdexpandargonce{\krd@setkeys[#1]}\XKV@rm
+}
+% We alias xkeyval's \savekeys to \savevaluekeys:
+\protected\def\savevaluekeys{\savekeys}
+% We split xkeyval's \presetkeys (head and tail) into
+% \krdpresetkeys (head only) and \krdpostsetkeys (tail only):
+\protected\def\krdpresetkeys{\@testopt\krd@presetkeys{KV}}
+\protected\def\krd@presetkeys[#1]#2#3{\presetkeys[#1]{#2}{#3}{}}
+\protected\def\krdpostsetkeys{\@testopt\krd@postsetkeys{KV}}
+\protected\def\krd@postsetkeys[#1]#2#3{\presetkeys[#1]{#2}{}{#3}}
+\protected\def\krd@disabledkey@err#1{%
+ \krd@err{Key '#1' has been disabled}
+ {You can't set or reset key '#1' at this\MessageBreak
+ late stage. Perhaps you should have set it \MessageBreak
+ earlier in \string\documentclass\@space or \string\usepackage}%
+}
+\protected\def\krddisablekeys{\XKV@testoptb\krd@disablekeys}
+\protected\def\krd@disablekeys#1{%
+ \def\XKV@tempa{#1}%
+ \krdcsvnormalize\XKV@tempa
+ \XKV@for@o\XKV@tempa\XKV@tempa{%
+ \krdifcsdef{\XKV@header\XKV@tempa}{}{%
+ \@latex@warning@no@line{Key '\XKV@tempa' is undefined:
+ couldn't be disabled}%
+ }%
+ \krdifcsdef{\XKV@header\XKV@tempa @default}{%
+ \edef\XKV@tempb{\noexpand\XKV@define@key{\XKV@tempa}[]}%
+ }{%
+ \edef\XKV@tempb{\noexpand\XKV@define@key{\XKV@tempa}}%
+ }%
+ \krdexpandarg{\expandafter\XKV@tempb\expandafter}%
+ {\krd@disabledkey@err{\XKV@tempa}}%
+ }%
+}
+\edef\krd@hashchar{\string#}
+
+% \krddefinekeys[<pref>]{<fam>}[<mp>]{
+% ord/<key>/<dft>/<f1>;
+% cmd/<key>/<dft>/<f1>;
+% bool/<key>/<dft>/<f1>;
+% bool+/<key>/<dft>/<f1>/<f2>;
+% choice/<key>/<dft>/<alt>/<f1>;
+% choice+/<key>/<dft>/<alt>/<f1>/<f2>;
+% }
+\protected\def\krddefinekeys{%
+ \begingroup
+ \endlinechar\m@ne
+ \krd@testst{\@testopt\krd@definekeys{KV}}%
+}
+\protected\def\krd@definekeys[#1]#2{%
+ \@testopt{\krd@d@finekeys{#1}{#2}}{krdmp@}%
+}
+\protected\def\krd@d@finekeys#1#2[#3]#4{%
+ \expandafter\endgroup
+ \edef\krd@keyst{0\ifkrd@st0\else1\fi}%
+ \krdindeftrue
+ \begingroup
+ \edef\krd@prefix{\krdtrimspace{#1}}%
+ \edef\krd@family{\krdtrimspace{#2}}%
+ \edef\krd@macpref{\krdtrimspace{#3}}%
+ \toks@{}%
+ \def\krd@rej{^?^}%
+ \def\krd@defna{.na}%
+ \def\krd@vals{}%
+ \let\krduserinput\relax
+ \let\krdorder\relax
+ \def\krd@splita##1/##2/{\krd@splitb##1/##2/.}%
+ \def\krd@splitb##1/##2/##3/##4/##5/##6/##7/##8/##9\krd@nil{%
+ \edef\krd@type{\krdzapspace{##1}}%
+ \edef\krd@name{\krdtrimspace{##2}}%
+ \edef\krd@default{\krdusearg\krdtrimspace{\@gobble##3}}%
+ \edef\krd@itemfour{\krdtrimspace{##4}}%
+ \edef\krd@itemfive{\krdtrimspace{##5}}%
+ \edef\krd@itemsix{\krdtrimspace{##6}}%
+ \@expandtwoargs\in@{\krd@hashchar}{\detokenize{##2}}%
+ \ifin@
+ \krd@err{Bad key name '\detokenize{##2}'}\krd@ehd
+ \fi
+ \if\krd@keyst
+ \krdifcsdef{\krd@prefix @\krd@family @##2}{%
+ \krd@err{Key '##2' already exists in
+ family '\krd@family'}\krd@ehd
+ }{}%
+ \fi
+ \@expandtwoargs\in@
+ {,\krdoxdetok\krd@type,}
+ {,\detokenize{ord,cmd,bool,bool+,choice,choice+},}%
+ \ifin@\else
+ \krd@err{Unknown key type '\krd@type'}\krd@ehd
+ \fi
+ % ord{0}cmd{1}bool{2}bool+{3}choice{4}choice+{5}
+ \krdusearg\krd@gettypenr{\krd@type}%
+ \ifnum\krd@typenr>\thr@@
+ \krdstripouterbraces{2}\krd@default
+ \ifcase0%
+ \ifx\krd@itemfour\@empty\else
+ \ifx\krd@itemfour\krd@rej\else
+ \ifx\krd@itemfour\krd@defna\else 1\fi\fi\fi\relax
+ \krd@err{Empty nominations for choice key \krd@name}\krd@ehd
+ \else
+ \krd@getaltlist{##4}%
+ \fi
+ \fi
+ \@expandtwoargs\in@
+ {,\krdoxdetok\krd@default,}{,\detokenize{true,false},}%
+ \edef\krd@vals{%
+ \ifx\krd@vals\@empty\else\krdexpandonce\krd@vals,\fi
+ \ifx\krd@default\krd@rej\else
+ \ifx\krd@default\krd@defna\else
+ \krd@name=\ifin@ false\else\krdexpandonce\krd@default\fi
+ \fi
+ \fi
+ }%
+ \krdexpanded{%
+ \toks@{\the\toks@
+ \krdncsname define@\krd@typefordef key\endcsname
+ \if\krd@plustype+\fi
+ [\krd@prefix]{\krd@family}%
+ \ifnum\krd@typenr>\krdz@[\krd@macpref]\fi
+ {\krd@name}%
+ \ifnum\krd@typenr>\thr@@
+ [\krduserinput\krdorder]{\krdexpandonce\krd@altlist@a}%
+ \fi
+ \ifx\krd@default\krd@rej\else
+ \ifx\krd@default\krd@defna\else
+ [{\krdexpandonce\krd@default}]%
+ \fi
+ \fi
+ {% callback-1
+ \ifnum\krd@typenr>\thr@@
+ \ifx\krd@itemfive\krd@rej\else
+ \ifx\krd@itemfive\krd@defna\else
+ \krdexpandonce\krd@itemfive
+ \fi
+ \fi
+ \krd@executealt{########1}{\krdexpandonce\krd@altlist@b}%
+ \else
+ \ifx\krd@itemfour\krd@rej\else
+ \ifx\krd@itemfour\krd@defna\else
+ \krdexpandonce\krd@itemfour
+ \fi
+ \fi
+ \fi
+ }%
+ \if\krd@plustype
+ {% callback-2
+ \ifnum\krd@typenr>\thr@@
+ \ifx\krd@itemsix\krd@rej
+ \noexpand\krd@keyvalerr
+ \else
+ \ifx\krd@itemsix\krd@defna
+ \noexpand\krd@keyvalerr
+ \else
+ \krdexpandonce\krd@itemsix
+ \fi
+ \fi
+ \else
+ \ifx\krd@itemfive\krd@rej
+ \noexpand\krd@keyvalerr
+ \else
+ \ifx\krd@itemfive\krd@defna
+ \noexpand\krd@keyvalerr
+ \else
+ \krdexpandonce\krd@itemfive
+ \fi
+ \fi
+ \fi
+ }%
+ \fi
+ }%
+ }%
+ }%
+ \edef\krd@list{\unexpanded{#4}}%
+ % Don't normalize for slash, since double slash (meaning, eg,
+ % "no value") will be made one slash.
+ \krdforeach*[;]\krd@list\if01\fi{}{}{%
+ \krd@splita##1/^?^/^?^/^?^/^?^/^?^/^?^/^?^/\krd@nil
+ }%
+ \krdexpanded{\endgroup
+ \the\toks@
+ \noexpand\krdsetkeys[\krd@prefix]%
+ {\krd@family}{\krdexpandonce\krd@vals}%
+ }%
+ \krdindeffalse
+}
+\protected\def\krd@gettypenr#1{%
+ \def\reserved@a##1#1##2##3\krd@nil{%
+ \def\krd@typenr{##2}%
+ \ifx\krd@typenr\krd@nnil
+ \krd@err{Invalid key type '#1'}\krd@ehd
+ \else
+ \edef\krd@typefordef{%
+ % Using \numexpr will remove \relax, which is needed
+ % to stop \ifcase's search for number.
+ \ifcase\numexpr\krd@typenr\relax\or
+ cmd\or bool\or bool\or choice\or choice\fi
+ }%
+ \fi
+ }%
+ \reserved@a ord{0}cmd{1}bool{2}bool+{3}choice{4}choice+{5}%
+ #1{\krd@nil}\krd@nil
+ \@expandtwoargs\in@{+\relax}{\krdoxdetok\krd@type\relax}%
+ \edef\krd@plustype{0\ifin@ 0\else 1\fi}%
+}
+\protected\def\krd@keyvalerr{%
+ \krd@getinnoval
+ \krd@err{Erroneous value '\krd@ival'
+ \MessageBreak for key or option '\XKV@tkey'}
+ {Invalid value for key '\XKV@tkey'.}%
+}
+\protected\def\krd@getaltlist#1{%
+ \begingroup
+ \def\krd@altlist@a{}%
+ \def\krd@altlist@b{}%
+ \def\krd@g@taltlist##1.do=##2.do=##3\krd@nil{%
+ \edef\XKV@tempa{\krdtrimspace{##1}}%
+ \krdstripouterbraces{2}\XKV@tempa
+ \edef\XKV@tempb{\krdoxdetok\XKV@tempa{\krdtrimspace{##2}}}%
+ \def\@do####1####2{%
+ \edef####1{%
+ \krdexpandonce####1\ifx####1\@empty\else,\fi
+ \krdexpandonce####2%
+ }%
+ }%
+ \@do\krd@altlist@a\XKV@tempa
+ \@do\krd@altlist@b\XKV@tempb
+ }%
+ \def\do##1{%
+ \krd@g@taltlist##1.do=.do=\krd@nil
+ }%
+ \krdfor{#1}%
+ \ifx\krd@altlist@a\@empty
+ \krd@err{No nominations for choice key}\@ehd
+ \def\krd@altlist@b{}%
+ \fi
+ \krdexpanded{\endgroup
+ \krdaftergr\krd@altlist@a\krdaftergr\krd@altlist@b
+ }%
+}
+\protected\def\krd@executealt#1#2{%
+ \edef\reserved@a{\krdtrimspace{#1}}%
+ \krdstripouterbraces{2}\reserved@a
+ \edef\reserved@a{\krdoxdetok\reserved@a}%
+ % There may be parameters characters in #2. So hide #2 in a macro:
+ \edef\reserved@b{\unexpanded{#2}}%
+ \def\reserved@c##1{%
+ \def\reserved@a####1##1####2####3\krd@nil{%
+ \edef\reserved@a{\unexpanded{####2}}%
+ \krdifx\reserved@a\krd@nnil{%
+ \krd@err{No choice match for key '\XKV@tkey'}\krd@ehd
+ }{%
+ ####2%
+ }%
+ }%
+ \expandafter\reserved@a\reserved@b#1{\krd@nil}\krd@nil
+ }%
+ \krdusearg\reserved@c\reserved@a
+}
+\def\krd@lengthofival{20}
+\protected\def\krd@getinnoval{%
+ \begingroup
+ \def\reserved@a##1=##2=##3\krd@nil{%
+ \def\krd@tval{##2}%
+ }%
+ \expandafter\reserved@a\CurrentOption==\krd@nil
+ \krdifx\krd@tval\@empty{%
+ \def\krd@ival{???}%
+ }{%
+ \def\krd@ival{}%
+ \@tempcnta\krdz@
+ \def\do##1{%
+ \def\reserved@a{##1}%
+ \krdifx\reserved@a\krd@nnil{}{%
+ \advance\@tempcnta\@ne
+ \ifnum\@tempcnta<\krd@lengthofival\relax
+ \edef\krd@ival{\krd@ival##1}%
+ \expandafter\do
+ \else
+ \def\do####1\krd@nil{}%
+ \expandafter\do
+ \fi
+ }%
+ }%
+ \expandafter\do\detokenize\expandafter{\krd@tval}\krd@nil
+ }%
+ \krdexpanded{\endgroup
+ \def\noexpand\krd@ival{\krd@ival}%
+ }%
+}
+\def\XKV@testopte#1{%
+ \XKV@ifstar{\XKV@sttrue\XKV@t@stopte#1}{\XKV@stfalse\XKV@t@stopte#1}%
+}
+\def\XKV@t@stopte#1{\@testopt{\XKV@t@st@pte#1}{KV}}
+\def\XKV@t@st@pte#1[#2]{%
+ \XKV@makepf{#2}%
+ \@ifnextchar<{\XKV@@t@st@pte#1}%
+ {\XKV@@t@st@pte#1<\@currname.\@currext>}%
+}
+\def\XKV@@t@st@pte#1<#2>{%
+ \XKV@sp@deflist\XKV@fams{#2}%
+ \@testopt#1{}%
+}
+\def\DeclareOptionX{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \XKV@ifstar\XKV@dox\XKV@d@x
+}
+\long\def\XKV@dox#1{\XKV@toks{#1}\edef\XKV@doxs{\the\XKV@toks}}
+\def\XKV@d@x{\@testopt\XKV@@d@x{KV}}
+\def\XKV@@d@x[#1]{%
+ \@ifnextchar<{\XKV@@@d@x[#1]}{\XKV@@@d@x[#1]<\@currname.\@currext>}%
+}
+\def\XKV@@@d@x[#1]<#2>#3{\@testopt{\define@key[#1]{#2}{#3}}{}}
+\def\ExecuteOptionsX{\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys}
+\def\ProcessOptionsX{\XKV@plfalse\XKV@testopte\XKV@pox}
+\def\XKV@pox[#1]{%
+ \let\XKV@tempa\@empty
+ \XKV@inpoxtrue
+ \let\@fileswith@pti@ns\@badrequireerror
+ \edef\XKV@testclass{\@currname.\@currext}%
+ \ifx\XKV@testclass\XKV@documentclass
+ \let\@unusedoptionlist\XKV@classoptionslist
+ \XKV@ifundefined{ver@xkvltxp.sty}{}{%
+ \@onelevel@sanitize\@unusedoptionlist
+ }%
+ \else
+ \ifXKV@st
+ \def\XKV@tempb##1,{%
+ \def\CurrentOption{##1}%
+ \ifx\CurrentOption\@nnil\else
+ \XKV@g@tkeyname##1=\@nil\CurrentOption
+ \XKV@key@if@ndefined{\CurrentOption}{}{%
+ \XKV@useoption{##1}%
+ \XKV@addtolist@n\XKV@tempa{##1}%
+ }%
+ \expandafter\XKV@tempb
+ \fi
+ }%
+ \expandafter\XKV@tempb\XKV@classoptionslist,\@nil,%
+ \fi
+ \fi
+ \expandafter\XKV@addtolist@o\expandafter
+ \XKV@tempa\csname opt@\@currname.\@currext\endcsname
+ \def\XKV@tempb{\XKV@setkeys[#1]}%
+ \expandafter\XKV@tempb\expandafter{\XKV@tempa}%
+ \let\XKV@doxs\relax
+ \let\XKV@rm\@empty
+ \XKV@inpoxfalse
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+}
+\def\XKV@useoption#1{%
+ \def\XKV@resa{#1}%
+ \XKV@ifundefined{ver@xkvltxp.sty}{}{%
+ \@onelevel@sanitize\XKV@resa
+ }%
+ \@expandtwoargs\@removeelement{\XKV@resa}%
+ {\@unusedoptionlist}\@unusedoptionlist
+}
+\krdnewlet\krdDeclareOption\DeclareOptionX
+\krdnewlet\krdExecuteOptions\ExecuteOptionsX
+\krdnewlet\krdProcessOptions\ProcessOptionsX
+\krdDeclareOption[KV]<keyreader>{lengthofival}[20]{%
+ \edef\krd@lengthofival{\number#1}%
+}
+\krdDeclareOption*{\PackageWarning{keyreader}{Unknown option
+ '\CurrentOption' ignored}}
+\krdExecuteOptions[KV]<keyreader>{lengthofival}
+\krdProcessOptions[KV]<keyreader>\relax
+
+\endinput