%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % % % This is file 'keyreader.sty', version 0.4, December 2011. % % % % 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) 2011 Ahmed Musa (amusa22@gmail.com). % % % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \ProvidesPackage{keyreader} [2011/12/20 v0.4 Robust xkeyval package interface (AM)] \ifcase \ifx\eTeXversion\@undefined\z@\else \ifnum\eTeXversion<\tw@\z@\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##1\end\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#1\end\else \edef\krd@restorecodes{% \krd@restorecodes \catcode#1=\the\catcode#1\relax }% \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\@undefined }% } \RequirePackage{xkeyval}[2008/08/13] \def\@space{ } \protected\def\krdnewlet#1{\@ifdefinable#1\relax\let#1} \krdnewlet\krd@nil\relax \def\krd@nnil{\krd@nil} \protected\def\krdAfterEndPackage{% \krdifcsndef{\@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*\krd@quark{\@gobble\krd@quark} \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*\krdifcsndef[1]{% \krdifblank{#1}{% \expandafter\@secondoftwo\@gobble }{% \ifcsname#1\endcsname \expandafter\@firstofone \else \expandafter\expandafter\expandafter \@secondoftwo\expandafter\@gobble \fi }{% \expandafter\krdifdef\csname#1\endcsname }% } \newcommand\krdifx[2]{% \ifx#1#2\krd@quark \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \long\def\krdifblank#1{% \ifcat$\detokenize\expandafter{\@gobble#1.}$% \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \def\krdifbool#1{% \krdifblank{#1}{% \@secondoftwo }{% \krdifcsndef{if#1}{% \csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname }{% \@latex@error{Undefined boolean '#1'}\@ehc }% }% } \def\krdifswitch@aux#1#2\krd@nil{% \krdifblank{#2}\@secondoftwo\@firstoftwo } \def\krdifswitch#1{% \krdifblank{#1}{% \@secondoftwo }{% \expandafter\krdifswitch@aux\romannumeral-`\q#1\krd@nil{% \if#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi }{% \@latex@error{Invalid switch '#1'}\@ehc }% }% } \krdifx\pdfstrcmp\@undefined{% \RequirePackage{pdftexcmds}% \krdifx\pdf@strcmp\@undefined{% \cpt@err{Neither \string\pdfstrcmp nor \string\pdf@strcmp exists}\@ehc }{% \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\krdifbraced#1{\krd@ifbraced#1\krd@nil{#1}} \def\krd@ifbraced#1\krd@nil#2{% \krdifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo } \def\krdexpandonce#1{\unexpanded\expandafter{#1}} \def\krdnoexpandcsn#1{\krdexpandonce{\csname#1\endcsname}} \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}}% } \newcount\krd@csvdepth \newif\ifkrd@lb \newif\ifkrd@st \krdnewlet\krdloopbreak\krd@lbtrue \begingroup \catcode`\&=7 \gdef\krdtrimspace#1{\krd@trimspace@a.#1& &} \gdef\krd@trimspace@a#1 &{\krd@trimspace@b#1&} \gdef\krd@trimspace@b#1{% \krdexpandonce{\romannumeral-`\q \expandafter\noexpand\@gobble#1}% } \endgroup \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}% }% } \def\krd@loopdostack{} \protected\def\krd@pushloopdo{% \global\advance\krd@csvdepth\@ne \def\reserved@a##1{\expandafter\@gobble\string##1@% \romannumeral\krd@csvdepth}% \def\do##1{\let\noexpand##1\krdnoexpandcsn{\reserved@a{##1}}}% \xdef\krd@loopdostack{% \krdfor{\krd@loopdo,\ifkrd@lb,\krd@loopact@a,\krd@loopact@b}% {\krdexpandonce\krd@loopdostack}% }% \def\do##1{\let\krdnoexpandcsn{\reserved@a{##1}}\noexpand##1}% \krdexpanded{% \krdfor{\krd@loopdo,\ifkrd@lb,\krd@loopact@a,\krd@loopact@b}% }% } \protected\def\krd@poploopdo{% \begingroup \def\reserved@a##1##{\endgroup##1\gdef\krd@loopdostack}% \expandafter\reserved@a\krd@loopdostack \global\advance\krd@csvdepth\m@ne } \protected\def\krd@testst#1{\@ifstar{\krd@sttrue#1}{\krd@stfalse#1}} \protected\def\krdlistloop{\krd@testst{\@testopt\krd@listloop,}} \protected\def\krd@listloop[#1]#2#3\fi#4#5#6{% \krd@pushloopdo \edef\krd@csvarg{\krdifbool{krd@st}\krdexpandonce\unexpanded{#2}}% \krdcsvnormalize[#1]\krd@csvarg \def\krd@loopact@a##1{#5}% \def\krd@loopact@b##1{#6}% #4\relax \def\krd@loopdo##1#1##2\krd@nnil{% \edef\krd@csvarg{\krdexpandonce{\@gobble##1}}% \krdifx\krd@csvarg\krd@nnil{}{% #3\relax \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {% \expandafter\krd@loopact@a\expandafter{\krd@csvarg}\relax }{% \expandafter\krd@loopact@b\expandafter{\krd@csvarg}\relax \krd@loopdo.##2\krd@nnil }% }% }% \expandafter\krd@loopdo\expandafter.\krd@csvarg#1\krd@nil#1\krd@nnil \krd@poploopdo } \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}{}{% \@latex@error{There is '#1=' in your key-value list}\@ehc }% }% } \endgroup \krd@setupnormalize{,} \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}% } \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}{}% } \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=\z@\let\XKV@rm\@empty\fi \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{preseth}% \krdexpandsecond\XKV@s@tkeys {{\krdexpandonce\XKV@resb}{\krdexpandonce\krd@na}}% \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{presett}% \let\CurrentOption\@empty } \protected\def\XKV@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\XKV@s@tkeys@a##1={% \def\reserved@a####1=####2\@nil{% \edef\reserved@a{\expandafter\krdtrimspace\expandafter{\@gobble####1}}% \krdifx\reserved@a\@empty{% \expandafter\XKV@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\XKV@s@tk@ys\CurrentOption==\@nil }% }% \reserved@a.% }% \XKV@for@o\key@list\CurrentOption{% \expandafter\XKV@s@tkeys@a\CurrentOption==\@nil }% } \protected\def\krdsetrmkeys{\XKV@testopta{\XKV@testoptc\krd@setrmkeys}} \protected\def\krd@setrmkeys[#1]{% \krdexpandargonce{\krd@setkeys[#1]}\XKV@rm } \protected\def\krd@disabledkey@err#1{% \@latex@error{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\krd@tempa{#1}% \krdcsvnormalize\krd@tempa \XKV@for@o\krd@tempa\krd@tempa{% \krdifcsndef{\XKV@header\krd@tempa}{}{% \@latex@warning@no@line{Key '\krd@tempa' is undefined: couldn't be disabled}% }% \krdifcsndef{\XKV@header\krd@tempa @default}{% \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}[]}% }{% \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}}% }% \krdexpandarg{\expandafter\krd@tempb\expandafter}% {\krd@disabledkey@err{\krd@tempa}}% }% } \edef\krd@hashchar{\string#} \protected\def\krddefinekeys{\krd@testst{\@testopt\krd@d@finekeys{KRD}}} \protected\def\krd@d@finekeys[#1]#2{\@testopt{\krd@d@f@nekeys{#1}{#2}}{krdmp@}} \protected\def\krd@d@f@nekeys#1#2[#3]#4{% \begingroup \let\ifkrd@keyst\ifkrd@st \edef\key@prefix{\krdtrimspace{#1}}% \edef\key@family{\krdtrimspace{#2}}% \edef\macro@prefix{\krdtrimspace{#3}}% \toks@{}% \def\krd@rej{^?^}% \def\key@vals{}% \def\krd@altlista{}% \def\krd@altlistb{}% \def\krd@splita##1/##2/{\krd@splitb##1/##2/.}% \def\krd@splitb##1/##2/##3/##4/##5/##6\krd@nil{% \edef\key@type{\krdtrimspace{##1}}% \edef\key@name{\krdtrimspace{##2}}% \@expandtwoargs\in@{\krd@hashchar}{\detokenize{##2}}% \ifin@ \@latex@error{Bad key name '\detokenize{##2}'}\@ehc \fi \ifkrd@keyst \krdifcsndef{\key@prefix @\key@family @##2}{% \@latex@error{Key '##2' already exists in family '\key@family'}\@ehc }{}% \fi \@expandtwoargs\in@{,\detokenize\expandafter{\key@type},}% {,\detokenize{ord,cmd,bool,choice},}% \ifin@\else \@latex@error{Unknown key type '\key@type'}\@ehc \fi \edef\key@default{\expandafter\krdtrimspace\expandafter{\@gobble##3}}% \edef\krd@resa{\krdtrimspace{##4}}% \edef\krd@resb{\krdtrimspace{##5}}% \@expandtwoargs\in@{,\detokenize\expandafter{\key@default},}% {,\detokenize{true,false},}% \edef\key@vals{% \ifx\key@vals\@empty\else\krdexpandonce\key@vals,\fi \ifx\key@default\krd@rej\else \key@name=\ifin@ false\else\krdexpandonce\key@default\fi \fi }% \def\reserved@a####1{% \def\reserved@a########1####1########2########3\krd@nil{% \def\key@typenr{########2}% \ifx\key@typenr\krd@nnil \@latex@error{Invalid key type '####1'}\@ehc \fi }% \reserved@a ord{0}cmd{1}bool{2}choice{3}####1{\krd@nil}\krd@nil }% \expandafter\reserved@a\expandafter{\key@type}% \ifnum\key@typenr=\thr@@ \edef\reserved@a{\unexpanded{##4}}% \krdifx\reserved@a\@empty{% \@latex@error{Empty alternate list for choice key \key@name}\@ehc }{% \krdifx\reserved@a\krd@rej{% \@latex@error{Empty alternate list for choice key \key@name}\@ehc }{% \krd@getaltlist{##4}% }% }% \fi \krdexpanded{% \toks@{\the\toks@ \krdnoexpandcsn{define@\ifnum\key@typenr>\z@\key@type\fi key}% \ifnum\key@typenr=\thr@@*\fi \ifnum\key@typenr>\@ne+\fi [\key@prefix]{\key@family}% \ifnum\key@typenr>\z@ \ifnum\key@typenr<\thr@@[\macro@prefix]\fi \fi {\key@name}% \ifnum\key@typenr=\thr@@ [\unexpanded{\userinput\order}]{\krdexpandonce\krd@altlista}% \fi \krdifx\key@default\krd@rej{}{% [\expandafter\krdifbraced\expandafter{\key@default}% {{{\krdexpandonce\key@default}}}{\krdexpandonce\key@default}]% }% {% \ifnum\key@typenr=\thr@@ \krdifx\krd@resb\krd@rej{}{\unexpanded{##5}}% \krd@executealt{########1}{\krdexpandonce\krd@altlistb}% \else \krdifx\krd@resa\krd@rej{}{\unexpanded{##4}}% \fi }% \ifnum\key@typenr>\@ne{\noexpand\krd@keyvalerr}\fi }% }% }% \edef\key@list{\unexpanded{#4}}% \krdcsvnormalize[/]\key@list \krdlistloop*[;]\key@list\ifx\end\@undefined\fi{}{}{% \krd@splita##1/^?^/^?^/^?^/^?^/\krd@nil }% \krdexpanded{\endgroup \the\toks@ \noexpand\krdsetkeys[\key@prefix]% {\key@family}{\krdexpandonce\key@vals}% }% } \protected\def\krd@keyvalerr{% \krd@getinnoval \@latex@error{Erroneous value '\krd@ival' for key or option \MessageBreak'\XKV@tkey'}{Invalid key value encountered.}% } \protected\def\krd@getaltlist#1{% \def\krd@g@taltlist##1.code=##2\krd@nil{% \edef\krd@tempa{\krdtrimspace{##1}}% \edef\krd@tempb{\krdexpandonce\krd@tempa{\krdtrimspace{##2}}}% \krdaddtolist*\krd@altlista\krd@tempa \krdaddtolist*\krd@altlistb\krd@tempb }% \krdlistloop[,]{#1}\ifx\end\@undefined\fi{}{}{% \@expandtwoargs\in@{\detokenize{.code=}}{\detokenize{##1}}% \krdifbool{in@}{% \krd@g@taltlist##1\krd@nil }{% \krd@g@taltlist##1.code=\krd@nil }% }% } \protected\def\krd@executealt#1#2{% \krdexpandsecond{\def\reserved@a##1}{\krdtrimspace{#1}}##2##3\krd@nil{% \edef\reserved@a{\unexpanded{##2}}% \krdifx\reserved@a\krd@nnil{% \@latex@error{No alternate list for key '\XKV@tkey'}\@ehc }{% ##2% }% }% \reserved@a#2#1{\krd@nil}\krd@nil } \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\z@ \def\do##1{% \def\reserved@a{##1}% \krdifx\reserved@a\krd@nnil{}{% \advance\@tempcnta\@ne \ifnum\@tempcnta<20\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}% }% } \krdnewlet\krdDeclareOption\DeclareOptionX \krdnewlet\krdExecuteOptions\ExecuteOptionsX \krdnewlet\krdProcessOptions\ProcessOptionsX \krdDeclareOption*{\PackageWarning{keyreader}{Unknown option '\CurrentOption' ignored.}} \krdProcessOptions[KRD]\relax \endinput