summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-10-17 22:50:05 +0000
committerKarl Berry <karl@freefriends.org>2012-10-17 22:50:05 +0000
commitdf2ce83ed9a6a3beca08c07cc656611e26d220d7 (patch)
tree086e2f15b6585eb8151e83f7852eb858db2f4b80
parent468e15f0c59bbedcccfaa606c1f72d3b6d3a8f9a (diff)
skeyval
git-svn-id: svn://tug.org/texlive/trunk@28005 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/README299
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdfbin609972 -> 0 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex2548
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdfbin0 -> 126230 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex431
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdfbin0 -> 136310 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex106
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls311
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty433
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdfbin0 -> 83477 bytes
-rw-r--r--Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex96
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty3184
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex6150
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex2583
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex266
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty437
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty44
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex70
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty352
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval.sty3766
-rwxr-xr-xMaster/tlpkg/libexec/ctan2tds1
21 files changed, 15415 insertions, 5662 deletions
diff --git a/Master/texmf-dist/doc/latex/skeyval/README b/Master/texmf-dist/doc/latex/skeyval/README
index 5dc7d3eae36..fe6e31d7d37 100644
--- a/Master/texmf-dist/doc/latex/skeyval/README
+++ b/Master/texmf-dist/doc/latex/skeyval/README
@@ -1,42 +1,257 @@
-%+++++++++++++++++++++++++++++++++++ INTRODUCTION +++++++++++++++++++++++++++++++++++%
-% %
-% This is the Readme file for the skeyval package, version 0.72. %
-% May 2010 %
-% %
-% Copyright (c) 2010 Ahmed Musa (a.musa@rocketmail.com). %
-% %
-%+++++++++++++++++++++++++++++++++++++ MOTIVATION +++++++++++++++++++++++++++++++++++%
-% %
-% The xkeyval package introduced many concepts for key definition and %
-% management. The skeyval package extends the functionality of the xkeyval %
-% package in many ways, including introducing: %
-% %
-% 1. Toggle keys %
-% 2. Complementary boolean and toggle keys %
-% 3. Mechanisms for reserving, unreserving, suspending, restoring, %
-% and removing keys %
-% 4. Tools for defining keys such that no existing key is inadvertently %
-% redefined %
-% 5. List normalization when setting keys %
-% 6. A mechanism for defining multiple keys of differing genres using only %
-% one command %
-% 7. Commands for checking the statuses of keys across multiple key prefixes %
-% and families %
-% 8. User-value keys and using pointers in defining keys %
-% 9. Some general-purpose LaTeX programming macros and hooks %
-% %
-%+++++++++++++++++++++++++++++++++++++ LICENSE ++++++++++++++++++++++++++++++++++++++%
-% %
-% 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. %
-% %
-%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \ No newline at end of file
+This is the README file for the 'skeyval' package.
+
+AUTHOR
+
+Ahmed Musa
+
+VERSION
+
+Version 1.1, October 2012.
+
+LOCATION ON CTAN
+
+macros/latex/contrib/skeyval
+
+LICENSE
+
+Copyright (c) 2010-2012 Ahmed Musa
+
+This software is author-maintained. Permission is granted to copy,
+distribute and/or modify this software under the terms of the
+LaTeX Project Public License, version 1.3 or higher. 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 any particular purpose.
+
+
+FILES
+
+The following files constitute the skeyval bundle and must be
+distributed as a whole:
+
+ readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex,
+ skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex,
+ skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls,
+ and skeyval-testpkg.sty.
+
+The skeyval package can be used by LaTeX and non-LaTeX users.
+LaTeX users should load the package via
+
+ \usepackage[<options>]{skeyval}
+
+or, in class files and packages,
+
+ \RequirePackage[<options>]{skeyval}
+
+Plain TeX users can do
+
+ \input skeyval-core
+
+Users of pre-version-1.0 of skeyval package can access former
+versions by entering the option 'compatibility' in <options> above.
+This option will automatically load version 0.73 (the version
+just before 1.0) of skeyval package. From version 1.0, the package
+has changed radically.
+
+
+SUMMARY
+
+The 's' in skeyval means 'skeleton keys' or 'master keys'.
+
+The skeyval package provides commands for compactly defining and
+initializing all types of key (ordinary, command, boolean, style, choice,
+etc). It attempts to combine the features of ltxkeys package (which has
+the syntax of the xkeyval package) and pgfkeys package. One of the powers
+of pgfkeys package lies in its use of handlers. But the way handlers
+are used in pgfkeys package does add to computational complexity and
+overheads. Family or key filtering in pgfkeys is particularly complex
+and inefficient. Nesting of family or key filtering is, in particular,
+not recommended.
+
+In pgfkeys package, handlers come at the end of the key name, so that
+if a key isn't defined, the system tests to find if the key has a
+handler at its end. If a handler is found and defined, the handler's
+callback (called 'code' by pgfkeys package) is executed on the
+current path.
+
+The skeyval package puts handlers at the beginning of the key
+(or a set of keys) and uses the handler to process the key (or a set
+of keys). This speeds up key processing and reduces the computational
+complexity. Key processing, including filtering, can be nested
+naturally and efficiently.
+
+The skeyval package also maintains and, in fact, greatly extends the
+functionality and syntaxes of the ltxkeys package. Very few examples
+of the functionality of skeyval package are
+
+1. The callbacks of keys can be readily modified using commands
+ like \skvaddtocallback, \skvprependtocallback, \skvappendtocallback,
+ or the handlers .prepend code, .append code, .add code.
+
+2. Apart from the usual keys in xkeyval and ltxkeys packages, it is
+ now possible to define a rather weird key like
+
+ \skvpntkey[KV]{fam}{evaluate (?) as (?) using (?)}{\edef#2{#3}}
+
+ The key name here is 'evaluate (?) as (?) by (?)'. It has three
+ arguments, indicated by the closed parenthesis. The mark '?' can be
+ replaced by any character or characters, and the key could have up
+ to 9 arguments. This key can be set as
+
+ \skvsetkeys[KV]{fam}{evaluate (\x) as (\y) using (\numexpr\x*2)}
+
+ We can also define the same key with the default values specified:
+
+ \skvpntkey[KV]{fam}{evaluate (?) as (?) using (?)}[\x\y{\numexpr\x*2}]{%
+ \def\argone{#1}\def\argtwo{#2}\def\argthree{#3}%
+ }
+
+ and set it as follows (if pgfmath package is loaded):
+
+ \skvsetkeys[KV]{fam}{%
+ evaluate (\x) as (\pgfmathresult) using (\pgfmathparse{\x^10})
+ }
+
+3. The parameters/arguments of callbacks of keys can be easily changed.
+ For example, to change the argument of keya, one way is via
+ the magical command \directkeys:
+
+ \directkeys{%
+ .exec=\def\avalue{a+b},
+ .prefixes={KV1,KV2},
+ .families={fam1,fam2},
+ .holder prefix=mp@,
+ .initialize keys after define,
+ .define keys={
+ .ord/keya/def-a/\def\xa##1{#1*##1*#2},
+ .arg/keya/#1+#2,
+ .cmd/.value required{keyb}/def-b/\def\cmdb##1{##1@#1},
+ },
+ .initial values={
+ keya=ini-value,
+ },
+ .ignore family=fam2,
+ .set keys={
+ keya=.expanded{\avalue}
+ },
+ % Nested \directkeys. The current path is put on stack
+ % and restored later, so that the nest is independent
+ % of its surrounding topology:
+ \directkeys{
+ .path=KV3/fam3,
+ .new keys={
+ .ord/keya/defa/\def\ya##1{#1*##1*#2},
+ .arg/keya/#1+#2,
+ .choice/keyc/center/{right,left,center,justified},
+ .arg expanded/keyc/#1,
+ .bool/keyd/true,
+ .cmd/.forbid value{keye}/defe/\def\ye##1{#1*##1},
+ },
+ },
+ .try set keys={
+ .paths={KV1/fam1,KV3/fam3},
+ .try=2, .goal=1
+ }{
+ keyc=left,keyd=false
+ },
+ .ignore path=KV1/fam1,
+ .exec=\def\cvalue{center},
+ .search also set keys={
+ .add prefix=KV3,
+ .add families={fam3,fam4},
+ .max attempts=4, .goal=2,
+ }{
+ keyc=.expand once{\cvalue}
+ },
+ .append values={
+ keya=\def\y##1{#1+##1},
+ keyb=\def\w##1{#1+##1},
+ },
+ .prepend code={
+ keyb=\def\pre##1{#1+##1},
+ },
+ .styles{
+ key1/keya=value1,
+ key2/keyb=value2
+ },
+ .inherit code={
+ key1/keyb, key2/keyd
+ },
+ .preset keys={
+ key1,key2
+ },
+ }
+
+ Unlike in pgfkeys package, when we use 'expand' or 'expanded'
+ in a handler, the expansion will invariably be done when the
+ key is set, not when it's being defined.
+
+ The handlers of skeyval package start with a dot (.),
+ as in pgfkeys package.
+
+4. Several new features are introduced by the skeyval package. For
+ example, we now have 'style' and 'link' keys in the context of
+ ltxkeys syntax. For example, to link keys via .link or .style
+ handler:
+
+ \directkeys{%
+ .link={key1, key2}/keya,
+ .link={key3, key4}/{keya, keyb},
+ .append style expand twice={key3, key4}/keyf=\valuea,
+ .prepend style expanded={key5, key6}/{keyc=#1, keyd=#1},
+ .prepend style={key7, key8}/{keyd=#1, keye=#1},
+ }
+
+5. The concepts of 'trying' to set a key with 'goals' is introduced.
+ The handler '.goal' can be interpreted in the sense of \pagegoal,
+ but applied to setting a key.
+ See an example above. Then there is 'search also' set keys.
+
+6. 'Quick keys' are a new concept. They're quite fast to define and set.
+
+7. Keys can be 'made', as in
+
+ \skvmakekeys[
+ .prefix=KVA, .families={fam1,fam2}, .holder prefix=mp@,
+ .all are new, .define in all families, .initialize after define
+ ]{%
+ .ords/{keya,keyb}/{default-a},
+ .cmds/{keyc,keyd}/,
+ .zcmd/key e/\def\cmde##1{##1}/
+ \edef\y{\detokenize\expandafter{\thp@keye}}\def\x##1{#1*key e*##1},
+ .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right},
+ .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi}
+ }
+
+ 'z-keys' are keys whose names are zapped (ie, spaces are removed)
+ internally. This is to allow holder/store macros to be used
+ without spaces in their names, while maintaining key names with
+ spaces.
+
+8. Keys can be set using \skvsetkeys, \directkeys (with the handlers
+ .set keys, .try, etc.), or \skvusekeys:
+
+ \krdusekeys[
+ .prefix=KVA,
+ .families={fam1,fam2},
+ .set in all families,
+ .save unknown keys
+ ]{%
+ keya,keyb
+ }
+
+9. Keys defined in families can be viewed in files using the package
+ 'skeyval-view'. The functionality of 'skeyval-view' is greater than
+ that of xkeyval-view package.
+
+10. Files skeyval-pstkey.sty and skeyval-pstkey.tex are provided for
+ PSTricks developers and users, as did xkeyval package.
+
+11. Some new and versatile looping macros are introduced in the
+ skeyval package. In fact, the powerful \newforeach list
+ processor of the 'loops' package has its roots in the 'skeyval-for'
+ module. It is a generalization of PGF's \foreach macro for
+ arbitrary parsers and list separators, including active parsers.
+
+
+% End of readme file \ No newline at end of file
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf
deleted file mode 100644
index b13fd223a11..00000000000
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf
+++ /dev/null
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex
deleted file mode 100644
index 075ebfb5766..00000000000
--- a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex
+++ /dev/null
@@ -1,2548 +0,0 @@
-\documentclass[a4paper,10pt,final,language=UKenglish,fancysec,fancyfnote]{amltxdoc}
-\makeatletter
-\let\sectionbreak\medbreak
-
-\begin{document}
-
-\begin{frontmatter}
-\suptitle{}
-\title{The \texttt{\color{blue}skeyval} Package\titleref{t1,t2}}
-\titlenote[t1]{The \pkgm{skeyval} was formerly called the \pkgm{keyreader} until
-version~0.5. The \asty{keyreader} is now obsolete and no longer supported.}
-\iftogon{pdf}{%
- \titlenote[t2]{The package is available at \url{\@titleurl}.}%
-}{%
- \titlenote[t2]{The package is available at \url{\@shorttitleurl}.}%
-}
-\subtitle{Version 0.72}
-\titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/skeyval/}
-\shorttitleurl{http://www.ctan.org/}
-\author{Ahmed Musa\Email{a.musa@rocketmail.com}\\Preston, Lancashire, UK}
-
-\NewLet\abstname\abstractname
-\redef*\abstractname{\vspace{-\baselineskip}}
-\begin{abstract}
-\frameshade[width=\hsize,fillcolor=yellow!20,framesep=2pt,framerule=2pt,
- framecolor=brown]{%
- \frameshade[fillcolor=white,width=2.5cm,framecolor=red,framerule=2pt]%
- {\centering\abstname}\small
- This package provides several extensions to the \pkgm{xkeyval}. It introduces toggle keys and complementary (bipolar and unipolar) native-boolean and toggle-boolean keys. It also provides mechanisms for reserving, unreserving, suspending, restoring, and removing keys. Furthermore, it introduces a set of commands for key definition which bar the developer or user from inadvertently redefining existing keys of the same family and prefix. Commands are provided for checking the statuses of keys across multiple key prefixes and families. Also, the package provides a scheme for defining multiple keys of different genres using only one command, thereby making it possible to considerably economize on tokens when defining keys. The package introduces the notion of ``user-value keys'' and provides facilities for managing those keys. The pointer mechanisms of the \asty{xkeyval}, which were only available at key setting time, are now invocable at key definition. Some other general-purpose developer macros and hooks are provided by the package.
-}
-\end{abstract}
-
-\NewLet\licname\licensename
-\redef*\licensename{\vspace{-\baselineskip}}
-\begin{license}
-\frameshade[width=\hsize,fillcolor=white,framesep=2pt,framerule=2pt,
- framecolor=brown]{\small
- \vspace{1ex}\centerline{\licname}\endgraf
- This work (\ie, all the files in the \asty{skeyval} bundle) may be distributed and/or modified under the conditions of the \lppl (LPPL), either version~1.3 of this license or any later version.
- \endgraf
- 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.
- \endgraf
- The package is now at open beta stage and package distributors are advised to wait for at least a stable version~1.0 before embarking on distribution. Bug reports and suggestions to improve the package are particularly welcome. Correspondents should use the file \asty{skeyval-bugreport.tex}, provided as part of the bundle, to report bugs.
- \endgraf\centerline{\makered{\CopyrightYear}}%
-}
-\end{license}
-\end{frontmatter}
-
-\newpage
-
-\frameshade[fillcolor=yellow!20,framecolor=brown,framerule=2pt,framesep=2pt,
- width=1.1\hsize]{\tableofcontents}
-
-\section{Motivation}
-\label{sec:motivation}
-
-\lletter{T}oggle booleans were introduced by the \pkgm{etoolbox} and have proved attractive mainly for two reasons: unlike the legacy/native \tex switches which require three commands per switch, toggles require only one command per switch, and toggles occupy their own separate namespace, thereby avoiding clashes with other macros. So we can effectively have both the following sets in the same file:
-\begin{example}
-|comm(Knuth/native switch:)
-\newif\ifmyboolean |tto 3 separate commands:
- \ifmyboolean \mybooleantrue
- \mybooleanfalse
-
-|comm(Toggle switch:)
-\newtog{myboolean} |tto only 1 command and no clash with
- commands in other namespaces
-\end{example}
-
-\Note A toggle is also a boolean or switch. We refer to it here as \emph{toggle} or \emph{toggle switch} or \emph{toggle boolean}. The term \emph{Knuth/native switch} is reserved here for \tex's legacy boolean or switch.
-
-The \pkg{xkeyval} can't be used to define and set toggle keys. The present package provides facilities for defining and setting toggle keys.
-
-Secondly, the \pkg{xkeyval} can't be used to define and set complementary (bipolar and unipolar) keys, which can be handy in the case of native boolean and toggle keys. Complementary bipolar keys are mutually exclusive keys, \ie, they never assume the same state of a two-valued logic, and they switch states automatically, depending on the state of any one of them. So whenever one of them assumes one of the two states of a two-valued logic, the other one automatically switches its state from whatever state it was previously, such that the two are never in the same state. Simple examples of complementary bipolar keys would be the options \acmd{draft} and \acmd{final} in a document; they are mutually exclusive. Complementary bipolar keys carry equal charge, \ie, each one can equally toggle the other with identical propensity, but the one that represents the default state of a two-valued logic is usually considered the primary, while the other is secondary. In many document classes, for instance, \acmd{final} is considered a default document option and \acmd{draft} would have to be explicitly selected by the user to toggle \acmd{final} to false.
-
-Complementary unipolar keys, on the other hand, are mutually inclusive, \ie, both are always in the same state of a two-valued logic: when one is switched to a particular state, the complement too is automatically toggled to the same state. An example of complementary unipolar keys would be the options \fx{hyperref} and \fx{microtype} in a package or class file. When \pkgm{hyperref} is loaded, we may want \pkgm{microtype} loaded as well, and vice versa. Complementary unipolar keys, like bipolar keys, also carry equal charge, \ie, one can toggle the other with equal propensity, but to the same state for the two keys. For a pair of unipolar keys, the primary key is the one that is associated with the default state.
-
-The present package introduces these concepts of bipolar and unipolar keys and additionally permits the submission of individual and different custom key macros to complementary (bipolar and unipolar) native boolean and toggle keys. Biunipolar keys, which combines the two concepts of bipolar and unipolar keys, are introduced as well.
-
-The third motivation for this package relates to economy of tokens in style files. The \pkg{xkeyval} provides \acmd{\define@cmdkeys} and \acmd{\define@boolkeys} for defining and setting multiple command keys and boolean keys, but in each category the keys must have the same default value and no key macro/function. This package seeks to lift these restrictions, so that multiple keys of all categories (ordinary keys, command keys, boolean keys, tog keys, and choice/menu keys) can be defined in one go (using only one command) and those keys can have different default values and functions. This greatly minimizes tokens, as hundreds of keys can, in principle, be issued simultaneously by one command.
-
-Fourthly, macros are introduced for defining all key types without the fear of inadvertently redefining existing keys in the same family and with the same key prefix. This has a philosophy akin to the \acmd{\newcommand} concept in \LaTeX.
-
-The package also provides facilities for disabling, suspending, restoring and removing keys across multiple families of keys. The pointer system of the \pkg{xkeyval} is also extended by the \pkg{skeyval}, and the notion of ``user-value'' keys is introduced and operationalized.
-
-Normally when setting keys, the \pkg{xkeyval} terminates with an error message if any key in the list of keys to be set is currently undefined or unknown. This means that if you have a set of keys to set simultaneously and you misspell a few of them, you would have to make several passes to get all the keys right. The \pkg{skeyval} takes a different approach. For each call to \acmd{\setkeys}, it saves the names of undefined keys (and their associated families and prefixes) in a macro and issues an error message (together with the contents of that macro) if at the end of the call that macro is non-empty. Such undefined keys are not set in the pass. In this way, you can correct all wrongly entered keys in one go, rather than repeat the pass for each of them.
-
-The new macros can be used together with the machinery from the \pkg{xkeyval} for efficient and versatile key management.
-
-\section{Brace stripping by the \texttt{xkeyval} package}
-
-The \pkg{xkeyval} strips off up to three levels of braces in the value part of the \acmd{key-value} pair: one by using the \pkgm{keyval}'s leading and trailing space removal command and two in internal parsings (at some known commands). The \asty{keyval} strips off only two levels of braces: one in using its space removal routine and one in internal parsings. The \pkgm{kvsetkeys} strips off only one level of braces. The matter of these differences has not yet been shown to have serious implications for existing or new packages, although it is apparently of concern to the \pkgm{keycommand}.
-
-The \pkg{skeyval} internally uses a space removal scheme that doesn't strip off braces from its arguments, but since the present package relies, to a good extent, on the engine of the \pkg{xkeyval}, the brace stripping effect has remained. We have had to redefine a significant number of the internal macros of the \pkg{xkeyval}, but getting rid of the brace-stripping issue would require even more substantial revision of the internal macros of the \pkg{xkeyval}. It can easily be solved but there is currently no sufficient reason to do so. If, odd enough, you want at least one level of braces to persist in the value part of the \acmd{key-value} pair throughout parsing, you simply surround the value with four levels of braces in the \acmd{\setkeys} command. If the users of this, or the \pkg{xkeyval}, feel that this issue is of significant concern, then it can be addressed in the future.
-
-\section{The \texttt{skeyval} package options}
-\label{sec:loading-package}
-
-The package can be loaded in style and class files by
-\begin{example}
-\RequirePackage[options]{skeyval}
-\end{example}
-and in document files via
-\begin{example}
-\usepackage[options]{skeyval}
-\end{example}
-where the user options and their default values are
-\begin{macro}
-keyparser=;, macroprefix=mp@, keyprefix=KV, keyfamily=fam,
-verbose=false
-\end{macro}
-\acmdm*{keyparser,macroprefix,keyprefix,keyfamily,verbose}
-
-The \ang{keyparser} is the separator between the keys in the key list to be defined in one go (see \cref{sec:multkeys-examples}). The \ang{macroprefix}, \ang{keyprefix}, and \ang{keyfamily} are, respectively, the macro prefix, key prefix and key family for all the keys to be defined upon the declaration of these options. All these options can be set or changed dynamically by using the \acmdm{\skvoptions} macro:
-\begin{macro}
-\skvoptions{keyparser=;, macroprefix=mp@, keyprefix=KV,
- keyfamily=fam}
-\end{macro}
-
-These options are explained in more detail in subsequent sections.
-
-If, as unlikely as it may seem, a clash arises between package and/or user macros as a result of the use of the defaults for \ang{macroprefix}, \ang{keyprefix} and \ang{keyfamily}, then the user will have to make his own choices for these defaults so as to avoid clashes.
-
-The \pkg{skeyval} issues a fatal error if it is loaded before (or run without) \acmd{\documentclass}.
-
-\section[Complementary native boolean keys]{Complementary native-boolean keys}
-\label{sec:comp-boolkeys}
-
-\subsection{Bipolar native-boolean keys}
-\label{sec:biboolkeys}
-
-As mentioned in \cref{sec:motivation}, complementary bipolar keys are keys that depend inversely on each other: when one of them is in a particular state of a two-valued logic, the other one automatically assumes the opposite or complementary state. For each pair of bipolar keys, one is normally assumed to be the primary key and the other the secondary. The primary boolean key will usually represent the default state of a two-valued logic. Whenever one bipolar key (primary or secondary) is true, its complement is automatically set false; and vice versa: when one bipolar key (primary or secondary) is false, its complement is automatically set true. Generally, the transition of the state of a key from negative (false) to positive (true) is associated with the execution of the key's macro.
-
-The syntax for creating bipolar native-boolean keys is
-\begin{macro}
-\define@biboolkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(func for primary boolean)}
- {|vang(func for secondary boolean)}
-\end{macro}
-\acmdm*{\define@biboolkeys}
-This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. When the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will use \acmd{true}. Infinite loops, which are possible in back-linked key settings, are avoided in the \pkg{skeyval}. The machinery of the \pkg{xkeyval}, such as \acmd{\setkeys}, \acmd{\presetkeys}, \acmd{\savekeys}, \acmd{\savevalue}, \acmd{\usevalue}, \etc, are all applicable to all complementary keys.
-
-As an example, we define below two bipolar native-boolean keys \ang{draft} and \ang{final} with different key macros:
-\begin{example}
-\define@biboolkeys[KV]{fam}[mp@]{draft}[true]{final}%
-{%
- \ifmp@draft
- \def\noneofone##1{}%
- \else
- \def\oneofone##1{##1}%
- \fi
-}{%
- \ifmp@final
- \def\noneoftwo##1##2{}%
- \else
- \def\oneoftwo##1##2{##1}%
- \fi
-}
-\end{example}
-The key prefix (default \fx{KV}), macro prefix (default \fx{mp@}), key macros (no default), and the default value of the primary boolean (\fx{true}) can all be empty:
-\begin{example}
-\define@biboolkeys{fam}{draft}{final}{}{}.
-\end{example}
-
-The defined complementary bipolar keys \ang{draft} and \ang{final} can now be set separately as follows:
-\begin{example}
-\setkeys[KV]{fam}{draft=true |makered(or) on}
-
-\setkeys[KV]{fam}{final=true |makered(or) on}
-\end{example}
-The second statement above reverses the boolean \ang{draft} to \ang{false}, which had been set in the first statement to \ang{true}. There is no apparent meaning to the following:
-\begin{example}
-\setkeys[KV]{fam}{draft=true,final=true}.
-\end{example}
-
-\Note
-In the \pkg{skeyval}, the acceptable values for native-boolean and toggle-boolean keys are \fx{true}, \fx{on}, \fx{false}, and \fx{off}. Toggle-booleans (\cref{sec:toggle-booleans}) and switches (\cref{sec:switches}) also accept these values. The value \fx{on} is synonymous with \fx{true}, whilst \fx{off} is an alias for \fx{false}. Being merely aliases, both \fx{on} and \fx{off} don't increase the number of commands per switch: the number remains three.
-
-The \pkg{skeyval} has the \acmdm{\NewIfs} and \acmdm{\DefIfs} macros, both of which define five commands per switch:
-\begin{macro}
-\NewIfs[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)]
-\DefIfs[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)]
-\end{macro}
-The command \fx{\NewIfs} provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register if the register didn't already exist. If the boolean register already existed, an error is flagged. Each member of \ang{boolean list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefIfs}, on the other hand, provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register whether or not the register already existed. If the boolean register already existed, and the package option \fx{verbose} is enabled, a message is entered in the transcript log file that the boolean has been redefined.
-
-The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}; the default is \fx{false}. The state \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. After declaring
-\begin{example}
-\NewIfs[bool]{a,b}[true]
-\end{example}
-you can say \fx{\ifboola}, \fx{\boolaon} and \fx{\boolaoff}, just like you would normally do \fx{\boolatrue} and \fx{\boolafalse}. The disadvantage of \fx{\NewIfs} and \fx{\DefIfs} is that they define five commands per switch; they should therefore be employed only in special circumstances.
-
-\subsection{Unipolar native-boolean keys}
-
-Unipolar boolean keys are two keys that are always in the same state: when one is true (or false), the other one is also true (or false). In this regard, the key macro is always executed when a key transits to the ``true'' state. The syntax for creating unipolar native-boolean keys is exactly as that for defining bipolar native-boolean keys:
-\begin{macro}
-\define@uniboolkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(func for primary boolean)}
- {|vang(func for secondary boolean)}
-\end{macro}
-\acmdm*{\define@uniboolkeys}
-This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. Again, if the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will assume it to be \fx{true}.
-
-The following example constructs two unipolar native-boolean keys:
-\begin{example}
-\NewToks[temptoks]{a,b}
-
-\define@uniboolkeys[KV]{fam}[mp@]{pdfmode}[true]{microtype}%
-{%
- \ifmp@pdfmode
- \temptoksa{Yes, in `pdfmode'}%
- \else
- \temptoksa{No, not in `pdfmode'}%
- \fi
-}{%
- \ifmp@microtype
- \temptoksb{Yes, `microtype' loaded}%
- \else
- \temptoksb{No, `microtype' not loaded}%
- \fi
-}
-\end{example}
-
-\subsection{Biunipolar native-boolean keys}
-\label{sec:biuni-boolean}
-
-Biunipolar keys are the generalized forms of bipolar and unipolar boolean keys, with one important restriction: unlike bipolar and unipolar keys, biunipolar keys have no symmetrical relationships. That is to say that the relationship between a pair of biunipolar keys is entirely determined by the primary key. A pair of biunipolar boolean keys possess only one of the following four types of relationship:
-\begin{enum}
-\item Unipolar property: When the primary key is \fx{false}, it sets the secondary key to \fx{false} (\RedStar\RedPlus-form of biunipolar keys). The secondary key macro isn't executed.
-\item Bipolar property: When the primary key is \fx{false}, it sets the secondary key to \fx{true} (\RedStar-form). The secondary key macro is executed.
-\item Bipolar property: When the primary key is \fx{true}, it sets the secondary key to \fx{false} (\RedPlus-form). The secondary key macro isn't executed.
-\item Unipolar property: When the primary key is \fx{true}, it sets the secondary key to \fx{true} (unsigned form). The secondary key macro is executed.
-\end{enum}
-Of course, the primary key can be true only after it has been set.
-
-The syntax for establishing biuni boolean keys is exactly like that for creating other complementary boolean keys, except for the optional \RedStar and \RedPlus signs:
-\begin{macro}
-\define@biuniboolkeys|redstar|redplus[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(macro for primary boolean)}
- {|vang(macro for secondary boolean)}
-\end{macro}
-\acmdm*{\define@biuniboolkeys,\define@biuniboolkeys*,\define@biuniboolkeys*+}
-
-As an example, consider the arbitrary package or class options \fx{review} and \fx{preprint}. The option \fx{preprint} can automatically toggle \fx{review} to true, but possibly not vice versa: not every \fx{preprint} is a manuscript for \fx{review}. This is depicted below:
-\begin{example}
-\define@biuniboolkeys[KV]{fam}[mp@]{preprint}[true]{review}{%
- |comm(No key macro for preprint; otherwise, it would)
- |comm(have come in here.)
-}{%
- \ifmp@review
- \SKV@BeforeDocumentStart{%
- \linespread{1.5}\selectfont
- \def\banner{\fbox{\textit{This is a review document}}}%
- }%
- \else
- \SKV@BeforeDocumentStart{\let\banner\@empty}%
- \fi
-}
-\end{example}
-\acmd*{\SKV@BeforeDocumentStart}
-
-As another example, consider the following biuni keys, each with its own macro:
-\begin{example}
-\define@biuniboolkeys|redstar|redplus[KV]{fam}[mp@]{brother}[true]{sister}{%
- \ifmp@brother
- \def\mybrother{Hamilton}%
- \fi
-}{%
- \ifmp@sister
- \SKV@AfterDocumentStart{\def\mysister{Kate}}%
- \else
- \SKV@AfterDocumentStart{\let\mysister\@gobble}%
- \fi
-}
-
-\setkeys[KV]{fam}{brother=true}
-\end{example}
-\acmd*{\SKV@AfterDocumentStart}
-
-\section{Toggle booleans and toggle keys}
-\label{sec:toggles}
-
-In the following \crefrange{sec:toggle-booleans}{sec:toggle-keys} we define toggle booleans/switches and use them to introduce toggle-boolean keys.
-
-\subsection{Toggle booleans}
-\label{sec:toggle-booleans}
-
-The following toggle switches are defined in the \pkg{skeyval}. They largely mimic those in the \pkg{etoolbox}, except for the commands \acmdm{\deftog} and \acmd{\requiretog}. The internal control sequences and user interfaces of the two packages are, however, different, thus avoiding clashes.
-
-All the commands in this section are robust and can be used in expansion or moving contexts without fear of premature expansion, but fragile arguments would need to be protected in those settings.
-
-\begin{macro}
-\deftog[|vang(optional prefix)]{|vang(toggle)}[|vang(optional state)]
-\end{macro}
-This defines a new \ang{toggle}, prefixed with \ang{prefix} upon definition, whether or not \ang{toggle} (with its prefix) is already defined. If \ang{toggle} is already defined, a warning message is logged in the transcript file (if the package option \acmd{verbose} is selected) and the new definition is effected. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}.
-
-\begin{macro}
-\newtog[|vang(optional prefix)]{|vang(toggle)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\newtog}
-This defines a new \ang{toggle}, prefixed with \ang{prefix} upon definition, if \ang{toggle} (with its prefix) is not already defined; otherwise the package issues a fatal error. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}.
-
-You can define a set of toggles by the following commands:
-\begin{macro}
-\NewTogs[|vang(optional prefix)]{|vang(toggles)}[|vang(optional state)]
-\DefTogs[|vang(optional prefix)]{|vang(toggles)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\NewTogs,\DefTogs}
-where \ang{toggles} is a comma-separated list. Each member of \ang{toggles} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. For example, we may define new toggles \fx{togx}, \fx{togy}, \fx{togz} by the following:
-\begin{example}
-\NewTogs[tog]{x,y,z}[true]
-\end{example}
-
-\begin{macro}
-\providetog{|vang(toggle)}
-\end{macro}
-\acmdm*{\providetog}
-This defines a new \ang{toggle} if \ang{toggle} is not already defined. If \ang{toggle} is already defined, the command does nothing. Please note that there are no tog prefix here, and that the default state is \fx{false}.
-
-\begin{macro}
-\requiretog{|vang(toggle)}
-\end{macro}
-\acmdm{\requiretog} takes arguments like \fx{\newtog} and behaves like \fx{\providetog} with the difference: if the toggle is already defined, the command \fx{\requiretog} calls \LaTeX's \acmdm{\CheckCommand} to make sure that the new and existing definitions are identical, whereas \fx{\providetog} assumes that if the toggle is already defined, the existing definition should persist. \fx{\requiretog} assures that a toggle will have the given definition, but (if the package option \fx{verbose} is selected) \fx{\requiretog} also warns the user if there was a previous and different existing definition. For example, if the toggle \ang{toga} is currently \ang{true}, then since all new toggles start out as \ang{false}, a call \fx{\requiretog{toga}} will, if the package option \fx{verbose} is selected, issue a warning in the log file that the new and old definitions of \ang{toga} don't agree and the new definition, therefore, can't go ahead. Note that there are no tog prefix here, and that the default state is \fx{false}.
-
-The \pkg{skeyval} also provides the command \acmd{\requirecmd}, which has the same logic as \fx{\requiretog} but can be used for general \latex commands, including those with optional arguments (see \cref{sec:misce-commands}).
-
-\begin{macro}
-\settog{|vang(toggle)}{|vang(true |amdvert false |amdvert on |amdvert off)}
-\end{macro}
-\acmdm*{\settog}
-This command sets \ang{toggle} to \ang{value}, where \ang{value} may be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. This statement will issue an error if \ang{toggle} wasn't previously defined.
-
-\begin{macro}
-\togon{|vang(toggle)}
-\togtrue{|vang(toggle)}
-\end{macro}
-\acmdm*{\togon, \togtrue}
-These set \ang{toggle} to \ang{true} or \fx{on}. They will issue an error if \ang{toggle} wasn't previously defined.
-
-\begin{macro}
-\togoff{|vang(toggle)}
-\togfalse{|vang(toggle)}
-\end{macro}
-\acmdm*{\togoff, \togfalse}
-These set \ang{toggle} to \ang{false} or \fx{off}. They will issue an error if \ang{toggle} wasn't previously defined.
-
-\begin{macro}
-\iftogon{|vang(toggle)}{|vang(true)}{|vang(false)}
-\iftogtrue{|vang(toggle)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\iftogon, \iftogtrue}
-These yield the \ang{true} statement if the boolean \ang{toggle} is currently \ang{true}, and \ang{false} otherwise. They will issue an error if \ang{toggle} wasn't previously defined.
-
-\begin{macro}
-\iftogoff{|vang(toggle)}{|vang(not true)}{|vang(not false)}
-\iftogfalse{|vang(toggle)}{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\iftogoff, \iftogfalse}
-These behave like \fx{\iftogon} and \fx{\iftogtrue} but reverse the logic of the test. They will issue an error if \ang{toggle} wasn't previously defined.
-
-\subsection{Toggle-boolean keys}
-\label{sec:toggle-keys}
-
-The user interfaces for defining toggle-boolean keys is exactly like those for native-boolean keys in the \pkg{xkeyval}. This allows all the machinery of the \pkg{xkeyval} (including \acmd{\setkeys}, \acmd{\presetkeys}, \acmd{\savekeys}, \acmd{\savevalue}, \acmd{\usevalue}, etc) to be applicable to toggle-boolean keys.
-
-As mentioned earlier, toggles have their own separate namespace. However, the \acmd{\setkeys} command (and friends) of the \pkg{xkeyval} is unaware of this. This can cause problems when the user uses the same name for native-boolean and toggle keys (or indeed any key type) in the same family and with the same key prefix, believing rightly that toggle keys have their own separate namespace. If this is a source of significant concern to any user, he will be well advised to instead use the commands \acmd{\newboolkey}, \acmd{\newboolkeys}, \acmd{\newtogkey}, \acmd{\newtogkeys}, \etc, of \cref{sec:redef-keys}. In those commands a mechanism is included to bar keys from having the same name as other keys in the same family and with the same prefix. Toggle keys can still share the same names with keys across families and key prefixes. Since it is not always certain which of the keys the user may want to first define (before its definition is possibly repeated), the fear of interference has necessitated new syntaxes for defining all key types, which completely avoid interference (see \cref{sec:redef-keys}).
-
-The user interfaces for defining toggle keys are
-\begin{macro}
-\define@togkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(function)}
-
-\define@togkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(function1)}{|vang(function2)}
-\end{macro}
-\acmdm*{\define@togkey,\define@togkey+}
-
-If the macro prefix \ang{mp} is not specified, these create a toggle of the form \fnn{prefix}{family}{key}{} using \acmd{\deftog} (which initializes the toggle switch to \fx{false}) and a key macro of the form \bs\fnn{prefix}{family}{key}{} which first checks the validity of the user input. If the value is valid, it uses it to set the toggle and then executes \ang{function}. If the user input wasn't valid (\ie, neither \fx{true} nor \fx{false}), then the toggle will not be set and the package will generate a fatal error to this effect.
-
-If \ang{mp} is specified, then the key definition process will create a toggle of the form \fnm{mp}{key}{}{} and a key macro of the form \bs\fnm{mp}{key}{}{}. The value \ang{default} will be used by the key macro when the user sets the key without a value.
-
-If the plus (\RedPlus) version of the macro is used, the user can specify two key macros \ang{function1} and \ang{function2}. If user input is valid, the macro will set the toggle and executes \ang{function1}; otherwise, it will not set the boolean but will execute \ang{function2}.
-
-As an example, consider the following:
-\begin{example}
-\define@togkey{fam}[my@]{frame}{%
- \iftogon{my@frame}{%
- \PackageInfo{mypack}{Turning frames on}%
- }{%
- \PackageInfo{mypack}{Turning frames off}%
- }%
-}
-
-\define@togkey|redplus{fam}{shadow}{%
- \iftogon{KV@fam@shadow}{%
- \PackageInfo{mypack}{Turning shadows on}%
- }{%
- \PackageInfo{mypack}{Turning shadows off}%
- }%
-}{%
- \PackageWarning{mypack}{Erroneous input `#1' ignored}%
-}
-\end{example}
-
-The first example creates the toggle \ang{my@frame} and defines the key macro
-\fx{\KV@fam@frame} to set the boolean (if the input is valid). The second key intimates
-the user of changed settings, or produces a warning when input was incorrect.
-
-It is also possible to define multiple toggle keys with a single command:
-\begin{macro}
-\define@togkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)]
-\end{macro}
-\acmdm*{\define@togkeys}
-This creates a toggle key for every entry in the comma-separated list \ang{keys}. As is the case with the commands \acmd{\define@cmdkeys} and \acmd{\define@boolkeys} from the \pkg{xkeyval}, the individual keys in this case can't have a custom function. See \cref{sec:def-multiple-keys} for how to define multiple keys with custom functions.
-
-As an example of defining multiple toggle keys, consider
-\begin{example}
-\define@togkeys{fam}[my@]{toga,togb,togc}
-\end{example}
-
-This is an abbreviation for
-\begin{example}
-\define@togkey{fam}[my@]{toga}{}
-\define@togkey{fam}[my@]{togb}{}
-\define@togkey{fam}[my@]{togc}{}
-\end{example}
-
-Now we can do
-\begin{example}
-\define@togkey{fam}[my@]{book}{%
- \iftogon{my@book}{\setkeys[KV]{fam}{togc=true}}{}%
-}
-\setkeys[KV]{fam}{book=true}
-\end{example}
-\acmd*{\define@togkey,\setkeys}
-Toggle keys can be set in the same way that other key types are set.
-
-The status of toggles can be examined by doing
-\begin{example}
-\show\SKV@toggle@|vang(mp)|vang(key)
-\end{example}
-when the \ang{mp} is present. When the user has specified no \ang{mp} in defining the key, he has to issue
-\begin{example}
-\show\SKV@toggle@|vang(prefix)@|vang(family)@|vang(key).
-\end{example}
-
-\section{Complementary toggle keys}
-\label{sec:comptogkeys}
-
-\subsection{Bipolar toggle-boolean keys}
-
-Similar to complementary native-boolean keys of \cref{sec:comp-boolkeys}, the \pkg{skeyval} introduces facilities for creating complementary (bipolar, unipolar and biunipolar) toggle keys. The syntax for defining bipolar toggle keys is identical to that for defining bipolar native-boolean keys:
-\begin{macro}
-\define@bitogkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary toggle)}[|vang(default value for primary toggle)]
- {|vang(secondary toggle)}{|vang(func for primary toggle)}
- {|vang(func for secondary toggle)}.
-\end{macro}
-\acmdm*{\define@bitogkeys}
-This command is robust and can be used in expansion contexts, but non-robust commands have to be protected. When the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary toggle-boolean is not supplied, the package will use \fx{true}. When one of the bipolar toggle keys (primary or secondary) is true, the other is automatically set false; and vice versa: when one toggle key (primary or secondary) is false, the other is automatically set true.
-
-As an example, we define below two bipolar toggle keys \ang{xdraft} and \ang{xfinal} with different key macros:
-\begin{example}
-\define@bitogkeys[KV]{fam}[mp@]{xdraft}[true]{xfinal}%
-{\def\gobble##1{}}{\def\firstofone##1{##1}}
-\end{example}
-The key prefix (default \fx{KV}), macro prefix (default \fx{mp@}), key macros (no default), and the default value of the primary boolean (default \fx{true}) can all be empty:
-\begin{example}
-\define@bitogkeys{fam}{xdraft}{xfinal}{}{}.
-\end{example}
-
-The defined bipolar toggle keys \ang{xdraft} and \ang{xfinal} can now be set as follows:
-\begin{example}
-\setkeys[KV]{fam}{xdraft=true}
-
-\setkeys[KV]{fam}{xfinal=true}
-\end{example}
-\acmd*{\setkeys}
-The second statement above reverses the toggle \ang{xdraft} to \ang{false}, which had been set in the first statement to \ang{true}.
-
-\Note
-Toggle keys may easily be confused with the conventional boolean keys, especially at the time of key setting. It is, therefore, always safer to use the syntaxes in \cref{sec:redef-keys} for defining keys; they avoid interference between new and existing keys.
-
-If we were to use the key names \acmd{draft} and \acmd{final} as toggle keys above, instead of \fx{xdraft} and \fx{xfinal}, there would have been a clash with the keys \acmd{draft} and \acmd{final} defined as (complementary) native-boolean keys in \cref{sec:comp-boolkeys}---because they share the same family \ang{fam} and prefix \ang{KV}. The names \acmd{draft} and \acmd{final} could safely be used as toggles only if the family \ang{fam} or prefix \ang{KV} is changed. See \cref{sec:avoiding-redef} for further details.
-
-\subsection{Unipolar toggle-boolean keys}
-
-The syntax for defining unipolar toggle keys is exactly the same as that for defining bipolar toggle keys:
-\begin{macro}
-\define@unitogkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary toggle)}[|vang(default value for primary toggle)]
- {|vang(secondary toggle)}{|vang(func for primary toggle)}
- {|vang(func for secondary toggle)}.
-\end{macro}
-\acmdm*{\define@unitogkeys}
-Here too, if the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary toggle key is not supplied, the package will use \acmd{true}.
-\begin{example}
-\define@unitogkeys[KV]{fam}[mp@]{draft}[true]{final}%
- {\def\x##1{}}{\def\y##1{##1}}
-\setkeys[KV]{fam}{draft=true}|comm(``final'' becomes ``true'' here.)
-\end{example}
-\acmd*{\setkeys}
-
-\subsection{Biunipolar toggle-boolean keys}
-
-The interface for creating biuni toggle keys is exactly like that for creating other complementary boolean keys, except for the optional \RedStar and \RedPlus signs. The interface is as follows (the meaning of the optional \RedStar and \RedPlus is given in \cref{sec:biuni-boolean}):
-\begin{macro}
-\define@biunitogkeys|redstar|redplus[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(macro for primary boolean)}
- {|vang(macro for secondary boolean)}
-\end{macro}
-\acmdm*{\define@biunitogkeys,\define@biunitogkeys*,\define@biunitogkeys*+}
-
-\begin{example}
-\define@biunitogkeys|redplus[KV]{fam}[mp@]{preprint}[true]{review}{%
- \iftogon{mp@preprint}{%
- \def\banner{\fbox{\textsf{This is a preprint copy}}}%
- }{}%
-}{%
- \iftogon{mp@review}{%
- \SKV@AtDocumentStart{\linespread{1.5}\selectfont}%
- \def\banner{\fbox{\textit{This is a review article}}}%
- }{%
- \let\banner\@empty
- }%
-}
-\setkeys[KV]{fam}{preprint=false |orr true}
-\end{example}
-\acmd*{\setkeys,\SKV@AtDocumentStart}
-
-\section[Defining multiple keys by one command]
- {Defining multiple keys of all genres by one command}
-\label{sec:def-multiple-keys}
-
-The user interface for defining multiple keys of all kinds in one go is the command \acmdm{\define@keylist}, whose syntax is
-\begin{macro}
-\define@keylist{|vang(key type/id), |vang(key), |vang(key default value),
- |vang(key macro/function); |vang(another set of key specifiers); etc}
-\end{macro}
-
-Here, there are five key types: 1~(ordinary key), 2~(command key), 3~(native-boolean key),
-4~(toggle-boolean key), and 5~(choice/menu key). The key types can be indicated either in numeral format (\fx{1}~to~\fx{5}) or in alphabetic format (\fx{ord}, \fx{cmd}, \fx{bool}, \fx{tog}, \fx{choice}, \fx{menu}). ``Choice'' and ``menu'' keys imply the same thing (key type~5): the user can pick the name he prefers. The key and its attributes are separated by commas; they constitute one ``object'' or ``instance''. The objects are separated by the \ang{keyparser}, which is the semicolon in the above example. The \ang{keyparser} is a package option and can be changed dynamically.
-
-If the key list is available in a macro, say,
-\begin{example}
-\def\keylist{|vang(key type/id), |vang(key), |vang(key default value),
- |vang(key macro/function); |vang(another set of key specifiers); etc},
-\end{example}
-then the keys can be defined by the starred form of \fx{\define@keylist}:
-\begin{example}
-\define@keylist|redstar\keylist.
-\end{example}
-\fx{\define@keylist}\redstar\ takes a macro as argument, while \fx{\define@keylist} accepts a key list.
-\acmdm*{\define@keylist*}
-
-The \fx{\define@keylist} macro uses the following commands in the background:
-\begin{example}
-\define@key, \define@cmdkey, \define@boolkey,
-\define@choicekey, \define@togkey.
-\end{example}
-\acmdm*{\define@cmdkey,\define@boolkey,\define@choicekey,\define@togkey}
-\acmd*{\define@key}
-Therefore, it assumes that it is safe to redefine a previously defined key. If this assumption is unwarranted, then the user should consider using the machinery of \cref{sec:redef-keys}. The machinery of \cref{sec:redef-keys} can be utilized to safely define new keys without the fear of inadvertently redefining an existing key within the same family and with the same key prefix.
-
-Keys defined by the tools in this section are amenable to management by pointers of \cref{sec:pointer-mech}.
-
-\subsection{Choice key values}
-\label{sec:choice-key-values}
-
-The \acmdm{\choicekeyvalues} macro is provided for defining choice keys; it lists the alternate
-admissible values for a choice key and thus can't be empty when a choice key
-is being defined via \fx{\define@keylist}. Its syntax is
-\begin{macro}
-\choicekeyvalues|redstar[|vang(prefix)][|vang(family)]{|vang(key)}{|vang(list)},
-\end{macro}
-where \ang{list} is a comma-separated list of admissible key values. Unless the key prefix or family changes, the unstarred variant of \fx{\choicekeyvalues} wouldn't allow you to set two \fx{\choicekeyvalues} for the same choice key. The starred variant \fx{\choicekeyvalues}\unskip\redstar, on the other hand, allows you to overwrite admissible choice values for a key within a specified family and with the given key prefix. The arguments \ang{prefix} and \ang{family} are optional, provided the key prefix and family have been specified before calling \fx{\choicekeyvalues}, using \fx{\skvoptions}. If \ang{prefix} and \ang{family} are not given, the prevailing key prefix and key family are used internally by \fx{\choicekeyvalues} to build distinct alternate values list for the choice key. Therefore, any number of choice keys are allowed to appear in one \acmd{\define@keylist} or \acmd{\define@keylist}\unskip\redstar\ statement, if their lists of alternate/admissible values have been set by \fx{\choicekeyvalues}.
-It doesn't matter which choice key first gets a \fx{\choicekeyvalues}.
-
-To further save tokens, the macro \fx{\choicekeyvalues} may be abbreviated by \acmdm{\CKVS}. It has to be provided for each choice key that is being defined.
-
-For example, if we want to define two choice keys \fx{align} and \fx{shootingmodes}, then before the call to \acmd{\define@keylist}, we have to set
-\begin{example}
-\CKVS{align}{center,right,left,justified}
-\CKVS{shootingmodes}{portrait,indoor,foliage,underwater}
-\end{example}
-
-As mentioned earlier, the key family and other package options can be changed dynamically via
-\begin{example}
-\skvoptions{keyparser=value,macroprefix=value,keyprefix=value,
- keyfamily=value}.
-\end{example}
-\acmd*{\skvoptions}
-
-In line with the philosophy of the \pkg{xkeyval}, all the choice keys to be defined using the \pkg{skeyval} require a menu: choice keys, by definition, have pre-ordained or expected values.
-
-\subsection{Some examples}
-\label{sec:multkeys-examples}
-
-In this section we provide a glimpse of the potential applications of the tools provided by the \pkg{skeyval} in the context of defining multiple keys by one command.
-
-Suppose that the key family and other attributes have been set as
-\begin{example}
-\skvoptions{keyparser=;,macroprefix=mp@,keyprefix=KV,
- keyfamily=fam}
-\end{example}
-\acmd*{\skvoptions}
-Further, suppose we wish to define a set of keys \fx{{color,angle,scale,align}}. The key \fx{color} will be defined as ordinary key, the keys \fx{angle} and \fx{scale} will de defined as command keys, while the key \fx{align} will be defined as a choice key. Assume that the \fx{align} key can only assume one of the values \leftbrace\fx{center} \amdvert\ \fx{right} \amdvert\ \fx{left} \amdvert\ \fx{justified}\rightbrace, where the first three values would further imply \fx{\centering}, \fx{\flushright}, and \fx{\flushleft}, respectively. Moreover, we assume that the key \fx{scale} will be associated with a macro called \fx{\mydo}, which depends on a previously defined macro \fx{\do}. Together with \fx{align}, we would also like to define another choice key: \fx{weather}. The key \fx{color} isn't associated with any macro. Then we can do:
-\begin{example}
-|comm(We use space freely in these examples for the sake)
-|comm(of illustration:)
-\def\someweather{windy}
-\CKVS{align}{center,right,left,justified}
-\CKVS{weather}{sunny,cloudy,lightrain,heavyrain,snow,
- sleet,\someweather}
-
-\def\funcforalign{%
- \ifcase\nr\relax
- \def\mp@align{\centering}%
- \or\def\mp@align{\flushright}%
- \or\def\mp@align{\flushleft}%
- \or\let\mp@align\relax
- \fi
-}
-|comm(Keys `color' and `mybool' have no macro.)
-|comm(Submitted value of key `angle' is ##1 |tto \mp@angle.)
-\define@keylist{%
- ord,color,gray!25,;
- cmd,angle,45,\def\anglevalue{##1};
- cmd,scale,1,\def\mydo####1{\do ####1};
- choice,align,center,\funcforalign;
- |makered(\listbreak);|label(mac:listbreak)
- bool,mybool,true,;
- choice,weather,sunny,\edef\Weather{\val}%
-}
-\setkeys[KV]{fam}{angle=45,scale=1cm,weather=cloudy}
-\end{example}
-\acmd*{\CKVS}
-
-Note the number of parameter characters in the definition of \fx{\mydo}. We will return to this matter in \cref{sec:macros-in-keymacros}. The \acmdm{\nr} and \acmdm{\val} macros are bin parameters for choice keys, as defined by the \pkg{xkeyval}. \fx{\val} contains the user input for the current key and \fx{\nr} contains the numeral corresponding to the numerical order of the user input in the \acmd{\CKVS} list, starting from~0 (zero). For example, in the \fx{\CKVS{align}} list, the \fx{\nr} values are \fx{center}~(0), \fx{right}~(1), \fx{left}~(2), and \fx{justified}~(3). These parameters thus refresh with the choice key and its user-supplied value.
-
-Instead of defining the macro \fx{\funcforalign} before hand, we can submit its replacement text directly to the macro \acmd{\define@keylist}, but, because \fx{\funcforalign} contains a conditional, some care is needed in doing so (see \cref{sec:condit-in-keys}). Once the key \fx{align} has been defined, the macro \fx{\funcforalign} can't be reused before the key \fx{align} is set. This is because it is at key setting time that the function \fx{\funcforalign} would be called. This is uneconomical: it is thus desirable to submit the key macro directly to \acmd{\define@keylist} irrespective of the presence of conditionals.
-
-Please note the \makered{\texttt{\string\listbreak}} token inserted on \macref{mac:listbreak} above. Because of it, the keys \fx{mybool} and \fx{weather} will not be read and defined; all the keys before \acmdm{\listbreak} (\ie, \fx{color}, \fx{angle}, \fx{scale} and \fx{align}) will be read and defined. All the entries for \fx{mybool} and \fx{weather} will instead be saved in the macro \acmdm{\SKV@remainder}, possibly for some other uses.
-
-Hundreds of keys can be defined efficiently in this way, using very few tokens. As another example, we consider the following keys:
-\acmd*{\CKVS,\define@keylist,\AtBeginDocument}
-\begin{example}
-\CKVS|redstar{align}{center,right,left,justified}
-\CKVS{election}{state,federal,congress,senate}
-
-\def\funcfortextwidth{\AtBeginDocument{\wlog{`textwidth' %
- is `\mp@textwidth'}}}
-
-\def\funcfortextheight{%
- \ifx\@empty\mp@textheight
- \wlog{`textheight' value empty}%
- \else
- \wlog{`textheight' value not empty}%
- \fi
-}
-
-\def\funcforpaperwidth{\wlog{`paperwidth' was defined as %
- ordinary key.}}
-
-\def\funcforalign{%
- \ifcase\nr\relax
- \def\mp@align{\centering}%
- \or\def\mp@align{\flushright}%
- \or\def\mp@align{\flushleft}%
- \or\let\mp@align\relax
- \fi
-}
-|comm(`boolvar', `paperheight' and `evensidemargin' have no)
-|comm(key macros:)
-\define@keylist{%
- bool,boolvar,true,;
- ord,paperheight,\paperheight,;
- ord,paperwidth,\paperwidth,\funcforpaperwidth;
- cmd,textheight,\textheight,\funcfortextheight;
- cmd,textwidth,\textwidth,\funcfortextwidth;
- ord,evensidemargin,\evensidemargin,;
- tog,togvar,true,\iftogon{mp@togvar}{\def\catch####1{####1}}%
- {\def\gobble####1{}};
- choice,align,center,\funcforalign;
- choice,election,congress,\def\electiontype{##1};
- cmd,testdim,2cm,\long\def\funcfortestdim####1{%
- A test dimension ####1 \endgraf\bigskip}%
-}
-
-\setkeys[KV]{fam}{togvar=true,testdim=1cm,election=senate}
-\end{example}
-The macro \fx{\electiontype} corresponds to \fx{\val} for choice key \fx{election}.
-Again, the intermediate/utility key macros can be reused only after their associated keys have been set.
-
-The same set of keys can be defined via the starred form of \acmd{\define@keylist}, as shown below:
-\begin{example}
-\def\keylistvector{%
- bool,boolvar,true,;
- ord,paperheight,\paperheight,;
- ord,paperwidth,\paperwidth,\funcforpaperwidth;
- cmd,textheight,\textheight,\funcfortextheight;
- cmd,textwidth,\textwidth,\funcfortextwidth;
- ord,evensidemargin,\evensidemargin,;
- tog,togvar,true,\iftogon{mp@togvar}{\def\catch####1{####1}}%
- {\def\gobble####1{}};
- choice,align,center,\funcforalign;
- choice,election,congress,\def\electiontype{##1};
- cmd,testdim,2cm,\long\def\funcfortestdim####1{%
- A test dimension ####1 \endgraf\bigskip}%
-}
-\define@keylist|redstar\keylistvector
-\end{example}
-\acmd*{\define@keylist*}
-
-Since the keys have been defined, they can now be set. In the following, we set only two of the keys:
-\begin{example}
-\setkeys[KV]{fam}{align=right,testdim=3cm}
-\end{example}
-\acmd*{\setkeys}
-
-The macro \fx{\mp@align} holds the value \fx{\flushright}, while \fx{\KV@fam@testdim} holds the macros:
-\begin{example}
-\def\mp@testdim{#1}
-\long\def\funcfortestdim##1{A test dimension ##1},
-\end{example}
-where \fx{#1} is the value (3cm) submitted for the key \fx{testdim}. The number of parameter characters normally increases in the macro \fx{\define@keylist} (see \cref{sec:macros-in-keymacros}). After setting the keys, you can do \fx{\show\mp@align} and \fx{\show\KV@fam@testdim} to confirm the above assertions.
-
-The rest of the defined keys can now be set as follows:
-\begin{example}
-\setkeys[KV]{fam}{boolvar=true,paperheight,paperwidth,
- textheight,textwidth=6cm}
-\end{example}
-\acmd*{\setkeys}
-Try \fx{\show\ifmp@boolvar} to confirm that \fx{boolvar} is now \ang{true}; it was originally set as \ang{false}. The macro \fx{\KV@fam@paperwidth} holds the function \fx{\funcforpaperwidth}, while \fx{\mp@textheight} holds the value submitted to key \fx{textheight} at any instance of \acmd{\setkeys}. By the above \acmd{\setkeys}, only the default values of \fx{paperheight}, \fx{paperwidth}, and \fx{textheight} are presently available.
-
-Instead of using macros to pass key macros and functions, it is also possible to use token list registers. Some examples are provided below:
-\begin{example}
-\NewToks[temptoks]{a,b}
-|comm(See page |pageref(page:newtoks) for definition of \NewToks and related commands.)
-
-\temptoksa{\ifmp@boola\def\do#1{%
- \def#1##1##2{\expandafter\expandafter\expandafter\in@
- \expandafter\expandafter\expandafter{\expandafter##1%
- \expandafter}\expandafter{##2}}}\fi}
-
-\temptoksb{\iftogon{mp@toga}{\def\order#1{Use `#1' now!}}%
- {\def\altorder#1{Don't use `#1' now!}}}
-
-\define@keylist{3,boola,true,\the\temptoksa;
- 4,toga,true,\the\temptoksb}
-
-\setkeys[KV]{fam}{boola=true,toga=true}
-
-|comm(You can now test your new function \do:)
-\def\y{x} \def\z{xxx}
-\do\x\x\y\z
-\end{example}
-\acmd*{\define@keylist}
-The advantage of using token list registers is that the parameter characters need not be doubled in the token list registers, unlike when using macros. The token list register \fx{\temptoksa} can be reused as soon as the key \fx{boola} has been set. See \cref{sec:condit-in-macros} for more information on using macros and token list registers to parse key functions.
-
-\subsubsection{Parameterized macros in key macros}
-\label{sec:macros-in-keymacros}
-
-The examples in \cref{sec:multkeys-examples} would have provided some glimpse of the rules guiding the use of parameter characters in key macros. The general rules are as follows:
-\begin{enum}
-\item When key macros are parsed through token list registers, the parameter characters shouldn't be doubled (\ie, use \cmdtext{\#1} for outermost parameters).
-\item When key macros are parsed via intermediate macros, the parameter characters should be doubled but only once (\ie, use \cmdtext{\#\#1} for outermost parameters).
-\item In all other cases (\ie, when using \fx{\define@keylist} or \acmd{\newkeylist} and their starred variants) the parameter characters should be doubled twice (\ie, use \cmdtext{\#\#\#\#1} for outermost parameters).
-\item Within \fx{\define@keylist} and \fx{\newkeylist}, you can refer to the user-submitted key value by \cmdtext{\#\#1}.
-\end{enum}
-\tex will flag a fatal error when any of these rules is breached. The need to double the parameter character arises from setting keys, not when defining keys. When absorbing their arguments, both \fx{\define@keylist} and \fx{\newkeylist} actually temporarily sanitize the parameter character.
-
-The following examples illustrate the use of these rules. The commands \fx{\skif}, \fx{\skifx}, \fx{\skelse} and \fx{\skfi} are described in \cref{sec:pseudo-primitives}.
-\begin{example}
-\define@keylist{%
- tog,toga,true,\iftogon{mp@toga}{%
- \def\swear####1{Repeat after me: `####1'!}%
- }{%
- \let\swear\@gobble
- }%
-}
-\setkeys[KV]{fam}{toga=true}
-
-\NewToks[temptoks]{a}
-
-\temptoksa={\long\def\funcforproclaim#1%
- {A proclaimed statement: #1}}
-\define@keylist{%
- bool,boola,true,\skif{mp@boola}\def\yes####1%
- {Accept `####1'!}\skelse\def\no####1{Reject `####1'!}\skfi;
- cmd,proclaim,Statement,\the\temptoksa
-}
-\setkeys[KV]{fam}{boola=true,proclaim=nature}
-
-\CKVS{align}{left,right,center}
-
-\define@keylist{choice,align,center,
- \skifcase\nr
- \def\hold####1{\def####1########1{===########1===}}%
- \skor
- \def\hold####1{\def####1########1{+++########1+++}}%
- \skfi
-}
-\setkeys[KV]{fam}{align=right}
-
-\CKVS{focus}{left,right,center}
-\def\keylistvector{%
- choice,focus,center,\def\hold####1%
- {\def####1########1{===########1===}}%
-}
-\define@keylist*\keylistvector
-\setkeys[KV]{fam}{focus=right}
-
-\def\keylistvector{cmd,keya,xxx,\def\hold####1%
- {\def####1########1{===########1===}}}
-\define@keylist*\keylistvector
-\setkeys[KV]{fam}{keya=yyy}
-
-\def\funcforkeyb{\def\hold##1{\def##1####1{===####1===}}}
-\define@keylist{cmd,keyb,xxx,\funcforkeyb}
-\setkeys[KV]{fam}{keyb=yyy}
-
-\define@cmdkey[KV]{fam}[mp@]{keyc}[xxx]{\def\hold##1{##1}}
-\setkeys[KV]{fam}{keyc=yyy}
-
-\def\keylistvector{%
- ord,keyda,aaa,\def\hold####1%
- {\def####1########1{===########1===}};
- cmd,keydb,bbb,\def\althold####1%
- {\def####1########1{***########1***}}%
-}
-\define@keylist*\keylistvector
-\setkeys[KV]{fam}{keyda=xxx,keydb=yyy}
-
-|comm(The next one fails. Why?)
-\define@keylist{%
- ord,keye,unknown,\def\hold##1{\def##1####1{####1}}%
-}
-\setkeys[KV]{fam}{keye=yyy}
-
-\define@keylist{%
- ord,keyfa,xxx,
- \skifx\x\y
- \def\hold####1{\def####1########1{===########1===}}%
- \skelse
- \def\hold####1{\def####1########1{***########1***}}%
- \skfi;
- cmd,keyfb,yyy,
- \SKV@ifx\x\y{%
- \def\nosupergobble####1{\def####1########1{########1}}%
- }{%
- \def\supergobble####1{\def####1########1{}}%
- }%
-}
-\setkeys[KV]{fam}{keyfa=value,keyfb=value}
-
-\def\funcforboolb{\ifmp@boolba\def\do##1{%
- \def##1####1####2{\expandafter\expandafter\expandafter\in@
- \expandafter\expandafter\expandafter{\expandafter####1%
- \expandafter}\expandafter{####2}}}\fi}
-
-\define@keylist{3,boolba,true,\funcforboolb;3,boolbb,true,;}
-\setkeys[KV]{fam}{boolba=true}
-
-\NewToks[temptoks]{a,b}
-
-\temptoksa{\ifmp@boolc\def\do#1{%
- \def#1##1##2{\expandafter\expandafter\expandafter\in@
- \expandafter\expandafter\expandafter{\expandafter##1%
- \expandafter}\expandafter{##2}}}\fi}
-\temptoksb{\iftogon{mp@togb}{\def\tempa#1{Use #1}}%
- {\def\tempb#1{Don't use #1}}}
-\define@keylist{3,boolc,true,\the\temptoksa;
- 4,togb,true,\the\temptoksb}
-
-\setkeys[KV]{fam}{boolc=true,togb=true}
-\do\x \def\y{x} \def\z{xxx} \x\y\z
-
-\def\keylistvector{bool,boold,true,
- \ifswitchon{mp@boold}{%
- \def\hold####1{\def####1########1{***########1***}}%
- }{%
- \def\hold####1{\def####1########1{===########1===}}%
- }%
-}
-\define@keylist*\keylistvector
-\setkeys[KV]{fam}{boold=true}
-\end{example}
-
-\subsection{Input error}
-\label{sec:input-error}
-
-Native-boolean, toggle-boolean and choice keys issue error messages if the key value is not valid, \ie, not in the list of admissible values. The admissible values of native-boolean and toggle keys are \fx{true} and \fx{false}. The valid values of choice keys are set by the user via \acmd{\CKVS}. The default input error is defined by the macro \fx{\SKV@inputerr}. It takes two arguments (\ie, value and key) and can be customized by the user.
-
-\subsection{Conditionals in key macros}
-\label{sec:condit-in-keys}
-
-\index{TeXBook=The \TeX Book}
-The \tex conditional primitives \fx{\if}, \fx{\ifx}, \fx{\else} and \fx{\fi} cannot appear in the key macro when \acmd{\define@keylist} is being invoked. The reason can be traced to the discussion on page~211 of the \TeX Book and the loops used in the \pkg{skeyval} to define keys by means of \acmd{\define@keylist}. There are many possible approaches to resolving this problem, but only four appear to be attractive (see \crefrange{sec:condit-in-macros}{sec:using-toggles}).
-
-\subsubsection[Using macros or token list registers]
- {Burying conditionals in intermediate macros or token list registers}
-\label{sec:condit-in-macros}
-
-Key macros/functions involving conditional operations such as
-\begin{example}
-\ifmp@bool \do \else \donot \fi
-\end{example}
-can be submitted to \acmd{\define@keylist} via intermediate macros, as seen above (in \cref{sec:multkeys-examples}), but the approach isn't economical and thus not advisable. Nevertheless, we give more examples of deploying intermediate macros below. Let the key macro prefix be \fx{mp@}, the key prefix be \fx{KV}, and the key family be \fx{fam}.
-
-Suppose we want to submit the following:
-\begin{example}
-\define@keylist{3,bool,true,\ifmp@bool \do \else \donot \fi}.
-\end{example}
-\acmd*{\define@keylist}
-The presence of \fx{\if} and \fx{\fi} in the argument will trigger an error when \tex is scanning and skipping tokens, and, secondly, because of the loops and conditionals used by the \pkg{skeyval} in defining keys via \acmd{\define@keylist}. Neither \fx{\protect} nor \fx{\noexpand} is helpful here. One solution is to first define
-\begin{example}
-\def\funcforbool{\ifmp@bool \do \else \donot \fi}
-\end{example}
-and then do
-\begin{example}
-\define@keylist{3,bool,true,\funcforbool},
-\end{example}
-\acmd*{\define@keylist}
-which will execute \fx{\funcforbool} when the key \fx{bool} is set. One significant drawback of this approach is that once the key \fx{bool} has been defined by the above statement, the function \fx{\funcforbool} may not be redefined and reused before the key \fx{bool} is set. This is wasteful and not advisable. This approach is included here only for demonstration purposes. The schemes in \crefrange{sec:pseudo-primitives}{sec:switches} are preferable.
-
-As another example, we may do
-\begin{example}
-\def\funcforboola{\ifmp@boola\def\do##1{%
- \def##1####1####2{\expandafter\expandafter\expandafter\in@
- \expandafter\expandafter\expandafter{\expandafter####1%
- \expandafter}\expandafter{####2}}}\fi}
-
-\define@keylist{3,boola,true,\funcforboola}
-
-\setkeys[KV]{fam}{boola=true}
-
-\def\y{x} \def\z{xxx} \do\x \x\y\z
-\end{example}
-
-Token list registers can be used here economically instead of macros. Below we define one native-boolean key and one toggle-boolean key:
-\begin{example}
-\NewToks[temptoks]{a,b}
-
-\temptoksa{\ifmp@boola\def\do#1{%
- \def#1##1##2{\expandafter\expandafter\expandafter\in@
- \expandafter\expandafter\expandafter{\expandafter##1%
- \expandafter}\expandafter{##2}}}\fi}
-
-\temptoksb{\iftogon{mp@toga}{\def\order#1{Use `#1' now!}}{}}
-
-\define@keylist{3,boola,true,\the\temptoksa;
- 4,toga,true,\the\temptoksb}
-
-\setkeys[KV]{fam}{boola=true,toga=true}
-\end{example}
-\acmd*{\define@keylist,\setkeys,\NewToks}
-You can see the significant reduction in the number of parameter characters when using token list registers. The utility token list registers \fx{\temptoksa} and \fx{\temptoksb} can be reused to define many other keys as soon as the keys \fx{boola} and \fx{toga} have been set. However, as noted earlier, the approach of using intermediate macros and token list registers to parse arguments to \fx{\define@keylist} is not attractive because of the overheads in the number of macros and token list registers.
-
-\subsubsection[Using pseudo-primitives]
- {Using pseudo-primitives to submit the conditionals}
-\label{sec:pseudo-primitives}
-
-There are two downsides to the above approach of hiding conditionals in macros: the macros have to be defined and, although they can be redefined and reused (after the associated key has been set), they tend to defeat the initial aim of the package, which is to economize on tokens.
-
-Suppose we want to define a native-boolean key \fx{mybool} with the following key macro:
-\begin{example}
-\ifmp@mybool
- \def\hold##1{\def##1####1{***####1***}}%
-\else
- \def\hold##1{\def##1####1{===####1===}}%
-\fi
-\end{example}
-where the key prefix \fx{KV}, key family \fx{fam}, and the macro prefix \fx{mp@} are assumed to have been defined previously. Then, instead of hiding the conditional in an intermediate macro, we may adopt the following:
-\begin{example}
-\define@keylist{3,mybool,true,
- |makered(\skif{|mcolor(mp@mybool)})\def\hold##1{\def##1####1{***####1***}}%
- |makered(\skelse)\def\hold##1{\def##1####1{===####1===}}|makered(\skfi)
-}
-
-\setkeys[KV]{fam}{mybool=true |makered(or) false}
-\hold\x
-\end{example}
-\acmdm*{\skif,\skifx,\skelse,\skfi}
-\acmd*{\skifcase,\skor,\define@keylist}
-Here we have used the pseudo-primitives \fx{\skif{mp@mybool}}, \fx{\skifx}, \fx{\skelse} and \fx{\skfi} for the commands \fx{\ifmp@mybool}, \fx{\ifx}, \fx{\else} and \fx{\fi}, respectively, to hide the latter four from \TeX's scanning and skipping mechanism. It should be noted that \fx{\skif{mp@mybool}} requires that the argument \ang{mp@mybool} be enclosed in braces. Something like \fx{\skifmp@mybool} will be interpreted by \tex as an undefined control sequence when the key \fx{mybool} is being set. Defining the command \fx{\skif{mp@mybool}} to be \fx{\ifmp@mybool} before hand would have failed because \tex's scanner would then get the hint of the assignment.
-
-\Note We haven't found any package that has defined \fx{\skif}, \fx{\skifx}, \fx{\skelse}, \fx{\skfi}, \fx{\skifcase} or \fx{\skor}. The \pkgm{xifthen}, for example, uses \fx{\OR}, not \fx{\skor}. If the situation changes in the future (\ie, if a package is observed to have defined any of these commands), they will be appropriately modified in the \pkg{skeyval}. Information and feedback from package users is solicited in this regard.
-
-We have redefined the \fx{\setkeys} command of the \pkg{xkeyval} to recognize that \fx{\skif{boolean}}, \fx{\skifx}, \fx{\skelse}, \fx{\skfi}, \fx{\skifcase} and \fx{\skor} stand for \fx{\ifboolean}, \fx{\ifx}, \fx{\else}, \fx{\fi}, \fx{\ifcase} and \fx{\or}, respectively. The redefined \fx{\setkeys} command has the same syntaxes as as in \pkg{xkeyval}:
-\begin{macro}
-\setkeys[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)}
-\setkeys|redstar[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)}
-\setkeys|redplus[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)}
-\setkeys|redstar|redplus[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)}.
-\end{macro}
-\acmdm*{\setkeys,\setkeys*,\setkeys*+}
-No errors are produced if any of the sets \ang{prefix}, \ang{families}, \ang{na}, and \ang{keys=values} is empty. In fact, an instruction such as \fx{\setkeys[]{}[]{}} is completely benign, and so is \fx{\setkeys{}{}}.
-
-\paragraph{Conditionals involving \textcolor{xmagenta1}{\@bs ifcase}:}
-
-The case of conditionals involving \fx{\ifcase} can be handled in the same way as those involving \fx{\if}:
-\begin{example}
-\CKVS{focus}{center,left,right,justified}
-
-\temptoksa{\ifcase\nr\relax
- \def\mp@focus{\centering}\or\def\mp@focus{\flushright}
- \or\def\mp@focus{\flushleft}\or\let\mp@focus\relax\fi}
-
-\define@keylist{5,focus,center,\the\temptoksa}
-\end{example}
-\acmd*{\CKVS,\define@keylist}
-
-This can be written more compactly as follows, which obviates the need for intermediate macros and list registers:
-\begin{example}
-\define@keylist{menu,focus,center,|makered(\skifcase)\nr\relax
- \def\mp@focus{\centering}|makered(\skor)\def\mp@focus{\flushright}
- |makered(\skor)\def\mp@focus{\flushleft}|makered(\skor)\let\mp@focus\relax|makered(\skfi)}
-\end{example}
-\acmdm*{\skifcase,\skor}
-Here, the \pkg{skeyval} uses \fx{\skifcase}, \fx{\skor}, and \acmd{\skfi} for \fx{\ifcase}, \fx{\or} and \fx{\fi}, respectively; otherwise, \tex would be grumpy.
-
-The key \fx{focus} can now be readily set: \fx{\setkeys[KV]{fam}{focus=left}}.
-
-\subsubsection[Using switches]{Using switches to submit the conditionals}
-\label{sec:switches}
-
-The approaches of \cref{sec:pseudo-primitives} provide a familiar \tex-like syntax for submitting conditionals to \fx{\define@keylist}. There is yet another approach that we developed. It is related to the native \tex boolean conditional. By \emph{switches} we mean the usual \tex's \fx{\iftrue} and \fx{\iffalse} booleans, but expressed in different syntax and semantics.
-
-New switches can be introduced by using the following commands:
-
-\begin{macro}
-\newswitch[|vang(optional prefix)]{|vang(boolean)}[|vang(optional state)]
-\defswitch[|vang(optional prefix)]{|vang(boolean)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\newswitch,\defswitch}
-The command \fx{\newswitch} provides a new native-boolean register of the form \fx{\if}\unskip\ang{prefix}\unskip\ang{boolean} if the register didn't already exist; if the register already existed, an error is flagged. The command \fx{\defswitch}, on the other hand, doesn't flag any error even if the switch register \ang{boolean} already existed. Instead it makes an entry (warning or information) in the transcript log file if the package option \fx{verbose} is selected.
-
-The optional \ang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}); the switch will be initialized to that state. With this definition, you can issue \fx{\if}\unskip\ang{switch}, \bs\ang{switch}\unskip\fx{true}, and \bs\ang{switch}\unskip\fx{false}. One advantage of \fx{\newswitch} is that a switch can start off as either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}), unlike the classical \tex's case in which all booleans start off as \fx{false}. Also, switches can be used where primitive \tex conditionals may prove impossible. For example, we know that you can't do \fx{\let\ifabc\iftrue} within the body of a conditional text without hiding the assignment from \tex's scanning mechanism.
-
-\begin{example}
-\newswitch{boola} |tto \newif\ifboola
-
-\newswitch[bool]{b}[true] |tto \newif\ifboolb \boolbtrue
-
-\newswitch[bool]{c}[on] |tto \newif\ifboolc \boolctrue
-
-\newswitch[bool]{d}[off] |tto \newif\ifboold \booldfalse
-\end{example}
-
-You can define many switches in a row by the following commands:
-\begin{macro}
-\NewSwitches[|vang(optional prefix)]{|vang(switches)}[|vang(optional state)]
-\DefSwitches[|vang(optional prefix)]{|vang(switches)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\NewSwitches,\DefSwitches}
-Each member of \ang{switches} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}).
-
-Here are some examples:
-
-\begin{example}
-\NewSwitches{x,y,z}[off]
- |tto \newswitch{x}[false] \newswitch{y}[false]
- \newswitch{z}[false]
-
-\DefSwitches[skv@]{u,w}[true]
- |tto \defswitch[skv@]{u}[true] \defswitch[skv@]{w}[true]
- |tto \defswitch{skv@u}[true] \defswitch{skv@w}[true]
-\end{example}
-
-Switches may be set and tested using the following commands:
-\begin{macro}
-\setswitch{|vang(switch)}{|vang(value/state)}
-
-\switchon{|vang(switch)} |tto \|vang(switch)true
-
-\switchtrue{|vang(switch)} |tto \|vang(switch)true
-
-\switchoff{|vang(switch)} |tto \|vang(switch)false
-
-\switchfalse{|vang(switch)} |tto \|vang(switch)false
-
-\ifswitchon{|vang(switch)}{|vang(true text)}{|vang(false text)}
-
-\ifswitchtrue{|vang(switch)}{|vang(true text)}{|vang(false text)}
-
-\ifswitchoff{|vang(switch)}{|vang(not true)}{|vang(not false)}
-
-\ifswitchfalse{|vang(switch)}{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\newswitch,\setswitch,\switchon,\switchoff,\ifswitchon,
-\ifswitchoff,\switchtrue,\switchfalse,\ifswitchtrue,
-\ifswitchfalse}
-
-\begin{example}
-\NewSwitches{w,x,y,z}
-
-\setswitch{w}{true} |tto \setswitch{w}{on}
-\setswitch{x}{on} |tto \setswitch{x}{true}
-\setswitch{y}{false} |tto \setswitch{y}{off}
-\setswitch{z}{off} |tto \setswitch{z}{false}
-
-\ifswitchon{x}{\def\xx{On}}{\def\xx{Off}}
-
-\ifswitchoff{y}{\def\yy{Off}}{\def\yy{On}}
-\end{example}
-
-Now how do we use switches in \fx{\define@keylist}? Suppose the key prefix is \fx{KV}, the key family is \fx{fam}, and the key macro is \fx{mp@}. Then the following works:
-\begin{example}
-\define@keylist{3,swa,true,
- |makered(\ifswitchon){mp@swa}{\def\say{Swtich `a' is true}}
- {\def\say{Swtich `a' is false}}}
-
-\setkeys[KV]{fam}{swa=true |makered(or) false |makered(or) on |makered(or) off}
-\end{example}
-\acmd*{\define@keylist}
-
-\Note Please note that ``switch keys'' are actually native-boolean keys (\fx{bool} or type~\fx{3} key). When setting native-boolean and toggle-boolean keys you can supply either \fx{true}, \fx{false}, \fx{on} or \fx{off} as values. We have modified the relevant internal macros of the \pkg{xkeyval} to make this possible for the native-boolean keys as well.
-
-\subsubsection[Using toggles]{Using toggles to submit the conditionals}
-\label{sec:using-toggles}
-
-Toggle booleans, described in \cref{sec:toggles}, can also be used to circumvent the problem of matching \fx{\if} and \fx{\fi} in difficult circumstances, since toggles aren't \tex primitives, and, as noted in \cref{sec:toggles}, toggles are very economical. For example, the following works:
-\begin{example}
-\define@keylist{4,toga,true,
- |makered(\iftogon){mp@toga}{\def\say{Toggle `a' is true}}%
- {\def\say{Toggle `a' is false}}}
-
-\setkeys[KV]{fam}{toga= true |makered(or) false}
-\end{example}
-\acmd*{\define@keylist,\iftogon}
-where the key prefix, key family, and macro prefix are still assumed to be \fx{KV}, \fx{fam}, \fx{mp@}, respectively. Recall that toggle keys are type~4 keys.
-
-\section{Key command and key environment}
-\label{sec:keycommand}
-
-The \fx{\define@keylist} macro of \cref{sec:def-multiple-keys}, together with the \fx{\newkeylist} macro of \cref{sec:avoiding-redef}, provides an attractive toolkit for developing a system for defining commands using keys, in the manner of the \pkgm{keycommand} but with a more compact user interface. See the \pkgm{skeycommand} for details.
-
-\section{Checking and redefining keys}
-\label{sec:check-redef-keys}
-
-\subsection{Checking the status of a key}
-\label{sec:status-keys}
-
-Three mechanisms have been introduced in the \pkg{skeyval} to ascertain the statuses of keys. These are as follows.
-
-\begin{macro}
-\ifkeydefined[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\ifkeydefined}
-This executes \ang{true} if \ang{key} is defined, reserved, or suspended with a prefix in \ang{prefixes} and family in \ang{families}; it returns \ang{false} otherwise. This is similar to
-the \pkg{xkeyval}'s \acmdm{\key@ifundefined}, but, apart from reversing the logic of the test, \fx{\ifkeydefined} loops over prefixes (in addition to looping over families) to locate the key, and also considers reserved and suspended keys as defined. The lists \ang{prefixes} and \ang{families} may contain nil, one or more elements.
-
-\begin{macro}
-\ifkeyreserved[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\ifkeyreserved}
-This returns \ang{true} if \ang{key} is reserved with a prefix in \ang{prefixes} and family in \ang{families}; it returns \ang{false} otherwise. Reserved keys are introduced in \cref{sec:reserve-keys}.
-
-\begin{macro}
-\ifkeysuspended[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\ifkeysuspended}
-This executes \ang{true} if \ang{key} is suspended with a prefix in \ang{prefixes} and family in \ang{families}; it executes \ang{false} otherwise. Suspended keys are introduced in \cref{sec:suspend-keys}.
-
-\subsection{Unintentional redefinition of keys}
-\label{sec:redef-keys}
-
-The \pkg{xkeyval}, by default, permits the automatic redefining of keys of the same \ang{prefix} and \ang{family}: at the point of defining a new key, the package doesn't, by default, check whether or not the key had been previously defined with the same \ang{prefix} and \ang{family}. In some circumstances this can be undesirable, and even dangerous, especially if the same key (of the same \ang{prefix} and \ang{family}) is mistakenly redefined with different macros/functions in the same package or across packages. One way to solve this problem is to use \pkg{xkeyval}'s \fx{\key@ifundefined} command (or the \pkg{skeyval}'s \fx{\ifkeydefined}) to confirm the status of a key prior to its definition. However, using these commands before defining every key can be laborious.
-
-Consider the following two scenarios:
-\begin{example}
-\define@key[KV]{fam}{keya}[$\star$]{\def\tempa##1{##1}}
-
-\define@boolkey[KV]{fam}{keya}[true]{%
- \ifKV@fam@keya\def\tempb{#1}\fi}
-
-\setkeys[KV]{fam}{keya=$\textbullet$}
-\end{example}
-\acmd*{\setkeys}
-Obviously the two definitions of \ang{keya} are valid and will be implemented but the \acmd{\setkeys} command here will issue an unintelligible error message, like \LaTeX's ``You are in trouble here \textellipsis''. The key \ang{keya} has been defined twice and \acmd{\setkeys} has sought to use its latest definition to set its value, which is incorrect. As mentioned in \cref{sec:toggle-keys}, the \acmd{\setkeys} command (and friends) of the \pkg{xkeyval} doesn't know if a key has been redefined in the same \ang{family} and with the same \ang{prefix}. At the high level, it doesn't consider the key type: it uses the latest definition of the key to set its value using the key's macro. This is particularly worrisome in the case of toggle keys, since although toggle keys have their own separate namespace, they can easily be confusing (at least to \acmd{\setkeys}) if they have names identical to other keys within the same family and with the same prefix. In fact, the problem can manifest itself in more ways than the scenario just depicted.
-
-If the package option \acmd{verbose} is enabled, the \pkg{skeyval} provides a warning system (by making an entry in the transcript log file) if an existing key is being redefined (within the same family and with the same prefix) by any of the following commands:
-\begin{macro}
-\define@key, \define@cmdkey, \define@cmdkeys,
-\define@choicekey, \define@boolkey, \define@boolkeys,
-\define@biboolkeys, \define@uniboolkeys, \define@biuniboolkeys,
-\define@togkey, \define@togkeys, \define@bitogkeys,
-\define@unitogkeys, \define@biunitogkeys
-\end{macro}
-
-The machinery of \cref{sec:avoiding-redef} can be used to avoid inadvertently redefining existing keys.
-
-\subsubsection{Avoiding multiple definitions of same key}
-\label{sec:avoiding-redef}
-
-For the above reasons, the \pkg{skeyval} introduces the following commands, which have the same syntaxes as their counterparts from the \asty{xkeyval} and \asty{skeyval} packages but which bar the user from repeated definition of keys with identical names within the same \ang{family} and with the same \ang{prefix}:
-\acmd*{\define@boolkey}
-\acmdm*{\newordkey,\newcmdkey,\newboolkey,\newboolkeys,\newtogkey,\newtogkeys,
-\newchoicekey,\newbiboolkeys,\newuniboolkeys,\newbiuniboolkeys,\newbitogkeys,
-\newunitogkeys,\newbiunitogkeys,\define@key,\define@cmdkey,
-\define@cmdkeys,\define@biboolkeys,\define@uniboolkeys,
-\define@biuniboolkeys,\define@bitogkeys,\define@unitogkeys,\define@biunitogkeys}
-\begin{macro}
-|comm(The following defines ``ordinary'' keys |:the counterpart)
-|comm(of \define@key from the xkeyval package|!:)
-\newordkey[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(default)]{|vang(funtion)}
-
-|comm(Counterpart of \define@cmdkey:)
-\newcmdkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(funtion)}
-
-|comm(Counterpart of \define@cmdkeys:)
-\newcmdkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)]
-
-|comm(Counterparts of \define@boolkey:)
-\newboolkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(funtion)}
-\newboolkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(funtion1)}{|vang(funtion2)}
-
-|comm(Counterpart of \define@boolkeys:)
-\newboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)]
-
-|comm(Counterpart of \define@biboolkeys:)
-\newbiboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(func for primary boolean)}
- {|vang(func for secondary boolean)}
-
-|comm(Counterpart of \define@uniboolkeys:)
-\newuniboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(func for primary boolean)}
- {|vang(func for secondary boolean)}
-
-|comm(Counterpart of \define@biuniboolkeys:)
-\newbiuniboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary boolean)}[|vang(default value for primary boolean)]
- {|vang(secondary boolean)}{|vang(func for primary boolean)}
- {|vang(func for secondary boolean)}
-
-|comm(Counterparts of \define@togkey:)
-\newtogkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(funtion)}
-\newtogkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]%
- {|vang(funtion1)}{|vang(funtion2)}
-
-|comm(Counterpart of \define@togkeys:)
-\newtogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)]
-
-|comm(Counterpart of \define@bitogkeys:)
-\newbitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary toggle)}[|vang(default value for primary toggle)]
- {|vang(secondary toggle)}{|vang(func for primary toggle)}
- {|vang(func for secondary toggle)}
-
-|comm(Counterpart of \define@unitogkeys:)
-\newunitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary toggle)}[|vang(default value for primary toggle)]
- {|vang(secondary toggle)}{|vang(func for primary toggle)}
- {|vang(func for secondary toggle)}
-
-|comm(Counterpart of \define@biunitogkeys:)
-\newbiunitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]
- {|vang(primary toggle)}[|vang(default value for primary toggle)]
- {|vang(secondary toggle)}{|vang(func for primary toggle)}
- {|vang(func for secondary toggle)}
-
-|comm(Counterparts of \define@choicekey:)
-\newchoicekey[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}%
- [|vang(default)]{|vang(funtion)}
-\newchoicekey|redstar[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}%
- [|vang(default)]{|vang(funtion)}
-\newchoicekey|redplus[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}%
- [|vang(default)]{|vang(funtion1)}{|vang(funtion2)}
-\newchoicekey|redstar|redplus[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}%
- [|vang(default)]{|vang(funtion1)}{|vang(funtion2)}
-
-|comm(Counterpart of \define@keylist:)
-\newkeylist{|vang(key type/id), |vang(key), |vang(key default value),
- |vang(key macro/function); |vang(another set of key specifiers); etc}.
-\end{macro}
-\acmdm*{\define@choicekey,\newchoicekey*,\newchoicekey*+,\newkeylist,\newkeylist*}
-
-The following aliases are defined in the \pkg{skeyval}:
-\begin{macro}
-\define@menukey|redstar|redplus |tto \define@choicekey|redstar|redplus
-\newmenukey|redstar|redplus |tto \newchoicekey|redstar|redplus
-\end{macro}
-\acmdm*{\define@menukey, \define@menukey*, \newmenukey, \newmenukey*}
-
-We could simply have redefined/modified the legacy key definition commands in the \pkg{xkeyval} to make it impossible to define keys of the same name in the same family and with the same prefix, but this approach would be unsafe since there are many packages using the \pkg{xkeyval} and those packages may well have redefined identical keys. Moreover, the legacy key definition commands from the \pkg{xkeyval} may be needed to redefine a disabled key (see \cref{sec:disable-reserv-keys}).
-
-All the commands of the type \textnewkey are robust and may be used in expansion contexts without fear of premature expansion, although expandable tokens in the definition may need to be protected. Commands of the type \textdefinekey are originally, in the \pkg{xkeyval}, non-robust and remain so in the \pkg{skeyval}.
-
-With the above macros, the following will flag an understandable error message, namely that the key \ang{keya} is about being redefined in the same family \ang{fam} and with the same prefix \ang{KV}:
-\begin{example}
-\newordkey[KV]{fam}{keya}[$\star$]{\def\tempa##1{##1}}
-
-\newboolkey[KV]{fam}{keya}[true]{%
- \ifKV@fam@keya\def\tempb{#1}\fi}
-\end{example}
-
-\section[Disabling, reserving, suspending keys, etc.]%
- {Disabling, localizing, reserving, suspending, restoring, and removing keys}
-\label{sec:disable-reserv-keys}
-
-Besides macros for defining keys, the \pkg{skeyval} also introduces mechanisms for disabling, localizing, reserving, suspending, restoring, and completely removing existing keys.
-
-\subsection{Disabling keys}
-\label{sec:disable-keys}
-
-The \pkg{skeyval} has modified the definition of \fx{\disable@keys} from the \pkg{xkeyval} to allow for looping over key prefixes and key families and for bespoke warnings and error messages, without engendering any potential conflict with the legacy \fx{\disable@keys}. The new command is still called \fx{\disable@keys} and has the same syntax as the native \fx{\disable@keys} of the \pkg{xkeyval}, except that the new command accepts key prefixes (instead of just one prefix) and key families (instead of just one family):
-\begin{macro}
-\disable@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}.
-\end{macro}
-\acmdm*{\disable@keys}
-Here \ang{prefixes}, \ang{families}, \ang{keys} are lists of comma-separated entries referring to the keys to be disabled. Each of the lists \ang{prefixes}, \ang{families}, \ang{keys} may contain nil, one or more elements. If any of the members in \ang{keys} can't be located in \ang{families} and with prefix in \ang{prefixes}, an informational (not error) message is logged in respect of this member, but only if the package option \fx{verbose} is selected.
-
-The legacy version of \fx{\disable@keys} (\ie, that of the \pkg{xkeyval}) is still available via the starred variant:
-\begin{macro}
-\disable@keys|redstar[|vang(prefix)]{|vang(family)}{|vang(keys)}
-\end{macro}
-\acmdm*{\disable@keys*}
-Note that this doesn't accept key prefixes and families, but only one key prefix and only one key family: the \fx{\disable@keys} command from the \pkg{xkeyval} can only be used to disable keys with the same \ang{prefix} and from the same \ang{family}, but not across prefixes and families.
-
-Any attempt to subsequently set or use a disabled key will prompt the following error message. (The \pkg{xkeyval} issues a warning in this case.) The error message can be modified by the user, but the names of the controls \fx{\SKV@disabledkey@err} and \acmd{\SKV@disabledkey} should be retained.
-\begin{macro}
-\def\SKV@disabledkey@err{%
- \PackageError{skeyval}{%
- Key |vang(key) with prefix |vang(prefix) in family |vang(family)
- was disabled on input line |vang(lineno)
- }{%
- You can't set or reset |vang(key) at this
- late stage. Perhaps you're required to set it
- earlier, within a package or in the document's preamble.
- }%
-}
-\end{macro}
-\acmdm*{\SKV@disabledkey@err}
-If the user attempts to disable an undefined key, the \pkg{xkeyval} issues a fatal error; the \pkg{skeyval}, on the other hand, issues a warning in the transcript log file (if the package option \acmd{verbose} is selected), since the situation isn't fatal to the outcome of the \latex pass or the document.
-
-Disabled keys can be redefined with commands in the \textdefinekey category but not with commands in the \textnewkey category, since a disabled key remains defined: only its macro has been replaced by an error message signifying the disabling of the key.
-
-\textbf{Note:} Reserved and suspended keys can't be disabled, until they are unreserved or restored (see \crefrange{sec:reserve-keys}{sec:suspend-keys}).
-
-\subsection{Localizing keys}
-\label{sec:local-keys}
-
-By localizing a key we mean disabling a key at the end of the current class or package file. This is basically the command \acmd{\disable@keys} executed on the hook \acmd{\SKV@BeforeClassEnd} or \acmd{\SKV@BeforePackageEnd}, depending on \acmd{\@currext}. The hooks \acmd{\SKV@BeforeClassEnd} and \acmd{\SKV@BeforePackageEnd} are described in \cref{sec:misce-commands} (\macrangeref{befpkgend}{befclsend}).
-
-The syntax for localizing keys is exactly like that for disabling keys:
-\begin{macro}
-\localize@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}.
-\end{macro}
-\acmdm*{\localize@keys}
-If any of the members of the set \ang{keys} is not found in any of the members of \ang{families} and with a prefix from \ang{prefixes}, an informational message is written into the log file (if the package option \fx{verbose} is selected), but no errors are flagged.
-
-The starred variant of \fx{\localize@keys} disables the keys listed in \ang{keys}, not at the end of the package or class file, but right before the start of document (\ie, at the boundary between the document preamble and \acmd{\AtBeginDocument}):
-\begin{macro}
-\localize@keys|redstar[|vang(prefixes)]{|vang(families)}{|vang(keys)}.
-\end{macro}
-\acmdm*{\localize@keys*}
-The hook used here is \acmd{\SKV@BeforeDocumentStart}, described in \cref{sec:misce-commands}, \macref{beforedocstart}.
-
-A key can be localized as soon as it is defined. In fact, a key can be localized even before it is defined: the actual disablement of the key will take place at the execution of the contents of \acmd{\SKV@BeforeClassEnd} or \acmd{\SKV@BeforePackageEnd} or \acmd{\SKV@BeforeDocumentStart}.
-
-Localized keys can be redefined with commands in the \textdefinekey category, but not with commands in the \textnewkey category.
-
-\subsection{Reserving and unreserving keys}
-\label{sec:reserve-keys}
-
-The \pkg{xkeyval} bars its users from defining new keys with \fx{XKV} as a prefix. The \pkg{skeyval} generalizes this concept via the following three developer macros:
-\begin{macro}
-\ReserveKeyPrefixNames{|vang(list)}
-\ReserveKeyPrefixNames|redstar{|vang(list)}
-\end{macro}
-\acmdm*{\ReserveKeyPrefixNames,\ReserveKeyPrefixNames*}
-This allows the package developer to bar the future use of names appearing in \ang{list} as key prefixes when defining, disabling, reserving and suspending keys; but not when setting keys. The \ang{list}, whose members are comma-separated, can be populated by the package developer as required. The starred variant takes effect at the end of current package; the unstarred one assumes immediate effect. If the developer wants to use any member of \ang{list} in his own package, it may be necessary for him to use the starred version.
-
-\begin{macro}
-\ReserveMacroPrefixNames{|vang(list)}
-\ReserveMacroPrefixNames|redstar{|vang(list)}
-\end{macro}
-\acmdm*{\ReserveMacroPrefixNames,\ReserveMacroPrefixNames*}
-This has a similar functionality to \fx{\ReserveKeyPrefixNames}, but applies to macro prefixes instead of key prefixes. The starred variant takes effect at the end of current package, while the unstarred one assumes immediate effect.
-
-\begin{macro}
-\ReserveFamilyNames{|vang(list)}
-\ReserveFamilyNames|redstar{|vang(list)}
-\end{macro}
-\acmdm*{\ReserveFamilyNames,\ReserveFamilyNames*}
-This reserves family names \ang{list} and prevents further use of members of \ang{list}. The starred variant takes effect at the end of current package, while the unstarred one assumes immediate effect.
-
-\textbf{Note:} The lists in these macros are scanned only when defining, disabling, reserving or suspending keys, and not when setting existing keys. If the lists were also to be scanned when keys are being set, then a situation could arise in which existing keys (including those defined by prior packages) couldn't be set.
-
-These macros could be used, for instances, to secure against future use the key prefixes, macro prefixes, and key families that have used in a new style or class file. For example, we have used these facilities to bar users of the \pkg{skeyval} from using the key prefix \fx{SKV}, the family name \fx{skeyval}, and the macro prefix \fx{SKV@} to define new keys in their packages.
-
-
-In addition to the above reservation commands, the \pkg{skeyval} also introduces the following command:
-\begin{macro}
-\reserve@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)},
-\end{macro}
-\acmdm*{\reserve@keys}
-where the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements. Defined, reserved and suspended keys can't be reserved.
-
-Reserved keys have to be unreserved with the following command before they can be defined and used:
-\begin{macro}
-\unreserve@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)},
-\end{macro}
-\acmdm*{\unreserve@keys}
-where, again, the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements. If a key was not previously reserved, this command will simply issue an informational message in the log file (if the package option \fx{verbose} is selected) and ignore that key. Defined keys and suspended keys can also be unreserved, which is equivalent to removing the keys (see \cref{sec:remove-keys}).
-
-\subsection{Suspending and restoring keys}
-\label{sec:suspend-keys}
-
-For some keys, it might be preferable to temporarily suspend them from a family (rather than disable or remove them) and restore them later. In this way, a key's state and macro can be frozen while the key remains defined.
-
-The syntax for suspending keys is
-\begin{macro}
-\suspend@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)},
-\end{macro}
-\acmdm*{\suspend@keys}
-where the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements.
-A key of particular prefix not previously defined in a family can't be suspended from that family. Similarly, a key previously suspended from a family can't be suspended again (for the second time) from the same family without being first restored in that family.
-
-Suspended keys can be restored to their frozen states (\name{ex ante} suspension) by the following command:
-\begin{macro}
-\restore@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}.
-\end{macro}
-\acmdm*{\restore@keys}
-Only keys (with a given prefix) previously suspended from a family can be restored in that family: ``unsuspended'' keys can't be restored.
-
-\subsection{Removing keys}
-\label{sec:remove-keys}
-
-The \pkg{skeyval} provides for removing keys completely, such that any attempt to set or use a removed key will prompt the error message that the key is undefined in the given family and with the given prefix. The command \acmd{\key@ifundefined} from the \pkg{xkeyval} and the macro \acmd{\ifkeydefined} from the \pkg{skeyval} will both identify a removed key as undefined. The syntax for removing keys is:
-\begin{macro}
-\remove@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}
-\end{macro}
-\acmdm*{\remove@keys}
-
-Removed keys can't be restored but can be redefined with the commands in both the \textnewkey and \textdefinekey categories.
-
-\section{User-value keys}
-\label{sec:uservaluekeys}
-
-We define these keys as those for which the user must supply values at key setting time whether or not the keys have default values. All the commands for defining new keys have a facility for providing the default value of a key, which would be used by the \acmd{\setkeys} macro if the user didn't supply a value for the key. If no default value has been specified for a key at definition time and no value is provided at key setting time, the \pkg{xkeyval} will issue a fatal error. This scenario is preserved by the \pkg{skeyval}. In addition, the \pkg{skeyval} introduces a facility for requiring a user to supply a value for a key whether or not that key had a default value at definition time. Why is this necessary or useful? You may specify default values for keys in a package or class file to aid future revisions of the package, or for other purposes, but such values may not be suitable for all users---or indeed for any user. Examples of this type of situation abound: the signatory to a letter, the module code or title in a faculty programme, \etc.
-
-The following command can be used to require a user to supply a value for a key at key setting time, whether or not that key has a default value:
-\begin{macro}
-\uservaluekeys[|vang(prefix)]{|vang(family)}{|vang(keys)}
-\end{macro}
-\acmdm*{\uservaluekeys}
-where \ang{keys} is the list of keys with \ang{prefix} and in \ang{family} for which the user must supply values at key setting time. It is obviously not logical to loop over key prefixes or families in this case. What the command \fx{\uservaluekeys} does is to populate the container \fnl{SKV}{prefix}{family}{uservalue} which is scanned for user-value key names at key setting time.
-
-The \fx{\uservaluekeys} macro works incrementally, \ie, new inputs are added to an existing list for the family in question only if they haven't previously been included.
-
-\begin{example}
-\newcmdkey[KV]{fam}[mp@]{keya}[12pt]{\def\x{#1}}
-\newboolkey[KV]{fam}[mp@]{boola}[true]%
- {\ifmp@boola\def\x{#1}\fi}
-
-\uservaluekeys[KV]{fam}{keya,boola}
-
-\setkeys[KV]{fam}{keya,boola=true}
- |tto |makered(Error: no value supplied for `keya')
-\end{example}
-\acmd*{\newcmdkey,\newboolkey,\setkeys}
-%\acmd*{\uservaluekeys}
-
-\subsection{Using pointers to dynamically indicate user-value keys}
-\label{sec:uservalue-pointers}
-
-Instead of using the macro \fx{\uservaluekeys} to accumulate user-value keys, there is another way to dynamically specify these keys at key definition time: by using pointers. At key definition time, the pointers \acmdm{\uservalue} and \acmdm{\guservalue} can be associated with a user-value key. In the following statements, the pointer \fx{\uservalue} specifies that the user of the affected key must supply a value at the time of using/setting the key. The pointer \fx{\uservalue} has local effect, \ie, its impact can't escape local groups; on the other hand, \fx{\guservalue} has global effect, \ie, using it within or out of a local group means that the user of the affected key must specify a value for the key at key setting time. \fx{\guservalue} ensures that the internal container \fnl{SKV}{prefix}{family}{uservalue} is defined globally so that the settings can escape local groups.
-
-\begin{example}
-\newordkey[KV]{fam}{|makered(\uservalue{|mcolor(keya)})}[12pt]{\def\x{#1}}
-
-\define@togkey|redplus[KV]{fam}[mp@]{|makered(\guservalue{|mcolor(toga)})}[true]%
-{%
- \iftogon{mp@toga}{\def\x{#1}}{}%
-}{%
- \@latex@error{Value `#1' not valid}\@ehc
-}
-\end{example}
-\acmd*{\newordkey,\define@togkey,\iftogon}
-
-As these examples show, the newly introduced pointers (namely, \fx{\uservalue} and \fx{\guservalue}) can be used to dynamically build a list of user-value keys. See \cref{sec:pointer-mech} for more comments on pointer systems.
-
-\section{Extensions to the pointer system of the \texttt{xkeyval} package}
-\label{sec:pointer-mech}
-
-The \pkg{xkeyval} introduced a key pointer system. This basically involves the pointers
-\acmdm{\savevalue}, \acmdm{\gsavevalue}, and \acmdm{\usevalue}. However, by the mechanism of that package, these pointers could be used only within the \acmd{\setkeys} command or context. In the key definition commands, the \fx{\usevalue} pointer could also be used in default values of keys, as in
-\begin{example}
-\define@key{fam}{keya}{\def\keya{#1}}
-\define@key{fam}{keyb}[|makered(\usevalue{|mcolor(keya)})]{\def\keyb{#1}}
-\define@key{fam}{keyc}[|makered(\usevalue{|mcolor(keyb)})]{\def\keyc{#1}}
-
-\setkeys{fam}{|makered(\savevalue{|mcolor(keya)})=test}
-\setkeys{fam}{|makered(\savevalue{|mcolor(keyb)})}|comm(Yes, this also works.)
-\setkeys{fam}{keyc}
-\end{example}
-\acmd*{\define@key,\setkeys}
-The default values of keys are called (invoked) within \acmd{\setkeys}. The pointers can't, however, be used as part of key names outside default values. The following, \eg, fails:
-\begin{example}
-\define@key{fam}{|makered(\savevalue{|mcolor(keya)})}{\def\keya{#1}}
-\end{example}
-The \pkg{skeyval} has extended the pointer system to be issuable as part of key names within key definition commands in the two scenarios illustrated above (within and outside default values). Moreover, the pointers \fx{\savevalue} and \fx{\gsavevalue} can be deployed concurrently with \acmd{\uservalue} and \acmd{\guservalue} of \cref{sec:uservalue-pointers} within the same key definition command. In combining the two pointer subclasses (\ie, \fx{\savevalue} subclass and \acmd{\uservalue} subclass) in the same key definition command, it doesn't matter which subclass comes first, as the following examples show.
-
-The pointers \fx{\savevalue} and \fx{\gsavevalue} make entries into the container \fnl{XKV}{prefix}{family}{save} that is used by the \pkg{xkeyval} to hold keys whose values should be saved at key setting time. The difference between \fx{\savevalue} and \fx{\gsavevalue} is that the former has a local effect while the latter can escape local groups (similar to the group properties of \acmd{\uservalue} and \acmd{\guservalue} of \cref{sec:uservalue-pointers}). The pointers \fx{\savevalue} and \fx{\gsavevalue} of the \pkg{skeyval} are entirely compatible with those of the \pkg{xkeyval}. One additional new feature is that the pointer \fx{\gsavevalue} prompts the global revision of the container \fnl{XKV}{prefix}{family}{save} and also makes global pointer entries\footnote{By \emph{global pointer entry} we mean an entry like \fx{\global{keya}} for \fx{keya} into the container \fnl{XKV}{prefix}{family}{save}.} of the affected keys into the container. The effects of the new feature are illustrated by the following examples. Depending on application, this new feature may be more attractive than the traditional one implemented via \acmd{\setkeys}. One obvious advantage of the new system emanates from the fact that some keys do not have default values.
-
-\subsection{Examples}
-
-\subsubsection{Legacy \texttt{xkeyval} pointer features}
-
-The following provide examples of legacy pointer features of the \pkg{xkeyval} (key pointers at key setting time):
-\acmdm*{\gsavekeys,\savekeys,\global\{key\}}
-\begin{example}
-\savekeys[KV]{fam}{keya,|makered(\global{|mcolor(keyb)})}
-\gsavekeys[KV]{fam}{keyc,keyd,|makered(\global{|mcolor(keye)})}|label(mac:gsavekeys)
-
-\setkeys[KV]{fam}{|makered(\gsavevalue{|mcolor(keyd)})=yyy,|label(mac:setkeyd)
- keye=|makered(\usevalue{|mcolor(keyd)})}
-\end{example}
-
-If we had included \fx{\global{keyb}} in \fx{\gsavekeys} of \macref{mac:gsavekeys}, its entry in \fx{\savekeys} would have been overwritten, since keys in the container \acmdm{\XKV@KV@fam@save} normally get overwritten if they have the same name. The macro \fx{\gsavekeys} ensures the global definition of \fx{\XKV@KV@fam@save} when the keys \fx{keyc}, \fx{keyd} and \fx{keye} are being included, while \fx{\global{keyb}} ensures that, when \fx{keyb} is used in a \acmd{\setkeys} command, its value will be saved globally to \fx{\KV@fam@keyb@value}. When the keys \fx{keyc} and \fx{keyd} are set, their values will be saved locally, even though the container \fx{\XKV@KV@fam@save} was defined globally when the keys \fx{keyc} and \fx{keyd} were inserted. However, when keys \fx{keyb} and \fx{keye} are set, their values will be saved globally (even though \fx{keyb} appears in \fx{\savekeys} and not in \fx{\gsavekeys}).
-
-The pointer \fx{\gsavevalue{keyd}} of \macref{mac:setkeyd} will ensure that the value of \fx{keyd} is saved globally to \fx{\KV@fam@keyd@value} at \acmd{\setkeys}.
-
-\subsubsection{Extensions by \texttt{skeyval} package}
-
-The following provide examples of new pointer features enabled by the \pkg{skeyval} (key pointers at key definition time):
-
-\begin{example}
-\define@key[KV]{fam}{|makered(\savevalue{|mcolor(keya)})}[xxx]{\def\x{*#1*}}
-
-\newordkey[KV]{fam}{|makered(\gsavevalue{|mcolor(keyb)})}[zzz]{\def\x{=#1=}}|label(mac:pointers:a)
-
-\newtogkey|redplus[KV]{fam}[mp@]{|makered(\savevalue\uservalue{|mcolor(toga)})}[true]%
-{
- \iftogon{mp@toga}{\def\x{#1}}{}%
-}{%
- \@latex@error{Value `#1' not valid}\@ehc
-}
-
-\define@cmdkey[KV]{fam}[mp@]{|makered(\uservalue\savevalue{|mcolor(keyc)})}%
- [www]{\def\x{#1}}
-
-\newboolkey|redplus[KV]{fam}[mp@]{|makered(\gsavevalue\uservalue{|mcolor(boola)})}%
-[true]{%
- \ifmp@boola\def\x{#1}\fi
-}{%
- \@latex@error{Value `#1' not valid}\@ehc
-}
-
-\define@cmdkey[KV]{fam}[mp@]{|makered(\guservalue\savevalue{|mcolor(keyd)})}%
- [www]{\def\x{#1}}
-
-\newchoicekey|redstar|redplus[KV]{fam}{|makered(\guservalue\gsavevalue{|mcolor(align)})}%
-[\val\nr]{center,right,left}[center]%
-{%
- \ifcase\nr\relax
- \def\@align{\centering}%
- \or
- \def\@align{\flushright}%
- \or
- \def\@align{\flushleft}%
- \fi
-}{%
- \@latex@error{Inadmissible value `#1' for align}\@ehc
-}
-
-\setkeys[KV]{fam}{keya=Hello World,keyb=|makered(\usevalue{|mcolor(keya)})}
-\end{example}
-\acmd*{\define@key,\define@cmdkey,\newchoicekey,\newordkey,
-\newtogkey,\setkeys,\iftogon}
-
-With the new mechanism of the \pkg{skeyval}, the \acmd{\gsavevalue} pointer in the command on \macref{mac:pointers:a} will ensure that \fx{\global{keyb}} (not \fx{keyb}) is inserted in the container \fx{\XKV@KV@fam@save} and that this container is updated globally after \fx{\global{keyb}} has been inserted. At \acmd{\setkeys}, in view of the entry \fx{\global{keyb}}, the value of \fx{keyb} will be saved globally. The same applies to keys \fx{boola} and \fx{align}. This thus has a double effect. Keys \fx{keyc} and \fx{keyd} will be saved locally.
-
-\section{Setting keys: list normalization}
-\label{sec:list-normal}
-
-We have redefined the \acmd{\setkeys} command of the \pkg{xkeyval} in two respects: firstly to accommodate the use of the \acmd{\skif}, \acmd{\skifx}, \acmd{\skelse}, and \acmd{\skfi} macros of \cref{sec:pseudo-primitives}, and secondly to automatically convert double (or even multiple) commas and equality signs inadvertently submitted by the user into single comma and single equality sign. The following exaggerated example depicts the difficulties that might arise and which we wish to address:
-\begin{example}
-\define@key[KV]{fam}{width}[1cm]{}
-\define@key[KV]{fam}{color}[black]{}
-\setkeys[KV]{fam}{width= =2cm, ,,color, == = =,green}
-\end{example}
-\acmd*{\define@key,\setkeys}
-
-Here, the legacy \acmd{\setkeys} will give the value nil to the key \fx{width}, and the default value of the key \fx{color}, if it was specified at key definition time, will be given to the key \fx{color}. Some of the mistakes (especially spurious values without keys) can disrupt a compilation run, while some (multiple commas and equality signs) will not be fatal to compilation but may lead to bizarre results of subsequent calculations. Mistakes of this kind can, surprisingly, be difficult to trace. The extra spaces and multiple commas aren't as serious as the multiple equality signs and values without keys, but we have taken care of all peculiar situations in the new \acmd{\setkeys}. Multiple commas, equality signs, and spaces are now detected and reduced appropriately: that is what we mean by key-value \emph{list normalization}. We have adopted the premise that ``\fx{,=}'' (comma followed by equal) and ``\fx{=,}'' (equal followed by comma) are both most likely to mean ``\fx{=}'' (equal). In the unlikely event that this premise fails, then the user may get tricky errors if he makes this type of mistake.
-
-If, for any reason, the user needs to pass keys with ``\fx{,=}'' and/or ``\fx{=,}'', then he may separate the comma from the equality sign with \fx{{}}, \eg, as in
-\begin{example}
-\setkeys[KV]{fam}{width=2cm,head={},tail=not measured},
-\end{example}
-\acmd*{\setkeys}
-which shows that the value of the key \fx{head} is \fx{\empty}, a valid and better assignment.
-
-\section{Miscellaneous macros}
-\label{sec:misce-commands}
-
-This package is predominantly about \latex keys and their efficient creation and management, but it also contains many commands for general \tex programming, such that a package author may not need to redefine most of them or load some other packages to access those commands. Some of the available commands are described in this section. The index provides a comprehensive quick resource locator for the commands.
-
-\macrosection{Defining new commands}
-
-The following are provided in the \pkg{skeyval} but you're advised to use the \fx{\TestProvidedCommand} macro (described below) to test that you are really using the \fx{\newdef} of the \pkg{skeyval}:
-\begin{macro}
-\SKV@newdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\newdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\end{macro}
-\acmdm*{\SKV@newdef,\SKV@newdef*,\newdef,\newdef*}
-These commands adopt \tex's syntax and accept parameter delimiters. They are both robust. The unstarred variant produces long macros. The command \fx{\newdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newdef}, on the other hand, is always available. If \ang{cs} was previously defined, both \fx{\SKV@newdef} and \fx{\newdef} will issue an error.
-
-\macrosubsection{Defining robust commands}
-
-\begin{macro}
-\SKV@robustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\robustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\end{macro}
-\acmdm*{\SKV@robustdef,\SKV@robustdef*,\robustdef,\robustdef*}
-These use \etex's \acmd{\protected} prefix to provide something resembling \latex's \acmdm{\DeclareRobustCommand} whilst conforming to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The command \fx{\robustdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@robustdef}, on the other hand, is always available. If \ang{cs} was previously defined, both \fx{\SKV@robustdef} and \fx{\robustdef} will issue an error. You can use the above \fx{\TestProvidedCommand} to check whether or not you are using the \fx{\robustdef} of the \pkg{skeyval}.
-
-\macrosubsection{\tex-like \@bs providecommand}
-
-\begin{macro}
-\SKV@providedef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\providedef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\SKV@providerobustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\providerobustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)}
-\end{macro}
-\acmdm*{\SKV@providedef,\SKV@providerobustdef,\providerobustdef,
-\SKV@providedef*,\SKV@providerobustdef*,\providerobustdef*}
-\acmds*\providedef\SKV@providedef
-These emulate \latex's \acmdm{\providecommand}, but they conform to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The commands \fx{\providedef} and \fx{\providerobustdef} are defined in the \pkg{skeyval} only if they haven't been defined by a previously loaded package; the commands \fx{\SKV@providedef} and \fx{\SKV@providerobustdef}, on the other hand, are always available. Macros defined by \fx{\SKV@providerobustdef} and \fx{\providerobustdef} are robust, while those defined by \fx{\SKV@providedef} and \fx{\providedef} are nonrobust. If \ang{cs} was previously defined, all these commands will simply ignore the new definition and enter a message to this effect in the log file (if the package option \fx{verbose} is selected).
-
-\macrosubsection{\@bs requirecmd}
-
-\begin{macro}
-\requirecmd{|vang(cs)}[|vang(number of args)][|vang(default)]%
- {|vang(replacement text)}
-\end{macro}
-This is explained in \cref{sec:toggle-booleans}. If \ang{cs} is already defined, \acmdm{\requirecmd} checks if the new and old definitions are identical. If they aren't, a warning message is logged in the transcript file (if the package option \fx{verbose} is selected) and the new definition is aborted.
-
-\macrosubsection{Testing \emph{provided} commands}
-
-\begin{macro}
-\TestProvidedCommand|vang(cs){|vang(true text)}{|vang(false text)}|label(mac:testprovide)
-\end{macro}
-This can be used to test whether or not one is using the \fx{\newdef} (or any other ``provided'' command) of the \pkg{skeyval}. Here \ang{cs} is either \fx{\newdef} or any ``provided'' command. In fact, if you define any command using the macro \fx{\SKV@providedef} or \fx{\SKV@providerobustdef} (see below), you can verify by \acmdm{\TestProvidedCommand} whether or not the new definition is the one in effect.
-
-\begin{example}
-\SKV@providerobustdef*\newcmd{\newcommand}
-
-\TestProvidedCommand\newcmd{%
- \@latex@info{`\string\newcmd' is `\string\newcommand'}%
-}{%
- \@latex@error{`\string\newcmd' isn't %
- `\string\newcommand'}\@ehd
-}
-\end{example}
-
-\begin{example}
-\SKV@providedef*\declarecommand{\newcommand}
-\TestProvidedCommand\declarecommand{}%
- {\let\declarecommand\newcommand}
-\end{example}
-
-\macrosection{Declaring new unique variables collectively}
-
-New definable variables can be introduced in sets by the following commands.
-
-\begin{macro}
-\NewBooleans[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)]
-\DefBooleans[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\NewBooleans,\DefBooleans}
-The function \fx{\NewBooleans} provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register if the register didn't already exist; if the boolean already existed, an error is flagged. \fx{\DefBooleans}, on the other hand, provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register whether or not the register already existed. If the boolean already existed, a warning message is logged in the transcript file if the package option \fx{verbose} is enabled.
-
-Each member of \ang{boolean list} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. The state \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}.
-\begin{example}
-\NewBooleans[bool]{a,b,c}[true]
- |tto \newif\ifboola \newif\ifboolb \newif\ifboolc
- \boolatrue \boolbtrue \boolctrue
-
-\NewBooleans{boold} |tto \newif\ifboold
-
-\DefBooleans[skv@]{e,f,g}[false]
- |tto \newif\ifskv@e \newif\ifskv@f \newif\ifskv@g
- \skv@efalse \skv@ffalse \skv@gfalse
-\end{example}
-Notice that members of the list \ang{boolean list} don't have \fx{\if} in their names.
-
-\begin{macro}
-\NewTogs[|vang(optional prefix)]{|vang(tog list)}[|vang(optional state)]
-\DefTogs[|vang(optional prefix)]{|vang(tog list)}[|vang(optional state)]
-\end{macro}
-\acmdm*{\NewTogs,\DefTogs}
-The command \fx{\NewTogs} provides a new toggle register for each member of the comma-separated list \ang{tog list} if the register didn't already exist, otherwise an error is flagged. The command \fx{\DefTogs}, on the other hand, will not raise any error even if the toggle already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the toggle has been redefined. Each member of \ang{tog list} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. The state \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}.
-\begin{example}
-\NewTogs[tog]{a,b,c}[true]
- |tto \newtog{toga} \newtog{togb} \newtog{togc}
- \togon{toga} \togon{togb} \togon{togc}
-
-\NewTogs{togd} |tto \newtog{togd}
-\end{example}
-
-\begin{macro}
-\NewToks[|vang(optional prefix)]{|vang(toks list)}
-\DefToks[|vang(optional prefix)]{|vang(toks list)}
-\end{macro}
-\acmdm*{\NewToks,\DefToks}\label{page:newtoks}
-This provides a new token list register for each member of the comma-separated list \ang{toks list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{toks list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefToks}, on the other hand, will not raise any error even if the token list register already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the register has been redefined.
-
-\begin{example}
-\NewToks[toks]{a,b,c}
- |tto \newtoks\toksa \newtoks\toksb \newtoks\toksc
-
-\NewToks{toksd} |tto \newtoks\toksd
-\end{example}
-
-\begin{macro}
-\NewCounts[|vang(optional prefix)]{|vang(counter list)}
-\DefCounts[|vang(optional prefix)]{|vang(counter list)}
-\end{macro}
-\acmdm*{\NewCounts,\DefCounts}
-This provides a new counter register for each member of the comma-separated list \ang{counter list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{counter list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefCounts}, on the other hand, will not raise any error even if the counter already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the counter has been redefined.
-
-\begin{macro}
-\NewDimens[|vang(optional prefix)]{|vang(dimen list)}
-\DefDimens[|vang(optional prefix)]{|vang(dimen list)}
-\end{macro}
-\acmdm*{\NewDimens,\DefDimens}
-This provides a new dimension register for each member of the comma-separated list \ang{dimen list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{dimen list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefDimens}, on the other hand, will not raise any error even if the dimension register already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the register has been redefined.
-
-\begin{macro}
-\NewBoxes[|vang(optional prefix)]{|vang(box list)}
-\DefBoxes[|vang(optional prefix)]{|vang(box list)}
-\end{macro}
-\acmdm*{\NewBoxes,\DefBoxes}
-This allocates a new box register for each member of the comma-separated list \ang{box list} if the box register didn't already exist, otherwise an error is flagged. Each member of \ang{box list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefBoxes}, on the other hand, will not raise any error even if the box register already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the register has been redefined.
-
-\begin{example}
-\NewBoxes[box]{a,b,c}
- |tto \newbox\boxa \newbox\boxb \newbox\boxc
-
-\NewBoxes{boxd} |tto \newbox\boxd
-\end{example}
-
-\begin{macro}
-\NewWrites[|vang(optional prefix)]{|vang(stream list)}
-\DefWrites[|vang(optional prefix)]{|vang(stream list)}
-\end{macro}
-\acmdm*{\NewWrites,\DefWrites}
-This allocates a new output stream for each member of the comma-separated list \ang{stream list} if the stream didn't already exist, otherwise an error is flagged. Each member of \ang{stream list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefWrites}, on the other hand, will not raise any error even if the write stream already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the stream has been redefined.
-\begin{example}
-\NewWrites[write]{a,b,c}
- |tto \newwrite\writea \newwrite\writeb \newwrite\writec
-
-\NewWrites{writed} |tto \newwrite\writed
-\end{example}
-
-\begin{macro}
-\NewReads[|vang(optional prefix)]{|vang(stream list)}
-\DefReads[|vang(optional prefix)]{|vang(stream list)}
-\end{macro}
-\acmdm*{\NewReads,\DefReads}
-
-This allocates a new input stream for each member of the comma-separated list \ang{stream list} if the stream didn't already exist, otherwise an error is flagged. Each member of \ang{stream list} is prefixed with \ang{prefix} upon definition. The command \fx{\DefReads}, on the other hand, will not raise any error even if the read stream already existed, but (if the package option \fx{verbose} is selected) will instead make an entry in the transcript log file to the effect that the stream has been redefined.
-
-The macros \fx{\NewBooleans}, \fx{\DefBooleans}, \fx{\NewToks}, \fx{\DefToks}, \fx{\NewCounts}, \fx{\DefCounts}, \fx{\NewDimens}, \fx{\DefDimens}, \fx{\NewBoxes}, \fx{\DefBoxes}, \fx{\NewWrites}, \fx{\DefWrites}, \fx{\NewReads}, and \fx{\DefReads} are non-outer, unlike their primitive counterparts.
-
-\macrosection{Defining new names}
-
-\begin{macro}
-\SKV@csdef|redstar|redplus{|vang(name)}{|vang(definition)}
-\SKV@csgdef|redstar|redplus{|vang(name)}{|vang(definition)}
-\SKV@csedef|redstar|redplus{|vang(name)}{|vang(definition)}
-\SKV@csxdef|redstar|redplus{|vang(name)}{|vang(definition)}
-\end{macro}
-\acmdm*{\SKV@csdef,\SKV@csgdef,\SKV@csedef,\SKV@csxdef,
-\SKV@csdef*,\SKV@csgdef*,\SKV@csedef*,\SKV@csxdef*,
-\SKV@csdef*+,\SKV@csgdef*+,\SKV@csedef*+,\SKV@csxdef*+}
-
-The variants of these commands without the plus (\RedPlus) sign turn \ang{name} into a control sequence in terms of \ang{definition} whether or not the control was already defined. No error or warning messages are issued. The variants with plus (\RedPlus) sign turn \ang{name} into a control sequence if it wasn't already defined; if it is already defined, an error message is flagged. The starred (\RedStar) variants give ``short'' macros, while the unstarred variants yield ``long'' definitions. These derive from a concept based on that of \acmd{\newcommand}, but (i)~\textrelaxed\ commands are considered undefined in this regard, and (ii)~these commands retain the powerful machinery of plain \tex.\footnote{The \pkg{skeyval} contains other undocumented tools for defining new commands.}
-
-\macrosection{Name use}
-
-\begin{macro}
-\SKV@csuse{|vang(name)}
-\end{macro}
-\acmdm*{\SKV@csuse}
-This is similar to \LaTeX's legacy \acmdm{\@nameuse} but returns \fx{\@empty} (instead of an error) if \ang{name} is undefined. This is due originally to \pkg{etoolbox}.
-
-\macrosection{\texttt{\@bs let} assignments}
-
-\begin{macro}
-\SKV@newlet{|vang(cs1)}{|vang(cs2)}
-\NewLet{|vang(cs1)}{|vang(cs2)}
-\SKV@newlet|redstar{|vang(cs1)}{|vang(cs2)}
-\end{macro}
-\acmdm*{\SKV@newlet,\SKV@newlet*,\NewLet}
-The first two of these assign \ang{cs2} to \ang{cs1} if \ang{cs2} exists and if \ang{cs1} isn't already defined, otherwise an error is flagged. \fx{\SKV@newlet}\unskip\redstar\ will assign \ang{cs2} to \ang{cs1} whether or not \ang{cs1} is already defined.
-
-The command \fx{\NewLet} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newlet}, on the other hand, is always available. You can use \acmd{\TestProvidedCommand} (\macref{mac:testprovide}) to test whether or not you are using the \fx{\NewLet} command of the \pkg{skeyval}.
-
-\begin{macro}
-\SKV@cslet{|vang(name)}{|vang(cs)}
-\SKV@letcs{|vang(cs)}{|vang(name)}
-\SKV@csletcs{|vang(name)}{|vang(name)}
-\end{macro}
-\acmdm*{\SKV@cslet,\SKV@letcs,\SKV@csletcs}
-These perform \fx{\let} assignments if the second argument is defined, otherwise an error message is flagged. The notation \ang{cs} means a control sequence, and \ang{name} means a control sequence name.
-
-\begin{macro}
-\SKV@cslet|redstar{|vang(name)}{|vang(cs)}
-\SKV@letcs|redstar{|vang(cs)}{|vang(name)}
-\SKV@csletcs|redstar{|vang(name)}{|vang(name)}
-\end{macro}
-\acmdm*{\SKV@cslet*,\SKV@letcs*,\SKV@csletcs*}
-These perform \fx{\let} assignments whether or not the second argument is defined. If the second argument is undefined, the first remains undefined and the hash table is not filled.
-
-\macrosection{Number and dimension expressions}
-
-\begin{macro}
-\SKV@numdef|redplus|redclam{|vang(num)}{|vang(expression)}
-\end{macro}
-\acmdm{\SKV@numdef} defines \ang{num} from \ang{expression} using \etex's \acmd{\numexpr}. If \ang{num} was previously undefined, it is first initialized with \acmd{\newcount} before the expression is built. If you do \fx{\SKV@numdef\x{1+2+3}}, you would need to prefix \fx{\x} with \fx{\the} or \acmd{\number} in expressions. Expressions defined by \fx{\SKV@numdef} can be used with \tex's operators such as \fx{\advance} or \fx{\multiply} and \etex's \acmd{\numexpr} operator.
-
-The plus sign (\RedPlus) means that \fx{\SKV@numdef} takes a control sequence name instead of a control sequence, while the exclamation mark (\RedClam) implies that the macro \fx{\SKV@numdef} effects a global assignment which can thus escape local groups.
-
-\begin{macro}
-\SKV@dimdef|redplus|redclam{|vang(dim)}{|vang(expression)}
-\end{macro}
-\acmdm{\SKV@dimdef} defines \ang{dim} from \ang{expression} using \etex's \acmd{\dimexpr}. If \ang{dim} was previously undefined, it is first initialized with \acmd{\newdimen} before the expression is built. If you do \fx{\SKV@dimdef\x{1pt+2pt+3pt}}, you would need to prefix \fx{\x} with \fx{\the} in expressions. Expressions defined by \fx{\SKV@dimdef} can be used with \etex's \acmd{\dimexpr} operator.
-
-The plus sign (\RedPlus) means that \fx{\SKV@dimdef} takes a control sequence name instead of a control sequence, while the exclamation mark (\RedClam) implies that the macro \fx{\SKV@dimdef} effects a global assignment which can thus escape local groups.
-
-\macrosection{Verifying definability}
-
-\begin{macro}
-\SKV@ifdefinable|vang(cs){|vang(function)}
-\SKV@csifdefinable|vang(cs name){|vang(function)}
-\end{macro}
-\acmdm*{\SKV@ifdefinable, \SKV@csifdefinable}
-\latex kernel's \fx{\@ifdefinable} fills up the hash table and also considers commands that are \fx{\relax}'ed as defined. Moreover, if the command being tested (\ang{cs} in the above example) is definable, the \fx{\@ifdefinable} macro begins executing \ang{function} while still in the \fx{\if} \textellipsis \fx{\fi} conditional. You can't do \fx{\let\ifabc\iftrue} in such conditionals. The command \fx{\SKV@ifdefinable}, which is robust, seeks to avoid these problems. \fx{\SKV@csifdefinable} expects a control sequence name instead of a control sequence.
-
-\begin{macro}
-\SKV@ifdefinable@n{|vang(list)}
-\end{macro}
-The macro \acmdm{\SKV@ifdefinable@n} accepts a comma-separated list of control sequence \emph{names} whose definability are to be tested. It should be noted that the macro \fx{\SKV@ifdefinable@n} doesn't accept \ang{function}, unlike the above \fx{\SKV@ifdefinable}. The aim of \fx{\SKV@ifdefinable@n} is simply to test the definability of instances/members of \ang{list}.
-\begin{example}
-\SKV@ifdefinable@n{ax,ay,az}
-\end{example}
-
-\begin{macro}
-\SKV@ifnewcmd|redstar|redplus[|vang(optional parser)]{|vang(list)}
-\end{macro}
-\acmdm*{\SKV@ifnewcmd,\SKV@ifnewcmd*,\SKV@ifnewcmd*+}
-
-The macro \fx{\SKV@ifnewcmd} is similar to, but more versatile, than the command \fx{\SKV@ifdefinable@n}. The star sign (\RedStar) in \fx{\SKV@ifnewcmd} indicates that \ang{list} is available in a macro, say \fx{\mylist}; and the plus sign (\RedPlus) shows \fx{\SKV@ifnewcmd} that members of \ang{list} (or \fx{\mylist}) are control sequence names, otherwise they are control sequences (see examples below). The default value of the optional \ang{parser} is ``,'' (comma). The macro \fx{\SKV@ifnewcmd}, like \fx{\SKV@ifdefinable@n} but unlike \fx{\SKV@ifdefinable}, doesn't execute any \ang{function}. Both \fx{\SKV@ifdefinable@n} and \fx{\SKV@ifnewcmd} are robust.
-
-\begin{example}
-\def\mylist{ax,ay,az}
-\SKV@ifnewcmd|redstar|redplus[,]\mylist
-\SKV@ifnewcmd|redstar|redplus\mylist
-\SKV@ifnewcmd|redplus{ax,ay,az}
-\SKV@ifnewcmd{\ax\ay\az}
-\def\my@list{\ax\ay\az}
-\SKV@ifnewcmd|redstar\my@list
-\def\my@@list{ax;ay;az}
-\SKV@ifnewcmd|redstar|redplus[;]\my@@list
-\SKV@ifnewcmd\ax |tto \SKV@ifnewcmd|redplus{ax} |tto \SKV@ifdefinable@n{ax}
-\end{example}
-
-\macrosection{Verifying the status of variables}
-
-\begin{macro}
-\SKV@ifdef|vang(cs){|vang(true)}{|vang(false)}
-\SKV@ifcsdef{|vang(name)}{|vang(true)}{|vang(false)}
-\SKV@ifundef|vang(cs){|vang(true)}{|vang(false)}
-\SKV@ifcsundef{|vang(name)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@ifdef,\SKV@ifcsdef,\SKV@ifundef,\SKV@ifcsundef}
-These use \etex's facilities to test the existence of the control sequence \ang{cs} or control sequence name \ang{name}. These commands aren't robust and may be used to determine the current state of the macro replacement text, if such replacement text contains these commands. \textrelaxed\ macros are considered undefined by \emph{all} these commands. To test if a macro is \textrelaxed, use the following commands:
-
-\begin{macro}
-\SKV@ifrelax|vang(cs){|vang(true)}{|vang(false)}
-\SKV@ifcsrelax{|vang(name)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@ifrelax,\SKV@ifcsrelax}
-
-\begin{macro}
-\SKV@ifdefax|vang(cs){|vang(defined)}{|vang(relaxed)}{|vang(undefined)}
-\SKV@ifcsdefax{|vang(name)}{|vang(defined)}{|vang(relaxed)}{|vang(undefined)}
-\end{macro}
-\acmdm*{\SKV@ifdefax,\SKV@ifcsdefax}
-These test if \ang{cs} or \ang{name} is defined, relaxed, or undefined. In using these three-valued logical tests, it is often easy to forget to include the null state (\ie, \ang{undefined}) because \tex is dominated by two-valued logical tests.
-
-\macrosection{Undefining macros}
-
-\begin{macro}
-\SKV@Undef|redstar|redplus|redclam[|vang(optional parser)]{|vang(cs)}
-\end{macro}
-\acmdm*{\SKV@Undef,\SKV@Undef*,\SKV@Undef*+}
-This undefines the macros or control sequence names in the list \ang{cs} (of nil, one or more elements) such that \tex will subsequently consider each element undefined. The star sign (\RedStar) indicates that \ang{cs} is given as a macro whose \emph{contents} are to be individually undefined, and the plus sign (\RedPlus) shows that \ang{cs} is made up of \emph{control sequence names} instead of control sequences. The exclamation mark (\RedClam) directs \fx{\SKV@Undef} to \emph{globally} undefine all the control sequences or names in \ang{cs}. Control sequence names are to be separated by the parser; control sequences shouldn't be separated. The default value of the \ang{parser} is ``,'' (comma). The command \fx{\SKV@Undef} is robust (it will thus not expand in expansion contexts), but fragile arguments would need to be protected in expansion contexts.\footnote{Macros such as \acmdm{\@ifnextchar}, \acmdm{\@ifstar}, and those involving optional arguments normally can't be evaluated in expansion contexts. The same applies to the \pkg{skeyval} macros with optional arguments. The \pkgm{etextools} introduced expandable variants of these commands, but in the contexts these commands are employed in the \pkg{skeyval}, the expandable variants aren't particularly advantageous. The main reason is that some of our internal macros (\eg, looping macros) aren't amenable to full expansion anyway. Actually, the \pkg{skeyval} provides the fully expandable variants (\acmdm{\SKV@TestOpt}, \acmdm{\SKV@IfStar}, \acmdm{\SKV@IfPlus}, and \acmdm{\SKV@IfAsk}) of the non-expandable commands \acmdm{\SKV@testopt}, \acmdm{\SKV@ifstar}, \acmdm{\SKV@ifplus}, and \acmdm{\SKV@ifask}. The commands \fx{\SKV@ifask} and \fx{\SKV@IfAsk} look for an optional question mark (\RedClam).}
-
-\begin{example}
-\def\unwanted{tempa,tempb,tempc,temp1}
-
-\SKV@Undef|redstar|redplus|redclam[,]\unwanted
-
-\def\unwanted{t1emp,te2mp,tem3p}
-
-\SKV@Undef|redstar|redplus|redclam[,]\unwanted
-
-\SKV@Undef|redplus|redclam[;]{tempd;tempe;tempf}
-
-\SKV@Undef\tempe
-
-\SKV@Undef|redclam{\tempea\tempeb\tempec\temped}
-
-\SKV@Undef|redplus{tempf}
-
-\SKV@Undef|redclam\tempg
-
-\def\notwanted{\temph\tempi\tempj}
-
-\SKV@Undef|redstar\notwanted
-\end{example}
-
-The following non-generic variants avoid the above complications of signs, but they don't take lists:
-\begin{macro}
-\SKV@undef{|vang(cs)} |tto \SKV@Undef{|vang(cs)}
-\SKV@gundef{|vang(cs)} |tto \SKV@Undef|redclam{|vang(cs)}
-\SKV@csundef{|vang(cs name)} |tto \SKV@Undef|redplus{|vang(cs)}
-\SKV@csgundef{|vang(cs name)} |tto \SKV@Undef|redplus|redclam{|vang(cs)}
-\end{macro}
-\acmdm*{\SKV@undef,\SKV@gundef,\SKV@csundef,\SKV@csgundef}
-
-\macrosection{Expansion control}
-
-\begin{macro}
-\SKV@expox{|vang(cs)}
-\end{macro}
-\acmdm*{\SKV@expox}
-This expands its argument \ang{cs} once and forbids further expansion.
-
-\begin{macro}
-\SKV@csexpox{|vang(name)}
-\end{macro}
-\acmdm*{\SKV@csexpox}
-This is similar to \fx{\SKV@expox} but accepts control sequence name \ang{name} instead of control sequence.
-
-\begin{macro}
-\SKV@exptx{|vang(cs)}
-\end{macro}
-\acmdm*{\SKV@exptx}
-This expands its argument \ang{cs} twice and forbids further expansion.
-
-\begin{macro}
-\SKV@csexptx{|vang(name)}
-\end{macro}
-\acmdm*{\SKV@csexptx}
-This is similar to \fx{\SKV@exptx} but accepts control sequence name \ang{name} instead of control sequence.
-
-\begin{macro}
-\SKV@expargs|vang(n)|vang(function)|vang(arg1)|vang(arg2)\@nil
-\end{macro}
-\acmdm*{\SKV@expargs}
-\LaTeX's \acmdm{\@expandtwoargs} is often used as a utility macro to expand two arguments \ang{arg1} and \ang{arg2} in order to execute \ang{function}. The command \fx{\SKV@expargs}, on the other hand, accepts up to four expansion types, signified by \ang{n}, which runs \mbox{from 0 to 3}:
-\begin{enum}
-\item If \ang{n} is 0, then \ang{arg2} is empty and only \ang{arg1} will be expanded before \ang{function} is executed.
-\item If \ang{n} is 1, then both \ang{arg1} and \ang{arg2} are nonempty but only \ang{arg2} will be expanded before \ang{function} is executed.
-\item When \ang{n} is 2, then both \ang{arg1} and \ang{arg2} are nonempty and both will be expanded before \ang{function} is executed. This is equivalent to \LaTeX's \fx{\@expandtwoargs}.
-\item If \ang{n} is 3, then both \ang{arg1} and \ang{arg2} are nonempty but only \ang{arg1} is expanded before \ang{function} is executed.
-\item If \ang{n} isn't in the list \fnv{0,1,2,3}, then an error message is flagged.
-\end{enum}
-Because \ang{arg2} is delimited, it can be empty. The command \fx{\SKV@expargs} can be used to save \fx{\expandafter}'s, but caution should be exercised in deploying it: for example, the \fx{\edef} it uses may expand too deeply in some cases. Also, precaution may be necessary when the expanded arguments (\ang{arg1} and/or \ang{arg2}) involve the \tex primitive \fx{\if}. When invoking \fx{\SKV@expargs}, the macros \fx{\SKV@expox} and \fx{\SKV@exptx} can be used to control the level of expansion.
-
-Some trivial examples follow:
-\begin{example}
-\SKV@expargs{0}{\def\tempc#1#2}{\def\noexpand##1{##2}}\@nil|label(mac:expargs)
-\tempc\tempa{aaa}
-\tempc\tempb{abcaaabbccbca}
-\SKV@expargs{2}\SKV@in@\tempa\tempb\@nil
-\show\ifin@
-\end{example}
-\acmd*{\SKV@in@}
-
-These expressions show how \fx{\SKV@expargs} can be used to economize on chains of \fx{\expandafter}'s. The expression on \macref{mac:expargs}, for example, isn't directly possible by \fx{\@expandtwoargs}.
-
-\macrosection{Checking values of \texttt{choice} keys}
-
-Choice keys should, by definition, have preordained values. This requirement can be useful even for non-choice keys, as we illustrate below.
-
-\begin{macro}
-\SKV@checkchoice{|vang(value)}{|vang(altlist)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@checkchoice}
-This is an enhanced form of \pkg{xkeyval}'s \fx{\XKV@checkchoice}. It checks if the user-submitted \ang{value} of a key (say, \ang{keya}) is in the list \ang{altlist}. It executes \ang{true} if \ang{value} is found in \ang{altlist} and \ang{false} otherwise. Additionally, it returns \acmd{\val} for the expanded value of \ang{value} and \acmd{\nr} for the numerical order of \acmd{\val} in the list \ang{altlist}. If \ang{value} isn't found in \ang{altlist}, then \acmd{\nr} will return $-1$. If \ang{value} and \ang{altlist} are buried in macros, the macros are fully expanded before the search for \ang{value} in the list \ang{altlist} is effected. In that case, \acmd{\val} will hold the expanded form of \ang{value} and can be used in subsequent computations.
-
-Choice keys do accept macros as values, but such values aren't directly suitable for matching against the contents of \ang{altlist}. For example, \ang{altlist} may be the set \fx{{left,right,center}}, but given as a macro \fx{\@altlist}, while \ang{value} is given as \fx{\def\@value{center}}. Obviously, \fx{\@value} contains one of the elements of \ang{altlist}, but choice keys won't know this without the expansion of both \fx{\@altlist} and \fx{\@value}. This is \name{raison d'\^e tre} of the \fx{\SKV@checkchoice} macro.
-
-Moreover, \fx{\SKV@checkchoice} can be used in the definition of non-choice keys. In the following example we check the value of an \emph{ordinary} key by means of \fx{\SKV@checkchoice}:
-\begin{example}
-\def\@altlist{left,right,center}
-\newordkey[KV]{fam}{keya}[true]{%
- \SKV@checkchoice{#1}{\@altlist}{%
- \ifcase\nr\relax
- \edef\tempa##1##2{##1===\val===##2}%
- \or
- \edef\tempa##1##2{##1***\val***##2}%
- \or
- \edef\tempa##1##2{##1+++\val+++##2}%
- \fi
- }{%
- \@latex@error{Wrong value for `keya'}\@eha
- }%
-}
-\def\@value{center}
-\setkeys[KV]{fam}{keya=\@value}
-\end{example}
-
-The reader may wish to do \fx{\show\tempa} to see what \fx{\tempa} gets upon setting the key \fx{keya}.
-
-\macrosection{Testing for substring}
-
-\begin{macro}
-\SKV@in@{|vang(substring)}{|vang(string)}
-\end{macro}
-\acmdm*{\SKV@in@}
-This is similar to the \latex kernel's \fny{\in@}{substring}{string} which tests if \ang{substring} is in \ang{string}, but the present test avoids the problem of false result, which is typified by the following test:
-\begin{example}
-\in@{aa}{ababba}
-\end{example}
-This incorrectly returns \acmdm{\ifin@} as \fx{\iftrue}. The macro \fx{\SKV@in@}, on the other hand, correctly gives \fx{\ifin@} as \fx{\iffalse} in this case. The command \fx{\SKV@in@} is robust.
-
-\begin{macro}
-\SKV@in@n{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)}
-\end{macro}
-\acmdm*{\SKV@in@n}
-This is similar to \fx{\SKV@in@} but, as shown here, the returned result has a different syntax.
-
-\begin{macro}
-\SKV@in@o{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)}
-\end{macro}
-\acmdm*{\SKV@in@o}
-This expands each of its two arguments once before the test.
-
-\begin{macro}
-\SKV@in@x{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)}
-\end{macro}
-\acmdm*{\SKV@in@x}
-This expands each of its two arguments fully before the test.
-
-\begin{macro}
-\in@tog{|vang(substring)}{|vang(string)}
-\end{macro}
-\acmdm*{\in@tog}
-In this case the returned boolean is the toggle switch \ang{in@} instead of the kernel's \ang{in@} switch which is used as \fx{\ifin@}. The toggle \ang{in@} can be used in the following way and in other manners that toggles can be employed:
-\begin{example}
-\iftogon{in@}{|vang(true text)}{|vang(false text)}.
-\end{example}
-\acmd*{\iftogon}
-The command \fx{\in@tog} is robust.
-
-\begin{macro}
-\in@tok{|vang(substring)}{|vang(string)}
-\end{macro}
-\acmdm*{\in@tok}
-Sometimes you want to use the \latex kernel's \fny{\in@}{substring}{string} to test if \ang{substring} is in \ang{string} irrespective of their catcodes. The robust command \fny{\in@tok}{substring}{string} makes this possible, and eliminates the tokens that would have been necessary if the user was required to first detokenize the two arguments. It returns the same switch \fx{\ifin@} as the kernel's \fny{\in@}{substring}{string}. Actually, it calls \fx{\SKV@in@} to avoid false returns.
-
-\macrosection{Testing equality of strings}
-
-\begin{macro}
-\SKV@ifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)}
-\SKV@ifstrnotequal{|vang(string1)}{|vang(string2)}{|vang(not true)}{|vang(not false)}
-\SKV@oifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)}
-\SKV@xifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@ifstrequal,\SKV@ifstrnotequal,\SKV@oifstrequal,\SKV@xifstrequal}
-In order to properly test the equality of strings, it may be necessary to remove leading and trailing spaces before the test. Such spaces may have cropped into the strings from input or from pre-processing and may invalidate the test. The macro \fx{\SKV@ifstrequal} takes care of such situations. It executes \ang{true} if \ang{string1} is equal (character code wise) to \ang{string2}, and \ang{false} otherwise. Both \ang{string1} and \ang{string2} are detokenized before the test. The macro \fx{\SKV@oifstrequal} is similar to \fx{\SKV@ifstrequal} but first expands its arguments (the two strings \ang{string1} and \ang{string2}) once before the test. The macro \fx{\SKV@xifstrequal} first expands its arguments fully before the test.
-
-\macrosection{Testing for empty or blank}
-
-\begin{macro}
-\SKV@ifempty{|vang(token)}{|vang(true)}{|vang(false)}
-\SKV@ifnotempty{|vang(token)}{|vang(not true)}{|vang(not false)}
-\SKV@oifempty{|vang(token)}{|vang(true)}{|vang(false)}
-\SKV@xifempty{|vang(token)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@ifempty,\SKV@ifnotempty,\SKV@oifempty,\SKV@xifempty}
-These yield \ang{true} if \ang{token} is empty, and \ang{false} otherwise. In the command \fx{\SKV@ifempty}, \ang{token} isn't expanded before the test; in the command \fx{\SKV@oifempty}, \ang{token} is expanded once before the test; in the command \fx{\SKV@xifempty}, \ang{token} is fully expanded before the test.
-
-\begin{macro}
-\SKV@ifblank{|vang(token)}{|vang(true)}{|vang(false)}
-\SKV@ifnotblank{|vang(token)}{|vang(not true)}{|vang(not false)}
-\SKV@oifblank{|vang(token)}{|vang(true)}{|vang(false)}
-\SKV@xifblank{|vang(token)}{|vang(true)}{|vang(false)}
-\end{macro}
-\acmdm*{\SKV@ifblank,\SKV@ifnotblank,\SKV@oifblank,\SKV@xifblank}
-
-These macros test if the argument is blank or not. The first of these is from \pkgm{ifmtarg}. \fx{\SKV@oifblank} expands its argument once before the test, while \fx{\SKV@xifblank} expands its argument fully before the test.
-
-\macrosection{Verifying \texttt{draft} and \texttt{final} options}
-
-\begin{macro}
-\SKV@ifdraft{|vang(true)}{|vang(false)}
-\SKV@ifnotdraft{|vang(not true)}{|vang(not false)}
-\SKV@iffinal{|vang(true)}{|vang(false)}
-\SKV@ifnotfinal{|vang(not true)}{|vang(not false)}
-\iftogon{draft}{|vang(true)}{|vang(false)}
-\iftogoff{draft}{|vang(not true)}{|vang(not false)}
-\iftogon{final}{|vang(true)}{|vang(false)}
-\iftogoff{final}{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\SKV@ifdraft,\SKV@ifnotdraft,\SKV@iffinal,\SKV@ifnotfinal,\iftogon\{draft\},
-\iftogoff\{draft\},\iftogon\{final\},\iftogoff\{final\}}
-
-These execute \ang{true} or \ang{false} depending on whether \fx{draft} or \fx{final} appears as \fx{true} in the options list of \acmd{\documentclass} or \fnx{\usepackage}{skeyval}.
-The default is that \fx{final} is true, which implies that \fx{draft} is false by default. The keys \fx{draft} and \fx{final} are complementary native-boolean keys (see \cref{sec:comp-boolkeys}), which reduces the risk of mixing them. These commands are robust.
-
-\begin{macro}
-\ifdraft{|vang(true)}{|vang(false)}
-\ifnotdraft{|vang(not true)}{|vang(not false)}
-\iffinal{|vang(true)}{|vang(false)}
-\ifnotfinal{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\ifdraft,\ifnotdraft,\iffinal,\ifnotfinal}
-These are also defined in the \pkg{skeyval}, but because packages such as \pkgm{ifdraft} already exist, the \pkg{skeyval} defines them only if they haven't already been defined. If they existed before \pkg{skeyval} is loaded, they aren't redefined, and (if the package option \acmd{verbose} is selected) a warning is logged in the transcript file to indicate that the definition being used isn't from the \pkg{skeyval}. The warning is logged only once. I am aware of the existence of only \fx{\ifdraft} outside the \pkg{skeyval}: therefore, the definition of \fx{\ifdraft} is deferred until \acmd{\AtBeginDocument}. You can use \acmd{\TestProvidedCommand} to check the version of the \fx{\ifdraft} that you are using.
-
-\macrosection{Verifying \texttt{dvi} and \texttt{pdf} modes}
-
-\begin{macro}
-\SKV@ifpdf{|vang(true)}{|vang(false)}
-\SKV@ifnotpdf{|vang(not true)}{|vang(not false)}
-\iftogon{pdf}{|vang(true)}{|vang(false)}
-\iftogoff{pdf}{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\SKV@ifpdf,\SKV@ifnotpdf,\iftogon\{pdf\},\iftogoff\{pdf\}}
-These execute \ang{true} or \ang{false} depending on whether \fx{dvi} or \fx{pdf} output is being produced. These commands are robust and may be used in expansion contexts.
-
-\begin{macro}
-\ifpdf{|vang(true)}{|vang(false)}
-\ifnotpdf{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\ifpdf,\ifnotpdf}
-These are available only if they haven't been previously defined by another package. If they existed outside the \pkg{skeyval}, a warning is logged in the transcript log file (if the package option \fx{verbose} is selected), but only once, and the commands are not redefined. In particular, the above \fx{\ifpdf} is available only at \acmd{\AtBeginDocument} and is defined only if it doesn't already exist. The reason is that the popular \pkg{hyperref} loads the \pkg{ifpdf} and the \pkg{ifpdf} will abort if it detects that \fx{\ifpdf} has been defined by a package loaded earlier.
-
-\Note The \fx{\ifpdf} command of the \pkg{ifpdf} is used in the \fx{\if} \ldots \fx{\else} \ldots \fx{\fi} conditional, while the above \fx{\ifpdf} command is used as indicated above. You can use the \acmd{\TestProvidedCommand} macro to check the version of the \fx{\ifpdf} command that you are using.
-
-\macrosection{Tests related to package loading}
-
-\begin{macro}
-\@ifpackagecurrent{|vang(package)}{|vang(date)}{|vang(true)}{|vang(false)}
-\@ifpackagenotcurrent{|vang(package)}{|vang(date)}{|vang(not true)}{|vang(not false)}
-\end{macro}
-\acmdm*{\@ifpackagecurrent,\@ifpackagenotcurrent}
-These executes \ang{true} if the date of the current/loaded version \ang{package} is greater than or equal to \ang{date}. This is similar to \latex's \acmdm{\@ifpackagelater} but, unlike the latter, both \fx{\@ifpackagecurrent} and \fx{\@ifpackagenotcurrent} are robust. My main reason for these commands is that the nomenclature \fx{\@ifpackagelater} is subject to the wrong interpretation of being space (rather than time) related.
-
-\begin{macro}
-\@afterpackageloaded{|vang(package)}{|vang(code)}
-\end{macro}
-\acmdm*{\@afterpackageloaded}
-This executes \ang{code} only after \ang{package} has been loaded. This has been optimized from the \pkgm{afterpackage} to avoid filling up the hash table with hooks that are \fx{relax}'ed or indeed undefined, and to warn the user if \ang{package} was not eventually loaded. If at the start of document, \ang{package} has not been loaded, a warning message is entered in the log file. Use the following \fx{\@ensurepackageloaded} macro if you really need an error message in this case.
-
-\begin{macro}
-\@ensurepackageloaded{|vang(packages)}
-\end{macro}
-\acmdm*{\@ensurepackageloaded}
-This will issue an error at start of document if any member of the comma-separated list \ang{packages} wasn't loaded before then. This command can be used to signpost those packages that must be loaded later.
-
-\macrosection{Commands restricted to package and preamble}
-
-\begin{macro}
-\SKV@onlypreamble|redplus{|vang(list)}
-\SKV@onlypackage
-\end{macro}
-\acmdm*{\SKV@onlypreamble,\SKV@onlypackage}
-The \latex kernel's macro \fx{\@onlypreamble} accepts only one command at a time (\ie, you can't give it a list of preamble commands in one go), and the error message \acmdm{\@notprerr} is not that precise, since it doesn't indicate the command that has been wrongly placed in the document's body. The use of \fx{\@onlypreamble} in a style or class file can be monotonous if the file has many preamble commands. The macro \fx{\SKV@onlypreamble} takes a comma-separated list \ang{list} of commands at once and gives precise error messages related to the incorrectly located commands. The \ang{list} may be populated with nil, one, or more control sequences. The plus sign~(\RedPlus) means that elements of \ang{list} are control sequence names instead of control sequences.
-\begin{example}
-\SKV@onlypreamble{\macroa, \macrob, \macroc}
-\SKV@onlypreamble|redplus{macroa, macrob, macroc}
-\end{example}
-All preamble commands can be collected together in one \fx{\SKV@onlypreamble}, preferably at the end of the style or class file.
-
-The function \fx{\SKV@onlypackage} may be used to restrict commands to packages only. For example, the following restricts the command \fx{\x} to packages only:
-\begin{example}
-\def\x#1{\SKV@onlypackage\usearg{#1}}
-\end{example}
-
-\macrosection{Extended \texttt{\@bs aftergroup} and \texttt{\@bs afterassignment}}
-
-\begin{macro}
-\SKV@aftergroup{|vang(code)}
-\SKV@aftergroup|redstar{|vang(code)}
-\SKV@afterassignment{|vang(code)}
-\SKV@afterassignment|redstar{|vang(code)}
-\end{macro}
-\acmdm*{\SKV@aftergroup,\SKV@aftergroup*,\SKV@afterassignment,\SKV@afterassignment*}
-
-\tex's \fx{\aftergroup} and \fx{\afterassignment} don't accept arbitrary code. The commands \fx{\SKV@aftergroup} and \fx{\SKV@afterassignment} execute the arbitrary \ang{code} after a group or assignment. The starred variants expand \ang{code} once before the assignment or before exiting the group. These commands don't accumulate the group and assignment counters indefinitely: the counters are initialized after each group or each assignment.
-
-Some examples follow:
-\begin{example}
-\let\gobblex\@firstofone
-\def\protected@mydef{%
- \let\@@protect\protect
- \let\protect\@unexpandable@protect
- \SKV@afterassignment{%
- \restore@protect
- \let\gobblex\@gobble
- }%
- \edef
-}
-
-\def\aa{aaa} \def\bb{bbb} \def\xx{xxx} \def\yy{yyy}
-
-|makered(\begin{document})
-\begingroup
- \SKV@aftergroup{\par\aa***\bb}%
- \SKV@aftergroup{\par\bb***\aa}%
- \begingroup
- \SKV@aftergroup{\par\xx+++\yy}%
- \SKV@aftergroup{\par\yy+++\xx}%
- \endgroup
-\endgroup
-|makered(\end{document})
-\end{example}
-\acmd*{\begin\{document\}}
-
-\macrosection{List processing}
-
-\begin{macro}
-\SKV@for@a{|vang(list)}|vang(cmd){|vang(function)}
-\SKV@for@b|vang(listcmd)|vang(cmd){|vang(function)}
-\end{macro}
-\acmdm*{\SKV@for@a,\SKV@for@b}
-These are fast for-loops that accept general list parsers and allow for list breaks, as well as give the remainder of the list if a break occurs within the list. Elements of \ang{list} are stored in \ang{cmd}, and \ang{function} is executed for each element of \ang{list}. \ang{list}, which is populated by parser-separated elements, is not expanded before the iteration; \ang{listcmd}, on the other hand, is expanded once before the commencement of the loop. The list parser is dynamically declarable via
-\begin{macro}
-\SKV@CommandGenParser{|vang(parser)} |orr
-\skvoptions{genparser=|vang(parser)}
-\end{macro}
-\acmdm*{\SKV@CommandGenParser}
-Also, these iteration macros use the more powerful \acmd{\SKV@ifblank} to check whether or not \ang{list} is empty or blank. The commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are robust, but in expansion contexts, both \ang{cmd} and \ang{function} will need to be protected. The \ang{parser} persists in effect until it is changed by another call to \fx{\SKV@CommandGenParser} or \acmd{\skvoptions} as above.
-
-\Note One snag with a generic list parser like \fx{\SKV@CommandGenParser} is that the user must always remember to call it and set the right parser before beginning an iteration, otherwise there might be unpleasant results, since a previous call to \fx{\SKV@CommandGenParser} might have set a parser that is no longer valid. To obviate this type of situation, the following commands are also provided in the \pkg{skeyval}:
-\begin{macro}
-\SKV@for[|vang(parser)]{|vang(list)}|vang(cmd){|vang(function)}
-\SKV@for|redstar[|vang(parser)]|vang(listcmd)|vang(cmd){|vang(function)}
-\end{macro}
-\acmdm*{\SKV@for,\SKV@for*}
-The \ang{parser} appears as an optional argument in these commands and its default value is ``\fx{,}'' (comma). These commands allow the user to provide the \ang{parser} with every call. The unstarred and starred versions of \fx{\SKV@for} are equivalent to \fx{\SKV@for@a} and \fx{\SKV@for@b}, respectively. Both sets (\fx{\SKV@for@a} and \fx{\SKV@for@b} \amdvert\ \fx{\SKV@for} and \fx{\SKV@for}\redstar) may be needed in different circumstances. In applications where the \ang{parser} is fixed, the commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are faster than \fx{\SKV@for} and \fx{\SKV@for}\redstar\ because in the former cases the \ang{parser} would then need to be set only once: each call to \fx{\SKV@for} or \fx{\SKV@for}\redstar, whether or not the optional \ang{parser} is provided, resets the \ang{parser}.
-
-The list parser itself is available in \acmd{\parser}, which can be used in \ang{function}. An example follows:
-\begin{example}
-\SKV@CommandGenParser{;}
-\SKV@for@a{a;b;c;d}\cmd{\if a\cmd `\cmd'\ is `a'\parser
-\else\space `\cmd'\ isn't `a'\parser\fi}.
-\end{example}
-This list can be broken after, say, elements ``\fx{a}'' and ``\fx{b}'', as follows:
-\begin{example}
-\SKV@for@a{a;b;|makered(listbreak);c;d}\cmd
-{\if a\cmd `\cmd'\ is `a'\parser\else\space `\cmd'\
-isn't `a'\parser\fi},
-\end{example}
-upon which the remainder of the list is accessible from \acmd{\SKV@remainder}.
-
-\begin{macro}
-\SKV@tfor@a{|vang(list)}|vang(cmd){|vang(function)}
-\SKV@tfor@b|vang(listcmd)|vang(cmd){|vang(function)}
-\end{macro}
-\acmdm*{\SKV@tfor@a,\SKV@tfor@b}
-The first of these (\ie, \fx{\SKV@tfor@a}) is equivalent to \latex kernel's \acmdm{\@tfor}, which loops over \ang{list} token-wise (character or control sequence token), but these two macros have been prompted by the following rationale. Note that \ang{list} is not a comma-separated list! In \fx{\SKV@tfor@b}, \ang{listcmd} is expanded once before the commencement of the loop. The two commands \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} are both robust.
-
-The \acmdm{\@break@tfor} of the \latex kernel allows the user to break out of the \fx{\@tfor} loop but provides no mechanism for saving the remainder of the \ang{list} upon breaking the list. Secondly, I have had trouble breaking out of simple \fx{\@tfor} loops. For example, the following fails: \latex complains of ``extra \string\fi'', the reason being obvious.
-\begin{example}
-\def\one{One}\def\two{Two}\def\three{Three}
-\@tfor\x:=\one\two|makered(\@break@tfor)\three\do{\x}
-\end{example}
-
-Thirdly, if the content of \fx{\x} above is sanitized/detokenized in the loop before being used in \ang{function} (or sanitized in the \ang{function} itself), then \fx{\@break@tfor} can't break the loop. Consider the following:
-\begin{example}
-\@tfor\x:=\one\two|makered(\@break@tfor)\three\do{%
- \edef\x{\detokenize\expandafter{\x}}%
-}
-\end{example}
-Clearly, \fx{\@break@tfor} can't break this loop. The macros \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} circumvent these problems. Additionally, they
-\begin{inenum}[(a)]
-\item reorder the arguments such that \ang{list} comes before \ang{cmd}, and
-\item remove the need for the usual delimitating tokens, thereby making their syntaxes mimic those of \acmd{\SKV@for@a} and \acmd{\SKV@for@b}.
-\end{inenum}
-
-In the following, the remainder of the list (namely, \fx{\three}) can be accessed from the macro \acmd{\SKV@remainder}:
-\begin{example}
-\SKV@tfor@a{\one\two|makered(\listbreak)\three}\x{%
- \edef\x{\detokenize\expandafter{\x}}%
-}
-\end{example}
-
-\begin{macro}
-\SKV@tfor{|vang(list)}|vang(cmd){|vang(function)}
-\SKV@tfor|redstar|vang(listcmd)|vang(cmd){|vang(function)}
-\end{macro}
-\acmdm*{\SKV@tfor,\SKV@tfor*}
-These are equivalent to \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} respectively.
-
-\macrosection{Hook management}
-\macrosubsection{Hooking to user-defined macros}
-
-\begin{macro}
-\SKV@appto|redstar|redplus|redclam|vang(cs){|vang(content)}
-\end{macro}
-\acmdm*{\SKV@appto,\SKV@appto*,\SKV@appto*+}
-This appends \ang{content} to \ang{cs}. If \ang{cs} was previously undefined, it is initialized with \ang{content}. The star (\RedStar) sign directs \fx{\SKV@appto} to expand \ang{content} once before appending \ang{content} to \ang{cs}. The plus (\RedPlus) sign means that \ang{cs} is a control sequence name instead of a control sequence, while the exclamation mark (\RedClam) instructs \fx{\SKV@appto} to append \ang{content} to \ang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts.
-
-Except for the initialization of undefined \ang{cs}, \fx{\SKV@appto}\redclam\ is equivalent to \latex's \acmdm{\g@addto@macro}.
-
-The following non-generic, less powerful, forms of \fx{\SKV@appto} are also available, but they don't have the starred (\RedStar) variants:
-\begin{macro}
-\apptomac|vang(cs){|vang(content)}
- |tto \SKV@appto|vang(cs){|vang(content)}
-\gapptomac|vang(cs){|vang(content)}
- |tto \SKV@appto|redclam|vang(cs){|vang(content)}
-\csapptomac{|vang(name)}{|vang(content)}
- |tto \SKV@appto|redplus{|vang(name)}{|vang(content)}
-\csgapptomac{|vang(name)}{|vang(content)}
- |tto \SKV@appto|redplus|redclam{|vang(name)}{|vang(content)}
-\end{macro}
-\acmdm*{\apptomac,\gapptomac,\csapptomac,\csgapptomac}
-
-\bigskip
-\begin{macro}
-\SKV@prepto|redstar|redplus|redclam|vang(cs){|vang(content)}
-\end{macro}
-\acmdm*{\SKV@prepto,\SKV@prepto*,\SKV@prepto*+}
-This prepends \ang{content} to \ang{cs}. If \ang{cs} was previously undefined, it is initialized with \ang{content}. The star (\RedStar) sign directs \fx{\SKV@prepto} to expand \ang{content} once before prepending it to \ang{cs}. The plus (\RedPlus) sign means that \ang{cs} is a control sequence name instead of a control sequence, while the exclamation mark (\RedClam) instructs \fx{\SKV@prepto} to prepend \ang{content} to \ang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts.
-
-Again, the following non-generic versions of \fx{\SKV@prepto} are available, but they don't have the starred (\RedStar) variants:
-\begin{macro}
-\preptomac|vang(cs){|vang(content)}
- |tto \SKV@prepto|vang(cs){|vang(content)}
-\gpreptomac|vang(cs){|vang(content)}
- |tto \SKV@prepto|redclam|vang(cs){|vang(content)}
-\cspreptomac{|vang(name)}{|vang(content)}
- |tto \SKV@prepto|redplus{|vang(name)}{|vang(content)}
-\csgpreptomac{|vang(name)}{|vang(content)}
- |tto \SKV@prepto|redplus|redclam{|vang(name)}{|vang(content)}
-\end{macro}
-\acmdm*{\preptomac,\gpreptomac,\cspreptomac,\csgpreptomac}
-
-\bigskip
-\begin{macro}
-\SKV@addtolist|redplus|redclam|redleft[|vang(parser)]|vang(csa)|vang(csb)
-\end{macro}
-\acmdm*{\SKV@addtolist,\SKV@addtolist+,\SKV@addtolist+<}
-This adds the contents of the macro \ang{csb} to the list in the container \ang{csa}. The plus sign~(\RedPlus) means that \ang{csa} is a control sequence name (instead of a control sequence); the exclamation mark~(\RedClam) directs \fx{\SKV@addtolist} to add the contents of \ang{csb} to \ang{csa} globally (to escape local groups); and the left angle (\RedLeft), if present, instructs \fx{\SKV@addtolist} to prepend the contents of \ang{csb} to the left of the contents of \ang{csa}, instead of appending to the right by default. The optional argument \ang{parser} is the list parser, ie, the separator of the instances in \ang{csa}. Its default value is ``,'' (comma).
-
-\macrosubsection{Package and document hooks}
-
-\begin{macro}
-\SKV@AtPackageEnd{|vang(code)}
-\SKV@AtClassEnd{|vang(code)}
-\end{macro}
-\acmdm*{\SKV@AtPackageEnd,\SKV@AtClassEnd}
-These are the robust versions of the well-known \latex hooks \acmd{\AtEndOfPackage} and \acmd{\AtEndOfClass}.
-
-\begin{macro}
-\SKV@BeforePackageEnd{|vang(code)} |label(befpkgend)
-\SKV@BeforeClassEnd{|vang(code)} |label(befclsend)
-\SKV@AfterPackageEnd{|vang(code)}
-\SKV@AfterClassEnd{|vang(code)}
-\end{macro}
-\acmdm*{\SKV@BeforePackageEnd,\SKV@BeforeClassEnd,\SKV@AfterPackageEnd,
-\SKV@AfterClassEnd}
-The first two of these hook to just before \acmd{\AtEndOfPackage} or \acmd{\AtEndOfClass}; the third and fourth hook to just after \fx{\AtEndOfPackage} or \acmd{\AtEndOfClass}. They are all robust. These commands have been necessitated by some tasks in the \pkg{skeyval}, but may be useful in some other contexts.
-
-\begin{macro}
-\SKV@AtDocumentStart{|vang(code)}
-\end{macro}
-\acmdm*{\SKV@AtDocumentStart}
-This is the robust version of the \latex hook \acmdm{\AtBeginDocument}. It can be used in expansion contexts without protection, but fragile arguments within it must be protected.
-
-\begin{macro}
-\SKV@BeforeDocumentStart{|vang(code)}|label(beforedocstart)
-\SKV@AfterDocumentStart{|vang(code)}|label(afterdocstart)
-\end{macro}
-\acmdm*{\SKV@BeforeDocumentStart,\SKV@AfterDocumentStart}
-These provide two more document hooks. They are both robust. The command \fx{\SKV@BeforeDocumentStart} differs from \fx{\AtBeginDocument} in that the former is executed right at
-the end of the preamble, before the main auxiliary file (as written on the previous \latex
-run) is read and prior to the execution of any \fx{\AtBeginDocument} code. It isn't possible
-to write to the auxiliary file at the point \fx{\SKV@BeforeDocumentStart} is executed.
-
-\fx{\SKV@AfterDocumentStart} differs from \fx{\AtBeginDocument} in the sense that the former is executed at the tag end of \acmd{\begin\{document\}}, after the execution of any \fx{\AtBeginDocument} code. Commands whose scope are restricted to the document's preamble with \acmd{\@onlypreamble} or \acmd{\SKV@onlypreamble} are no longer committable when \fx{\SKV@AfterDocumentStart} is being executed.
-
-\begin{macro}
-\SKV@AtDocumentEnd{|vang(code)}
-\SKV@BeforeLastPage{|vang(code)}
-\SKV@AfterLastPage{|vang(code)}
-\SKV@AfterDocumentEnd{|vang(code)}
-\end{macro}
-\acmdm*{\SKV@AtDocumentEnd,\SKV@BeforeLastPage,\SKV@AfterLastPage,
-\SKV@AfterDocumentEnd}
-The last three of these are wrappers developed based on the \pkgm{atveryend}, which provides a consistent mechanism for \acmd{\enddocument} methods. The macro
-\fx{\SKV@AtDocumentEnd} is the robust equivalent of \acmd{\AtEndDocument}. The macro \fx{\SKV@BeforeLastPage} appends \ang{code} after the \acmd{\@enddocumenthook} but before the last \acmd{\clearpage}, and thus before the last shipout. The command \fx{\SKV@AfterLastPage} executes \ang{code} after the last \acmd{\clearpage} invoked within \acmd{\enddocument}, \ie, after the last shipout but before the main auxiliary file is closed. This is, \eg, the right instance to record the last document page in the auxiliary file.
-
-The command \fx{\SKV@AfterDocumentEnd} appends \ang{code} to the very end of the document, after all of the end-of-document codes have been executed (\ie, after the main .aux file of the current pass has been read and all \acmd{\AtEndDocument} codes have been effected, except font and label/reference warnings).
-
-\macrosection{Inputting files}
-
-\begin{macro}
-\InputFileOnce[|vang(path)]{|vang(file)}
-\InputFileOnce|redstar[|vang(path)]{|vang(file)}
-\end{macro}
-\acmdm*{\InputFileOnce}
-The unstarred variant of this command inputs \ang{file} on \ang{path} but only once in one \latex pass. The argument \ang{path} is optional and its default value is the current/document's environment/directory. If \ang{file} had previously been read, a warning message is entered in the transcript log file (if the package option \acmd{verbose} is selected) and the input is aborted. If \ang{file} doesn't exist on \ang{path}, as many as desired opportunities are given to the user to type in the correct filename on the screen, or enter ``no'' to continue with the \latex pass without inputting the file.
-
-If the user wants to input \ang{file} more than once in one document, then he should use the starred (\RedStar) variant of \fx{\InputFileOnce}.
-
-\section{References}
-
-All the \texorlatex packages cited in this guide are available on \ctan.
-
-\section{Version history}
-\label{sec:version-hist}
-
-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 star sign (\RedStar) means the subject features in the package but is not reflected anywhere in this user guide.
-
-\begin{versionhist}
- \begin{version}{0.1}{2010/01/01}
- \item First public release under the name \pkg{keyreader}\xsecref
- \item Introduced complementary native-boolean keys \secref{sec:comp-boolkeys}
- \item Provided machinery for reading multiple keys of all kinds from just one command \secref{sec:def-multiple-keys}
- \end{version}
-
- \begin{version}{0.2}{2010/01/10}
- \item Fixed a bug and optimized the \acmd{\define@keylist} loop \secref{sec:def-multiple-keys}
- \end{version}
-
- \begin{version}{0.3}{2010/01/20}
- \item Introduced toggles and toggle-boolean keys \secref{sec:toggles}
- \end{version}
-
- \begin{version}{0.4}{2010/02/01}
- \item Introduced complementary toggle-boolean keys \secref{sec:comptogkeys}
- \end{version}
-
- \begin{version}{0.5}{2010/02/23}
- \item Changed the name of the package from \pkg{keyreader} to \pkg{skeyval}\xsecref
- \item Introduced the following macros\secref{sec:status-keys}
- \begin{veritem}
- \ifkeydefined, \ifkeyreserved, \ifkeysuspended
- \end{veritem}
- \acmd*{\ifkeydefined,\ifkeyreserved,\ifkeysuspended}
-
- \item Provided the following facilities \secref{sec:avoiding-redef}
- \begin{veritem}
- \newordkey, \newcmdkey, \newboolkey, \newchoicekey,
- \newtogkey, \define@biboolkeys, \newbiboolkeys,
- \define@bitogkeys, \newbitogkeys, \define@uniboolkeys,
- \newuniboolkeys, \define@unitogkeys, \newunitogkeys,
- \define@biuniboolkeys, \newbiuniboolkeys,
- \define@biunitogkeys, \newbiunitogkeys
- \end{veritem}
-
- \acmd*{\newordkey,\newcmdkey,\newboolkey,\newchoicekey,\newtogkey,
- \define@biboolkeys,\newbiboolkeys,\define@bitogkeys,\newbitogkeys,
- \define@uniboolkeys,\newuniboolkeys,\define@unitogkeys,\newunitogkeys,
- \define@biuniboolkeys,\newbiuniboolkeys,\define@biunitogkeys,\newbiunitogkeys}
-
- \item Provided mechanisms for disabling, localizing, reserving, unreserving, suspending, restoring, and removing keys \secref{sec:disable-reserv-keys}
- \item Redefined a few of \pkg{xkeyval}'s internal macros \xsecref
- \item Normalization of key-value lists before parsing \secref{sec:list-normal}
- \item Included some developer macros \secref{sec:misce-commands}
- \end{version}
-
- \begin{version}{0.6}{2010/03/30}
- \item Modified the mechanics of the internal macros of the following \secref{sec:reserve-keys}
- \begin{veritem}
- \ReserveKeyPrefixNames, \ReserveKeyPrefixNames|redstar,
- \ReserveMacroPrefixNames, \ReserveMacroPrefixNames|redstar,
- \ReserveFamilyNames, \ReserveFamilyNames|redstar
- \end{veritem}
-
- \acmd*{\ReserveKeyPrefixNames,\ReserveMacroPrefixNames,\ReserveFamilyNames,
- \ReserveKeyPrefixNames*,\ReserveMacroPrefixNames*,\ReserveFamilyNames*}
-
- \item Introduced the following macros \secref{sec:misce-commands}
-
- \begin{veritem}
- \SKV@AtPackageEnd, \SKV@BeforePackageEnd,
- \SKV@AfterPackageEnd, \SKV@AtDocumentEnd,
- \SKV@BeforeLastPage, \SKV@AfterLastPage,
- \SKV@AfterDocumentEnd, \SKV@onlypreamble,
- \SKV@onlypackage, \SKV@ifdraft, \SKV@iffinal,
- \SKV@ifpdf, \@ensurepackageloaded, \InputFileOnce,
- \newswitch, \defswitch, etc.
- \end{veritem}
-
- \acmd*{\SKV@AtPackageEnd,\SKV@BeforePackageEnd,\SKV@AfterPackageEnd,
- \SKV@AtDocumentEnd,\SKV@BeforeLastPage,\SKV@AfterLastPage,\InputFileOnce,
- \SKV@AfterDocumentEnd,\SKV@onlypreamble,\SKV@ifdraft,\SKV@iffinal,\SKV@ifpdf,
- \@ensurepackageloaded}
-
- \item Alert the user if \pkg{skeyval} is loaded before \acmd{\documentclass} \secref{sec:loading-package}
- \item Introduced ``user-value'' keys \secref{sec:uservaluekeys}
- \item Extended the pointer system of the \pkg{xkeyval} \secref{sec:pointer-mech}
- \item Corrected a bug in the \pkg{xkeyval} which, if \acmd{\setkeys} is nested in a class file, gives non-empty \acmdm{\@unusedoptionlist} even if all the options of \acmd{\documentclass} have been used \xsecref
- \end{version}
-
- \begin{version}{0.7}{2010/05/05}
- \item Native-boolean and toggle-boolean keys now accept \fx{on} and \fx{off} as values,
- in addition to \fx{true} and \fx{false} \secref*{sec:toggle-booleans}{sec:switches}
- \item Replaced the former \acmd{\NewIfs} with \acmd{\NewBooleans} and redefined \fx{\NewIfs} \secref{sec:biboolkeys}
- \item Introduced \acmd{\DeclareKeyCommand} \xsecref
-
- \end{version}
-
- \begin{version}{0.71}{2010/05/06}
- \item Corrected a bug in one of the internal conditional tests \xsecref
- \item Removed \fx{\DeclareKeyCommand} to create a separate \pkg{skeycommand} \xsecref
- \end{version}
-
- \begin{version}{0.72}{2010/05/21}
- \item The parameter character is made temporarily innocent when the arguments of \fx{\define@keylist} and \fx{\newkeylist} are being absorbed \secref{sec:def-multiple-keys}
- \item Debugged why, \eg, \fx{#1} in the following definition would refer to the wrong quantity in the \pkg{xkeyval}:
- \xsecref
- \begin{veritem}
- \define@boolkey[KV]{fam}[mp@]{keya}[true]{\def\x{#1}}
- \end{veritem}
- \end{version}
-
-\end{versionhist}
-
-\newpage
-\IndexPreamble{Index numbers refer to page numbers.}
-\IndexPreambleFormat{\centering}
-\IndexColumns\tw@
-\printindex
-\end{document}
-
-%%% End of file skeyval-guide.tex %%% \ No newline at end of file
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf
new file mode 100644
index 00000000000..5efe8797009
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex
new file mode 100644
index 00000000000..2617d621840
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke1.tex
@@ -0,0 +1,431 @@
+
+\RequirePackage{skeyval-ltxpatch}
+
+% With 'skeyval-ltxpatch' loaded, class options will not be zapped and
+% expandable commands can be passed as options.
+
+\documentclass[
+ text style=\ttfamily,
+ show author=true,
+ insertwatermark,
+ watermarktext={skeyval-test1\\[.25ex]Page~\thepage},
+ watermarkcolor=brown!80!yellow
+]{skeyval-testclass}
+
+\skvifpackageloaded{xcolor}{}{\usepackage[dvipsname]{xcolor}}
+\usepackage{lipsum}
+
+
+% The command \cmdalign is just for illustrating how key values
+% may be expanded at key setting time:
+\def\cmdalign{justified}
+
+\usepackage[
+ author=Albert X\"avier Einstein,
+ align=.expanded{\cmdalign},
+ show author=true,
+ unknown-option,
+]{skeyval-testpkg}
+
+\makeatletter
+
+% Keys whose names are zapped internally:
+\skvzcmdkeys[KV]{fam}[mp@]{provide value,give value}[true]{}
+\skvzboolkeys[KV]{fam}[mp@]{provide value,give value}[true]{}
+
+% Parenthesized keys are keys with names that have parentheses.
+% The following is a key of 3 arguments. The default values are
+% \x, \y, and \numexpr\x*2.
+\skvpntkey[KV]{fam}{evaluate (?) as (?) using (?)}[\x\y{\numexpr\x*2}]{%
+ \def\argone{#1}\def\argtwo{#2}\def\argthree{#3}%
+ % '\detokenize{\pgfmath}' won't work here!
+ \skvxifin{\relax\string\pgfmath}{\relax\detokenize{#3}}{%
+ #3%
+ }{%
+ \edef#2{#3}%
+ }%
+}
+
+% The above parenthesized key can be set as follows:
+\def\cmda{2}
+\skvsetkeys[KV]{fam}{%
+ evaluate (\cmda) as (\cmdb) using (\pgfmathsetmacro\cmdb{\cmda*10})
+}
+%\show\argthree
+
+\newcommand*\vgap{\endgraf\medskip}
+\def\keycval{xx}
+
+%% +++++++++++++++ Examples of using \directkeys command +++++++++ %%
+
+% Note: When the value of a handler contains equality sign (=) or
+% comma (,), it should be enclosed in braces.
+
+\directkeys*{
+ .exec=\skvsratchcnt\z@,
+ .prefix = KV1,
+ .family = fam1,
+ .holder prefix = mp@,
+ .add paths={KV2/fam2,KV3/fam3},
+ .ignore roots={KV2/fam2,KV3/fam3},
+ .restore roots={KV2/fam2,KV3/fam3},
+ .save initial values of keys,
+ .initialize keys after define=false,
+ .new keys = {
+ .ord/keya/{dfta,dftb}/
+ \def\cmda##1{#1*##1*#2}
+ \logsetting
+ ,
+ .arg/keya/{#1,#2},
+ .cmd/keyb/{1cm,2cm}/
+ \edef\boxht{\the\dimexpr#1*2\relax}
+ \edef\boxwd{\the\dimexpr#1*10\relax},
+ .choice/keyc/center/{right,left,center,justified},
+ .bool/keyd/true,
+ .cmd/keye/dfte/\def\cmde##1{##1#1},
+ .cmd/keyf/dftf/\def\cmdf##1{##1#1},
+ .ord/.value required{keyg}/dftg,
+ .ord/.forbid value{keyh}/dfth,
+ },
+ .args={
+ keyb={#1,#2}
+ },
+ .set={
+ keya={val1,val2},keyb={2.5cm,5cm}
+ },
+ .get value={KV1}{fam1}{keya}\cmda,
+ .ignore keys={
+ keyd,keye
+ },
+ .set with defaults={
+ keyd,keye,keyf,keyg
+ },
+ .restore keys = keye,
+ .choice=keye/{
+ center.do=\def\curralign##1{\hfil##1\hfil},
+ right.do=\def\curralign##1{\hfill##1},
+ left.do=\def\curralign##1{##1\hfill},
+ justified.do=\let\curralign\@iden
+ },
+ .exec code ={
+ \def\leftval{left}\def\rightval{right}
+ \def\rrightval{\rightval}
+ },
+ % key1 and key2 are undefined. They will be defined internally
+ % with the default values of keyc and keyd:
+ .prepend style={
+ key1/{keyc=.expanded{\rightval}},key2/{keyd=false}
+ },
+ .append style={
+ key1/{keye=right,keyf=valf}
+ },
+ % When key3 and key4 are set, use their expanded values to set keye:
+ .elink={
+ {key3,key4}/keye
+ },
+ .style expand twice={
+ key5/{keyf=#1,keyg=#1}
+ },
+ .set keys={
+ key3=.expand once{\leftval},
+ key5=.expand twice{\rrightval}
+ },
+ .prepend link={
+ {key6,key7}/{keye,keyf},{key8,key9}/{keye,keyg}
+ },
+ .exec code=\skvsetkeys[KV1]{fam1}{key6=center},
+ % Set keya and keyb on previously declared and the following paths.
+ % Enter known keys in \mysuccesslist. Try 14 families; stop when
+ % 12 families have been hit (ie, keys have been set in them
+ % successfully):
+ .search also set keys={
+ .add prefixes={KV3,KV4},
+ .add families={fam3,fam4},
+ .try=14,
+ .upper goal=12,
+ .success list=\mysuccesslist
+ }{
+ keya={val1,val2},keyb={1cm,2cm}
+ },
+% .exec code={\show\mysuccesslist},
+ \directkeys*{
+ .exec=\skvsratchcnt\z@\def\mysuccesslist{},
+ .paths={KUA/fam1,KUB/fam2},
+ .define keys={
+ .ords/{keya,keyb,keyc}/.na/
+ \def\y##1{#1*##1}
+ \typeout{***}
+ \logsetting
+ ,
+ }
+ },
+ % '.try set keys' works independent of previously declared paths:
+ .try set keys={
+ .prefixes={KUA,KUB,KUC},
+ .families={fam1,fam2,fam3,fam4},
+ .try=8,
+ .upper goal=4,
+ .lower goal=2,
+ .ignore keys={keyb,keyc},
+ .success list=\mysuccesslist
+ }{
+ keya=vala,keyb=valb,keyc=valc
+ },
+% .exec code={\show\mysuccesslist},
+}
+
+\makeatother
+
+\begin{document}
+
+\title{The \texttt{\textcolor{blue}{skeyval}} Package\\[1ex]
+ Version 1.1\\[1ex]
+ \textsf{Test document 1}}
+\author{Ahmed Musa}
+\maketitle
+
+%%+++++++++++++++++++ Producing arbitrary texts +++++++++++++++++++++%%
+
+\noindent
+An author writing an article for publication in \textsc{TUGboat} is
+encouraged to create it on a computer file and submit it on magnetic tape.
+\par
+\hfill{\small Barbara Beeton, 1981}
+\par\bigskip
+
+\begin{\mpfalign}
+\skvxifstrcmp\mpfalign{justified}{\noindent}{}
+\mpftextstyle
+The printer should refuse to employ wandering men, foreigners who,
+after having committed some grievous error, can easily disappear and
+return to their own country.
+\hfill{\small Hieronymus Hornschuch (1608)}\endgraf
+\end{\mpfalign}
+
+
+\begingroup
+\par\bigskip
+\noindent
+If you want to find out anything from the theoretical physicists
+about the methods they use, I advise you to stick closely to
+one principle: don't listen to their words, fix your mind
+on their deeds.
+\ifmpfshowauthor
+ \nobreak
+ \quad\hskip\fill\finalhyphendemerits0\relax
+ \textcolor{red}{\mpfauthor}
+\fi
+\endgroup
+
+
+%%++++++++++++++++++++++ Shadow boxes ++++++++++++++++++++++++%%
+
+\par\bigskip
+\begin{center}
+\hrule
+\par\bigskip
+\newshadowbox{test 1}
+\newshadowbox[framecolor=magenta,shadecolor=cyan,shadowsize=8pt,
+ align=left]{test 2}
+\newshadowbox[shadow=false,boxwidth=1cm]{test 3}
+\newshadowbox[framesize=2pt,framecolor=red,shadowcolor=green]{test 4}
+\newshadowbox[put frame=false,shadow,shadowsize=9pt,shadecolor=yellow,
+ shadowcolor=violet!50,align=right]{test 5}
+\par\bigskip
+\hrule
+\end{center}
+
+
+%%++++++++++++++++++++++++++ Citation ++++++++++++++++++++++++%%
+
+\par\bigskip
+\noindent
+\newcitation[
+ author=George Bernard Shaw (1856--1950),
+ show author,
+ leftmargin=0pt,
+ rightmargin=0pt,
+ put frame,
+ framecolor=blue,
+ shadecolor=yellow!25!green!14,
+ frame thickness=1pt,
+]{%
+ A man of great common sense and good taste; meaning thereby
+ a man without originality and/or moral courage.
+}
+
+\par\bigskip
+\noindent
+\newcitation[
+ author=George Bernard Shaw (1856--1950),
+ show author,
+ leftmargin=0pt,
+ rightmargin=0pt,
+ put frame=false,
+ framecolor=yellow!30!blue,
+ shadecolor=yellow!25,
+ frame thickness=5pt,
+ width=.8\textwidth,
+]{%
+ A man of great common sense and good taste; meaning thereby
+ a man without originality and/or moral courage.
+}
+
+\par\bigskip
+\noindent
+\newcitation[
+ author=Mohammed Ali,
+ show author,
+ leftmargin=0pt,
+ rightmargin=0pt,
+ put frame,
+ framecolor=red!70!green,
+ shadecolor=magenta!5!red!4,
+ frame thickness=10pt,
+]{%
+ I always say I was `the greatest'; I have never said I was the smartest.
+ \vgap
+ At home I am a nice, quiet guy, but I don't want the world to know.
+ Humble people, I have found, don't get very far.
+ \vgap
+ To win, you must have the skill and the will. But the will must be
+ stronger than the skill.
+ \vgap
+ I'm the best golfer; I just haven't played it yet.
+}
+
+
+%++++++++++++++++++ Collecting body of environment +++++++++++++++++++%
+
+\bigskip
+\begin{collectbody}[
+ title=Example of collect body,
+ title scale=.8,
+ title text style=\ttfamily\color{red}
+]
+\lipsum[1]
+\end{collectbody}
+
+
+\end{document}
+
+
+%%+++++++++++++++++++++ Examples of \skvmakekeys +++++++++++++++++++%%
+
+\skvmakekeys[
+ prefix=KVA,
+ families={fam1,fam2},
+ hp=thp@,
+ all new,
+ define in all families,
+ initialize=true
+]{%
+ .ords/{keya,keyb}/{default-a},
+ .cmds/{keyc,keyd}/,
+ .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right},
+ .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi},
+}
+%\skvshowcs{KVA/fam2/keyf.@cbk}
+%\skvshowcs{KVA/fam1/keyb.@defa}
+\def\keybval{xx}
+\skvsetkeys[KVA]{fam1}{keyb=.expand once{\keybval}}
+
+
+%%+++++++++++++++++++++ Examples of \skvusekeys +++++++++++++++++++%%
+
+\skvmakekeys[
+ .prefix=KVA,
+ .families={fam1,fam2},
+ .hp=thp@,
+ .all new
+]{%
+ .ord/keya/{default-a}/\def\y##1{##1*#1*##1},
+ .ord/keyb/defa-b,
+}
+
+\def\keybval{xx}
+
+\skvusekeys[
+ .prefix=KVA,
+ .families={fam1,fam2},
+ .set in all families,
+ .save unknown keys
+]{%
+ keya,
+ keyb=.expand once{\keybval}
+}
+
+% Families fam3 and fam4 aren't defined. Hence, with 'save unknown keys'
+% set to 'true' by default, keys keya and keyb are saved as rm keys with
+% their default values.
+\skvusekeys[
+ .prefix=KVA,
+ .families={fam3,fam4},
+ .set in all families,
+ .save unknown keys
+]{%
+ keya,keyb=.expand once{\keybval}
+}
+%\skvshowcs{KVA/fam3/.@rmkeys}
+%\skvshowcs{KVA/fam4/.@rmkeys}
+
+
+%%+++++++++++++++ Key values with unbalanced conditionals ++++++++++++%%
+
+\skvcmdkey[SKVT]{fam}[mpf]{keya}[keya-defa]{\def\keyaval{#1}}
+\skvsetkeys[SKVT]{fam}{keya=\fi}
+
+%%+++++++++++++++++++++ Examples of \skvkeyslet +++++++++++++++++++%%
+
+\skvsaveinitialvaluekeys[KV]{fam}{keya,keyb,keyc}
+%\skvshowcs{KV/fam/.@needini}
+\skvmakekeys[
+ prefix=KV, family=fam, hp=thp@, all new,initialize,save initial values
+]{%
+ .ord/keya/defa-a/\def\keyay##1{##1*#1*##1},
+ .cmds/{keyb,keyc}/defa-b/\def\keyby##1{##1*#1*##1},
+ .cmd/keyd,
+}
+%\skvshowcs{KV/fam/.@inikv}
+\skvignorekeys[KV]{fam}{keyb,keyc}
+\skvkeyslet[KV]{fam}{keyA=keya,keyB=keyb,keyC=keyc}
+\skvshowcs{KV/fam/.@needini}
+
+
+%++++++++++++++++++ Evaluating boolean expressions +++++++++++++++++++%
+
+\skvifexpr{%
+ not ( expr { \skvifdef\xa } and expr { \skvifempty\xa } )
+ or ( expr { \skvifdef\xb } or expr { \skvifx\xa\xb } )
+}{%
+ \def\x{T}%
+}{%
+ \def\x{F}%
+}
+
+%++++++++++++++++++++++++++++ \cicadaloop +++++++++++++++++++++++++++%
+
+\makeatletter
+\@tempcnta\z@
+\def\blist{{X};\fi;{Y};Z}
+\def\stack{}
+\let\romn\romannumeral
+\cicadaloop{{a},\if,{b},c}\if01\fi{%
+ \advance\@tempcnta by\@ne
+ \@tempcntb\z@\@tempswafalse
+ \cicadaloop*[;]\blist\if@tempswa\fi{%
+ \advance\@tempcntb by\@ne
+ \typeout{Doing \romn\@tempcnta, \romn\@tempcntb:
+ \detokenize{#1, ##1}}%
+ \edef\stack{%
+ \unexpanded\expandafter{\stack}\noexpand\do
+ {\romn\@tempcnta,\romn\@tempcntb}{\unexpanded{#1;##1}}%
+ }%
+ \ifnum\@tempcntb>\tw@\@tempswatrue\fi
+ }%
+}
+\makeatother
+
+% End of file skeyval-pokayoke1.tex
+
+
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf
new file mode 100644
index 00000000000..a81a562fef7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex
new file mode 100644
index 00000000000..84696094258
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-pokayoke2.tex
@@ -0,0 +1,106 @@
+\documentclass[
+ insertwatermark,
+ firstpagenumber=2,
+ maketitlepage,
+ unknown-key
+]{skeyval-testclass}
+
+\setskeyvaltestclass{%
+ watermarktext={skeyval-test2\\[.25ex]Page~\thepage}
+}
+
+\usepackage{lipsum}
+\usepackage{xcolor}
+
+% If you try to load 'skeyval-testpkg' with options, the options
+% will all be zapped, unless you load 'skeyval-ltxpatch' on top of
+% \documentclass.
+
+\setuptextemphasis{usecolour=true,usebold,useitalics=true}
+
+\begin{document}
+
+\title{%
+ The \texttt{\textcolor{blue}{skeyval}} Package\\[2ex]
+ Version 1.1\\[1ex]
+ \textsf{Test document 2}
+ \footnote{Made by \texttt{skeyval-testclass, Version~1.1.}}%
+}
+\author{Ahmed Musa\footnote{\texttt{amusa22@gmail.com}.}}
+
+\maketitle
+
+\lipsum[1]
+
+\xem{\lipsum[1]}
+
+\setuptextemphasis{color=blue}
+
+\xem{\lipsum[1]}
+
+\setuptextemphasis{usecolor=false, usebold=false, useitalic=false}
+
+\xem{\lipsum[1]}
+
+\lipsum[1]
+
+\setuptextemphasis{make-textemphasis-inactive}
+
+\xem{\lipsum[1]}
+
+% This will raise an error: 'dummy-option' has been disabled
+% at begin document:
+% \setuptextemphasis{dummy-option}
+
+\begin{tikzpicture}[shading=ball]
+\newforeach \x/\cola in {0/red,1/green,2/blue,3/yellow} do {%
+ \newforeach \y/\colb in {0/red,1/green,2/blue,3/yellow} {%
+ \node[
+ circle,double,draw=-\cola!50!\colb,fill=\cola!50!\colb,
+ thick,inner sep=2pt,
+ minimum size=10mm,font=\bfseries\color{white}
+ ] at (\x*2,\y*2) {\x,\y};
+ }%
+}
+\end{tikzpicture}
+
+\bigskip
+\parindent-20pt
+\begin{tikzpicture}
+\draw[step=.5cm,blue!65,very thin] (0,0) grid (13,6);
+\newforeach \x in {1,2,...,5,7,8,...,12} {
+ \newforeach \y in {1,...,5} do {
+ \draw (\x,\y) +(-.5,-.5) rectangle ++(.5,.5);
+ \draw (\x,\y) node{\x,\y};
+ }
+}
+\end{tikzpicture}
+
+\bigskip
+\begingroup
+\catcode`\,=13
+\gdef\alist{1,2,...,5,7,8,...,12}
+\endgroup
+\parindent-20pt
+\begin{tikzpicture}
+\draw[step=.5cm,blue!65,very thin] (0,0) grid (13,6);
+\newforeach* \x [
+ count in=\xc all \x satisfying \ifnum\x>5\fi
+] in \alist {
+ \newforeach[
+ parser={;},
+ evaluate=\y as \ye using \numexpr\y*10
+ ]
+ \y:\z in {1:red; 2:green; 3:blue; 4:brown; 5:purple} do {
+ \draw [fill=\z\ifnum\x>5!\ye\fi](\x,\y) +(-.5,-.5) rectangle ++(.5,.5);
+ \draw (\x,\y) node {\x,\y};
+ }
+}
+\global\let\xc\xc
+\end{tikzpicture}
+%\show\xc
+
+
+\end{document}
+
+% End of file skeyval-pokayoke2.tex \ No newline at end of file
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls b/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls
new file mode 100644
index 00000000000..02de214caa0
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-testclass.cls
@@ -0,0 +1,311 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-testclass.cls', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\ProvidesClass{skeyval-testclass}
+ [2012/10/15 v1.1 skeyval test class (AM)]
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
+\@ifpackageloaded{xcolor}{}{\RequirePackage{xcolor}}
+\@ifpackageloaded{pifont}{}{\RequirePackage{pifont}}
+\@ifpackageloaded{tikz}{}{\RequirePackage{tikz}}
+
+\skvAtBeginEveryPage{\skvcl@maybewm}
+\let\skvcl@maybewm\relax
+\def\skvcl@watermark{%
+ \tikz[overlay,remember picture]{%
+ \node [\skvcl@watermarkcolor,inner sep=0pt,rotate=45,align=center,
+ scale=\skvcl@watermarkscale,font=\fontseries{b}\fontfamily{bch}%
+ \fontsize{\skvcl@fontsize@a}{\skvcl@fontsize@b}\selectfont] at
+ ([shift={(\skvcl@watermarkxshift,-\skvcl@watermarkyshift)}]%
+ current page.north west){%
+ \skvcl@watermarktext
+ };
+ }%
+}
+
+\skvrobustdef*\skvcl@titlecmds{%
+ \setcounter{footnote}{0}%
+ \def\do##1{\global\let##1\@empty}%
+ \do\@thanks\do\@author\do\@date\do\@title
+ \def\do##1{\global\let##1\relax}%
+ \do\thanks\do\maketitle\do\@maketitle\do\title\do\author\do
+ \date\do\and\let\do\relax
+ \let\@fnsymbol\orig@fnsymbol
+}
+\let\orig@fnsymbol\@fnsymbol
+
+\skvrobustredef*\skv@fnsymbol#1{%
+ \unskip\ifcase#1\or\ding{'106}\or\ding{'110}\or\ding{'111}\or
+ \ding{'112}\or\ding{'113}\or\ding{'114}\or\ding{'121}\or
+ \ding{'122}\else\@ctrerr\fi
+}
+\skvrobustdef*\skvcl@newfootnotestyle{%
+ \def\@makefnmark{%
+ \rlap{\@textsuperscript{\normalfont\skv@fnsymbol\@thefnmark}}%
+ }%
+ \long\def\@makefntext##1{%
+ \parindent1em\relax\noindent
+ \hb@xt@1.8em{\hss\@textsuperscript{%
+ \normalfont\skv@fnsymbol\@thefnmark}%
+ }%
+ ##1%
+ }%
+}
+\skvnewlet\skv@sav@footnote\footnote
+\skvnewlet\skv@sav@thanks\thanks
+\AtEndOfPackage{%
+ \skvdisablekeys[SKVC]{title}{%
+ insertwatermark
+ }%
+}
+\AtBeginDocument{%
+ \def\footnote{\unskip\skv@sav@footnote}%
+ \def\thanks{\unskip\skv@sav@thanks}%
+ \skvdisablekeys[SKVC]{textemphasis}{dummy-option}%
+ \skvdisablekeys[SKVC]{title}{%
+ maketitlepage,firstpagenumber,pagenumberstyle
+ }%
+}
+\let\skvcl@settitlepageno\@gobble
+
+% LaTeX will zap spaces in key name, anyway. So our options don't have
+% spaces within themselves.
+
+\directkeys*{%
+ .every unknown option={
+ \PassOptionsToClass{\CurrentOption}{article}
+ },
+ .message type when disabled option is invoked=error,
+ .prefix=SKVC,
+ % Extended text emphasis:
+ .family=textemphasis,
+ .hp=xem@,
+ .new options={
+ .bool/useitalic/true,
+ .bool/usebold/true,
+ .bool/usecolor/true,
+ .cmd/color/red,
+ .bool/make-textemphasis-inactive/true/
+ \ifskvindef\else
+ \skvifbooltrue xem@make-textemphasis-inactive\then
+ \PackageInfo{skeyval-testclass}
+ {Extended text emphasis has been made inactive}
+ \let\xem\emph
+ \fi
+ \fi
+ ,
+ .ord/dummy-option/\@nil,
+ },
+ .links={
+ useitalics/useitalic,
+ usecolour/usecolor,
+ colour/color,
+ },
+ % Modifying the article title:
+ .change family=title,
+ .hp=skvcl@,
+ .new options={
+ .bool/putdate/true,
+ .cmd/datefont/\large,
+ .bool/clearpage/true,
+ .bool/maketitlepage/true/
+ \skvifbooltrue skvcl@maketitlepage\then
+ \ifskvindef\else
+ \PassOptionsToClass{titlepage}{article}
+ \fi
+ \fi
+ ,
+ .cmd/firstpagenumber/\@nil/
+ \ifx\skvcl@firstpagenumber\@nnil\else
+ \skvensureinteger{page number}\skvcl@firstpagenumber
+ \AtBeginDocument{%
+ \gdef\pagenumbering##1{%
+ \global\c@page\skvcl@firstpagenumber\relax
+ \gdef\thepage{\csname @##1\endcsname\c@page}%
+ }%
+ % Default:
+ \pagenumbering{arabic}%
+ \let\skvcl@settitlepageno\@iden
+ }%
+ \fi
+ ,
+ .cmd/pagenumberstyle/\@nil/
+ \ifx\skvcl@pagenumberstyle\@nnil\else
+ \skvAfterBeginDocument{\pagenumbering{#1}}%
+ \fi
+ ,
+ .cmd/pretitleskip/10pt,
+ .cmd/posttitleskip/10pt,
+ .cmd/authorfont/\large,
+ .cmd/titlefont/\huge,
+ .bool/insertwatermark/true/
+ \skvifbooltrue skvcl@insertwatermark\then
+ \ifskvindef\else
+ \let\skvcl@maybewm\skvcl@watermark
+ \fi
+ \fi
+ ,
+ .cmd/watermarkxshift/.5\paperwidth,
+ .cmd/watermarkyshift/.5\paperheight,
+ .cmd/watermarktext/DRAFT/
+ \skvstripouterbraces{2}\skvcl@watermarktext
+ ,
+ .cmd/fontsize/{14.4,17}/
+ \def\skvcl@fontsize@a{#1}\def\skvcl@fontsize@b{#2}
+ ,
+ .args/fontsize/{#1,#2},
+ .cmd/watermarkscale/5,
+ .cmd/watermarkcolor/gray!55,
+ },
+ .styles={
+ showdate/putdate=#1,
+ first-page-number/firstpagenumber=#1,
+ titlepage/maketitlepage=#1,
+ },
+ % Options execution & processing:
+ .families = {textemphasis,title},
+ .execute options+={
+ useitalic,usebold,usecolor,color,
+ make-textemphasis-inactive=false,putdate,datefont,
+ clearpage=false,pretitleskip,posttitleskip,
+ authorfont,titlefont,watermarkscale,firstpagenumber,
+ insertwatermark=false,watermarkxshift,watermarkyshift,
+ watermarktext,fontsize
+ },
+% .mega process options*={
+% prefix=SKVC,
+% families={textemphasis,title},
+% },
+ .copy class options and process options in all families,
+}
+
+\skvrobustdef*\setskeyvaltestclass{%
+ \skvsetkeys*+[SKVC]{textemphasis,title}%
+}
+
+% Setting up extended text emphasis:
+\skvrobustdef*\setuptextemphasis#1{\skvsetkeys[SKVC]{textemphasis}{#1}}
+\newcommand*\xem[1]{\xem@emph{\xem@bold{\xem@colortext{\xem@color}{#1}}}}
+\newcommand*\xem@emph{%
+ \skvifbooltrue xem@useitalic\then
+ \expandafter\emph
+ \else
+ \expandafter\@firstofone
+ \fi
+}
+\newcommand*\xem@bold{%
+ \skvifbooltrue xem@usebold\then
+ \expandafter\textbf
+ \else
+ \expandafter\@firstofone
+ \fi
+}
+\newcommand*\xem@colortext{%
+ \skvifbooltrue xem@usecolor\then
+ \expandafter\textcolor
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+
+\LoadClass{article}
+
+\if@titlepage
+ \renewcommand\maketitle{%
+ \ifskvcl@clearpage
+ \clearpage
+ \fi
+ \begin{titlepage}%
+ \skvcl@newfootnotestyle
+ \let\footnotesize\small
+ \let\footnoterule\relax
+ \let\footnote\thanks
+ \null\vfil
+ \vskip\skvcl@pretitleskip\relax
+ \begin{center}%
+ {\skvcl@titlefont\@title\par}%
+ \vskip\skvcl@posttitleskip\relax
+ {%
+ \skvcl@authorfont
+ \lineskip.75em\relax
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par
+ }%
+ \vskip1.5em\relax
+ \skvifbooltrue skvcl@putdate\then{{\skvcl@datefont\@date}}\fi
+ \end{center}\par
+ \@thanks
+ \vfil\null
+ \end{titlepage}%
+ \skvcl@settitlepageno{\c@page\skvcl@firstpagenumber\relax}%
+ \skvcl@titlecmds
+ }
+\else
+ \renewcommand\maketitle{%
+ \par
+ \begingroup
+ \skvcl@newfootnotestyle
+ \if@twocolumn
+ \ifnum\col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
+ \else
+ \newpage
+ \global\@topnum\z@
+ \@maketitle
+ \fi
+ \thispagestyle{plain}\@thanks
+ \endgroup
+ \skvcl@titlecmds
+ }
+ \def\@maketitle{%
+ \newpage
+ \null
+ \vskip\skvcl@pretitleskip\relax
+ \begin{center}%
+ \let\footnote\thanks
+ {\skvcl@titlefont\@title\par}%
+ \vskip\skvcl@posttitleskip\relax
+ {\skvcl@authorfont
+ \lineskip.5em\relax
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par
+ }%
+ \vskip1em\relax
+ \skvifbooltrue skvcl@putdate\then{\skvcl@datefont\@date}\fi
+ \end{center}%
+ \par
+ \vskip1.5em\relax
+ }
+\fi
+
+\endinput
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty b/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty
new file mode 100644
index 00000000000..eae0c324f7d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-testpkg.sty
@@ -0,0 +1,433 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-testpkg.sty', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\ProvidesPackage{skeyval-testpkg}
+ [2012/10/15 v1.1 skeyval test package 1 (AM)]
+\NeedsTeXFormat{LaTeX2e}
+\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
+\RequirePackage{graphicx}
+
+\skvdisabledkeysmessagetype{warning}
+
+%%++++++++++++++++ Passing options to packages +++++++++++++++++++%%
+
+\skvdeclarebooloption[SKVT]<passoptions>[skvtp@]{verbose}[true]{}
+
+% Declare options with default values that will be used when the options
+% are called without user values:
+% \DeclarePassedOptions{<option>=<default>,...}
+\skvrobustdef*\skvDeclarePassedOptions#1{%
+ \skvkvparse{#1}\skv@tempa{%
+ \def\do##1=##2=##3\@nil{%
+ \skvdeclareoption{##1}[##2]{%
+ \skvifcsdef{ver@##1.sty}{%
+ \skv@warn{Package '##1' has been loaded and
+ \MessageBreak now you've asked for it to be loaded}%
+ }{%
+ \skvAfterProcessOptions{%
+ \RequirePackage[####1]{##1}%
+ }%
+ }%
+ }%
+ }%
+ \expandafter\do\skv@tempa==\@nil
+ }%
+}
+
+\skvDeclarePassedOptions{%
+ hyperref={colorlinks,breaklinks},xcolor=svgnames
+}
+
+%%+++++++++++++++++++ Producing arbitrary texts +++++++++++++++++%%
+
+% The key 'align' could have defined using \skvchoicekey, as in
+% 'shadowbox' family below.
+\newcommand*\justified{}
+\skvordkey[SKVT]{abrtext}{align}[right]{%
+ \skvifcase\skvxifstrcmp{#1}
+ {left}{\def\mpfalign{flushleft}}
+ {right}{\def\mpfalign{flushright}}
+ {center}{\def\mpfalign{center}}
+ {justified}{\def\mpfalign{justified}}
+ \elsedo
+ \PackageError{skeyval-testpkg}
+ {Invalid value `#1' for align}
+ {You have issued an illegal value `#1' for option `align'.}%
+ \endif
+}
+
+\skvzcmdkey[SKVT]{abrtext}[mpf]{text style}[\rmfamily]{}
+\skvcmdkey[SKVT]{abrtext}[mpf]{author}[Karl Berry]{}
+\skvzboolkey[SKVT]{abrtext}[mpf]{show author}[true]{}
+
+% Using pointers to expand values of keys while setting keys:
+\def\alignval{right}
+\def\alignvalb{\alignval}
+\def\stextstyle{\sffamily}
+
+\skvsetkeys[SKVT]{abrtext}{align=.expand twice{\alignvalb},
+ text style=.expand once{\stextstyle},author,show author}
+
+%%+++++++++++++++++++++++++++ Citations +++++++++++++++++++++++++++%%
+
+% Keys defined by \skvdefinekeys are automatically initialiized when
+% the option 'initialize' is true. In general, to save initialize
+% key values at key definition, you need to call \skvsaveinitialvaluekeys
+% before defining the keys.
+
+\skvsaveinitialvaluekeys[SKVT]{citation}{put frame,width,show author,author,
+ textcolor,fonttype,leftmargin,rightmargin,preskip,framecolor,shadecolor,
+ frame thickness}
+
+\newbox\skv@testbox
+\skvdefinekeys*[SKVT]{citation}[ctt@]{%
+ .cmd/width/\hsize,
+ .zbool/show author/true,
+ .cmd/author//, % empty default
+ .zbool/put frame/true,
+ .cmd/framecolor/black,
+ .cmd/shadecolor/white,
+ .cmd/textcolor/black,
+ .zcmd/frame thickness/.4pt,
+ .cmd/fonttype/\normalfont,
+ .cmd/leftmargin/\leftmargin,
+ .cmd/rightmargin/\rightmargin,
+ .cmd/preskip/0ex,
+ .cmd/width/\textwidth,
+ .ord/dummy key/\@nil,
+}
+% Keys defined by \skvdefinekeys are automatically initialiized when
+% the option 'initialize' is true. When \skvsaveinitialvaluekeys has been
+% called for a set of keys, those keys can be initialized via
+% \skvinitializekeys:
+\skvinitializekeys[SKVT]{citation}[dummy key]
+
+\newcommand\newcitation[2][]{%
+ \skvsetkeys[SKVT]{citation}{#1}%
+ \sbox\skv@testbox{%
+ \ctt@fonttype
+ \textit{\textcolor{\ctt@textcolor}{\ctt@author}}%
+ }%
+ \list{}{%
+ \setlength\leftmargin{\ctt@leftmargin}%
+ \setlength\rightmargin{\ctt@leftmargin}%
+ }%
+ \vspace*{\ctt@preskip}%
+ \item\relax
+ \ifctt@putframe
+ \begingroup
+ \fboxrule\ctt@framethickness\relax
+ \fcolorbox{\ctt@framecolor}{\ctt@shadecolor}{%
+ \fi
+ \parbox{\ctt@width}{%
+ \ctt@fonttype\textcolor{\ctt@textcolor}{\ignorespaces#2}%
+ \ifctt@showauthor
+ \hspace*{\fill}\nolinebreak[1]%
+ \quad\hspace*{\fill}\finalhyphendemerits\z@\relax
+ \usebox\skv@testbox
+ \fi
+ }%
+ \ifctt@putframe}\endgroup\fi
+ \endlist
+ % Restore default values of keys:
+ \skvinitializekeys[SKVT]{citation}[]
+}
+
+
+%%++++++++++++++++++++++++ Shadow boxes ++++++++++++++++++++++%%
+
+\newdimen\shadowspread
+
+\skvdefinekeys*[SKVT]{shadowbox}[shb@]{%
+ .zbool/put frame/true,
+ .bool/shadow/true,
+ .cmd/framecolor/black,
+ .cmd/shadecolor/white,
+ .cmd/shadowcolor/gray!55,
+ .cmd/boxwidth/2cm,
+ .ord/framesize/.5pt/\def\currfboxrule{#1},
+ .ord/shadowsize/2pt/\shadowspread=\dimexpr#1\relax,
+ .choice/align/center/{%
+ center.do=\def\curralign##1{\hfil##1\hfil},
+ right.do=\def\curralign##1{\hfill##1},
+ left.do=\def\curralign##1{##1\hfill},
+ justified.do=\let\curralign\@iden
+ }
+}
+
+\skvdefinekeys*[SKVT]{testfam}[shb@]{%
+ .zbool/put shadow/true,% Test zbool
+ .zcmd/shade color/gray!55, % Test .zcmd
+}
+
+\skvdisablekeys[SKVT]{testfam}{put shadow, shade color}
+
+% 'Presetting keys' means set the following keys whenever \setkeys is called.
+% These keys should be set BEFORE the keys listed in the current argument of
+% \setkeys are set, provided that these keys aren't listed in the current
+% argument of \setkeys. If these keys appear in the current argument of \setkeys,
+% then obviously the user has new values for them or he wants the keys to be
+% set with their default values.
+
+% 'Postsetting keys' means set the following keys whenever \setkeys is called.
+% These keys should be set AFTER the keys listed in the current argument of
+% \setkeys are set, provided that these keys aren't listed in the current
+% argument of \setkeys.
+
+% The command \presetkeys of the xkeyval package expects both 'head' and 'tail'.
+% The skeyval package splits \presetkeys into two, hopefully less confusing,
+% commands: \skvpresetkeys and \skvpostsetkeys.
+
+% There is also command \skvpreposetkeys, which combines \skvpresetkeys and
+% \skvpostsetkeys. This expects both head and tail and is equivalent to
+% xkeyval's \presetkeys.
+
+\skvpresetkeys[SKVT]{shadowbox}{%
+ put frame,framecolor=black,framesize=.8pt,boxwidth=2cm,align=center,
+ shadecolor=gray!15
+}
+
+\skvpostsetkeys[SKVT]{shadowbox}{%
+ shadow=.use value{put frame},shadowcolor=.use value{framecolor}!40,
+ shadowsize=\dimexpr.use value{framesize}*5\relax
+}
+
+\newcommand*\newshadowbox[2][]{%
+ \skvsetkeys[SKVT]{shadowbox}{#1}%
+ \begingroup
+ \ifshb@putframe
+ \fboxrule=\dimexpr\currfboxrule\relax
+ \else
+ \fboxrule=0pt
+ \fi
+ \ifshb@shadow\else\shadowspread=0pt \fi
+ \sbox\z@{\fcolorbox{\shb@framecolor}{\shb@shadecolor}{%
+ \hb@xt@\shb@boxwidth{\curralign{#2}}%
+ }}%
+ \hskip\shadowspread
+ \color{\shb@shadowcolor}%
+ \rule[-\dp0]{\wd0}{\dimexpr\ht0+\dp0\relax}%
+ \llap{\raisebox{\shadowspread}{\box0\hskip\shadowspread}}%
+ \endgroup
+}
+
+%%++++++++++++++++++++++++ The \directkeys command ++++++++++++++++++++%%
+
+% The following are meant to demonstrate the use of the macro \directkeys:
+
+\newcount\skvsratchcnt
+\def\logsetting{%
+ \advance\skvsratchcnt\@ne
+ \typeout{'\skvcurrentkey' set: no.
+ \ifnum\skvsratchcnt<10 0\fi\the\skvsratchcnt, %
+ path: \skvcurrentprefix/\skvcurrentfamily}%
+}
+\directkeys{%
+ % #1 will be the user-value of the handler 'some handler'.
+ .new handlers = {
+ .some handler=\def\x##1{##1*#1},
+ .phantom handler=,
+ },
+ .handler let = {
+ .another handler=.some handler,
+ .do nothing handler=.phantom handler
+ },
+ .kill handlers={
+ .another handler,
+ .do nothing handler
+ },
+ .define handlers={
+ .j handler=\def\x##1{##1*#1},
+ .j handler=\def\y##1{##1*#1},
+ },
+ .define narg handlers={
+ .j1 handler={2}{\def\x##1{##1*#1*#2}},
+ .j2 handler={3}{\def\x##1{##1*#1*#2*#3}}
+ },
+ .new narg handlers={
+ % Error: handler j1 already exists:
+ % .j1 handler={2}{\def\x##1{##1*#1*#2}},
+ .k handler={2}{\def\x##1{##1*#1*#2}},
+ .l handler={3}{\def\x##1{##1*#1*#2*#3}}
+ },
+ .holder prefix = mp@,
+ .prefix = KV,
+ .add prefixes = {KVA,KVD},
+ .families = {fam1, fam2},
+ .add family = {fam3},
+ .add families = {fama,famb,famc},
+ .ignore prefixes = {KVA,KVD},
+ .ignore families = {fama,famb,famc},
+ .restore families = {fama,famb},
+ .restore roots = {KVA/fama,KVD/famc},
+% .ignore keys = {keyb,keyc},
+ .new keys = {
+ .ord/keya/keya-default,
+ .cmd/keyb/keyb-default/\def\x##1{##1#1},
+ .cmd/keyc/keyc-default,
+ .choice/keyd/center/{right,left,center},
+ .bool/keye/true/
+ \ifskvindef\else
+ \logsetting
+ \fi
+ \ifmp@keye\def\y##1{##1#1}\fi
+ ,
+ .bool/keyf/true/,
+ .bool/keyg/true/
+ },
+ .ignore keys = {keyb,keyc},
+ % Stop processing this list:
+ % .list break,
+ .restore keys = {keyb,keyc},
+ .preset keys = {keyb,keyc},
+ .postset keys = {keyb,keyc},
+ % save unknown keys in the default macro \<pref>@<fam>@rmkeys:
+ .save unknown keys = true,
+ .save unknown keys in = \macroa,
+ .set keys = {keya,keyb,keyc,keyd,keye},
+ .set keys = {keya=keya-value,keyb=\def\y####1{####1}},
+ .set keys* = {keya=keya-value,keyf},
+ .set keys* = {keya=keya-value,keyf},
+ .ignore keys = {keyf},
+ .set rmkeys*,
+ % Execute arbitrary code:
+ .exec code=\def\x#1{#1},
+ % Nesting of \directkeys is possible. At the end of the nest, prevailing
+ % variables of \directkeys revert to their previous (door) values:
+ \directkeys{
+ .prefixes = {KVA,KVB},
+ .family = fam3,
+ .holder prefix = hp@,
+ .define keys = {
+ .cmd/keya/keya-default/\def\x##1{##1#1},
+ .ord/keyb/keyb-default,
+ },
+ .set keys = {keya=vala},
+ },
+ .exec code = \def\keycval{true},
+ % Prepend style keye to key1 and key2:
+ .prepend style={key1/{keye=.expanded{\keycval}},key2/{keye=false}},
+ .prepend style={{key3,key4}/{keye=true,keyf=true}, key5/{keye=false}},
+ % Prepend style keyd to key6:
+ .prepend style={key6/{keyd=right}},
+ % Append styles keye and keyf to key7 and key8:
+ .append style={key7/{keye=true},key8/{keyf=false}},
+ %
+ % The next two link keyb and keyc to key9. #1 here refers to the
+ % current value of key9. The same effect can be achieved directly
+ % via the '.link' handler:
+ .prepend style={key9/{keyb=#1}},
+ .append style={key9/{keyc=#1}},
+ .set keys = {key9=val9},
+ % Link keye and keyf to key10 and key11. The values of key10 and
+ % key11 are used to set keye and keyf. key10 and key11 are hence
+ % 'parent keys'.
+ .link={key10/keye, key11/keyf},
+ .set keys = {key10=true},
+ .ignore key = keyf,
+ .save unknown keys in = \macrob,
+ .setkeys = {keya,keyb,keyf},
+ .disable keys = {keye,keyf},
+}
+
+%%++++++++++++++++++++++ Collecting body of environment +++++++++++++++++%%
+
+\skvmakekeys[
+ .prefix=KV,
+ .family=collectbody,
+ .hp=mp,
+ .initialize,
+ .endlinechar=-1
+]{%
+ .cmd/title//,
+ .zcmd/title scale/1,
+ .zcmd/body scale/1,
+ .cmd/width/\textwidth,
+ .zcmd/title text style//,
+ .zcmd/body text style//,
+ .cmd/action//
+}
+
+\newsavebox{\boxbody}
+\newenvironment{collectbody}[1][]{%
+ \skvusekeys[.prefix=KV,.family=collectbody]{#1}%
+ \ifx\mptitle\@empty\else\skvafterfi
+ \begin{center}%
+ \scalebox{\mptitlescale}{\mptitletextstyle\mptitle}%
+ \end{center}%
+ \fi
+ \begin{lrbox}{\boxbody}%
+ \begin{minipage}{\mpwidth}%
+ \mpbodytextstyle\mpaction
+}{%
+ \end{minipage}%
+ \end{lrbox}%
+ \scalebox{\mpbodyscale}{\usebox{\boxbody}}%
+}
+
+
+%%+++++++++++++++++++++ Changing the key parser ++++++++++++++++++++%%
+
+\setupskeyval{key parser={;}}
+\AfterDefineKeys{\setupskeyval{keyparser={,}}}
+\skvdefinekeys*[SKVT]{example}[exm@]{%
+ .zbool/put frame/true;
+ .cmd/shadecolor/green;
+ .ord/framesize/.5pt/\def\currfboxrule{#1};
+ .choice/align/center/{%
+ center.do=\def\curralign##1{\hfil##1\hfil},
+ right.do=\def\curralign##1{\hfill##1},
+ left.do=\def\curralign##1{##1\hfill},
+ justified.do=\let\curralign\@iden
+ };
+}
+%\setupskeyval{keyparser={,}}
+
+%%++++++++++++++++++++++++++ Options section ++++++++++++++++++++++%%
+
+\def\skvtp@unknownoptions{}
+
+\skvunknownoptionhandler[SKVT]<abrtext,shadowbox,citation,passoptions>{%
+ \edef\skvtp@unknownoptions{%
+ \skvtp@unknownoptions\ifx\skvtp@unknownoptions\@empty\else,\fi
+ #3%
+ }%
+ \AtEndDocument{%
+ \ifx\skvtp@unknownoptions\@empty\else
+ \PackageWarningNoLine{skeyval-testpkg}
+ {Unknown keys: \skvtp@unknownoptions}%
+ \fi
+ }%
+}
+\skvexecuteoptions[SKVT]<abrtext>{align=.expanded{\alignval},
+ text style=.expand once{\stextstyle},author,show author}
+
+\skvprocessoptions*+[SKVT]<abrtext,shadowbox,citation,passoptions>\relax
+%\skvrestrictedprocessoptions*+[SKVT]<abrtext,shadowbox,citation,passoptions>\relax
+
+\endinput
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf
new file mode 100644
index 00000000000..320b74097e2
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex
new file mode 100644
index 00000000000..c29448d04b5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-view-pokayoke1.tex
@@ -0,0 +1,96 @@
+\documentclass{skeyval-testclass}
+\usepackage[xcolor-options=dvipsnames]{skeyval-view}
+
+\makeatletter
+
+\setupviewkeys{length of default=30}
+
+\skvdefinekeys[KV]{fam1}[vhp@]{%
+ .ord/keya/default-a,
+ .cmd/keyb,
+ .zcmd/key c/\def\cmdc##1{##1}/
+ \edef\y{\detokenize\expandafter{\vhp@keyc}}\def\x##1{#1*key c*##1},
+ .choice/keyd/center/
+ {center.do=\def\x##1{#1*##1},left.do={\def\ans{#1}},right},
+ .bool/show shadow/true,
+ .zbool/show center/true/\edef\cmd{\ifvhp@showcenter Yes\else No\fi},
+ .ord/keye,
+ .cmd/keyf,
+}
+%\show\y
+%\skvshowcs{KV@fam1@show center}
+%\show\cmd
+
+% Define some keys:
+\directkeys*{
+ .prefix=KV,
+ .family=fam2,
+ .holder prefix=hp@,
+ .initialize keys after define,
+ .define keys={%
+ .ord/keya,
+ .ord/galaxy/Messier 51a/\def\constellation{Canes Venatici},
+ .choice/planet/Earth/{Earth.do=\def\x##1{#1*##1},Mars,Jupiter},
+ .bool/space travel/true,
+ .cmd/astronaut/Yuri Gagarin/
+ \edef\x{\ifx\hp@astronaut\@empty Neil Armstrong\else\hp@astronaut\fi},
+ .ord/space observatory/Hubble Space Telescope/
+ \def\father{Lyman Spitzer~(1914--1997)},
+ },
+}
+
+\makeatother
+
+\begin{document}
+
+\title{The \texttt{\textcolor{blue}{skeyval-view}} Package\\[.25ex]
+ Version 1.1\\[1ex]
+ \textsf{Test document}}
+\author{Ahmed Musa}
+\maketitle
+
+\skvviewkeys{%
+ .show={
+ family=fam1,
+ color=blue
+ },
+ .show={
+ families={fam1,fam2},
+ only those with default=true,
+ write to file=\jobname.skvv,
+ show labels=true,
+ show wlabels=true,
+ },
+ .show={
+ family=fam1,
+ only those with default=[none],
+ show labels=true,
+ color=cyan,
+ },
+ .show={
+ families={fam1,fam2},
+ only those without default=true,
+ color=purple,
+ },
+ .show={
+ family=fam2,
+ columns={prefix,family,key type,default},
+ color=teal
+ },
+ .show={
+ only those in family=fam2,
+ columns={family,type,default}
+ },
+ .show={
+ only those in families={fam1,fam2},
+ columns={prefix,family,type,default},
+ color=magenta
+ }
+}
+
+\newpage
+Find more information about the \textcolor{red}{\texttt{show shadow}} option on page~\pageref{KV/fam1/show shadow}.
+
+\end{document}
+
+% End of file skeyval-view-pokayoke1.tex \ No newline at end of file
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty
new file mode 100644
index 00000000000..1f65a1d0100
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-bc.sty
@@ -0,0 +1,3184 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-bc.sty', version 0.73 of skeyval package, %
+% January 2011. This file is provided only for backward compatibility %
+% (bc) of the package. Beginning from version 1.0, September 2012, the %
+% package has changed radically. %
+% %
+% 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). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\begingroup
+\catcode064 11% @
+\catcode123 01% {
+\catcode125 02% }
+\def\SKV@tempa{\endgroup
+ \edef\SKV@restorecodes{%
+ \catcode035 \the\catcode035% #
+ \catcode064 \the\catcode064% @
+ \catcode123 \the\catcode123% {
+ \catcode125 \the\catcode125% }
+ \catcode061 \the\catcode061% =
+ }%
+}
+\SKV@tempa
+\catcode035 06% #
+\catcode061 12% =
+\catcode064 11% @
+\catcode123 01% {
+\catcode125 02% }
+\def\SKV@setcode#1#2{%
+ \edef\SKV@restorecodes{%
+ \SKV@restorecodes
+ \catcode#1 \the\catcode#1\relax
+ }%
+ \catcode#1 #2\relax
+}
+\AtEndOfPackage{%
+ \SKV@AfterPackageEnd{%
+ \SKV@restorecodes
+ \SKV@Undef!{\SKV@setcode\SKV@restorecodes}%
+ }%
+}
+\SKV@setcode{010}{12}% ^^J
+\SKV@setcode{032}{10}% SP
+\SKV@setcode{033}{12}% !
+\SKV@setcode{036}{03}% $
+\SKV@setcode{038}{03}% &
+\SKV@setcode{040}{12}% (
+\SKV@setcode{041}{12}% )
+\SKV@setcode{042}{12}% *
+\SKV@setcode{043}{12}% +
+\SKV@setcode{044}{12}% ,
+\SKV@setcode{045}{12}% -
+\SKV@setcode{047}{12}% /
+\SKV@setcode{058}{12}% :
+\SKV@setcode{059}{12}% ;
+\SKV@setcode{060}{12}% >
+\SKV@setcode{062}{12}% <
+\SKV@setcode{063}{12}% ?
+\SKV@setcode{091}{12}% [
+\SKV@setcode{093}{12}% ]
+\SKV@setcode{096}{12}% `
+\SKV@setcode{126}{13}% ~
+\def\SKV@rcsid$#1: #2 #3 #4 #5${#4 v#3}
+\ProvidesPackage{skeyval}[%
+ \SKV@rcsid $Id: skeyval.sty,v 0.72 2010/05/21 09:00:00 Ahmed Musa $
+ Extensions to the xkeyval parser (AM)
+]
+\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+\ifnum0=0%
+ \ifx\eTeXversion\SKV@undefined1\else\ifnum\eTeXversion<\tw@1\fi\fi
+\else
+ \PackageError{skeyval}{eTeX not loaded or old version}%
+ {This package requires eTeX version 2 or later.}%
+ \endinput
+\fi
+\newtoks\SKV@toks
+\newcount\SKV@depth
+\protected\def\@nil{\@nil}
+\def\@nnil{\@nil}
+\def\@space{ }
+\long\def\@firstofthree#1#2#3{#1}
+\long\def\@secondofthree#1#2#3{#2}
+\long\def\@thirdofthree#1#2#3{#3}
+\long\def\@gobblethree#1#2#3{}
+\long\def\SKV@car#1#2\@nil{#1}
+\long\def\SKV@cdr#1#2\@nil{#2}
+\long\def\SKV@carcube#1#2#3#4\@nil{#1#2#3}
+\def\SKV@threexp{\expandafter\expandafter\expandafter}
+\def\SKV@aftercs#1#2{\expandafter#1\csname#2\endcsname}
+\def\SKV@xaftercs#1#2{\SKV@threexp#1\csname#2\endcsname}
+\SKV@aftercs\let{SKV@1of1}\@firstofone
+\SKV@aftercs\let{SKV@1of2}\@firstoftwo
+\SKV@aftercs\let{SKV@2of2}\@secondoftwo
+\SKV@aftercs\let{SKV@1of3}\@firstofthree
+\SKV@aftercs\let{SKV@2of3}\@secondofthree
+\SKV@aftercs\let{SKV@3of3}\@thirdofthree
+\def\SKV@ifx#1#2{\@nameuse{SKV@\ifx#1#21\else2\fi of2}}
+\def\SKV@unifx#1#2{\@nameuse{SKV@\ifx#1#22\else1\fi of2}}
+\def\SKV@csifx#1#2{\begingroup\expandafter\endgroup\expandafter
+ \SKV@ifx\csname#1\endcsname#2}
+\def\SKV@uncsifx#1#2{\begingroup\expandafter\endgroup\expandafter
+ \SKV@unifx\csname#1\endcsname#2}
+\def\SKV@ifxcs#1#2{\begingroup\expandafter\endgroup\expandafter
+ \SKV@ifx\expandafter#1\csname#2\endcsname}
+\def\SKV@unifxcs#1#2{\begingroup\expandafter\endgroup\expandafter
+ \SKV@unifx\expandafter#1\csname#2\endcsname}
+\def\SKV@ifdefined#1{\@nameuse{SKV@\ifdefined#11\else2\fi of2}}
+\def\SKV@oifdefined#1{\@nameuse{SKV@\expandafter\SKV@ifdefined#1{1}{2}of2}}
+\def\SKV@unifdefined#1{\@nameuse{SKV@\SKV@ifdefined{#1}{2}{1}of2}}
+\def\SKV@ifcsname#1{\@nameuse{SKV@\ifcsname#1\endcsname1\else2\fi of2}}
+\def\SKV@unifcsname#1{\@nameuse{SKV@\SKV@ifcsname{#1}{2}{1}of2}}
+\def\SKV@ifnum#1#2#3{\@nameuse{SKV@\ifnum#1#2#3 1\else2\fi of2}}
+\protected\def\SKV@AtEndAfterPackageEnd#1{\AtEndOfPackage
+ {\SKV@AfterPackageEnd{#1}}}
+\begingroup
+\def\SKV@tempa{%
+ \def\SKV@nodocerr{%
+ \PackageError{skeyval}{'skeyval' package loaded before
+ \string\documentclass}{Load skeyval package after
+ \string\documentclass.}%
+ \endinput
+ }%
+ \def\SKV@tempb##1\@nil,{}%
+ \def\SKV@tempa##1,{%
+ \def\@currname{##1}%
+ \SKV@ifx\SKV@documentclass\SKV@undefined{%
+ \SKV@ifx\@currname\@nnil{}{%
+ \filename@parse\@currname
+ \SKV@unifx\filename@ext\@clsextension{}{%
+ \SKV@unifcsname{opt@\filename@area\filename@base.%
+ \filename@ext}{}{%
+ \edef\SKV@documentclass{\filename@area%
+ \filename@base.\filename@ext}%
+ }%
+ }%
+ \SKV@tempa
+ }%
+ }{%
+ \let\SKV@tempa\SKV@tempb\SKV@tempa
+ }%
+ }%
+ \SKV@ifx\@filelist\relax\SKV@nodocerr{%
+ \SKV@ifx\@filelist\@gobble\SKV@nodocerr{%
+ \expandafter\SKV@tempa\@filelist,\@nil,%
+ }%
+ }%
+ \SKV@ifx\SKV@documentclass\SKV@undefined\SKV@nodocerr\relax
+}
+\SKV@tempa\endgroup
+\def\SKV@notdefinable{%
+ \PackageError{skeyval}%
+ {Command '\@backslashchar\resvd@a' not definable,
+ \MessageBreak or name '\@backslashchar\@qend...' illegal}%
+ {Command '\@backslashchar\resvd@a' already defined.}%
+}
+\def\SKV@ifdefinable#1{%
+ \begingroup
+ \escapechar92\relax
+ \xdef\resvd@a{\expandafter\@gobble\string#1}%
+ \edef\resvd@b{\expandafter\SKV@car\string#1\@nil}%
+ \SKV@ifx\resvd@b\@backslashchar{}{%
+ \PackageError{skeyval}{Backslash required}{Backslash
+ required in argument of '\string\SKV@ifdefinable'.}%
+ }%
+ \SKV@ifdefined#1{%
+ \SKV@ifx{#1}\relax{\aftergroup\@firstofone}%
+ {\aftergroup\SKV@notdefinable}%
+ }{%
+ \edef\resvd@b{\unexpanded\expandafter{\csname end\resvd@a\endcsname}}%
+ \expandafter\SKV@ifx\resvd@b\relax{%
+ \SKV@ifx\resvd@a\@qrelax{\aftergroup\SKV@notdefinable}%
+ {\aftergroup\@firstofone}
+ }{\aftergroup\SKV@notdefinable}%
+ }%
+ \endgroup
+}
+\def\SKV@csifdefinable#1{\begingroup\expandafter\endgroup
+ \expandafter\SKV@ifdefinable\csname#1\endcsname}
+\newcommand*\@ifpackagecurrent[2]{%
+ \@nameuse{SKV@\ifnum\SKV@threexp\@parse@version
+ \csname ver@#1.\@pkgextension\endcsname//00\@nil
+ <\expandafter\@parse@version#2//00\@nil2\else1\fi of2}%
+}
+\newcommand*\@ifpackagenotcurrent[2]{%
+ \@nameuse{SKV@\@ifpackagecurrent{#1}{#2}{2}{1}of2}}
+\newcommand*\@ifloadedandcurrent[2]{%
+ \begingroup
+ \@ifpackageloaded{#1}{%
+ \@ifpackagecurrent{#1}{#2}{\aftergroup\@firstofthree}{%
+ \aftergroup\@secondofthree}}{\aftergroup\@thirdofthree}%
+ \endgroup
+}
+\@ifloadedandcurrent{xkeyval}{2008/08/13}{}{%
+ \PackageError{skeyval}%
+ {Your loaded version of xkeyval package is not current}%
+ {You need version 2.6a (or higher) of xkeyval package.}%
+ \endinput
+}{\RequirePackage{xkeyval}[2008/08/13]}
+\newcommand*\SKV@ifdefinable@n[1]{%
+ \XKV@sp@deflist\SKV@tempa{#1}%
+ \XKV@for@o\SKV@tempa\SKV@tempa{%
+ \edef\resvd@a{\SKV@threexp\SKV@car
+ \expandafter\string\SKV@tempa\@nil}%
+ \SKV@unifx\resvd@a\@backslashchar{}{%
+ \PackageError{skeyval}{Backslash not allowed}{Backslash not
+ allowed in argument of '\string\SKV@ifdefinable@n'.}%
+ }%
+ \SKV@csifdefinable\SKV@tempa\relax
+ }%
+}
+\SKV@ifdefinable@n{SKV@def,SKV@d@f,SKV@pdef,SKV@pd@f}
+\protected\def\SKV@def{\@star@or@long\SKV@d@f}
+\def\SKV@d@f#1{\SKV@ifdefinable#1{\l@ngrel@x\def#1}}
+\protected\def\SKV@pdef{\@star@or@long\SKV@pd@f}
+\def\SKV@pd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\def#1}}
+\SKV@pdef*\SKV@gdef{\@star@or@long\SKV@gd@f}
+\SKV@def*\SKV@gd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\gdef#1}}
+\SKV@pdef*\SKV@edef{\@star@or@long\SKV@ed@f}
+\SKV@def*\SKV@ed@f#1{\SKV@ifdefinable#1{\l@ngrel@x\edef#1}}
+\SKV@pdef*\SKV@pgdef{\@star@or@long\SKV@pgd@f}
+\SKV@def*\SKV@pgd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\gdef#1}}
+\SKV@pdef*\SKV@pedef{\@star@or@long\SKV@ped@f}
+\SKV@def*\SKV@ped@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\edef#1}}
+\SKV@pdef*\SKV@pxdef{\@star@or@long\SKV@pxd@f}
+\SKV@def*\SKV@pxd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\xdef#1}}
+\SKV@pdef*\SKV@redef{\@star@or@long\SKV@red@f}
+\SKV@def*\SKV@red@f#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@unifdefined{#1}{}{%
+ \SKV@ifx{#1}\relax{}{%
+ \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
+ }%
+ }%
+ \l@ngrel@x\def#1%
+}
+\SKV@pdef*\SKV@csredef{\SKV@aftercs\SKV@redef}
+\SKV@pdef*\SKV@predef{\@star@or@long\SKV@pred@f}
+\SKV@def*\SKV@pred@f#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@unifdefined{#1}{}{%
+ \SKV@ifx{#1}\relax{}{%
+ \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
+ }%
+ }%
+ \l@ngrel@x\protected\def#1%
+}
+\SKV@pdef*\SKV@cspredef{\SKV@aftercs\SKV@predef}
+\SKV@def*\SKV@vbmsg#1#2{%
+ \begingroup
+ \def\@i{info}\def\@ii{warn}\def\@iii{#1}%
+ \@nameuse{SKV@\ifSKV@verbose1\else2\fi of2}%
+ {\SKV@ifx\@i\@iii
+ {\SKV@info{#2}}%
+ {\SKV@ifx\@ii\@iii{\SKV@warn{#2}}{}}%
+ }{}%
+ \endgroup
+}
+\define@boolkeys[KV]{skeyval@i}[SKV@]{st,pl,cl,rt,
+ lt,sw,sk,loc,uv}[true]
+\setkeys[KV]{skeyval@i}{st,pl,cl,rt,lt,sw,sk,loc,uv}
+\define@boolkey+[KV]{skeyval}[SKV@]{verbose}[true]{}{%
+ \SKV@inputerr{#1}{verbose}%
+}
+\setkeys[KV]{skeyval}{verbose=false}
+\SKV@pdef\SKV@info#1{\PackageInfo{skeyval}{#1\@gobble}}
+\SKV@pdef\SKV@warn#1{\PackageWarningNoLine{skeyval}{#1}}
+\SKV@pdef\SKV@err#1#2{\PackageError{skeyval}{#1}{#2}}
+\SKV@def*\SKV@MB{\MessageBreak}
+\SKV@pdef\SKV@afterfi#1\fi{\fi#1}
+\SKV@pdef\SKV@afterelsefi#1\else#2\fi{\fi#1}
+\SKV@pdef\SKV@afterfifi#1\fi#2\fi{\fi#2\fi#1}
+\SKV@def*\SKV@badargerr#1#2{%
+ \SKV@err{Invalid #2 argument for command '\@backslashchar#1'}%
+ {Bad #2 argument for command '\@backslashchar#1'.\SKV@MB
+ You need to look again at user instruction\SKV@MB
+ for command '\@backslashchar#1'.}%
+}
+\SKV@def*\SKV@state#1#2#3{%
+ \ifcase#1\relax
+ \def\SKV@ste{XKV@prefix,XKV@fams,XKV@tkey,XKV@na,ifXKV@st,%
+ ifXKV@pl,ifXKV@knf,CurrentOption,ifSKV@sk}%
+ \SKV@ifempty{#3}{\advance\XKV@depth\@ne}{}%
+ \or
+ \def\SKV@ste{ifSKV@st,ifSKV@pl,ifSKV@cl,ifSKV@rt,ifSKV@lt}%
+ \SKV@ifempty{#3}{\advance\SKV@depth\@ne}{}%
+ \else
+ \SKV@err{Unknown state identifier '#1'}%
+ {I expected '\string#1' to be number 0 or 1.}%
+ \fi
+ \XKV@for@o\SKV@ste\SKV@ste{%
+ \SKV@aftercs\let{\SKV@ste#2\SKV@aftercs}{\SKV@ste#3}%
+ }%
+ \ifcase#1\relax
+ \SKV@ifempty{#2}{\advance\XKV@depth\m@ne}{}%
+ \or
+ \SKV@ifempty{#2}{\advance\SKV@depth\m@ne}{}%
+ \fi
+}
+\SKV@def*\XKV@savstate{\SKV@state{0}{@\romannumeral\XKV@depth}{}}
+\SKV@def*\XKV@resstate{\SKV@state{0}{}{@\romannumeral\XKV@depth}}
+\SKV@def*\SKV@savstate{\SKV@state{1}{@\romannumeral\SKV@depth}{}}
+\SKV@def*\SKV@resstate{\SKV@state{1}{}{@\romannumeral\SKV@depth}}
+\def\XKV@srstate#1#2{\SKV@state{0}{#1}{#2}}
+\SKV@def*\SKV@scantoksa{\SKV@savstate\SKV@testoptf\SKV@sc@ntoksa}
+\SKV@def\SKV@sc@ntoksa[#1]#2{%
+ \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
+ \SKV@for[#1]{#2}\SKV@resvda{%
+ \ifSKV@pl
+ \SKV@ifcsdef\SKV@resvda{}{%
+ \SKV@err{Command '\SKV@csexpox\SKV@resvda' undefined}%
+ {I can't scan contents of undefined command
+ '\SKV@csexpox\SKV@resvda'}%
+ }%
+ \SKV@expnext\SKV@ensurenoscape\SKV@resvda
+ \expandafter\let\expandafter\SKV@resvdb%
+ \csname\SKV@resvda\endcsname
+ \else
+ \expandafter\SKV@ifdef\SKV@resvda{}{%
+ \SKV@err{Command '\SKV@expox\SKV@resvda' undefined}%
+ {I can't scan contents of undefined command
+ '\SKV@expox\SKV@resvda'}%
+ }%
+ \SKV@expnext\SKV@ensurescape\SKV@resvda
+ \expandafter\let\expandafter\SKV@resvdb\SKV@resvda
+ \fi
+ \SKV@noexpparse\SKV@resvdb
+ \begingroup
+ \edef\SKV@resvdb##1##2{##1{##2{\SKV@expox\SKV@resvdb}}}%
+ \everyeof{\noexpand}\endlinechar\m@ne\makeatletter
+ \SKV@resvdb{\xdef\SKV@resvdb}{\scantokens\expandafter}%
+ \endgroup
+ \ifSKV@pl
+ \gl@l@x\SKV@aftercs\let\SKV@resvda\SKV@resvdb
+ \else
+ \gl@l@x\expandafter\let\SKV@resvda\SKV@resvdb
+ \fi
+ }%
+ \SKV@resstate
+}
+\SKV@def*\SKV@emptycmds{\SKV@savstate\SKV@testoptf\SKV@em@tycmds}
+\SKV@def\SKV@em@tycmds[#1]#2{%
+ \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
+ \SKV@for[#1]{#2}\SKV@resvda{%
+ \ifSKV@pl
+ \SKV@expnext\SKV@ensurenoscape\SKV@resvda
+ \gl@l@x\SKV@aftercs\let\SKV@resvda\@empty
+ \else
+ \SKV@expnext\SKV@ensurescape\SKV@resvda
+ \gl@l@x\expandafter\let\SKV@resvda\@empty
+ \fi
+ }%
+ \SKV@resstate
+}
+\SKV@pdef*\SKV@csdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\def}}
+\SKV@pdef*\SKV@csgdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\gdef}}
+\SKV@pdef*\SKV@csedef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\edef}}
+\SKV@pdef*\SKV@csxdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\xdef}}
+\SKV@def*\SKV@newcs#1#2{%
+ \ifSKV@st\let\l@ngrel@x\relax\else\let\l@ngrel@x\long\fi
+ \ifSKV@pl
+ \let\SKV@next\SKV@n@wcs
+ \else
+ \def\SKV@next{\l@ngrel@x\SKV@aftercs}%
+ \fi
+ \SKV@resstate\SKV@next#1{#2}%
+}
+\SKV@def*\SKV@n@wcs#1#2{%
+ \SKV@ifcsname{#2}%
+ {\SKV@csifx{#2}\relax{}{\def\resvd@a{#2}\SKV@notdefinable}}%
+ {\l@ngrel@x\SKV@aftercs{#1}{#2}}%
+}
+\SKV@def*\SKV@csuse#1{\SKV@ifcsname{#1}{\@nameuse{#1}}{}}
+\SKV@pdef\SKV@expargs#1#2#3#4\@nil{%
+ \begingroup
+ \protected@edef\SKV@tempa{\endgroup
+ \ifcase#1\relax
+ \unexpanded{#2}{#3}%
+ \or
+ \unexpanded{#2#3}{#4}%
+ \or
+ \unexpanded{#2}{#3}{#4}%
+ \or
+ \unexpanded{#2}#3\unexpanded{#4}%
+ \else
+ \SKV@err{Unknown expansion type '\string#1' for
+ \string\SKV@expargs}{I expected your first
+ argument '\string#1' to be between 0 and 3.}%
+ \fi
+ }%
+ \SKV@tempa
+}
+\SKV@def*\SKV@findescape#1{%
+ \begingroup\escapechar92\relax
+ \edef\resvd@a{\expandafter\SKV@car\string#1\@nil}%
+ \expandafter\aftergroup\csname SKV@%
+ \SKV@ifx\resvd@a\@backslashchar{1}{2}of2\endcsname
+ \endgroup
+}
+\SKV@def*\SKV@ensurescape#1{%
+ \SKV@findescape{#1}{}%
+ {\SKV@err{Backslash required in '\string#1'}%
+ {I expected a backslash to be the leading\SKV@MB
+ character in your argument '\string#1'.}}%
+}
+\SKV@def*\SKV@ensurenoscape#1{%
+ \SKV@findescape{#1}%
+ {\SKV@err{Backslash not allowed in '\string#1'}%
+ {I didn't expect a backslash to be the leading\SKV@MB
+ character in your argument '\string#1'.}}{}%
+}
+\SKV@pdef\SKV@ifnextchar#1#2#3{%
+ \let\SKV@nxc#1\def\SKV@nxa{#2}\def\SKV@nxb{#3}%
+ \futurelet\@temptoks\SKV@ifnextch@r
+}
+\SKV@def*\SKV@ifnextch@r{%
+ \ifx\@temptoks\SKV@nxc\let\SKV@nxb\SKV@nxa\fi\SKV@nxb
+}
+\SKV@pdef\SKV@ifchar#1#2#3{%
+ \SKV@ifnextchar#1{\begingroup
+ \def\SKV@tempa#1{\endgroup#2}\SKV@tempa}{#3}%
+}
+\SKV@pdef*\SKV@ifstar{\SKV@ifchar{*}}
+\SKV@pdef*\SKV@ifplus{\SKV@ifchar{+}}
+\SKV@pdef*\SKV@ifask{\SKV@ifchar{?}}
+\SKV@pdef*\SKV@ifclam{\SKV@ifchar{!}}
+\SKV@pdef*\SKV@ifright{\SKV@ifchar{>}}
+\SKV@pdef*\SKV@ifleft{\SKV@ifchar{<}}
+\SKV@pdef*\SKV@if@brack#1#2{\SKV@ifnextchar[{#1}{#2}}
+\SKV@pdef*\SKV@if@paren#1#2{\SKV@ifnextchar({#1}{#2}}
+\SKV@pdef*\SKV@if@left#1#2{\SKV@ifnextchar<{#1}{#2}}
+\SKV@pdef*\SKV@testopt#1#2{\SKV@if@brack{#1}{#1[{#2}]}}
+\SKV@pdef*\SKV@testopta#1{\SKV@t@stopta{\SKV@t@st@pta{#1}}}
+\SKV@pdef*\SKV@t@stopta#1{\SKV@ifstar{\SKV@sttrue#1}{\SKV@stfalse#1}}
+\SKV@pdef*\SKV@t@st@pta#1{\SKV@ifplus{\SKV@pltrue#1}{\SKV@plfalse#1}}
+\SKV@pdef*\SKV@t@st@p@a#1{\SKV@ifclam{\SKV@cltrue#1}{\SKV@clfalse#1}}
+\SKV@pdef*\SKV@testoptb#1{\SKV@t@stopta{\SKV@t@st@pta{\SKV@t@st@p@a{#1}}}}
+\SKV@pdef*\SKV@t@stoptb#1{\SKV@t@stopta{\SKV@t@st@pta{#1}}}
+\SKV@pdef*\SKV@testoptc#1{\SKV@t@st@pta{\SKV@t@st@p@a{#1}}}
+\SKV@pdef*\SKV@testoptd#1{\SKV@t@stopta{\SKV@testopt#1{,}}}
+\SKV@pdef*\SKV@testopte#1{\SKV@testoptb{\SKV@testopt#1{,}}}
+\SKV@pdef*\SKV@t@stopte#1{\SKV@t@stoptb{\SKV@testopt#1{,}}}
+\SKV@pdef*\SKV@testoptf#1{\SKV@testoptc{\SKV@testopt#1{,}}}
+\SKV@pdef*\SKV@testoptg#1{\SKV@ifright{\SKV@rttrue#1}{\SKV@rtfalse#1}}
+\SKV@pdef*\SKV@t@stoptg#1{\SKV@ifleft{\SKV@lttrue#1}{\SKV@ltfalse#1}}
+\SKV@pdef*\SKV@testopth#1#2{\SKV@if@left{#1}{#1<{#2}>}}
+\SKV@pdef*\SKV@testoptp#1#2{\SKV@if@paren{#1}{#1({#2})}}
+\SKV@def*\SKV@Test@pt#1{\@nameuse{SKV@\SKV@ifempty{#1}{1}{2}of2}}
+\SKV@def*\SKV@IfBrack#1#2#3{\SKV@IfBr@ck#1&[&{#2}{#3{#1}}}
+\SKV@def*\SKV@IfBr@ck#1[#2&#3#{\SKV@Test@pt{#1#2}}
+\SKV@def*\SKV@TestOpt#1#2#3{\SKV@IfBr@ck#1&[&{#2#1}{#2[{#3}]{#1}}}
+\SKV@def*\SKV@IfStar#1#2#3{\SKV@IfSt@r#1&*&{#2}{#3{#1}}}
+\SKV@def*\SKV@IfSt@r#1*#2&#3#{\SKV@Test@pt{#1#2}}
+\SKV@def*\SKV@IfPlus#1#2#3{\SKV@IfPl@s#1&+&{#2}{#3{#1}}}
+\SKV@def*\SKV@IfPl@s#1+#2&#3#{\SKV@Test@pt{#1#2}}
+\SKV@def*\SKV@IfAsk#1#2#3{\SKV@IfA@k#1&?&{#2}{#3{#1}}}
+\SKV@def*\SKV@IfA@k#1?#2&#3#{\SKV@Test@pt{#1#2}}
+\SKV@def*\SKV@csalloc#1{\@nameuse{new#1\SKV@aftercs}}
+\SKV@pdef*\csnewif{\SKV@csalloc{if}}
+\SKV@pdef*\csnewtoks{\SKV@csalloc{toks}}
+\SKV@pdef*\csnewcount{\SKV@csalloc{count}}
+\SKV@pdef*\csnewdimen{\SKV@csalloc{dimen}}
+\SKV@pdef*\csnewbox{\SKV@csalloc{box}}
+\SKV@pdef*\csnewwrite{\SKV@csalloc{write}}
+\SKV@pdef*\csnewread{\SKV@csalloc{read}}
+\SKV@pdef*\NewWrites{\SKV@swtrue\SKV@testopt\SKV@NewWrites{}}
+\SKV@pdef*\DefWrites{\SKV@swfalse\SKV@testopt\SKV@NewWrites{}}
+\SKV@def*\SKV@NewWrites[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Write stream '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewwrite{#1\SKV@tempa}%
+ }%
+}
+\SKV@pdef*\NewReads{\SKV@swtrue\SKV@testopt\SKV@NewReads{}}
+\SKV@pdef*\DefReads{\SKV@swfalse\SKV@testopt\SKV@NewReads{}}
+\SKV@def*\SKV@NewReads[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Read stream '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewread{#1\SKV@tempa}%
+ }%
+}
+\SKV@pdef*\NewIfs{\SKV@swtrue\SKV@testopt\SKV@NewIfs{}}
+\SKV@pdef*\DefIfs{\SKV@swfalse\SKV@testopt\SKV@NewIfs{}}
+\SKV@def*\SKV@NewIfs[#1]#2{\SKV@testopt{\SKV@N@wIfs[#1]{#2}}{false}}
+\SKV@def*\SKV@N@wIfs[#1]#2[#3]{%
+ \ifSKV@sw
+ \SKV@getswstate\NewIfs{#3}%
+ \else
+ \SKV@getswstate\DefIfs{#3}%
+ \fi
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \begingroup
+ \SKV@oifstrequal{\SKV@tempa}{x}{\SKV@swnameerr{x}}%
+ {\SKV@oifstrequal{\SKV@tempa}{on}{\SKV@swnameerr{on}}%
+ {\SKV@oifstrequal{\SKV@tempa}{off}{\SKV@swnameerr{off}}%
+ {\SKV@oifstrequal{\SKV@tempa}{tog}{\SKV@swnameerr{tog}}%
+ {\SKV@oifstrequal{\SKV@tempa}{switch}{\SKV@swnameerr{switch}}%
+ {}}}}}\endgroup
+ \ifSKV@sw
+ \SKV@csifdefinable{if#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{if#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Boolean '\@backslashchar
+ if#1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \SKV@aftercs\SKV@N@wIf@{if#1\SKV@tempa}%
+ \@nameuse{#1\SKV@tempa\SKV@swval}%
+ }%
+}
+\SKV@def*\SKV@N@wIf@#1{%
+ \@tempcnta\escapechar\escapechar\m@ne
+ \let#1\iffalse
+ \SKV@If#1\iftrue
+ \SKV@If#1\iffalse
+ \let\ifon\iftrue
+ \let\ifoff\iffalse
+ \SKV@If#1\ifon
+ \SKV@If#1\ifoff
+ \escapechar\@tempcnta
+}
+\def\SKV@If#1#2{%
+ \SKV@aftercs\def{\expandafter\@gobbletwo\string#1%
+ \expandafter\@gobbletwo\string#2}{\let#1#2}%
+}
+\SKV@pdef*\NewBooleans{\SKV@swtrue\SKV@testopt\SKV@NewBooleans{}}
+\SKV@pdef*\DefBooleans{\SKV@swfalse\SKV@testopt\SKV@NewBooleans{}}
+\SKV@def*\SKV@NewBooleans[#1]#2{%
+ \SKV@testopt{\SKV@B@oleans[#1]{#2}}{false}}
+\SKV@def*\SKV@B@oleans[#1]#2[#3]{%
+ \ifSKV@sw
+ \SKV@getswstate\NewBooleans{#3}%
+ \else
+ \SKV@getswstate\DefBooleans{#3}%
+ \fi
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \SKV@oifstrequal{\SKV@tempa}{tog}{%
+ \SKV@err{'tog' not allowed as a boolean name}\@ehc
+ }{%
+ \SKV@oifstrequal{\SKV@tempa}{switch}{%
+ \SKV@err{'switch' not allowed as a boolean name}\@ehc
+ }{}%
+ }%
+ \SKV@ifstrnotequal{#1\SKV@tempa}{x}{}{%
+ \SKV@err{'\string\ifx' is a TeX primitive}%
+ {Why do you want to redefine '\string\ifx'? This is dangerous.}%
+ }%
+ \ifSKV@sw
+ \SKV@csifdefinable{if#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{if#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Switch '\@backslashchar if#1\SKV@tempa'
+ redefined\on@line}%
+ }%
+ \fi
+ \csnewif{if#1\SKV@tempa}%
+ \@nameuse{#1\SKV@tempa\SKV@swval}%
+ }%
+}
+\SKV@pdef*\NewTogs{\SKV@swtrue\SKV@testopt\SKV@NewTogs{}}
+\SKV@pdef*\DefTogs{\SKV@swfalse\SKV@testopt\SKV@NewTogs{}}
+\SKV@def*\SKV@NewTogs[#1]#2{\SKV@testopt{\SKV@NewT@gs[#1]{#2}}{false}}
+\SKV@def*\SKV@NewT@gs[#1]#2[#3]{%
+ \ifSKV@sw
+ \SKV@getswstate\NewTogs{#3}%
+ \else
+ \SKV@getswstate\DefTogs{#3}%
+ \fi
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \edef\SKV@tempa{#1\SKV@tempa}%
+ \ifSKV@sw
+ \SKV@expnext\newtog\SKV@tempa
+ \else
+ \SKV@expnext\deftog\SKV@tempa
+ \fi
+ \SKV@expargs{0}{\@nameuse{tog\SKV@swval}}\SKV@tempa\@nil
+ }%
+}
+\SKV@pdef*\NewToks{\SKV@swtrue\SKV@testopt\SKV@NewToks{}}
+\SKV@pdef*\DefToks{\SKV@swfalse\SKV@testopt\SKV@NewToks{}}
+\SKV@def*\SKV@NewToks[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Token register '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewtoks{#1\SKV@tempa}%
+ }%
+}
+\SKV@pdef*\NewCounts{\SKV@swtrue\SKV@testopt\SKV@NewCounts{}}
+\SKV@pdef*\DefCounts{\SKV@swfalse\SKV@testopt\SKV@NewCounts{}}
+\SKV@def*\SKV@NewCounts[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Counter register '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewcount{#1\SKV@tempa}%
+ }%
+}
+\SKV@pdef*\NewDimens{\SKV@swtrue\SKV@testopt\SKV@NewDimens{}}
+\SKV@pdef*\DefDimens{\SKV@swfalse\SKV@testopt\SKV@NewDimens{}}
+\SKV@def*\SKV@NewDimens[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Dimension register '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewdimen{#1\SKV@tempa}%
+ }%
+}
+\SKV@pdef*\NewBoxes{\SKV@swtrue\SKV@testopt\SKV@NewBoxes{}}
+\SKV@pdef*\DefBoxes{\SKV@swfalse\SKV@testopt\SKV@NewBoxes{}}
+\SKV@def*\SKV@NewBoxes[#1]#2{%
+ \SKV@for[,]{#2}\SKV@tempa{%
+ \SKV@expnext\SKV@ensurenoscape\SKV@tempa
+ \ifSKV@sw
+ \SKV@csifdefinable{#1\SKV@tempa}\relax
+ \else
+ \SKV@ifcsundef{#1\SKV@tempa}{}{%
+ \SKV@vbmsg{warn}{Box register '\@backslashchar
+ #1\SKV@tempa' redefined\on@line}%
+ }%
+ \fi
+ \csnewbox{#1\SKV@tempa}%
+ }%
+}
+\SKV@def\SKV@expnext#1#2{%
+ \SKV@ifblank{#1}{%
+ \SKV@badargerr{SKV@expnext}{first}%
+ }{%
+ \SKV@ifblank{#2}{%
+ \SKV@badargerr{SKV@expnext}{second}%
+ }{%
+ \ifcat$\detokenize\expandafter{\SKV@cdr#1\@nil}$%
+ \SKV@afterelsefi
+ \expandafter#1\expandafter{#2}%
+ \else
+ \SKV@afterfi
+ \SKV@badargerr{SKV@expnext}{first}%
+ \fi
+ }%
+ }%
+}
+\SKV@pdef*\SKV@ifnewcmd{\SKV@savstate\SKV@t@stopte\SKV@ifn@wcmd}
+\SKV@def*\SKV@ifn@wcmd[#1]#2{%
+ \ifSKV@st
+ \ifSKV@pl
+ \def\SKV@ndl{\SKV@for*[#1]#2}%
+ \else
+ \def\SKV@ndl{\SKV@tfor*#2}%
+ \fi
+ \else
+ \ifSKV@pl
+ \def\SKV@ndl{\SKV@for[#1]{#2}}%
+ \else
+ \def\SKV@ndl{\SKV@tfor{#2}}%
+ \fi
+ \fi
+ \SKV@ndl\SKV@ndl{%
+ \ifSKV@pl
+ \SKV@despacectt\SKV@ndl
+ \SKV@csifdefinable\SKV@ndl\relax
+ \else
+ \expandafter\SKV@ifdefinable\SKV@ndl\relax
+ \fi
+ }%
+ \SKV@resstate
+}
+\let\SKV@no\z@
+\SKV@pdef*\SKV@aftergroup{%
+ \SKV@ifstar{\SKV@aft@rgroup\@firstofone}%
+ {\SKV@aft@rgroup\unexpanded}%
+}
+\SKV@def\SKV@aft@rgroup#1#2{%
+ \edef\SKV@no{\the\numexpr\SKV@no+1}%
+ \SKV@aftercs\xdef{SKV@aft@rgr@up\SKV@no}{%
+ \SKV@csgundef{SKV@aft@rgr@up\SKV@no}%
+ #1{#2}%
+ }%
+ \SKV@aftercs\aftergroup{SKV@aft@rgr@up\SKV@no}%
+}
+\SKV@pdef*\SKV@afterassignment{%
+ \SKV@ifstar{\SKV@aft@rassignment\@firstofone}%
+ {\SKV@aft@rassignment\unexpanded}%
+}
+\SKV@def\SKV@aft@rassignment#1#2{%
+ \begingroup
+ \edef\SKV@no{\the\numexpr\SKV@no+1}%
+ \SKV@aftercs\xdef{SKV@aft@rassignm@nt\SKV@no}{%
+ \SKV@csgundef{SKV@aft@rassignm@nt\SKV@no}%
+ #1{#2}%
+ }%
+ \expandafter\endgroup\expandafter\afterassignment
+ \csname SKV@aft@rassignm@nt\SKV@no\endcsname
+}
+\SKV@def*\SKV@sp@def#1#2{%
+ \edef\@sp@def{\the\SKV@toks}%
+ \SKV@toks\expandafter{%
+ \romannumeral-`\q\SKV@sp@d@f\noexpand\noexpand#1& &}%
+ \edef#2{\the\SKV@toks}%
+ \SKV@toks\expandafter{\@sp@def}%
+ \SKV@undef\@sp@def
+}
+\SKV@def*\SKV@sp@d@f#1 &{\SKV@sp@d@f@#1&}
+\SKV@def*\SKV@sp@d@f@#1&#2{\romannumeral-`\q#1}
+\SKV@def*\SKV@expox#1{\unexpanded\expandafter{#1}}
+\SKV@def*\SKV@csexpox#1{\SKV@aftercs\SKV@expox{#1}}
+\SKV@def*\SKV@exptx#1{\unexpanded\SKV@threexp{#1}}
+\SKV@def*\SKV@csexptx#1{\SKV@aftercs\SKV@exptx{#1}}
+\SKV@def\SKV@noexpcs#1{\unexpanded\expandafter{\csname#1\endcsname}}
+\SKV@pdef*\SKV@undef#1{\let#1\SKV@undefined}
+\SKV@pdef*\SKV@gundef{\global\SKV@undef}
+\SKV@pdef*\SKV@csundef#1{\SKV@aftercs\SKV@undef{#1}}
+\SKV@pdef*\SKV@csgundef{\global\SKV@csundef}
+\SKV@def*\SKV@undeflist{\SKV@savstate\SKV@t@st@p@a\SKV@und@flist}
+\SKV@def*\SKV@und@flist#1{%
+ \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
+ \XKV@for@n{#1}\SKV@resvd{%
+ \SKV@expnext\SKV@ensurescape\SKV@resvd
+ \gl@l@x\expandafter\SKV@undef\SKV@resvd
+ }%
+ \SKV@resstate
+}
+\SKV@pdef*\SKV@Undef{\SKV@savstate\SKV@testopte\SKV@Und@f}
+\SKV@def*\SKV@Und@f[#1]#2{%
+ \ifSKV@st
+ \ifSKV@pl
+ \def\SKV@ndl{\SKV@for*[#1]#2}%
+ \else
+ \def\SKV@ndl{\SKV@tfor*#2}%
+ \fi
+ \else
+ \ifSKV@pl
+ \def\SKV@ndl{\SKV@for[#1]{#2}}%
+ \else
+ \def\SKV@ndl{\SKV@tfor{#2}}%
+ \fi
+ \fi
+ \SKV@ndl\SKV@ndl{%
+ \ifSKV@pl
+ \SKV@despacectt\SKV@ndl
+ \ifSKV@cl\expandafter\global\fi
+ \SKV@threexp\let
+ \expandafter\csname\SKV@ndl\endcsname\SKV@undefined
+ \else
+ \ifSKV@cl\expandafter\global\fi
+ \expandafter\let\SKV@ndl\SKV@undefined
+ \fi
+ }%
+ \SKV@resstate
+}
+\SKV@def*\SKV@ifdef#1{%
+ \SKV@ifdefined{#1}%
+ {\@nameuse{SKV@\SKV@ifx{#1}\relax{2}{1}of2}}\@secondoftwo
+}
+\SKV@def*\SKV@ifundef#1{\@nameuse{SKV@\SKV@ifdef{#1}{2}{1}of2}}
+\SKV@def*\SKV@ifcsdef#1{%
+ \SKV@ifcsname{#1}%
+ {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
+ \relax{2}{1}of2}}\@secondoftwo
+}
+\SKV@def*\SKV@ifcsundef#1{\@nameuse{SKV@\SKV@ifcsdef{#1}{2}{1}of2}}
+\SKV@def*\SKV@ifonedef#1{%
+ \def\SKV@resvda{#1}\SKV@swtrue
+ \XKV@whilist\SKV@resvda\SKV@resvdb\ifSKV@sw\fi{%
+ \SKV@oifdefined\SKV@resvdb\SKV@swfalse\SKV@swtrue
+ }%
+ \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
+}
+\SKV@def\DeclarePackageCommand#1#2{%
+ \SKV@ensurescape{#2}%
+ \SKV@ifdef#2{%
+ \edef\resvd@a{\expandafter\@gobble\string#2}%
+ \SKV@cslet{Saved\resvd@a}#2%
+ \edef\resvd@a##1{\SKV@AtEndAfterPackageEnd%
+ {##1Saved\resvd@a\noexpand\endcsname}}%
+ \resvd@a{\expandafter\let\expandafter#2\csname}%
+ \SKV@undef\resvd@a
+ }{\SKV@AtEndAfterPackageEnd{\SKV@Undef!#2}}%
+ #1#2%
+}
+\SKV@pdef*\SKV@providedef{\@star@or@long{\SKV@pr@videdef{}}}
+\SKV@pdef*\SKV@providerobustdef{\@star@or@long{\SKV@pr@videdef\protected}}
+\SKV@def\SKV@pr@videdef#1#2{%
+ \SKV@ensurescape{#2}%
+ \edef\SKV@prov@d{\expandafter\@gobble\string#2}%
+ \SKV@aftercs\let{SKV@test@\SKV@prov@d}\SKV@undefined
+ \SKV@ifdef#2{%
+ \SKV@vbmsg{info}{Command '\string#2' already defined:\SKV@MB
+ Not redefined\on@line}%
+ \SKV@afterassignment{\SKV@gundef\SKV@pr@vid}%
+ \def\SKV@pr@vid
+ }{%
+ \SKV@afterassignment{%
+ \SKV@aftercs\edef{SKV@test@\SKV@prov@d}%
+ {\expandafter\strip@prefix\meaning#2}%
+ }%
+ \l@ngrel@x#1\def#2%
+ }%
+}
+\SKV@def\TestProvidedCommand#1{%
+ \SKV@ensurescape{#1}%
+ \begingroup
+ \SKV@ifmacro#1{%
+ \edef\SKV@resvda{\expandafter\@gobble\string#1}%
+ \edef\SKV@resvdb{\expandafter\strip@prefix\meaning#1}%
+ \expandafter\aftergroup\csname SKV@\expandafter
+ \ifx\expandafter\SKV@resvdb
+ \csname SKV@test@\SKV@resvda\endcsname
+ 1\else2\fi of2\endcsname
+ }{\aftergroup\@secondoftwo}%
+ \endgroup
+}
+\SKV@pdef*\SKV@newdef{\SKV@def}
+\SKV@providerobustdef*\newdef{\SKV@def}
+\SKV@providerobustdef*\redef{\SKV@redef}
+\SKV@pdef*\SKV@robustdef{\SKV@pdef}
+\SKV@providerobustdef*\robustdef{\SKV@pdef}
+\SKV@providerobustdef*\robustredef{\SKV@predef}
+\SKV@providerobustdef*\providedef{\SKV@providedef}
+\SKV@providerobustdef*\providerobustdef{\SKV@providerobustdef}
+\SKV@providerobustdef*\aftercommission{\SKV@afterassignment}
+\SKV@providerobustdef*\aftercoterie{\SKV@aftergroup}
+\SKV@def*\SKV@ifmacro#1{%
+ \begingroup
+ \edef\SKV@tempa##1{\def##1####1\detokenize{macro}:####2&}%
+ \SKV@tempa\SKV@tempa{\expandafter\aftergroup
+ \csname SKV@\SKV@ifblank{##2}{2}{1}of2\endcsname}%
+ \edef\SKV@tempb##1{##1\detokenize{macro}:&}%
+ \SKV@tempb{\expandafter\SKV@tempa\meaning#1}%
+ \endgroup
+}
+\SKV@def\SKV@csifmacro{\SKV@aftercs\SKV@ifmacro}
+\SKV@def\SKV@ifnotmacro#1{\SKV@ifmacro{#1}\@secondoftwo\@firstoftwo}
+\SKV@def*\SKV@simplecmdpatch{\begingroup\@makeother{\#}%
+ \SKV@testopt\SKV@simpl@cmdpatch{########1}}
+\SKV@def*\SKV@simpl@cmdpatch[#1]#2#3#4{%
+ \edef\SKV@resvda##1##2{%
+ \def##1####1\detokenize{macro:}####2->####3&{%
+ #1\def\string#2####2{##2####3&}%
+ }%
+ \def##2####1\detokenize{#3}####2&{####1\detokenize{#4}####2}%
+ \edef##1{##1\meaning#2&}%
+ }%
+ \SKV@resvda\SKV@resvda\SKV@resvdb
+ \everyeof{\noexpand}\endlinechar\m@ne\makeatletter
+ \catcode`\#=6\relax
+ \scantokens\expandafter{\SKV@resvda}%
+ \global\let#2#2%
+ \endgroup
+}
+\SKV@def*\SKV@ifrelax#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@ifdefined{#1}%
+ {\@nameuse{SKV@\SKV@ifx{#1}\relax{1}{2}of2}}\@secondoftwo
+}
+\SKV@def*\SKV@ifcsrelax#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsname{#1}%
+ {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
+ \relax{1}{2}of2}}\@secondoftwo
+}
+\SKV@def*\SKV@ifdefax#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@ifdefined{#1}%
+ {\@nameuse{SKV@\SKV@ifx{#1}\relax{2}{1}of3}}\@thirdofthree
+}
+\SKV@def*\SKV@ifcsdefax#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsname{#1}%
+ {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
+ \relax{2}{1}of3}}\@thirdofthree
+}
+\SKV@def*\SKV@despacectt#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@expnext\SKV@sp@def{#1}#1%
+}
+\SKV@def\SKV@detokdespace#1{%
+ \edef#1{\detokenize\expandafter{#1}}%
+ \SKV@despacectt#1%
+}
+\SKV@def\SKV@ifblank#1{\SKV@ifbl@nk#1&&\@secondoftwo\@firstoftwo:}
+\SKV@def\SKV@ifbl@nk#1#2&#3#4#5:{#4}
+\SKV@def\SKV@ifnotblank#1{\SKV@ifbl@nk#1&&\@firstoftwo\@secondoftwo:}
+\SKV@def\SKV@oifblank#1{\expandafter\SKV@ifblank\expandafter{#1}}
+\SKV@def\SKV@xifblank#1{\SKV@expargs{0}\SKV@ifblank{#1}\@nil}
+\SKV@def\SKV@ifstrequal#1#2{%
+ \begingroup
+ \edef\resvd@a{\detokenize{#1}}%
+ \edef\resvd@b{\detokenize{#2}}%
+ \SKV@despacectt\resvd@a\SKV@despacectt\resvd@b
+ \expandafter\aftergroup
+ \csname SKV@\SKV@ifx\resvd@a\resvd@b{1}{2}of2\endcsname
+ \endgroup
+}
+\SKV@def\SKV@ifstrnotequal#1#2{%
+ \SKV@ifstrequal{#1}{#2}\@secondoftwo\@firstoftwo}
+\SKV@def\SKV@oifstrequal#1#2{%
+ \@expandtwoargs\SKV@ifstrequal{\SKV@expox{#1}}{\SKV@expox{#2}}}
+\SKV@def\SKV@xifstrequal#1#2{\@expandtwoargs\SKV@ifstrequal{#1}{#2}}
+\SKV@def\SKV@ifempty#1{\@nameuse{SKV@\ifcat$\detokenize{#1}$1\else2\fi of2}}
+\SKV@def\SKV@ifnotempty#1{\@nameuse{SKV@\SKV@ifempty{#1}{2}{1}of2}}
+\SKV@def\SKV@oifempty#1{\SKV@expnext\SKV@ifempty{#1}}
+\SKV@def\SKV@xifempty#1{\SKV@expargs{0}\SKV@ifempty{#1}\@nil}
+\SKV@def*\SKV@remparser{\SKV@testopt\SKV@remp@rser{,}}
+\SKV@def\SKV@remp@rser[#1]#2{%
+ \begingroup
+ \ifx#2\@empty\else
+ \edef#2{#1\SKV@expox{#2}}%
+ \def\SKV@tempa#1##1\@nil{%
+ \gdef#2{##1}\futurelet\@temptoks\SKV@t@mp##1\@nil
+ }%
+ \def\SKV@t@mp##1\@nil{%
+ \ifx\@temptoks\@sptoken
+ \SKV@expnext\SKV@sp@def{#2}#2%
+ \expandafter\SKV@tempa\expandafter#1#2\@nil
+ \else
+ \if#1\@temptoks\expandafter\SKV@tempa#2\@nil\fi
+ \fi
+ }%
+ \expandafter\SKV@tempa#2\@nil
+ \fi
+ \endgroup
+}
+\SKV@pdef*\SKV@appto{\SKV@savstate\SKV@testoptb{\SKV@hooktomac{>}}}
+\SKV@pdef*\SKV@prepto{\SKV@savstate\SKV@testoptb{\SKV@hooktomac{<}}}
+\SKV@def\SKV@hooktomac#1#2#3{%
+ \ifSKV@st\let\SKV@iii\SKV@expox\else\let\SKV@iii\unexpanded\fi
+ \ifSKV@pl
+ \let\@ifundef\SKV@ifcsundef\let\SKV@iv\SKV@csexpox
+ \def\SKV@i##1{\def\SKV@ii####1{\SKV@aftercs##1{####1}}}%
+ \ifSKV@cl\SKV@i\xdef\else\SKV@i\edef\fi
+ \else
+ \let\@ifundef\SKV@ifundef\let\SKV@iv\SKV@expox
+ \ifSKV@cl\def\SKV@ii##1{\xdef##1}\else
+ \def\SKV@ii##1{\edef##1}\fi
+ \fi
+ \@ifundef{#2}{%
+ \SKV@ii{#2}{\SKV@iii{#3}}%
+ }{%
+ \SKV@ifstrequal{#1}{>}%
+ {\SKV@ii{#2}{\SKV@iv{#2}\SKV@iii{#3}}}%
+ {\SKV@ii{#2}{\SKV@iii{#3}\SKV@iv{#2}}}%
+ }%
+ \SKV@resstate
+ \SKV@undeflist!{\SKV@i,\SKV@ii,\SKV@iii,\SKV@iv}%
+}
+\SKV@pdef\apptomac#1#2{%
+ \SKV@ifundef{#1}{\edef#1{\unexpanded{#2}}}%
+ {\edef#1{\SKV@expox{#1}\unexpanded{#2}}}%
+}
+\SKV@pdef*\gapptomac{\global\apptomac}
+\SKV@pdef*\csapptomac{\SKV@aftercs\apptomac}
+\SKV@pdef*\csgapptomac{\global\csapptomac}
+\SKV@pdef\preptomac#1#2{%
+ \SKV@ifundef{#1}{\edef#1{\unexpanded{#2}}}%
+ {\edef#1{\unexpanded{#2}\SKV@expox{#1}}}%
+}
+\SKV@pdef*\gpreptomac{\global\preptomac}
+\SKV@pdef*\cspreptomac{\SKV@aftercs\preptomac}
+\SKV@pdef*\csgpreptomac{\global\cspreptomac}
+\SKV@pdef*\SKV@addtolist{\SKV@savstate\SKV@testoptc{%
+ \SKV@t@stoptg{\SKV@testopt\SKV@addt@list{,}}}}
+\SKV@def*\SKV@addt@list[#1]{%
+ \def\parser{#1}%
+ \ifSKV@cl\let\glob@l@def\xdef\else\let\glob@l@def\edef\fi
+ \ifSKV@pl
+ \def\SKV@next##1{\SKV@aftercs\SKV@addt@l@st{##1}}%
+ \else
+ \let\SKV@next\SKV@addt@l@st
+ \fi
+ \SKV@next
+}
+\SKV@def\SKV@addt@l@st#1#2{%
+ \SKV@ifundef{#1}{%
+ \glob@l@def#1{\SKV@expox{#2}}%
+ }{%
+ \SKV@ifx#1\@empty{%
+ \glob@l@def#1{\SKV@expox{#2}}%
+ }{%
+ \ifSKV@lt
+ \glob@l@def#1{\SKV@expox{#2}\parser\SKV@expox{#1}}%
+ \else
+ \glob@l@def#1{\SKV@expox{#1}\parser\SKV@expox{#2}}%
+ \fi
+ }%
+ }%
+ \SKV@resstate
+}
+\SKV@pdef*\SKV@relax#1{\let#1\relax}
+\SKV@pdef*\SKV@grelax{\global\SKV@relax}
+\SKV@pdef*\SKV@csrelax{\SKV@aftercs\SKV@relax}
+\SKV@pdef*\SKV@csgrelax{\global\SKV@csrelax}
+\@ifpackageloaded{atveryend}{%
+ \@ifpackagecurrent{atveryend}{2010/03/24}{}{%
+ \SKV@err{Your loaded version of atveryend package is
+ not current}\@ehc}}{\RequirePackage{atveryend}[2010/03/24]}
+\SKV@pdef*\SKV@notprerr{%
+ \SKV@err{You have issued a preamble command here}%
+ {Move shown command to document preamble.}%
+}
+\SKV@pdef*\SKV@notenderr{%
+ \SKV@err{You've called an \string\enddocument\space command\SKV@MB
+ at the wrong place}{Move command to before \string\enddocument.}%
+}
+\SKV@pdef*\SKV@AtDocumentStart{\AtBeginDocument}
+\SKV@pdef*\SKV@BeforeDocumentStart{\SKV@appto!\SKV@beforedocstart}
+\def\SKV@beforedocstart{}
+\SKV@prepto\document{%
+ \endgroup
+ \let\SKV@BeforeDocumentStart\@firstofone
+ \SKV@beforedocstart
+ \let\SKV@BeforeDocumentStart\SKV@notprerr
+ \SKV@gundef\SKV@beforedocstart
+ \begingroup
+}
+\SKV@pdef*\SKV@AfterDocumentStart{\SKV@appto!\SKV@afterdocstart}
+\def\SKV@afterdocstart{}
+\SKV@appto\document{%
+ \let\SKV@AfterDocumentStart\@firstofone
+ \SKV@afterdocstart
+ \let\SKV@AfterDocumentStart\SKV@notprerr
+ \SKV@gundef\SKV@afterdocstart\ignorespaces
+}
+\SKV@BeforeDocumentStart{\let\SKV@AtDocumentStart\@firstofone}
+\SKV@pdef*\SKV@AtDocumentEnd{\AtEndDocument}
+\SKV@pdef*\SKV@BeforeLastPage{\SKV@appto!\SKV@beforelastpage}
+\def\SKV@beforelastpage{}
+\SKV@AtDocumentEnd{%
+ \let\SKV@bef@relastpage\AtVeryEnd@BeforeClearDocumentHook
+ \def\AtVeryEnd@BeforeClearDocumentHook{%
+ \let\SKV@BeforeLastPage\@firstofone
+ \SKV@beforelastpage\SKV@bef@relastpage
+ \let\SKV@BeforeLastPage\SKV@notenderr
+ \SKV@Undef!{\SKV@beforelastpage\SKV@bef@relastpage}%
+ }%
+}
+\SKV@pdef*\SKV@AfterLastPage{\SKV@appto!\SKV@afterlastpage}
+\def\SKV@afterlastpage{}
+\SKV@AtDocumentEnd{%
+ \let\SKV@afterl@stpage\AtVeryEnd@AfterLastShipoutHook
+ \def\AtVeryEnd@AfterLastShipoutHook{%
+ \let\SKV@AfterLastPage\@firstofone
+ \SKV@afterlastpage\SKV@afterl@stpage
+ \let\SKV@AfterLastPage\SKV@notenderr
+ \SKV@Undef!{\SKV@afterlastpage\SKV@afterl@stpage}%
+ }%
+}
+\SKV@pdef*\SKV@AfterDocumentEnd{\SKV@appto!\SKV@afterenddoc}
+\def\SKV@afterenddoc{}
+\SKV@AtDocumentEnd{%
+ \let\SKV@aft@renddoc\AtVeryEnd@AtVeryEndDocumentHook
+ \def\AtVeryEnd@AtVeryEndDocumentHook{%
+ \let\SKV@AfterDocumentEnd\@firstofone
+ \SKV@afterenddoc\SKV@aft@renddoc
+ \let\SKV@AfterDocumentEnd\SKV@notenderr
+ \SKV@Undef!{\SKV@afterenddoc\SKV@aft@renddoc}%
+ }%
+}
+\SKV@pdef\SKV@AtPackageEnd{\AtEndOfPackage}
+\SKV@pdef*\SKV@BeforePackageEnd{%
+ \SKV@prepto+{\@currname.\@currext-h@@k}%
+}
+\SKV@pdef*\SKV@AfterPackageEnd{%
+ \SKV@appto+{\@currname.\@currext-skvh@@k}%
+}
+\let\SKV@AtClassEnd\SKV@AtPackageEnd
+\let\SKV@BeforeClassEnd\SKV@BeforePackageEnd
+\let\SKV@AfterClassEnd\SKV@AfterPackageEnd
+\SKV@prepto\@popfilename{%
+ \SKV@csuse{\@currname.\@currext-skvh@@k}%
+ \SKV@csgundef{\@currname.\@currext-skvh@@k}%
+}
+\SKV@pdef\@afterpackageloaded#1{%
+ \SKV@AtDocumentStart{%
+ \SKV@ifcsdef{ver@#1.\@pkgextension}{}{%
+ \SKV@warn{Package '#1' was never loaded}%
+ }%
+ }
+ \SKV@ifcsdef{ver@#1.\@pkgextension}{%
+ \let\SKV@next\@firstofone
+ }{%
+ \def\SKV@next{\SKV@appto+{#1.\@pkgextension-skvh@@k}}%
+ }%
+ \SKV@next
+}
+\let\SKV@steno\z@
+\SKV@pdef*\SKV@for{\SKV@savstate\SKV@testoptd\SKV@f@r}
+\SKV@pdef*\SKV@f@r[#1]{%
+ \let\SKV@steno\@ne
+ \ifSKV@st
+ \def\SKV@next{\SKV@for@b[#1]}%
+ \else
+ \def\SKV@next{\SKV@CommandGenParser{#1}\SKV@for@a}%
+ \fi
+ \SKV@next
+}
+\SKV@pdef*\SKV@CommandGenParser#1{%
+ \def\parser{#1}%
+ \protected\long\def\SKV@for@a##1##2##3{%
+ \SKV@ifblank{##1}\SKV@fornoop\SKV@forloop
+ ##2{##3}##1#1\@nil
+ }%
+ \long\def\SKV@forloop##1##2##3#1##4\@nil{%
+ \edef##1{\unexpanded{##3}}%
+ \SKV@ifstrequal{##3}{\listbreak}{%
+ \SKV@keylistrema##4\@nil#1%
+ }{%
+ \SKV@ifblank{##4}{%
+ ##2\relax
+ \ifnum\SKV@steno=\@ne\expandafter\SKV@resstate\fi
+ \let\SKV@steno\z@
+ }{%
+ ##2\relax\SKV@forloop##1{##2}##4\@nil
+ }%
+ }%
+ }%
+ \long\def\SKV@fornoop##1\@nil{}%
+}
+\SKV@pdef*\SKV@for@b{\SKV@testopt\SKV@f@r@b{,}}
+\SKV@def\SKV@f@r@b[#1]#2{%
+ \SKV@CommandGenParser{#1}\SKV@expnext\SKV@for@a{#2}%
+}
+\SKV@pdef*\SKV@tfor{\SKV@ifstar\SKV@tfor@b\SKV@tfor@a}
+\SKV@pdef*\SKV@tfor@a#1#2#3{%
+ \SKV@ifblank{#1}{%
+ \SKV@vbmsg{warn}{Empty list for '\string\SKV@tfor@a'\on@line}%
+ }{%
+ \SKV@ifblank{#3}{%
+ \SKV@vbmsg{warn}%
+ {Empty function for '\string\SKV@tfor@a'\on@line}%
+ }{%
+ \SKV@tforloop#1\@nil\@nil&#2{#3}%
+ }%
+ }%
+}
+\SKV@def\SKV@tforloop#1#2&#3#4{%
+ \long\def#3{#1}%
+ \SKV@ifstrequal{#1}{\listbreak}{%
+ \let\SKV@next\SKV@tforrema
+ }{%
+ \SKV@ifstrequal{#1}{\@nil}{%
+ \let\SKV@next\SKV@tfornoop
+ }{%
+ #4\relax\let\SKV@next\SKV@tforloop
+ }%
+ }%
+ \SKV@next#2&#3{#4}%
+}
+\SKV@def\SKV@tfornoop#1&#2#3{}
+\SKV@pdef*\SKV@tforrema#1\@nil\@nil&#2#3{%
+ \long\edef\SKV@remainder{\unexpanded{#1}}%
+}
+\SKV@pdef*\SKV@tfor@b#1#2#3{\SKV@expnext\SKV@tfor@a{#1}#2{#3}}
+\SKV@def*\SKV@preamblecmds{}
+\SKV@pdef*\SKV@onlypreamble{\SKV@savstate\SKV@t@st@pta\SKV@onlypre@mble}
+\SKV@pdef*\SKV@onlypre@mble#1{%
+ \SKV@for[,]{#1}\SKV@resvd{%
+ \SKV@despacectt\SKV@resvd
+ \ifSKV@pl
+ \SKV@expnext\SKV@ensurenoscape\SKV@resvd
+ \edef\SKV@resvd##1##2{\SKV@appto!##1{##2\SKV@noexpcs{\SKV@resvd}}}%
+ \else
+ \SKV@expnext\SKV@ensurescape\SKV@resvd
+ \edef\SKV@resvd##1##2{\SKV@appto!##1{##2\SKV@expox{\SKV@resvd}}}%
+ \fi
+ \SKV@resvd\SKV@preamblecmds\SKV@dopreamble
+ }%
+ \SKV@resstate
+}
+\SKV@AfterDocumentStart{%
+ \gdef\SKV@dopreamble#1{%
+ \gdef#1{\SKV@err{'\string#1' is a preamble command}%
+ {Move command '\string#1' to document preamble.}}%
+ }%
+ \SKV@preamblecmds
+ \global\let\SKV@dopreamble\@gobble
+}
+\SKV@pdef*\SKV@onlypackage{%
+ \SKV@xifempty{\@currname\@currext}{%
+ \SKV@err{Not in package environment}%
+ {The command at top level of this message\SKV@MB
+ is available only in package environment.}%
+ }{}%
+}
+\def\SKV@aftergroupdef#1#2{%
+ \expandafter\endgroup\expandafter\def\expandafter#1%
+ \expandafter{#2}%
+}
+\SKV@def*\SKV@noexpparse#1{%
+ \begingroup
+ \def\SKV@resa{}%
+ \edef\SKV@tempa{\detokenize\expandafter{#1}\@backslashchar&}%
+ \edef\SKV@tempb##1{\def##1####1\@backslashchar####2&}%
+ \SKV@tempb\SKV@tempb{%
+ \SKV@ifempty{##2}{%
+ \edef\SKV@resa{\SKV@expox\SKV@resa##1}%
+ }{%
+ \edef\SKV@resa{\SKV@expox\SKV@resa##1%
+ \string\noexpand\@backslashchar}%
+ \SKV@tempb##2&%
+ }%
+ }%
+ \expandafter\SKV@tempb\SKV@tempa
+ \expandafter\endgroup\expandafter\toks@\expandafter{\SKV@resa}%
+ \edef#1{\the\toks@}%
+}
+\SKV@def*\SKV@CommandKeyParser#1{%
+ \long\def\SKV@d@fine@keylist##1{%
+ \global\let\ifSKV@st\ifSKV@st
+ \endgroup
+ \SKV@undeflist!{\skif,\skifx,\skifcase,\skor,\skelse,\skfi}%
+ \ifSKV@st
+ \edef\@keylist{\detokenize\expandafter{##1}}%
+ \else
+ \edef\@keylist{\detokenize{##1}}%
+ \fi
+ \SKV@scantoksa\@keylist
+ \SKV@resstate
+ \SKV@expnext\SKV@checksanitizec\@keylist\SKV@tempa
+ \expandafter\SKV@readkeylist\SKV@tempa#1\@nil
+ }%
+ \long\def\SKV@readkeylist##1#1##2\@nil{%
+ \SKV@ifblank{##1}{}%
+ {%
+ \SKV@ifstrequal{##1}{\listbreak}{%
+ \SKV@keylistrema##2\@nil#1%
+ }{%
+ \SKV@define@multkeys##1\@nil
+ \SKV@ifblank{##2}\relax{\SKV@readkeylist##2\@nil}%
+ }%
+ }%
+ }%
+}
+\SKV@def*\SKV@checksanitizec#1#2{%
+ \XKV@ch@cksanitize{#1}#2;%
+ \ifin@\else\XKV@ch@cksanitize{#1}#2,\fi
+ \ifin@\@selective@sanitize[0]{,;}#2\fi
+}
+\SKV@pdef\SKV@checkchoice#1#2#3#4{%
+ \XKV@savstate\XKV@sttrue\XKV@pltrue
+ \SKV@expargs{3}{\XKV@checkchoice[\val\nr]}{{#1}{#2}}{{#3}{#4}}\@nil
+ \XKV@resstate
+}
+\SKV@simplecmdpatch\XKV@ch@ckch@ice{%
+ \XKV@err{value `\the\XKV@toks' is not allowed}%
+}{%
+ \SKV@err{Value '\the\XKV@toks' is not allowed}%
+ {You have submitted an invalid value for a key.\SKV@MB
+ You may proceed if you like but expect funny results.}%
+}
+\SKV@simplecmdpatch\XKV@@ch@ckchoice{%
+ \XKV@err{value `\the\XKV@toks' is not allowed}%
+}{%
+ \SKV@err{Value '\the\XKV@toks' is not allowed}%
+ {You have submitted an invalid value for a key.\SKV@MB
+ You may proceed if you like but expect funny results.}%
+}
+\SKV@pdef*\SKV@inputerr#1#2{%
+ \SKV@err{Erroneous value '#1' for key '#2'}%
+ {Please use the correct value for key '#2'\SKV@MB
+ of families '\XKV@fams'.}%
+}
+\SKV@def*\SKV@despacelist{\SKV@savstate\SKV@testoptd\SKV@desp@celist}
+\SKV@def*\SKV@desp@celist[#1]#2{%
+ \begingroup
+ \let\SKV@resa\@empty
+ \ifSKV@st
+ \def\SKV@dsl{\SKV@for*[#1]#2}%
+ \else
+ \def\SKV@dsl{\SKV@for[#1]{#2}}%
+ \fi
+ \SKV@dsl\SKV@dsl{%
+ \SKV@despacectt\SKV@dsl
+ \SKV@appto*\SKV@resa{\expandafter#1\SKV@dsl}%
+ }%
+ \ifx\SKV@resa\@empty\else\SKV@remparser[#1]\SKV@resa\fi
+ \ifSKV@st\global\let#2\SKV@resa\fi
+ \endgroup
+ \SKV@resstate
+}
+\SKV@def*\SKV@tdespacelt#1{%
+ \SKV@tfor{#1}\SKV@dsl{\expandafter\SKV@despacectt\SKV@dsl}%
+}
+\SKV@pdef*\ReserveKeyPrefixNames{\SKV@ifstar\SKV@rkpn@m@s\SKV@rkpn@mes}
+\SKV@def*\SKV@rkpn@mes#1{\SKV@appto!\SKV@rkpnames{,#1}}
+\SKV@def*\SKV@rkpn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rkpnames{,#1}}}
+\SKV@pdef*\ReserveMacroPrefixNames{\SKV@ifstar\SKV@rmpn@m@s\SKV@rmpn@mes}
+\SKV@def*\SKV@rmpn@mes#1{\SKV@appto!\SKV@rmpnames{,#1}}
+\SKV@def*\SKV@rmpn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rmpnames{,#1}}}
+\SKV@pdef*\ReserveFamilyNames{\SKV@ifstar\SKV@rfn@m@s\SKV@rfn@mes}
+\SKV@def*\SKV@rfn@mes#1{\SKV@appto!\SKV@rfnames{,#1}}
+\SKV@def*\SKV@rfn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rfnames{,#1}}}
+\SKV@def*\SKV@rkpnames{XKV}
+\SKV@def*\SKV@rmpnames{XKV}
+\SKV@def*\SKV@rfnames{XKV}
+\ReserveKeyPrefixNames*{SKV}
+\ReserveMacroPrefixNames*{SKV}
+\ReserveFamilyNames*{skeyval}
+\SKV@def*\SKV@newlet{\SKV@savstate\SKV@t@stopta\SKV@n@wlet}
+\SKV@def*\SKV@n@wlet#1#2{%
+ \SKV@ifdef#1{%
+ \ifSKV@st
+ \SKV@ifdef#2{%
+ \let#1#2%
+ \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
+ }{%
+ \SKV@err{Command '\string#2' undefined}%
+ {I can't let '\string#1' to '\string#2'.}%
+ }%
+ \else
+ \SKV@err{Command '\string#1' already defined}%
+ {I can't let '\string#1' to '\string#2'.}%
+ \fi
+ }{%
+ \SKV@ifdef#2{\let#1#2}{%
+ \SKV@err{Command '\string#2' undefined}%
+ {I can't let '\string#1' to '\string#2'.}%
+ }%
+ }%
+ \SKV@resstate
+}
+\AtEndOfPackage{\SKV@providedef*\NewLet{\SKV@newlet}}
+\SKV@pdef*\SKV@cslet{\SKV@savstate\SKV@t@stopta\SKV@csl@t}
+\SKV@def*\SKV@csl@t#1#2{%
+ \ifSKV@st
+ \def\SKV@next{\SKV@aftercs\let{#1}#2}%
+ \else
+ \def\SKV@next{%
+ \SKV@ifdef{#2}{%
+ \SKV@aftercs\let{#1}#2%
+ }{%
+ \SKV@err{Command '\string#2' undefined}%
+ {You may use the starred version of \string\SKV@cslet.}%
+ }%
+ }%
+ \fi
+ \SKV@resstate\SKV@next
+}
+\SKV@pdef*\SKV@letcs{\SKV@savstate\SKV@t@stopta\SKV@l@tcs}
+\SKV@def*\SKV@l@tcs#1#2{%
+ \ifSKV@st
+ \def\SKV@next{%
+ \begingroup\expandafter\endgroup
+ \expandafter\let\expandafter#1\csname#2\endcsname
+ }%
+ \else
+ \def\SKV@next{%
+ \SKV@ifcsdef{#2}{%
+ \expandafter\let\expandafter#1\csname#2\endcsname
+ }{%
+ \SKV@err{Command '\@backslashchar#2' undefined}%
+ {You may use the starred version of \string\SKV@letcs.}%
+ }%
+ }%
+ \fi
+ \SKV@resstate\SKV@next
+}
+\SKV@pdef*\SKV@csletcs{\SKV@savstate\SKV@t@stopta\SKV@csl@tcs}
+\SKV@def*\SKV@csl@tcs#1#2{%
+ \ifSKV@st
+ \def\SKV@next{%
+ \begingroup\expandafter\endgroup
+ \expandafter\let\csname#1\SKV@aftercs\endcsname{#2}%
+ }%
+ \else
+ \def\SKV@next{%
+ \SKV@ifcsdef{#2}{%
+ \SKV@aftercs\let{#1\SKV@aftercs}{#2}%
+ }{%
+ \SKV@err{Command '\@backslashchar#2' undefined}%
+ {You may use the starred version of \string\SKV@csletcs.}%
+ }%
+ }%
+ \fi
+ \SKV@resstate\SKV@next
+}
+\SKV@pdef*\SKV@numdef{\SKV@savstate\SKV@testoptc{\SKV@expr{num}}}
+\SKV@pdef*\SKV@dimdef{\SKV@savstate\SKV@testoptc{\SKV@expr{dim}}}
+\SKV@def*\SKV@expr#1{%
+ \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
+ \ifSKV@pl
+ \def\SKV@next##1{%
+ \edef\resvd@a####1{####1{#1}\SKV@csexpox{##1}}%
+ \resvd@a\SKV@ex@r
+ }%
+ \else
+ \def\SKV@next{\SKV@ex@r{#1}}%
+ \fi
+ \SKV@resstate\SKV@next
+}
+\SKV@def*\SKV@ex@r#1#2#3{%
+ \SKV@ensurescape@ne{#2}{#3}%
+ \SKV@ifstrequal{#1}{num}%
+ {\def\resvd@a{count}}{\def\resvd@a{dimen}}%
+ \SKV@ifundef{#2}{%
+ \@nameuse{new\resvd@a}#2%
+ \gl@l@x#2=\@nameuse{#1expr}#3\relax
+ }{%
+ \gl@l@x#2=\@nameuse{#1expr}#3\relax
+ }%
+}
+\SKV@def*\SKV@ensurescape@ne#1#2{%
+ \SKV@ensurescape{#1}%
+ \SKV@ifnotempty{#2}{}%
+ {\SKV@err{Argument '\string#2' is empty}%
+ {Empty argument '\string#2' is invalid.\SKV@MB
+ I expected a nonempty argument here.}%
+ }%
+}
+\SKV@def*\SKV@badkeylistparser{%
+ \SKV@err{Key list parser '\SKV@keyparser' not allowed}%
+ {Use semicolon (preferable) or colon as parser.}%
+}
+\define@boolkey+[KV]{skeyval}[SKV@]{xchoicelist}[true]{}{%
+ \SKV@inputerr{#1}{xchoicelist}%
+}
+\define@cmdkey[KV]{skeyval}[SKV@]{genparser}[,]{%
+ \@onelevel@sanitize\SKV@genparser
+ \SKV@despacectt\SKV@genparser
+ \SKV@expargs{0}\SKV@CommandGenParser\SKV@genparser\@nil
+}
+\define@cmdkey[KV]{skeyval}[SKV@]{keyparser}[;]{%
+ \@onelevel@sanitize\SKV@keyparser
+ \SKV@xifblank\SKV@keyparser\SKV@badkeylistparser\relax
+ \SKV@despacectt\SKV@keyparser
+ \begingroup
+ \def\SKV@tempa{,}\SKV@detokdespace\SKV@tempa
+ \SKV@ifx\SKV@keyparser\SKV@tempa
+ {\aftergroup\SKV@badkeylistparser}{}%
+ \endgroup
+ \SKV@expargs{0}\SKV@CommandKeyParser\SKV@keyparser\@nil
+}
+\SKV@def*\SKV@keyprefix@err{%
+ \SKV@err{Key prefix '\SKV@keyprefix' is not allowed}%
+ {Use another prefix name instead of '\SKV@keyprefix'.}%
+}
+\define@cmdkey[KV]{skeyval}[SKV@]{keyprefix}[KV]{%
+ \SKV@xifblank\SKV@keyprefix\SKV@keyprefix@err\relax
+ \SKV@despacectt\SKV@keyprefix
+ \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rkpnames}}%
+ \SKV@tempa\@nil
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@ifx\SKV@keyprefix\SKV@tempa\SKV@keyprefix@err\relax
+ }%
+}
+\SKV@def*\SKV@keyfamily@err{%
+ \SKV@err{Key family '\SKV@keyfamily' is not allowed}%
+ {Use another family name instead of '\SKV@keyfamily'.}%
+}
+\define@cmdkey[KV]{skeyval}[SKV@]{keyfamily}[fam]{%
+ \SKV@xifblank\SKV@keyfamily\SKV@keyfamily@err\relax
+ \SKV@despacectt\SKV@keyfamily
+ \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rfnames}}%
+ \SKV@tempa\@nil
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@ifx\SKV@keyfamily\SKV@tempa\SKV@keyfamily@err\relax
+ }%
+}
+\SKV@def*\SKV@macroprefix@err{%
+ \SKV@err{Macro prefix '\SKV@macroprefix' is not allowed}%
+ {Use another macro prefix name instead of '\SKV@macroprefix'.}%
+}
+\define@cmdkey[KV]{skeyval}[SKV@]{macroprefix}[mp@]{%
+ \SKV@xifblank\SKV@macroprefix\SKV@macroprefix@err\relax
+ \SKV@despacectt\SKV@macroprefix
+ \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rmpnames}}%
+ \SKV@tempa\@nil
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@ifx\SKV@macroprefix\SKV@tempa\SKV@macroprefix@err\relax
+ }%
+}
+\SKV@BeforePackageEnd{\deftog{draft}\deftog{final}}
+\define@boolkey+[KV]{skeyval}[SKV@]{draft}[true]{%
+ \ifSKV@draft
+ \setkeys[KV]{skeyval}{final=false}%
+ \SKV@AtPackageEnd{\ifSKV@draft\togon{draft}\else
+ \togoff{draft}\fi}%
+ \fi
+}{%
+ \SKV@inputerr{#1}{draft}%
+}
+\define@boolkey+[KV]{skeyval}[SKV@]{final}[true]{%
+ \ifSKV@final
+ \setkeys[KV]{skeyval}{draft=false}%
+ \SKV@AtPackageEnd{\ifSKV@final\togon{final}\else
+ \togoff{final}\fi}%
+ \fi
+}{%
+ \SKV@inputerr{#1}{final}%
+}
+\DeclareOptionX*{\SKV@warn{Unknown option '\CurrentOption' ignored}}
+\ExecuteOptionsX[KV]<skeyval>{genparser,keyparser,keyprefix,
+ keyfamily,macroprefix,final}
+\ProcessOptionsX*[KV]<skeyval>\relax
+\SKV@pdef*\skvoptions#1{\setkeys[KV]{skeyval}{#1}}
+\SKV@pdef*\SKV@ifdraft{\@nameuse{SKV@\ifSKV@draft1\else2\fi of2}}
+\SKV@pdef*\SKV@iffinal{\@nameuse{SKV@\ifSKV@final1\else2\fi of2}}
+\SKV@pdef*\SKV@ifnotdraft{\@nameuse{SKV@\SKV@ifdraft2\else1\fi of2}}
+\SKV@pdef*\SKV@ifnotfinal{\@nameuse{SKV@\SKV@iffinal2\else1\fi of2}}
+\def\SKV@useinfo#1{Not using '\@backslashchar#1' of 'skyeval' package}
+\SKV@pdef*\SKV@in@#1#2{%
+ \def\in@@##1#1##2##3\in@@{\ifx\in@##2\in@false\else\in@true\fi}%
+ \in@@#2\@mil#1\in@\in@@
+}
+\SKV@pdef*\SKV@in@n#1#2{%
+ \SKV@in@{#1}{#2}%
+ \@nameuse{SKV@\ifin@1\else2\fi of2}%
+}
+\SKV@pdef*\SKV@in@o#1#2{%
+ \@expandtwoargs\SKV@in@{\SKV@expox{#1}}{\SKV@expox{#2}}%
+ \@nameuse{SKV@\ifin@1\else2\fi of2}%
+}
+\SKV@pdef*\SKV@in@x#1#2{%
+ \@expandtwoargs\SKV@in@{#1}{#2}%
+ \@nameuse{SKV@\ifin@1\else2\fi of2}%
+}
+\SKV@pdef*\in@tog#1#2{%
+ \SKV@in@{#1}{#2}%
+ \ifin@\togon{in@}\else\togoff{in@}\fi
+}
+\AtEndOfPackage{\deftog{in@}}
+\SKV@pdef*\in@tok#1#2{%
+ \begingroup
+ \SKV@expnext\SKV@sp@def{\detokenize{#1}}\SKV@tempa
+ \SKV@expnext\SKV@sp@def{\detokenize{#2}}\SKV@tempb
+ \@expandtwoargs\SKV@in@\SKV@tempa\SKV@tempb
+ \global\let\ifin@\ifin@
+ \endgroup
+}
+\AtBeginDocument{%
+ \SKV@ifundef\ifdraft
+ {\SKV@pdef*\ifdraft{\SKV@ifdraft}}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{ifdraft}}}%
+}
+\SKV@ifundef\ifnotdraft
+ {\SKV@pdef*\ifnotdraft{\SKV@ifnotdraft}}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{ifnotdraft}}}
+\SKV@ifundef\iffinal
+ {\SKV@pdef*\iffinal{\SKV@iffinal}}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{iffinal}}}
+\SKV@ifundef\ifnotfinal
+ {\SKV@pdef*\ifnotfinal{\SKV@ifnotfinal}}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{ifnotfinal}}}
+\SKV@def\SKV@star@or@long#1{%
+ \SKV@ifstar
+ {\let\l@ngrel@x\relax\def\@star@or@none{*}#1}%
+ {\let\l@ngrel@x\long\def\@star@or@none{}#1}%
+}
+\SKV@pdef\requirecmd{\SKV@star@or@long\SKV@require@cmd}
+\SKV@def\SKV@require@cmd#1{%
+ \SKV@ensurescape{#1}%
+ \SKV@ifdefined{#1}%
+ {\CheckCommand\@star@or@none}{\newcommand\@star@or@none}{#1}%
+}
+\SKV@redef\@check@eq#1#2{%
+ \SKV@ifx{#1}{#2}{}{%
+ \SKV@vbmsg{warn}{%
+ Previous definition of '\string#1'\SKV@MB
+ doesn't match your new definition.\SKV@MB
+ * I haven't redefined '\string#1' *}%
+ }%
+}
+\SKV@def*\SKV@getswstate#1#2{%
+ \SKV@checkchoice{#2}{true,on,false,off}{%
+ \ifcase\nr\relax
+ \def\SKV@swval{true}%
+ \or
+ \def\SKV@swval{true}%
+ \or
+ \def\SKV@swval{false}%
+ \or
+ \def\SKV@swval{false}%
+ \fi
+ }{%
+ \SKV@swvalerr{#1}{#2}%
+ }%
+}
+\SKV@pdef*\newswitch{\SKV@swtrue\SKV@testopt\SKV@newswitch{}}
+\SKV@pdef*\defswitch{\SKV@swfalse\SKV@testopt\SKV@newswitch{}}
+\SKV@def*\SKV@newswitch[#1]#2{\SKV@testopt{\SKV@n@wswitch[#1]{#2}}{false}}
+\SKV@def*\SKV@n@wswitch[#1]#2[#3]{%
+ \SKV@in@n{,}{#2}{%
+ \SKV@err{%
+ Command \ifSKV@sw'\string\newswitch'\else'\string\defswitch'\fi\space
+ doesn't accept list
+ }{%
+ Please submit only one switch to \ifSKV@sw'\string\newswitch'\else
+ '\string\defswitch'\fi\SKV@MB at a time. You may consider using
+ \ifSKV@sw'\string\NewSwitches'\else'\string\DefSwitches'\fi\SKV@MB
+ if you really want to define a set of switches.
+ }%
+ }{}%
+ \SKV@ensurenoscape{#2}%
+ \SKV@ifstrnotequal{#1#2}{x}{}{%
+ \SKV@err{'\string\ifx' is a TeX primitive}%
+ {You can't redefine '\string\ifx'! This is dangerous.}%
+ }%
+ \ifSKV@sw
+ \SKV@getswstate\newswitch{#3}%
+ \SKV@csifdefinable{if#1#2}\relax
+ \else
+ \SKV@getswstate\defswitch{#3}%
+ \SKV@ifcsundef{if#1#2}{}{%
+ \SKV@vbmsg{warn}{Switch '\@backslashchar if#1#2' redefined\on@line}%
+ }%
+ \fi
+ \csnewif{if#1#2}%
+ \@nameuse{#1#2\SKV@swval}%
+}
+\SKV@newlet\NewSwitches\NewBooleans
+\SKV@newlet\DefSwitches\DefBooleans
+\SKV@def*\setswitch#1#2{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsundef{if#1}{%
+ \SKV@noswerr{#1}%
+ }{%
+ \SKV@getswstate\setswitch{#2}%
+ \csname#1\SKV@swval\endcsname
+ }%
+}
+\SKV@def*\switchon#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}}{\@nameuse{#1true}}%
+}
+\SKV@newlet\switchtrue\switchon
+\SKV@def*\switchoff#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}}{\@nameuse{#1false}}%
+}
+\SKV@newlet\switchfalse\switchoff
+\SKV@def*\ifswitchon#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}\@gobbletwo}%
+ {\@nameuse{SKV@\@nameuse{if#1}1\else2\fi of2}}%
+}
+\SKV@newlet\ifswitchtrue\ifswitchon
+\SKV@def*\ifswitchoff#1{%
+ \SKV@ensurenoscape{#1}%
+ \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}\@gobbletwo}%
+ {\@nameuse{SKV@\@nameuse{if#1}2\else1\fi of2}}%
+}
+\SKV@newlet\ifswitchfalse\ifswitchoff
+\SKV@pdef*\SKV@noswerr#1{%
+ \SKV@err{Switch '\string#1' is undefined}%
+ {You need to first define the switch '\string#1'.}%
+}
+\SKV@pdef*\SKV@swnameerr#1{%
+ \SKV@err{'\string\if#1' not allowed as a boolean}%
+ {Invalid boolean name '\string#1'.}%
+}
+\SKV@def*\SKV@swvalerr#1#2{%
+ \SKV@err{\string#1\space error: invalid boolean value '#2'}%
+ {Valid boolean values are 'true', 'on', 'false', and 'off'.}%
+}
+\SKV@pdef*\SKV@undeftog@err#1{%
+ \SKV@err{Toggle '#1' undefined}%
+ {You need to first define '#1' before use.}%
+}
+\SKV@pdef*\newtog{\SKV@swtrue\SKV@testopt\SKV@newtog{}}
+\SKV@pdef*\deftog{\SKV@swfalse\SKV@testopt\SKV@newtog{}}
+\SKV@def*\SKV@newtog[#1]#2{\SKV@testopt{\SKV@n@wtog[#1]{#2}}{false}}
+\SKV@def*\SKV@n@wtog[#1]#2[#3]{%
+ \SKV@in@n{,}{#2}{%
+ \SKV@err{%
+ Command \ifSKV@sw'\string\newtog'\else'\string\deftog'\fi\space
+ doesn't accept list
+ }{%
+ Please submit only one tog to \ifSKV@sw'\string\newtog'\else
+ '\string\deftog'\fi\space at a time.\SKV@MB You can use
+ \ifSKV@sw'\string\NewTogs'\else'\string\DefTogs'\fi\space
+ to define a set of togs.
+ }%
+ }{}%
+ \SKV@ensurenoscape{#2}%
+ \ifSKV@sw
+ \SKV@getswstate\newtog{#3}%
+ \SKV@ifcsdef{SKV@toggle@#1#2}{%
+ \SKV@err{Toggle '#1#2' already defined}%
+ {Please provide a new toggle or use '\string\deftog'.}%
+ }{}%
+ \else
+ \SKV@getswstate\deftog{#3}%
+ \SKV@ifcsundef{SKV@toggle@#1#2}{}{%
+ \SKV@vbmsg{warn}{Toggle '#1#2' redefined\on@line}%
+ }%
+ \fi
+ \SKV@csletcs{SKV@toggle@#1#2}{SKV@t@ggle\SKV@swval}
+}
+\SKV@pdef*\providetog#1{%
+ \SKV@ifcsdef{SKV@toggle@#1}{%
+ \SKV@vbmsg{info}%
+ {Toggle '#1' already defined.\SKV@MB Not redefined\on@line}%
+ }{\SKV@cslet{SKV@toggle@#1}\@secondoftwo}%
+}
+\SKV@pdef*\requiretog#1{\SKV@aftercs\requirecmd{SKV@toggle@#1}[2]{##2}}
+\SKV@def*\settog#1#2{%
+ \SKV@ifcsdef{SKV@toggle@#1}{%
+ \SKV@ifcsdef{SKV@t@ggle#2}{%
+ \SKV@csletcs{SKV@toggle@#1}{SKV@t@ggle#2}%
+ }{%
+ \SKV@err{Inadmissible value '#2' for toggle '#1'}%
+ {Valid values for toggles are 'true', 'or', 'false', and 'off'.}%
+ }%
+ }{\SKV@undeftog@err{#1}}%
+}
+\SKV@def*\togon#1{%
+ \SKV@ifcsdef{SKV@toggle@#1}{%
+ \SKV@cslet{SKV@toggle@#1}\SKV@t@ggleon
+ }{\SKV@undeftog@err{#1}}%
+}
+\SKV@def*\togoff#1{%
+ \SKV@ifcsdef{SKV@toggle@#1}{%
+ \SKV@cslet{SKV@toggle@#1}\SKV@t@ggleoff
+ }{\SKV@undeftog@err{#1}}%
+}
+\SKV@newlet\togtrue\togon
+\SKV@newlet\togfalse\togoff
+\SKV@newlet\SKV@t@ggleon\@firstoftwo
+\SKV@newlet\SKV@t@ggleoff\@secondoftwo
+\SKV@newlet\SKV@t@ggletrue\@firstoftwo
+\SKV@newlet\SKV@t@gglefalse\@secondoftwo
+\SKV@def*\iftogon#1{%
+ \SKV@ifcsdef{SKV@toggle@#1}{\@nameuse{SKV@toggle@#1}}%
+ {\SKV@undeftog@err{#1}}%
+}
+\SKV@def*\iftogoff#1{%
+ \SKV@ifcsdef{SKV@toggle@#1}{%
+ \@nameuse{SKV@toggle@#1}\@secondoftwo\@firstoftwo}%
+ {\SKV@undeftog@err{#1}\@gobbletwo}%
+}
+\SKV@newlet\iftogtrue\iftogon
+\SKV@newlet\iftogfalse\iftogoff
+\deftog{pdf}
+\SKV@ifundef\pdfoutput{}{%
+ \ifnum\pdfoutput<\@ne
+ \SKV@pdef*\SKV@ifpdf{\@secondoftwo}%
+ \else
+ \togon{pdf}%
+ \SKV@pdef*\SKV@ifpdf{\@firstoftwo}%
+ \fi
+ \SKV@pdef*\SKV@ifnotpdf{\SKV@ifpdf\@secondoftwo\@firstoftwo}%
+}
+\SKV@ifundef\ifnotpdf
+ {\let\ifnotpdf\SKV@ifnotpdf}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{ifnotpdf}}}
+\SKV@AtDocumentStart{%
+ \SKV@ifundef\ifpdf
+ {\SKV@pdef*\ifpdf{\SKV@ifpdf}}%
+ {\SKV@vbmsg{info}{\SKV@useinfo{ifpdf}}}%
+}
+\SKV@pdef*\SKV@definedkey@err#1{%
+ \SKV@ifcsundef{\XKV@header#1}{}{%
+ \SKV@err{Key '#1' already defined in family '\XKV@tfam'\SKV@MB
+ with prefix '\SKV@pref'}{Use another key name instead of '#1'.}%
+ }%
+}
+\SKV@pdef*\define@togkey{\SKV@skfalse
+ \XKV@t@stopta{\XKV@testoptd\SKV@define@togkey{}}}
+\SKV@def*\SKV@define@togkey#1#2[#3]{%
+ \SKV@findkeypointers{#2}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@Undef+{\XKV@header\SKV@resa,SKV@toggle@#1\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \ifXKV@pl
+ \def\SKV@next{\SKV@aftercs\SKV@d@f@ne@togkey}%
+ \else
+ \def\SKV@next{\SKV@aftercs\SKV@d@fine@togkey}%
+ \fi
+ \begingroup
+ \edef\SKV@tempa{\endgroup
+ {\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
+ \aftergroup\SKV@next\SKV@tempa
+}
+\SKV@def*\SKV@d@fine@togkey#1#2#3#4#5{%
+ \SKV@d@f@ne@t@gkey#1{#2}{#3}{#4}%
+ {{\SKV@expargs{0}{\SKV@getswstate\SKV@d@fine@togkey}\XKV@resa\@nil
+ \settog{#3}{\SKV@swval}#5}}%
+}
+\SKV@def*\SKV@d@f@ne@togkey#1#2#3#4#5#6{%
+ \SKV@d@f@ne@t@gkey#1{#2}{#3}{#4}%
+ {{\SKV@expargs{0}{\SKV@getswstate\SKV@d@f@ne@togkey}\XKV@resa\@nil
+ \settog{#3}{\SKV@swval}#5}{#6}}%
+}
+\SKV@def*\SKV@d@f@ne@t@gkey#1#2#3#4#5{%
+ \deftog{#3}%
+ \ifXKV@st\XKV@define@default{#2}{#4}\fi
+ \edef#1##1{%
+ \def#1####1{##1\unexpanded{\XKV@sttrue\XKV@checkchoice[\XKV@resa]}%
+ {####1}{true,false,on,off}\unexpanded{#5}%
+ }%
+ }%
+ \ifXKV@pl#1\XKV@pltrue\else#1\XKV@plfalse\fi
+}
+\SKV@pdef*\define@togkeys{\SKV@skfalse
+ \XKV@plfalse\XKV@testoptd\SKV@define@togkeys{}}
+\SKV@def*\SKV@define@togkeys#1#2[#3]{%
+ \SKV@despacelist{#2}%
+ \SKV@for*[,]\SKV@resa\SKV@tempa{%
+ \SKV@expargs{3}%
+ \SKV@d@fine@togkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
+ }%
+}
+\SKV@def*\SKV@d@fine@togkeys#1#2#3{%
+ \SKV@findkeypointers{#1}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@Undef+{\XKV@header\SKV@resa,SKV@toggle@#2\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \edef\SKV@tempa##1##2##3{%
+ ##1\@nameuse{\XKV@header\SKV@resa}%
+ {\SKV@resa}{#2\SKV@resa}{#3}{{##2{#2\SKV@resa}{##3}}}%
+ }%
+ \SKV@tempa\SKV@d@f@ne@t@gkey\settog\XKV@resa
+}
+\SKV@pdef*\newordkey{\SKV@skfalse\XKV@testoptb\SKV@newordkey}
+\SKV@def*\SKV@newordkey#1{%
+ \SKV@findkeypointers{#1}%
+ \SKV@expnext\SKV@definedkey@err\SKV@resa
+ \begingroup
+ \edef\SKV@tempa{\endgroup
+ \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}%
+ {\noexpand\SKV@d@fine@key{\SKV@resa}}%
+ }%
+ \SKV@tempa
+}
+\SKV@pdef*\newcmdkey{\SKV@skfalse\XKV@testoptd\SKV@newcmdkey{cmd}}
+\SKV@def*\SKV@newcmdkey#1#2[#3]#4{%
+ \SKV@reservmp{#1}\SKV@rmpnames
+ \SKV@findkeypointers{#2}%
+ \SKV@expnext\SKV@definedkey@err\SKV@resa
+ \ifXKV@st
+ \SKV@afterfi
+ \SKV@expnext\XKV@define@default\SKV@resa{#3}%
+ \fi
+ \begingroup
+ \edef\SKV@tempa{\def\SKV@noexpcs{\XKV@header\SKV@resa}####1}%
+ \edef\SKV@tempb{\def\SKV@noexpcs{#1\SKV@resa}\unexpanded{{##1}#4}}%
+ \expandafter\expandafter\expandafter\endgroup
+ \expandafter\SKV@tempa\expandafter{\SKV@tempb}%
+}
+\SKV@pdef*\newcmdkeys{\SKV@skfalse\XKV@testoptd\SKV@newcmdkeys{cmd}}
+\SKV@def*\SKV@newcmdkeys#1#2[#3]{%
+ \SKV@despacelist{#2}%
+ \SKV@for*[,]\SKV@resa\SKV@tempa{%
+ \edef\SKV@tempa{\noexpand\SKV@newcmdkey{#1}{\SKV@tempa}}%
+ \SKV@tempa[#3]{}%
+ }%
+}
+\SKV@pdef*\newchoicekey{\SKV@skfalse
+ \XKV@testopta{\XKV@testoptb\SKV@newchoicekey}}
+\SKV@def*\SKV@newchoicekey#1{%
+ \SKV@findkeypointers{#1}%
+ \SKV@expnext\SKV@definedkey@err\SKV@resa
+ \begingroup
+ \edef\SKV@tempa##1{\endgroup\SKV@testopt{##1{\SKV@resa}}{}}%
+ \SKV@tempa\XKV@d@fine@choicekey
+}
+\let\newmenukey\newchoicekey
+\SKV@pdef*\newboolkey{\SKV@skfalse
+ \XKV@t@stopta{\XKV@testoptd\SKV@newboolkey{}}}
+\SKV@def*\SKV@newboolkey#1#2[#3]{%
+ \SKV@findkeypointers{#2}%
+ \SKV@expnext\SKV@definedkey@err\SKV@resa
+ \ifXKV@pl
+ \def\SKV@next{\SKV@aftercs\XKV@d@f@ne@boolkey}%
+ \else
+ \def\SKV@next{\SKV@aftercs\XKV@d@fine@boolkey}%
+ \fi
+ \edef\SKV@tempa{{\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
+ \expandafter\SKV@next\SKV@tempa
+}
+\SKV@pdef*\newboolkeys{\SKV@skfalse
+ \XKV@plfalse\XKV@testoptd\SKV@newboolkeys{}}
+\SKV@def*\SKV@newboolkeys#1#2[#3]{%
+ \SKV@despacelist{#2}%
+ \SKV@for*[,]\SKV@resa\SKV@tempa{%
+ \SKV@definedkey@err\SKV@tempa
+ \SKV@expargs{3}%
+ \XKV@d@fine@boolkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
+ }%
+}
+\SKV@pdef*\newtogkey{\SKV@skfalse
+ \XKV@t@stopta{\XKV@testoptd\SKV@newtogkey{}}}
+\SKV@def*\SKV@newtogkey#1#2[#3]{%
+ \SKV@findkeypointers{#2}%
+ \SKV@expnext\SKV@definedkey@err\SKV@resa
+ \ifXKV@pl
+ \def\SKV@next{\SKV@aftercs\SKV@d@f@ne@togkey}%
+ \else
+ \def\SKV@next{\SKV@aftercs\SKV@d@fine@togkey}%
+ \fi
+ \begingroup
+ \edef\SKV@tempa{\endgroup
+ {\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
+ \aftergroup\SKV@next\SKV@tempa
+}
+\SKV@pdef*\newtogkeys{\SKV@skfalse
+ \XKV@plfalse\XKV@testoptd\SKV@newtogkeys{}%
+}
+\SKV@def*\SKV@newtogkeys#1#2[#3]{%
+ \SKV@despacelist{#2}%
+ \SKV@for*[,]\SKV@resa\SKV@tempa{%
+ \SKV@definedkey@err\SKV@tempa
+ \SKV@expargs{3}\SKV@d@fine@togkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
+ }%
+}
+\SKV@pdef*\define@biboolkeys{\SKV@compopta\define@boolkey\SKV@biboolkeys}
+\SKV@pdef*\newbiboolkeys{\SKV@compopta\newboolkey\SKV@biboolkeys}
+\SKV@pdef*\define@uniboolkeys{\SKV@compopta\define@boolkey\SKV@uniboolkeys}
+\SKV@pdef*\newuniboolkeys{\SKV@compopta\newboolkey\SKV@uniboolkeys}
+\SKV@pdef*\define@biuniboolkeys{%
+ \SKV@savstate
+ \SKV@t@stoptb{\SKV@compopta\define@boolkey\SKV@biuniboolkeys}%
+}
+\SKV@pdef*\newbiuniboolkeys{%
+ \SKV@savstate
+ \SKV@t@stoptb{\SKV@compopta\newboolkey\SKV@biuniboolkeys}%
+}
+\SKV@pdef*\define@bitogkeys{\SKV@compopta\define@togkey\SKV@bitogkeys}
+\SKV@pdef*\newbitogkeys{\SKV@compopta\newtogkey\SKV@bitogkeys}
+\SKV@pdef*\define@unitogkeys{\SKV@compopta\define@togkey\SKV@unitogkeys}
+\SKV@pdef*\newunitogkeys{\SKV@compopta\newtogkey\SKV@unitogkeys}
+\SKV@pdef*\define@biunitogkeys{%
+ \SKV@savstate
+ \SKV@t@stoptb{\SKV@compopta\define@togkey\SKV@biunitogkeys}%
+}
+\SKV@pdef*\newbiunitogkeys{%
+ \SKV@savstate
+ \SKV@t@stoptb{\SKV@compopta\newtogkey\SKV@biunitogkeys}%
+}
+\SKV@def*\SKV@compopta#1#2{%
+ \let\SKV@c@mpkey#1\let\SKV@co@pkey#2%
+ \SKV@testopt{\SKV@compoptb}{KV}%
+}
+\SKV@def*\SKV@compoptb[#1]#2{\SKV@testopt{\SKV@compoptc[#1]{#2}}{mp@}}
+\SKV@def*\SKV@compoptc[#1]#2[#3]#4{%
+ \SKV@testopt{\SKV@co@pkey[#1]{#2}[#3]{#4}}{true}}
+\SKV@def*\SKV@biboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \ifswitchon{#3#4}{\switchoff{#3#6}}{\switchon{#3#6}#8\relax}%
+ }%
+ \@namedef{#1@#2@#6@func}{%
+ #8\relax
+ \ifswitchon{#3#6}{\switchoff{#3#4}}{\switchon{#3#4}#7\relax}%
+ }%
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@uniboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \ifswitchon{#3#4}{\switchon{#3#6}#8\relax}{\switchoff{#3#6}}%
+ }%
+ \@namedef{#1@#2@#6@func}{%
+ #8\relax
+ \ifswitchon{#3#6}{\switchon{#3#4}#7\relax}{\switchoff{#3#4}}%
+ }%
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@biuniboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \SKV@aftercs\def{#1@#2@#6@func}{#8\relax}%
+ \ifswitchon{SKV@st}{%
+ \ifswitchon{SKV@pl}{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\ifswitchon{#3#4}{}{\switchoff{#3#6}}%
+ }%
+ }{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \ifswitchon{#3#4}{}{\switchon{#3#6}\@nameuse{#1@#2@#6@func}}%
+ }%
+ }%
+ }{%
+ \ifswitchon{SKV@pl}{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\ifswitchon{#3#4}{\switchoff{#3#6}}{}%
+ }%
+ }{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \ifswitchon{#3#4}{\switchon{#3#6}\@nameuse{#1@#2@#6@func}}{}%
+ }%
+ }%
+ }%
+ \SKV@resstate
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@bitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \iftogon{#3#4}{\togoff{#3#6}}{\togon{#3#6}#8\relax}%
+ }%
+ \@namedef{#1@#2@#6@func}{%
+ #8\relax
+ \iftogon{#3#6}{\togoff{#3#4}}{\togon{#3#4}#7\relax}%
+ }%
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@unitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax
+ \iftogon{#3#4}{\togon{#3#6}#8\relax}{\togoff{#3#6}}%
+ }%
+ \@namedef{#1@#2@#6@func}{%
+ #8\relax
+ \iftogon{#3#6}{\togon{#3#4}#7\relax}{\togoff{#3#4}}%
+ }%
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@biunitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
+ \@namedef{#1@#2@#6@func}{#8}%
+ \ifswitchon{SKV@st}{%
+ \ifswitchon{SKV@pl}{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\iftogoff{#3#4}{\togoff{#3#6}}{}%
+ }%
+ }{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\iftogoff{#3#4}{\togon{#3#6}#8\relax}{}%
+ }%
+ }%
+ }{%
+ \ifswitchon{SKV@pl}{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\iftogon{#3#4}{\togoff{#3#6}}{}%
+ }%
+ }{%
+ \@namedef{#1@#2@#4@func}{%
+ #7\relax\iftogon{#3#4}{\togon{#3#6}#8\relax}{}%
+ }%
+ }%
+ }%
+ \SKV@resstate
+ \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+}
+\SKV@def*\SKV@compk@y#1#2#3#4#5#6{%
+ \SKV@c@mpkey+[#1]{#2}[#3]{#4}[#5]{\@nameuse{#1@#2@#4@func}}%
+ {\SKV@inputerr{##1}{#4}}%
+ \SKV@c@mpkey+[#1]{#2}[#3]{#6}[#5]{\@nameuse{#1@#2@#6@func}}%
+ {\SKV@inputerr{##1}{#6}}%
+}
+\SKV@pdef*\SKV@keylistrema#1\@nil#2{%
+ \long\edef\SKV@remainder{\unexpanded{#1}}%
+ \SKV@oifblank{\SKV@remainder}{}{%
+ \def\SKV@tempa##1#2\@nil{\def\SKV@remainder{##1}}%
+ \expandafter\SKV@tempa\SKV@remainder\@nil
+ }%
+}
+\SKV@pdef*\define@keylist{%
+ \SKV@define@keylist\define@key\define@cmdkey
+ \define@boolkey\define@togkey\define@choicekey
+}
+\SKV@pdef*\newkeylist{%
+ \SKV@define@keylist\newordkey\newcmdkey
+ \newboolkey\newtogkey\newchoicekey
+}
+\newcommand*\SKV@define@keylist[5]{%
+ \let\SKV@def@ordkey#1%
+ \let\SKV@def@cmdkey#2%
+ \let\SKV@def@boolkey#3%
+ \let\SKV@def@togkey#4%
+ \let\SKV@def@choicekey#5%
+ \SKV@savstate
+ \begingroup
+ \@makeother{\#}%
+ \SKV@t@stopta\SKV@d@fine@keylist
+}
+\SKV@def*\choicekeyvalues{%
+ \SKV@t@stopta{\SKV@testopt\SKV@choic@keyvalues\SKV@keyprefix}}
+\SKV@def*\SKV@choic@keyvalues[#1]{%
+ \SKV@testopt{\SKV@choic@keyv@lues[#1]}\SKV@keyfamily}
+\SKV@def*\SKV@choic@keyv@lues[#1][#2]#3#4{%
+ \ifSKV@st
+ \SKV@csedef{#1@#2@#3@altlist}{#4}%
+ \else
+ \SKV@ifcsundef{#1@#2@#3@altlist}{%
+ \SKV@csedef{#1@#2@#3@altlist}{#4}%
+ }{%
+ \SKV@err
+ {Problem with \string\choicekeyvalues\space for key '#3'}%
+ {You have attempted to set two \string\choicekeyvalues\SKV@MB
+ for choice key '#3' in the same family '#2'\SKV@MB
+ with the same prefix '#1'. You can only do\SKV@MB
+ that if you use the starred variant of \string\choicekeyvalues.}%
+ }%
+ \fi
+}
+\SKV@newlet\CKVS\choicekeyvalues
+\SKV@def*\SKV@detok@z@p#1{%
+ \edef#1{\detokenize\expandafter{#1}\space}%
+ \edef#1{\expandafter\zap@space#1\@empty}%
+}
+\SKV@def*\SKV@detok@zsp#1{%
+ \SKV@ensurescape{#1}%
+ \begingroup
+ \SKV@for*[,]#1\SKV@tempa{%
+ \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}\space}%
+ \edef\SKV@tempa{\expandafter\zap@space\SKV@tempa\@empty}%
+ \SKV@csxdef*{SKV@zsp@\expandafter\@gobble\SKV@tempa}%
+ {\SKV@expox{\SKV@tempa}}%
+ }%
+ \endgroup
+}
+\SKV@def*\SKV@detok@dsp#1{%
+ \SKV@ensurescape{#1}%
+ \begingroup
+ \SKV@for*[,]#1\SKV@tempa{%
+ \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}}%
+ \SKV@despacectt\SKV@tempa
+ \SKV@csxdef*{SKV@dsp@\expandafter\@gobble\SKV@tempa}%
+ {\SKV@expox{\SKV@tempa}}%
+ }%
+ \endgroup
+}
+\SKV@def*\SKV@exceplist{%
+ \par,\if,\ifcase,\or,\else,\skif,\iftog,\ifswitch}
+\SKV@detok@dsp\SKV@exceplist
+\SKV@def*\SKV@noiferr#1#2{%
+ \SKV@err{You can't use '\@backslashchar #1' in\SKV@MB
+ key macro within keylist}%
+ {Use '\@backslashchar #2' instead of '\@backslashchar #1'.}%
+}
+\SKV@pdef*\uservalue{\uservalue}
+\SKV@pdef*\guservalue{\guservalue}
+\SKV@pdef*\savevalue{\savevalue}
+\SKV@pdef*\gsavevalue{\gsavevalue}
+\SKV@def\SKV@define@multkeys#1,#2,#3,#4\@nil{%
+ \let\SKV@altlisterr\z@
+ \SKV@sp@def{#1}\SKV@tempa
+ \SKV@checkchoice{\SKV@tempa}{ord,cmd,bool,tog,choice,menu}{%
+ \ifnum\nr=5%
+ \let\SKV@keytype\nr
+ \else
+ \edef\SKV@keytype{\the\numexpr\nr+1}%
+ \fi
+ }{%
+ \SKV@checkchoice{\SKV@tempa}{1,2,3,4,5}{%
+ \edef\SKV@keytype{\the\numexpr\nr+1}%
+ }{%
+ \SKV@err{Unknown key type/identifier '\string#1'}%
+ {Valid key types are 'ord', 'cmd', 'bool', 'tog',
+ 'choice', 'menu',\SKV@MB and '1', '2', '3', '4', '5'}%
+ }%
+ }%
+ \SKV@ifnotempty{#2}{}{%
+ \SKV@err{No key name specified for key type '\string#1'}%
+ {\string\define@keylist: key name required for all keys}%
+ }%
+ \begingroup
+ \SKV@ifblank{#4}{}{%
+ \edef\SKV@tempb{\detokenize{#4}\space}%
+ \edef\SKV@tempb{\expandafter\zap@space\SKV@tempb\@empty}%
+ \@expandtwoargs\SKV@in@\SKV@dsp@if\SKV@tempb
+ \ifin@
+ \@expandtwoargs\SKV@in@\SKV@dsp@iftog\SKV@tempb
+ \ifin@\else
+ \@expandtwoargs\SKV@in@\SKV@dsp@ifswitch\SKV@tempb
+ \ifin@\else\SKV@noiferr{if}{skif}\fi
+ \fi
+ \fi
+ \@expandtwoargs\SKV@in@\SKV@dsp@par\SKV@tempb
+ \ifin@\SKV@afterfi\SKV@noiferr{par}{endgraf}\fi
+ \@expandtwoargs\SKV@in@\SKV@dsp@ifcase\SKV@tempb
+ \ifin@\SKV@afterfi\SKV@noiferr{ifcase}{skifcase}\fi
+ \@expandtwoargs\SKV@in@\SKV@dsp@or\SKV@tempb
+ \ifin@\SKV@afterfi\SKV@noiferr{or}{skor}\fi
+ \@expandtwoargs\SKV@in@\SKV@dsp@else\SKV@tempb
+ \ifin@\SKV@afterfi\SKV@noiferr{else}{skelse}\fi
+ }%
+ \protected@edef\SKV@tempa{\endgroup
+ \ifcase\SKV@keytype\relax
+ \or
+ \noexpand\SKV@def@ordkey[\SKV@keyprefix]{\SKV@keyfamily}%
+ {#2}[#3]{\unexpanded{#4}}%
+ \or
+ \noexpand\SKV@def@cmdkey[\SKV@keyprefix]{\SKV@keyfamily}%
+ [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}%
+ \or
+ \noexpand\SKV@def@boolkey+[\SKV@keyprefix]{\SKV@keyfamily}%
+ [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}{%
+ \unexpanded{\SKV@inputerr{##1}{#2}}%
+ }%
+ \or
+ \noexpand\SKV@def@togkey+[\SKV@keyprefix]{\SKV@keyfamily}%
+ [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}{%
+ \unexpanded{\SKV@inputerr{##1}{#2}}%
+ }%
+ \or
+ \SKV@ifcsdef{\SKV@keyprefix @\SKV@keyfamily @#2@altlist}{}%
+ {\let\SKV@altlisterr\@ne}%
+ \noexpand\SKV@def@choicekey*+[\SKV@keyprefix]{\SKV@keyfamily}{#2}%
+ [\unexpanded{\val\nr}]{%
+ \SKV@csuse{\SKV@keyprefix @\SKV@keyfamily @#2@altlist}%
+ }[#3]{\unexpanded{#4}}{\unexpanded{\SKV@inputerr{##1}{#2}}}%
+ \fi
+ }%
+ \SKV@tempa
+ \ifnum\SKV@altlisterr=\@ne
+ \SKV@afterfi
+ \SKV@err{%
+ Choice key '#2' can't be defined.\SKV@MB
+ Alternate key values list for '#2' is empty
+ }{%
+ You need to first define admissible\SKV@MB
+ key values through '\string\choicekeyvalues'\SKV@MB
+ for choice key '#2'.
+ }%
+ \fi
+}
+\SKV@def*\SKV@resvfampf#1#2{%
+ \begingroup
+ \SKV@expnext\XKV@checksanitizeb#2\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \XKV@knftrue
+ \XKV@whilist\SKV@tempa\SKV@tempa\ifXKV@knf\fi{%
+ \SKV@aftercs\ifx{XKV@#1}\SKV@tempa\XKV@knffalse\fi
+ }%
+ \unless\ifXKV@knf
+ \SKV@afterfi
+ \SKV@err{Key #1 '\SKV@tempa' is reserved}%
+ {You have used a reserved key #1: '\SKV@tempa'.\SKV@MB
+ Use another #1 name instead of '\SKV@tempa'.}%
+ \fi
+ \endgroup
+}
+\SKV@redef*\XKV@makepf#1{%
+ \SKV@sp@def{#1}\XKV@prefix
+ \unless\ifSKV@sk
+ \SKV@resvfampf{prefix}\SKV@rkpnames
+ \fi
+ \edef\SKV@pref{\ifx\XKV@prefix\@empty\else\XKV@prefix\fi}%
+ \edef\XKV@prefix{\ifx\XKV@prefix\@empty\else\XKV@prefix @\fi}%
+}
+\SKV@redef*\XKV@makehd#1{%
+ \SKV@expargs{3}\SKV@sp@def{{#1}}\XKV@header\@nil
+ \unless\ifSKV@sk
+ \SKV@resvfampf{family}\SKV@rfnames
+ \fi
+ \edef\XKV@header{%
+ \XKV@prefix\ifx\XKV@header\@empty\else\XKV@header @\fi}%
+}
+\SKV@def*\SKV@resolvekey#1#2\@nil#3{%
+ \def\SKV@resolve##1#2##2##3\@nil##4{%
+ \edef##4{\unexpanded{##2}}%
+ \ifx##4\@nnil
+ \edef##4{\unexpanded{##1}}%
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ \SKV@resolve#1#2{\@nil}\@nil#3%
+}
+\SKV@def*\SKV@addtouserval{%
+ \SKV@addtolist+{SKV@\XKV@header uservalue}\SKV@resa}
+\SKV@def*\SKV@gaddtouserval{%
+ \SKV@addtolist+!{SKV@\XKV@header uservalue}\SKV@resa}
+\SKV@def*\SKV@addtosave{\SKV@addtolist+{XKV@\XKV@header save}\SKV@resa}
+\SKV@def*\SKV@gaddtosave{\begingroup
+ \edef\SKV@tempa{\endgroup
+ \SKV@addtolist+!{XKV@\XKV@header save}{\global{\SKV@resa}}}%
+ \SKV@tempa
+}
+\SKV@def*\SKV@findkeypointers#1{%
+ \SKV@resolvekey{#1}\uservalue\savevalue\@nil\SKV@resa
+ {\SKV@addtouserval\SKV@addtosave}%
+ {\SKV@resolvekey{#1}\guservalue\savevalue\@nil\SKV@resa
+ {\SKV@gaddtouserval\SKV@addtosave}%
+ {\SKV@resolvekey{#1}\savevalue\uservalue\@nil\SKV@resa
+ {\SKV@addtouserval\SKV@addtosave}%
+ {\SKV@resolvekey{#1}\gsavevalue\uservalue\@nil\SKV@resa
+ {\SKV@addtouserval\SKV@gaddtosave}%
+ {\SKV@resolvekey{#1}\guservalue\gsavevalue\@nil\SKV@resa
+ {\SKV@gaddtouserval\SKV@gaddtosave}%
+ {\SKV@resolvekey{#1}\gsavevalue\guservalue\@nil\SKV@resa
+ {\SKV@gaddtouserval\SKV@gaddtosave}%
+ {\SKV@resolvekey{#1}\uservalue\@nil\SKV@resa
+ {\SKV@addtouserval}%
+ {\SKV@resolvekey{#1}\guservalue\@nil\SKV@resa
+ {\SKV@gaddtouserval}%
+ {\SKV@resolvekey{#1}\savevalue\@nil\SKV@resa
+ {\SKV@addtosave}%
+ {\SKV@resolvekey{#1}\gsavevalue\@nil\SKV@resa
+ {\SKV@gaddtosave}%
+ {}}}}}}}}}}%
+}
+\SKV@predef*\define@key{\SKV@skfalse\XKV@testoptb\XKV@define@key}
+\def\XKV@define@key#1{%
+ \SKV@findkeypointers{#1}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@csundef{\XKV@header\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \begingroup
+ \edef\SKV@tempa{\endgroup
+ \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}%
+ {\noexpand\SKV@d@fine@key{\SKV@resa}}%
+ }%
+ \SKV@tempa
+}
+\def\XKV@d@fine@key#1[#2]#3{%
+ \XKV@define@default{#1}{#2}%
+ \@namedef{\XKV@header#1}##1{#3}%
+}
+\def\SKV@d@fine@key#1#2{\@namedef{\XKV@header#1}##1{#2}}
+\SKV@def*\SKV@reservmp#1#2{%
+ \begingroup
+ \SKV@sp@def{#1}\SKV@tempb
+ \SKV@expnext\XKV@checksanitizeb#2\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \XKV@knftrue
+ \XKV@whilist\SKV@tempa\SKV@tempa\ifXKV@knf\fi{%
+ \ifx\SKV@tempb\SKV@tempa\XKV@knffalse\fi
+ }%
+ \unless\ifXKV@knf
+ \SKV@afterfi
+ \SKV@err{Macro prefix '\SKV@tempa' is reserved}%
+ {You have used a reserved macro prefix: '\SKV@tempa'.\SKV@MB
+ Use another macro prefix name instead of '\SKV@tempa'.}%
+ \fi
+ \endgroup
+}
+\SKV@predef*\define@cmdkey{%
+ \SKV@skfalse\XKV@testoptd\XKV@define@cmdkey{cmd}}
+\SKV@predef*\define@cmdkeys{%
+ \SKV@skfalse\XKV@testoptd\XKV@define@cmdkeys{cmd}}
+\def\XKV@define@cmdkey#1#2[#3]#4{%
+ \SKV@reservmp{#1}\SKV@rmpnames
+ \SKV@findkeypointers{#2}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@Undef+{\XKV@header\SKV@resa,#1\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \ifXKV@st
+ \SKV@afterfi
+ \SKV@expnext\XKV@define@default\SKV@resa{#3}%
+ \fi
+ \begingroup
+ \def\SKV@tempa{%
+ \expandafter\def\csname\XKV@header\SKV@resa\endcsname####1}%
+ \SKV@threexp\endgroup\expandafter\SKV@tempa\expandafter%
+ {\expandafter\def\csname#1\SKV@resa\endcsname{##1}#4}%
+}
+\SKV@predef*\define@choicekey{\SKV@skfalse
+ \XKV@testopta{\XKV@testoptb\XKV@define@choicekey}}
+\SKV@newlet\define@menukey\define@choicekey
+\def\XKV@define@choicekey#1{%
+ \SKV@findkeypointers{#1}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@csundef{\XKV@header\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \begingroup
+ \edef\SKV@tempa{\endgroup
+ \SKV@testopt{\noexpand\XKV@d@fine@choicekey{\SKV@resa}}{}%
+ }%
+ \SKV@tempa
+}
+\SKV@predef*\define@boolkey{\SKV@skfalse
+ \XKV@t@stopta{\XKV@testoptd\XKV@define@boolkey{}}}
+\SKV@predef*\define@boolkeys{\SKV@skfalse
+ \XKV@plfalse\XKV@testoptd\XKV@define@boolkeys{}}
+\def\XKV@define@boolkey#1#2[#3]{%
+ \SKV@findkeypointers{#2}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}%
+ \SKV@Undef+{\XKV@header\SKV@resa,#1\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \ifXKV@pl
+ \def\SKV@next{\SKV@aftercs\XKV@d@f@ne@boolkey}%
+ \else
+ \def\SKV@next{\SKV@aftercs\XKV@d@fine@boolkey}%
+ \fi
+ \edef\SKV@tempa{{\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
+ \expandafter\SKV@next\SKV@tempa
+}
+\def\XKV@d@fine@boolkey#1#2#3#4#5{%
+ \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}%
+ {{\SKV@expargs{0}{\SKV@getswstate\XKV@d@fine@boolkey}\XKV@resa\@nil
+ \csname#3\SKV@swval\endcsname#5}}%
+}
+\def\XKV@d@f@ne@boolkey#1#2#3#4#5#6{%
+ \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}%
+ {{\SKV@expargs{0}{\SKV@getswstate\XKV@d@f@ne@boolkey}\XKV@resa\@nil
+ \csname#3\SKV@swval\endcsname#5}{#6}}%
+}
+\def\XKV@d@f@ne@b@olkey#1#2#3#4#5{%
+ \csnewif{if#3}%
+ \ifXKV@st\XKV@define@default{#2}{#4}\fi
+ \edef#1##1{%
+ \def#1####1{##1\unexpanded{\XKV@sttrue\XKV@checkchoice[\XKV@resa]}%
+ {####1}{true,false,on,off}\unexpanded{#5}%
+ }%
+ }%
+ \ifXKV@pl#1\XKV@pltrue\else#1\XKV@plfalse\fi
+}
+\def\XKV@d@fine@boolkeys#1#2#3{%
+ \SKV@findkeypointers{#1}%
+ \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
+ prefix '\SKV@pref' redefined\on@line}
+ \SKV@Undef+{\XKV@header\SKV@resa,#2\SKV@resa}%
+ }%
+ \SKV@expnext\SKV@reservkey@err\SKV@resa
+ \SKV@expnext\SKV@suspkey@err\SKV@resa
+ \edef\SKV@tempa##1##2##3{%
+ ##1\@nameuse{\XKV@header\SKV@resa}{\SKV@resa}%
+ {#2\SKV@resa}{#3}{{##2{#2\SKV@resa##3}}}%
+ }%
+ \SKV@tempa\XKV@d@f@ne@b@olkey\@nameuse\XKV@resa
+}
+\SKV@pdef*\reserve@keys{\@testopt\SKV@reserve@keys{KV}}
+\SKV@def*\SKV@reserve@keys[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@res@rve@keys\SKV@tempa{#2}{#3}%
+ }%
+}
+\SKV@def*\SKV@res@rve@keys#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@for@b\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \SKV@res@rve@k@ys{#3}%
+ }%
+}
+\SKV@def*\SKV@res@rve@k@ys#1{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@ifcsdef{\XKV@header\SKV@tempa}{%
+ \SKV@err{%
+ Key '\SKV@tempa' with prefix '\SKV@pref' in family
+ \SKV@MB '\XKV@tfam' is already defined
+ }{%
+ Key '\SKV@tempa' in family '\XKV@tfam' can't be reserved.
+ \SKV@MB You may wish to remove it before reserving it.
+ \SKV@MB In that case, you can use '\string\remove@keys'.
+ }%
+ }{%
+ \SKV@csedef*{\XKV@header\SKV@tempa}{%
+ \SKV@err{%
+ Key '\SKV@tempa' with prefix '\SKV@pref' in family
+ '\XKV@tfam'\SKV@MB was reserved\on@line
+ }{%
+ Unreserve '\SKV@tempa' before use.
+ }%
+ }%
+ \SKV@csdef*{\XKV@header\SKV@tempa @reser}{}%
+ }%
+ }%
+}
+\SKV@def*\SKV@reservkey@err#1{%
+ \SKV@ifcsdef{\XKV@header#1@reser}\SKV@err\@gobbletwo
+ {Key '#1' with prefix '\SKV@pref'\SKV@MB
+ is reserved in family '\XKV@tfam'}{Unreserve '#1' before use.}%
+}
+\SKV@def*\ifkeyreserved{\@testopt\SKV@ifkeyreserved{KV}}
+\SKV@def*\SKV@ifkeyreserved[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@swtrue
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@ifkey@reserved\SKV@tempa{#2}{#3}%
+ }%
+ \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
+}
+\SKV@def*\SKV@ifkey@reserved#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@sp@def{#3}\XKV@tkey
+ \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
+ \XKV@makehd\XKV@tfam
+ \SKV@ifcsdef{\XKV@header\XKV@tkey @reser}\SKV@swfalse\relax
+ }%
+}
+\SKV@def*\ifkeysuspended{\@testopt\SKV@ifkeysuspended{KV}}
+\SKV@def*\SKV@ifkeysuspended[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@swtrue
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@ifkey@suspended\SKV@tempa{#2}{#3}%
+ }%
+ \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
+}
+\SKV@def*\SKV@ifkey@suspended#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@sp@def{#3}\XKV@tkey
+ \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
+ \XKV@makehd\XKV@tfam
+ \SKV@ifcsdef{\XKV@header\XKV@tkey @susp}\SKV@swfalse\relax
+ }%
+}
+\SKV@def*\ifkeydefined{\@testopt\SKV@ifkeydefined{KV}}
+\SKV@def*\SKV@ifkeydefined[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@swtrue
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@ifk@ydefined\SKV@tempa{#2}{#3}%
+ }%
+ \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
+}
+\SKV@def*\SKV@ifk@ydefined#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@sp@def{#3}\XKV@tkey
+ \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
+ \XKV@makehd\XKV@tfam
+ \SKV@ifcsdef{\XKV@header\XKV@tkey}\SKV@swfalse\relax
+ }%
+}
+\SKV@def*\SKV@disabledkey@err{%
+ \SKV@err{%
+ Key '\SKV@disabledkey' with prefix '\SKV@pref' in family
+ \SKV@MB '\XKV@tfam' was disabled\on@line
+ }{%
+ You can't set or reset '\SKV@disabledkey' at this\SKV@MB
+ late stage. Perhaps you're required to set it \SKV@MB
+ earlier, within a package or in the document's preamble.
+ }%
+}
+\def\disable@keys{%
+ \SKV@ifstar{\@testopt\XKV@disable@keys{KV}}%
+ {\@testopt\SKV@disable@keys{KV}}%
+}
+\SKV@def*\SKV@disable@keys[#1]#2#3{%
+ \SKV@locfalse
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@dis@ble@keys\SKV@tempa{#2}{#3}%
+ }%
+}
+\SKV@def*\SKV@dis@ble@keys#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@for@b\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \SKV@dis@ble@k@ys{#3}%
+ }%
+}
+\SKV@def*\SKV@dis@ble@k@ys#1{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
+ \ifSKV@verbose\SKV@disabledkey@warn\fi
+ }{%
+ \SKV@dis@ble@k@y@\SKV@tempa
+ }%
+ }%
+}
+\def\SKV@disabledkey@warn{%
+ \SKV@warn{Key '\SKV@tempa' with prefix '\SKV@pref'
+ \SKV@MB is undefined in family '\XKV@tfam':
+ \SKV@MB can't be \ifSKV@loc localized
+ \else disabled\fi\on@line
+ }%
+}
+\def\SKV@disabledkey@info{%
+ \SKV@info{Key '\SKV@disabledkey' with prefix '\SKV@pref'
+ in family '\XKV@tfam'\SKV@MB was \ifSKV@loc localized
+ \else disabled\fi\on@line
+ }%
+}
+\SKV@def*\SKV@dis@ble@k@y@#1{%
+ \edef\SKV@disabledkey{#1}%
+ \SKV@ifcsundef{\XKV@header#1@default}{%
+ \edef#1{\noexpand\XKV@define@key{#1}}%
+ }{%
+ \edef#1{\noexpand\XKV@define@key{#1}[]}%
+ }%
+ \SKV@expargs{0}#1\SKV@disabledkey@err\@nil
+ \ifSKV@verbose\SKV@disabledkey@info\fi
+}
+\SKV@pdef*\localize@keys{%
+ \SKV@onlypackage\SKV@savstate
+ \SKV@t@stopta{\@testopt\SKV@localize@keys{KV}}%
+}
+\SKV@def*\SKV@localize@keys[#1]#2#3{%
+ \SKV@loctrue
+ \ifSKV@st
+ \expandafter\SKV@BeforeDocumentStart
+ \else
+ \expandafter\SKV@AfterPackageEnd
+ \fi
+ {%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@dis@ble@keys\SKV@tempa{#2}{#3}%
+ }%
+ }%
+ \SKV@resstate
+}
+\SKV@def*\SKV@suspkey@err#1{%
+ \SKV@ifcsdef{\XKV@header#1@susp}\SKV@err\@gobbletwo
+ {Key '#1' was suspended from family '\XKV@tfam'}%
+ {You can use \string\restore@key\space to restore '#1'.}%
+}
+\SKV@def*\SKV@suspkey@e@r{%
+ \SKV@err{Key '\SKV@suspkey' in family '\XKV@tfam' was\SKV@MB
+ suspended\on@line}{You can use \string\restore@key\space
+ to restore '\SKV@suspkey'.}%
+}
+\SKV@pdef*\suspend@keys{\@testopt\SKV@suspend@keys{KV}}
+\SKV@def*\SKV@suspend@keys[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@s@spend@keys\SKV@tempa{#2}{#3}%
+ }%
+}
+\SKV@def*\SKV@s@spend@keys#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@for@b\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \SKV@s@sp@nd@keys{#3}%
+ }%
+}
+\SKV@def*\SKV@s@sp@nd@keys#1{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
+ \SKV@vbmsg{warn}{%
+ Key '\SKV@tempa' with prefix '\SKV@pref'
+ \SKV@MB is undefined in family '\XKV@tfam':
+ \SKV@MB can't be suspended\on@line}%
+ }{%
+ \SKV@s@sp@nd@k@ys\SKV@tempa
+ }%
+ }%
+}
+\SKV@def*\SKV@s@sp@nd@k@ys#1{%
+ \SKV@ifcsdef{\XKV@header#1@susp}{%
+ \SKV@err{%
+ Key '#1' with prefix '\SKV@pref'
+ was suspended from family '\XKV@tfam'
+ }{%
+ You can use \string\restore@key\space to restore '#1'.
+ }%
+ }{%
+ \edef\SKV@suspkey{#1}%
+ \global\SKV@csletcs{\XKV@header#1@susp}{\XKV@header#1}%
+ \SKV@csedef*{\XKV@header#1}{\SKV@suspkey@e@r}%
+ \SKV@vbmsg{info}{Key '\SKV@suspkey' with prefix '\SKV@pref' in
+ \SKV@MB family '\XKV@tfam' was suspended\on@line}%
+ }%
+}
+\SKV@pdef*\restore@keys{\@testopt\SKV@restore@keys{KV}}
+\SKV@def*\SKV@restore@keys[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@r@store@keys\SKV@tempa{#2}{#3}%
+ }%
+}
+\SKV@def*\SKV@r@store@keys#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@for@b\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \SKV@r@st@re@keys{#3}%
+ }%
+}
+\SKV@def*\SKV@r@st@re@keys#1{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
+ \SKV@vbmsg{warn}{Key '\SKV@tempa' with prefix '\SKV@pref'
+ \SKV@MB is undefined in family '\XKV@tfam':
+ \SKV@MB can't be restored\on@line}%
+ }{%
+ \SKV@r@st@re@k@ys\SKV@tempa
+ }%
+ }%
+}
+\SKV@def*\SKV@r@st@re@k@ys#1{%
+ \SKV@ifcsundef{\XKV@header#1@susp}{%
+ \SKV@err{Key '#1' wasn't suspended from family
+ \SKV@MB '\XKV@tfam': can't be restored\on@line}%
+ {I can't restore unsuspended key '#1'}%
+ }{%
+ \edef\SKV@restoredkey{#1}%
+ \SKV@csletcs{\XKV@header#1}{\XKV@header#1@susp}%
+ \SKV@csundef{\XKV@header#1@susp}%
+ \SKV@vbmsg{info}{Key '\SKV@restoredkey' with prefix
+ '\SKV@pref' in family \SKV@MB '\XKV@tfam' restored\on@line}%
+ }%
+}
+\SKV@pdef*\remove@keys{\@testopt\SKV@remove@keys{KV}}
+\SKV@def*\SKV@remove@keys[#1]#2#3{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for*[,]\SKV@tempa\SKV@tempa{%
+ \SKV@expnext\SKV@r@move@keys\SKV@tempa{#2}{#3}%
+ }%
+}
+\SKV@def*\SKV@r@move@keys#1#2#3{%
+ \XKV@makepf{#1}%
+ \XKV@checksanitizeb{#2}\XKV@fams
+ \SKV@despacelist*\XKV@fams
+ \SKV@for@b\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam
+ \SKV@r@m@ve@keys{#3}%
+ }%
+}
+\SKV@def*\SKV@r@m@ve@keys#1{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@despacelist*\SKV@tempa
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@ifcsundef{\XKV@header\SKV@tempa @susp}{}{%
+ \SKV@err{Key '\SKV@tempa' with prefix '\SKV@pref'
+ \SKV@MB was suspended from family '\XKV@tfam':
+ \SKV@MB I can't remove/unreserve it\on@line.
+ \SKV@MB You need to first restore key '\SKV@tempa'
+ \SKV@MB before you can remove/unreserve it}%
+ {First restore key '\SKV@tempa' before removing it.}%
+ }%
+ \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
+ \SKV@vbmsg{warn}{Key '\SKV@tempa' with prefix '\SKV@pref'
+ \SKV@MB is undefined in family '\XKV@tfam':
+ \SKV@MB I can't remove or unreserve it\on@line}%
+ }{%
+ \SKV@r@m@ve@k@ys\SKV@tempa
+ }%
+ }%
+}
+\SKV@def*\SKV@r@m@ve@k@ys#1{%
+ \begingroup
+ \edef\SKV@tempa{\XKV@header#1,\XKV@header#1@default,
+ \XKV@header#1@func,\XKV@header#1@altlist,
+ \XKV@header#1@reser
+ }%
+ \SKV@for@b\SKV@tempa\SKV@tempa{%
+ \SKV@despacectt\SKV@tempa
+ \SKV@csgundef{\SKV@tempa}%
+ }%
+ \endgroup
+ \SKV@vbmsg{info}{Key '#1' with prefix '\SKV@pref' in family\SKV@MB
+ '\XKV@tfam' was removed\on@line}%
+}
+\SKV@newlet\unreserve@keys\remove@keys
+\SKV@def*\uservaluekeys{\XKV@testoptb\SKV@uservaluekeys}
+\SKV@def*\SKV@uservaluekeys#1{%
+ \SKV@ifcsundef{SKV@\XKV@header uservalue}{%
+ \XKV@checksanitizeb{#1}\SKV@tempa
+ \SKV@csxdef*{SKV@\XKV@header uservalue}{\SKV@expox{\SKV@tempa}}%
+ }{%
+ \SKV@aftercs\XKV@merge{SKV@\XKV@header uservalue}{#1}\XKV@getsg
+ }%
+}
+\SKV@def*\SKV@undefinedkeys#1#2#3{%
+ \edef\SKV@resvd##1{\SKV@addtolist![;]##1{(#1:#2:#3)}}%
+ \SKV@resvd\SKV@und@finedkeys
+}
+\SKV@predef*\ExecuteOptionsX{%
+ \SKV@sktrue\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys}
+\SKV@predef*\setkeys{\SKV@sktrue\XKV@testopta{\XKV@testoptc\XKV@setkeys}}
+\SKV@newlet\SKVSetKeys\setkeys
+\SKV@pdef*\UseSkeyvalSetkeys{%
+ \SKV@ifx\setkeys\SKVSetKeys\relax{\let\setkeys\SKVSetKeys}%
+}
+\SKV@redef*\XKV@setkeys[#1]#2{%
+ \def\skif##1{%
+ \SKV@ensurenoscape{##1}%
+ \SKV@ifcsdef{if##1}{}{%
+ \SKV@err{Undefined boolean '##1'}%
+ {'\string\skif' error: boolean '##1' undefined.}%
+ }%
+ \csname if##1\endcsname
+ }%
+ \let\skifx\ifx
+ \let\skifcase\ifcase
+ \let\skor\or
+ \let\skelse\else
+ \let\skfi\fi
+ \let\SKV@und@finedkeys\@empty
+ \XKV@checksanitizea{#2}\XKV@resb
+ \SKV@normalizea\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
+ \XKV@usepresetkeys{#1}{preseth}%
+ \SKV@expnext\XKV@s@tkeys\XKV@resb{#1}%
+ \XKV@usepresetkeys{#1}{presett}%
+ \let\CurrentOption\@empty
+ \SKV@skfalse
+ \SKV@ifx\SKV@und@finedkeys\@empty{}{%
+ \def\SKV@tempa{stop}%
+ \SKV@warn{\string\setkeys\space error: Unknown keys:\SKV@MB
+ \SKV@expox\SKV@und@finedkeys}%
+ \typein[\answer]{%
+ ^^JThe following keys are undefined and couldn't be set:
+ ^^J\SKV@expox\SKV@und@finedkeys
+ ^^JEnter 'stop' or 'go' and <return> to continue.}%
+ \ifx\answer\SKV@tempa\stop\fi
+ }%
+}
+\SKV@redef*\XKV@s@tk@ys#1=#2=#3\@nil{%
+ \XKV@g@tkeyname#1=\@nil\XKV@tkey
+ \SKV@expnext\SKV@sp@def\XKV@tkey\XKV@tkey
+ \SKV@ifx\XKV@tkey\@empty{%
+ \SKV@ifempty{#2}{}{%
+ \SKV@err{No key specified for value '#2'}%
+ {You have supplied a value '#2' without key name.\SKV@MB
+ This is certainly an error on your part.\SKV@MB
+ I can't process this value without key name.\SKV@MB
+ Please enter 'X' and <return>. Correct the error and rerun.}
+ }%
+ }{%
+ \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}%
+ \unless\ifin@
+ \XKV@knftrue
+ \SKV@sp@def{#2}\XKV@tempa
+ \ifXKV@preset
+ \XKV@s@tk@ys@{#3}%
+ \else
+ \ifXKV@pl
+ \XKV@for@eo\XKV@fams\XKV@tfam{%
+ \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}%
+ }%
+ \else
+ \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{%
+ \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}%
+ }%
+ \fi
+ \fi
+ \ifXKV@knf
+ \ifXKV@inpox
+ \SKV@ifx\XKV@doxs\relax{%
+ \unless\ifx\@currext\@clsextension
+ \let\CurrentOption\XKV@tkey\@unknownoptionerror
+ \fi
+ }{%
+ \XKV@doxs
+ }%
+ \else
+ \ifXKV@st
+ \XKV@addtolist@o\XKV@rm\CurrentOption
+ \else
+ \SKV@undefinedkeys\SKV@pref\XKV@fams\XKV@tkey
+ \fi
+ \fi
+ \else
+ \ifXKV@inpox\ifx\XKV@testclass\XKV@documentclass
+ \SKV@expnext\XKV@useoption\CurrentOption
+ \fi\fi
+ \fi
+ \fi
+ }%
+}
+\SKV@redef*\XKV@s@tk@ys@#1{%
+ \SKV@ifcsundef{\XKV@header\XKV@tkey}{%
+ \SKV@vbmsg{warn}{No key macro for key '\XKV@tkey'\SKV@MB
+ in families '\XKV@fams'}%
+ }{%
+ \XKV@knffalse
+ \SKV@ifcsundef{SKV@\XKV@header uservalue}{}{%
+ \SKV@aftercs\SKV@testuservaluekey
+ {SKV@\XKV@header uservalue}\XKV@tkey
+ \ifSKV@uv
+ \SKV@ifnotblank{#1}{}{%
+ \SKV@err{You're required to supply a value\SKV@MB
+ for key '\XKV@tkey' in families '\XKV@fams'}%
+ {Please supply a value for key '\XKV@tkey'\SKV@MB
+ of families '\XKV@fams' and rerun.\SKV@MB
+ The originator of this key meant it to\SKV@MB
+ require a user value.}%
+ }%
+ \fi
+ }%
+ \SKV@ifcsundef{XKV@\XKV@header save}{}{%
+ \SKV@aftercs\XKV@testsavekey{XKV@\XKV@header save}\XKV@tkey
+ }%
+ \ifXKV@rkv
+ \ifXKV@sg\expandafter\global\fi
+ \SKV@aftercs\let{XKV@\XKV@header\XKV@tkey @value}\XKV@tempa
+ \fi
+ \SKV@expnext\XKV@replacepointers\XKV@tempa
+ \SKV@ifblank{#1}{%
+ \SKV@ifcsundef{\XKV@header\XKV@tkey @default}{%
+ \SKV@err{'\XKV@tkey' in family '\XKV@tfam' with\SKV@MB
+ prefix '\XKV@pref' has no default value and\SKV@MB
+ you haven't supplied a value for it either}%
+ {Supply a value for key '\XKV@tkey' and rerun.}%
+ }{%
+ \SKV@xaftercs\XKV@default{\XKV@header\XKV@tkey @default}\@nil
+ }%
+ }{%
+ \XKV@savstate
+ \csname\XKV@header\XKV@tkey\expandafter
+ \endcsname\expandafter{\XKV@tempa}\relax
+ \XKV@resstate
+ }%
+ }%
+}
+\SKV@def*\SKV@testuservaluekey#1#2{%
+ \SKV@swtrue\SKV@uvfalse
+ \XKV@whilist#1\SKV@tempa\ifSKV@sw\fi{%
+ \ifx#2\SKV@tempa\SKV@uvtrue\SKV@swfalse\fi
+ }%
+}
+\SKV@def*\SKV@remspaceletter#1#2{%
+ \begingroup
+ \SKV@toks\expandafter{#2 #1}%
+ \def\SKV@tempa##1 #1##2\@nil{%
+ \SKV@ifblank{##2}{%
+ \SKV@toks{##1}%
+ }{%
+ \SKV@toks{##1#1##2}%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ }%
+ }%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ \xdef#2{\the\SKV@toks}%
+ \endgroup
+}
+\SKV@def*\SKV@remletterspace#1#2{%
+ \begingroup
+ \SKV@toks\expandafter{#2#1 }%
+ \def\SKV@tempa##1#1 ##2\@nil{%
+ \SKV@ifblank{##2}{%
+ \SKV@toks{##1}%
+ }{%
+ \SKV@toks{##1#1##2}%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ }%
+ }%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ \xdef#2{\the\SKV@toks}%
+ \endgroup
+}
+\SKV@def*\SKV@remletterletter#1#2{%
+ \begingroup
+ \SKV@toks\expandafter{#2#1#1}%
+ \def\SKV@tempa##1#1#1##2\@nil{%
+ \SKV@toks{##1#1##2}%
+ \SKV@ifblank{##2}{}{%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil}%
+ }%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ \def\SKV@tempa##1#1#1\@nil{\gdef#2{##1}}%
+ \expandafter\SKV@tempa\the\SKV@toks#1\@nil
+ \endgroup
+}
+\SKV@def*\SKV@remcommaequal#1#2{%
+ \begingroup
+ \SKV@toks\expandafter{#2#1}%
+ \def\SKV@tempa##1#1##2\@nil{%
+ \SKV@ifblank{##2}{%
+ \SKV@toks{##1}%
+ }{%
+ \SKV@toks{##1=##2}%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ }%
+ }%
+ \expandafter\SKV@tempa\the\SKV@toks\@nil
+ \xdef#2{\the\SKV@toks}%
+ \endgroup
+}
+\SKV@def*\SKV@normalizea#1{%
+ \@expandtwoargs\SKV@in@{ ,}{\SKV@expox{#1}}%
+ \ifin@\SKV@remspaceletter{,}#1\fi
+ \@expandtwoargs\SKV@in@{, }{\SKV@expox{#1}}%
+ \ifin@\SKV@remletterspace{,}#1\fi
+ \@expandtwoargs\SKV@in@{,,}{\SKV@expox{#1}}%
+ \ifin@\SKV@remletterletter{,}#1\fi
+ \@expandtwoargs\SKV@in@{ =}{\SKV@expox{#1}}%
+ \ifin@\SKV@remspaceletter{=}#1\fi
+ \@expandtwoargs\SKV@in@{= }{\SKV@expox{#1}}%
+ \ifin@\SKV@remletterspace{=}#1\fi
+ \@expandtwoargs\SKV@in@{==}{\SKV@expox{#1}}%
+ \ifin@\SKV@remletterletter{=}#1\fi
+ \@expandtwoargs\SKV@in@{,=}{\SKV@expox{#1}}%
+ \ifin@\SKV@remcommaequal{,=}#1\fi
+ \@expandtwoargs\SKV@in@{=,}{\SKV@expox{#1}}%
+ \ifin@\SKV@remcommaequal{=,}#1\fi
+}
+\SKV@def*\SKV@gobblescape{%
+ \ifnum\escapechar>255\else
+ \ifnum\escapechar<0\else
+ \expandafter\expandafter
+ \csname @gobble\ifnum\escapechar=32 space\fi
+ \SKV@threexp\endcsname
+ \fi\fi
+ \string%
+}
+\SKV@def*\SKV@save#1{%
+ \SKV@ensurescape{#1}%
+ \edef\SKV@tempa{saved\SKV@gobblescape#1}%
+ \SKV@ifcsdef\SKV@tempa{%
+ \SKV@err{%
+ \string#1\space already saved. You've to restore\SKV@MB
+ it or undefine '\SKV@csexpox{\SKV@tempa}' before\SKV@MB
+ you can save \string#1\space again
+ }\@ehc
+ }{%
+ \SKV@ifdef{#1}{%
+ \SKV@cslet\SKV@tempa{#1}%
+ }{%
+ \SKV@err{Undefined '\string#1' can't be saved\on@line}%
+ {You can't restore undefined commands.\SKV@MB
+ So why save undefined '\string#1' here?}%
+ }%
+ }%
+}
+\SKV@def*\SKV@restore#1{%
+ \SKV@ensurescape{#1}%
+ \edef\SKV@tempa{saved\SKV@gobblescape#1}%
+ \SKV@ifcsdef\SKV@tempa{%
+ \def\SKV@next{\SKV@letcs#1\SKV@tempa\SKV@csundef\SKV@tempa}%
+ }{%
+ \SKV@err{%
+ '\@nameuse\SKV@tempa' is undefined:\SKV@MB
+ '\string#1' can't be restored\on@line
+ }{%
+ '\string#1' can't be restored\on@line.\SKV@MB
+ Note that each call to \string\SKV@restore\space
+ undefines\SKV@MB the saved command.
+ }%
+ }%
+ \SKV@next
+}
+\SKV@providedef*\input@path{}
+\SKV@pdef*\InputFileOnce{%
+ \def\SKV@inputfile##1##2{%
+ \InputIfFileExists{##2}{%
+ \SKV@cslet{##2@read}\@empty
+ \let\SKV@inp@tfile\relax
+ }{%
+ \typein[\answer]{^^J! File '\string##2' does not exist.^^J
+ Enter filename or 'no' and <return> to continue.}%
+ \SKV@oifstrequal{\answer}{no}{%
+ \let\SKV@inp@tfile\relax
+ }{%
+ \def\SKV@inp@tfile{%
+ \SKV@expargs{0}{\SKV@InputFileOnce[##1]}\answer\@nil
+ }}}}%
+ \let\SKV@no\z@
+ \SKV@save\input@path
+ \SKV@t@stopta{\SKV@testopt\SKV@InputFileOnce{.}}%
+}
+\SKV@def*\SKV@InputFileOnce[#1]#2{%
+ \SKV@appto!\input@path{{#1/}}%
+ \ifSKV@st
+ \SKV@afterelsefi
+ \SKV@inputfile{#1}{#2}%
+ \else
+ \SKV@afterfi
+ \SKV@ifcsdef{#2@read}{%
+ \SKV@vbmsg{warn}{File '#2' already read:\SKV@MB
+ File '#2' can't be read again}%
+ }{%
+ \SKV@inputfile{#1}{#2}%
+ }%
+ \fi
+ \SKV@inp@tfile
+ \ifnum\SKV@no=\z@\SKV@restore\input@path\fi
+ \let\SKV@no\@ne
+}
+\SKV@pdef*\SKV@notloadederr#1{%
+ \SKV@ifcsdef{ver@#1.\@pkgextension}{}{%
+ \SKV@err{Package '#1' wasn't loaded}%
+ {Document has begun and package '#1' wasn't loaded.\SKV@MB
+ You wanted package '#1' loaded.}%
+ }%
+}
+\SKV@def*\SKV@notloaded{}
+\SKV@pdef*\@ensurepackageloaded#1{%
+ \SKV@for[,]{#1}\SKV@resvd{%
+ \edef\SKV@resvd##1##2{\SKV@appto!##1{##2{\SKV@resvd}}}%
+ \SKV@resvd\SKV@notloaded\SKV@doloaded
+ }%
+}
+\SKV@AtDocumentStart{%
+ \let\SKV@doloaded\SKV@notloadederr
+ \SKV@notloaded
+ \global\let\SKV@doloaded\@gobble
+}
+\SKV@onlypreamble{%
+ \SKV@preamblecmds,\SKV@onlypreamble,\@afterpackageloaded,
+ \@ifpackagecurrent,\@ifpackagenotcurrent,\@ifloadedandcurrent,
+ \@ensurepackageloaded,\SKV@AtPackageEnd,\SKV@AtClassEnd,
+ \SKV@BeforePackageEnd,\SKV@BeforeClassEnd,\SKV@AfterPackageEnd,
+ \SKV@AfterClassEnd,\SKV@BeforeLastPage,\SKV@AfterLastPage,
+ \SKV@AfterDocumentEnd,\UseSkeyvalSetkeys
+}
+
+\endinput
+
+%%% End of file skeyval.sty %%%
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex
new file mode 100644
index 00000000000..13e0a2a37f2
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-core.tex
@@ -0,0 +1,6150 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-core.tex', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\csname skeyval-core-loaded\endcsname
+\expandafter\let\csname skeyval-core-loaded\endcsname\endinput
+
+% Remove ++++++++++++++++++++++++++++++++++++++++++
+\RequirePackage[notraceifs]{codetrace}
+
+\begingroup
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode044 12 % ,
+\def\skv@prova{\endgroup
+ \def\do##1,{%
+ \ifx\do##1\else
+ \catcode##1\string=\the\catcode##1\relax
+ \expandafter\do
+ \fi
+ }%
+ \edef\skv@core@restorecodes{\do035,064,123,125,061,059,\do,}%
+}
+\skv@prova
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode061 12 % =
+\catcode044 12 % ,
+\def\do#1=#2,{%
+ \ifx\do#1\else
+ \edef\skv@core@restorecodes{%
+ \skv@core@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,\do=,%
+
+\newdimen\skvz@\skvz@=0pt\relax
+\ifcase
+ \ifx\eTeXversion\@undefined\skvz@\else
+ \ifnum\eTeXversion<\tw@\skvz@\else\@ne\fi\fi
+ \errhelp{This package requires eTeX version 2 or higher.}%
+ \errmessage{skeyval package: eTeX not loaded or old version.}
+ \expandafter\endinput
+\fi
+
+\newif\ifskv@inlatex
+\ifx\ProvidesFile\@undefined
+ \skv@inlatexfalse
+ \message{File 'skeyval-core.tex' 2012/10/15 v1.1:
+ Core of 'skeyval' key-value parser (AM)}
+ \input skeyval-ltxcmds
+\else
+ \skv@inlatextrue
+ \ProvidesFile{skeyval-core.tex}
+ [2012/10/15 v1.1 Base file of skeyval package (AM)]
+ \@addtofilelist{skeyval-core.tex}
+ \long\def\@nodocument#1{%
+ \@latex@error{'#1' appeared\on@line\space without
+ \noexpand\begin{document}}\@ehd
+ }
+\fi
+
+% skeyval-ltxcmds.tex defines \PackageError, etc:
+\protected\def\skv@warn{\PackageWarningNoLine{skeyval}}
+\protected\def\skv@err{\PackageError{skeyval}}
+
+\protected\def\skvtracingall{%
+ \tracinggroups\@ne\tracingifs\@ne\loggingall\tracingassigns\@ne
+}
+\let\skvloggingall\skvtracingall
+
+% A \relax'ed command should not be redefined, because we don't know
+% if it is temporarily or permanently made \relax.
+\long\def\skvifdefinable#1#2{%
+ \ifdefined#1%
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ {\@latex@error{Command '\string#1' already defined}\@ehd}
+ {#2}%
+}
+
+% \skvgenloop{<parser>}{<list>}{<1.parameter.callback>}
+% The parser may be empty. This is the case for nsv/tsv lists.
+\def\skvgenloop#1#2#3{%
+ \def\skv@gendo##1#1{%
+ \ifx\skv@gendo##1\expandafter\@gobble\else\expandafter\@iden\fi
+ {#3\skv@gendo}%
+ }%
+ \skv@gendo#2#1\skv@gendo#1%
+}
+\def\skvnewregister#1#2{%
+ \def\skv@prova{#1}%
+ \def\skv@provb{\bool}%
+ % We don't want to expose \if:
+ \def\skv@provc{\if}%
+ \ifx\skv@prova\skv@provb
+ \let\skv@prova\skv@provc
+ \fi
+ \skvgenloop{}{#2}{%
+ \skvifdefinable##1{%
+ \csname new\expandafter\expandafter\expandafter\@gobble
+ \expandafter\string\skv@prova\endcsname##1%
+ }%
+ }%
+}
+\let\skvnewregisters\skvnewregister
+
+\skvnewregisters\toks{\skv@toksa\skv@toksb}
+
+% \skvletmanytocmd{<nsv.cmdlist>}{<cmd>}
+\long\def\skvletmanytocmd#1#2{%
+ \skvgenloop{}{#1}{\let##1= #2}%
+}
+
+% Sometimes we change \bgroup temporarily to avoid \futurelet confusing
+% it with explicit \bgroup character. The change does confuse \skvifnextchar
+% if we used \bgroup in \skvifnextchar. Hence let us use \skv@orig@bgroup
+% in \skvifnextchar:
+\let\skv@orig@bgroup\bgroup
+
+% We modify LaTeX kernel's \@ifnextchar to eliminate the need for
+% doubling the hash character in #2 or #3. \@nextseen may be needed
+% outside the group; so we use \global.
+\long\def\skvsimpleifnextchar#1#2#3{%
+ \begingroup
+ \let\reserved@d=#1%
+ \edef\reserved@a{\endgroup\unexpanded{#2}}%
+ \edef\reserved@b{\endgroup\unexpanded{#3}}%
+ \global\futurelet\@nextseen\skv@simpleifnext
+}
+\def\skv@simpleifnext{%
+ \ifx\@nextseen\@sptoken
+ % Experience shows that this \skv@ifnextdo must be unique: If we were
+ % to use \next or some other generic command, it might have been
+ % let to \if or \fi before being assigned here and will confuse
+ % the above \ifx:
+ \let\skv@ifnextdo\skv@simpleifn@xt
+ \else
+ \ifx\@nextseen\reserved@d
+ \let\skv@ifnextdo\reserved@a
+ \else
+ \let\skv@ifnextdo\reserved@b
+ \fi
+ \fi
+ \skv@ifnextdo
+}
+\lowercase{\def\skv@simpleifn@xt} {%
+ \global\futurelet\@nextseen\skv@simpleifnext
+}
+\long\protected\def\skvifnextchar#1#2#3{%
+ \skvsimpleifnextchar\skv@orig@bgroup{%
+ \skvsimpleifnextchar{#1}{#2}{#3}%
+ }{%
+ % Test for \egroup, so that, eg, {\loggingall\LoadClass{article}}
+ % doesn't fail because of the closing brace:
+ \skvsimpleifnextchar\egroup{%
+ \skvsimpleifnextchar{#1}{#2}{#3}%
+ }{%
+ \skv@ifnextchar@a{#1}{#2}{#3}
+ }%
+ }%
+}
+\long\def\skv@ifnextchar@a#1#2#3#4{%
+ \edef\reserved@a{\skv@ifnextchar@b{#1}\skv@ifnextchar@b{#4}}%
+ \expandafter\ifx\reserved@a
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ {#2}{#3}#4%
+}
+\long\def\skv@ifnextchar@b#1{%
+ \expandafter\skv@ifnextchar@c\string#1\relax\noboundary{#1}%
+}
+\long\def\skv@ifnextchar@c#1#2\noboundary#3{%
+ \ifx\relax#2%
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ {#1}{\unexpanded{#3}}%
+}
+
+\long\def\skvgobbleldspaces{\skvifnextchar x{}{}}
+\long\def\skvgobbleleadingspaces{\skvsimpleifnextchar x{}{}}
+\long\protected\def\skvstarorlong#1{%
+ \skvifstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}%
+}
+\long\protected\def\skv@testopt#1#2{\skvifnextchar[{#1}{#1[{#2}]}}
+\long\protected\def\skvifstar#1{\skvifnextchar*{\@firstoftwo{#1}}}
+\def\skv@def@#1#2#3{%
+ \ifdefined#3%
+ \ifx#3\relax\else
+ \skv@err{Command \detokenize{#3} already exists}\@ehd
+ \fi
+ \fi
+ \ifcat$\detokenize{#2}$\else
+ \ifx#2p\expandafter\expandafter\expandafter\protected\fi
+ \fi
+ \l@ngrel@x\csname#1def\endcsname#3%
+}
+\def\skv@csdef@#1#2#3{%
+ \def\skv@prova{\skv@def@{#1}{#2}}%
+ \expandafter\skv@prova\csname#3\endcsname
+}
+\def\skv@redef@#1#2#3{%
+ \ifcat$\detokenize{#2}$\else
+ \ifx#2p\expandafter\expandafter\expandafter\protected\fi
+ \fi
+ \l@ngrel@x\csname#1def\endcsname#3%
+}
+\protected\def\skvrobustdef{\skvstarorlong{\skv@def@{}{p}}}
+\skvrobustdef*\skvrobustredef{\skvstarorlong{\skv@redef@{}{p}}}
+\skvrobustdef*\skvrobustgdef{\skvstarorlong{\skv@def@{g}{p}}}
+\skvrobustdef*\skvnewdef{\skvstarorlong{\skv@def@{}{}}}
+\skvrobustdef*\skvnewedef{\skvstarorlong{\skv@def@{e}{}}}
+\skvrobustdef*\skvnewgdef{\skvstarorlong{\skv@def@{g}{}}}
+\skvrobustdef*\skvrobustcsdef{\skvstarorlong{\skv@csdef@{}{p}}}
+\skvrobustdef*\skvnewcsdef{\skvstarorlong{\skv@csdef@{}{}}}
+\skvrobustdef*\skvifplus#1{\skvifnextchar+{\@firstoftwo{#1}}}
+
+\skvrobustdef*\skvshowcs#1{%
+ \begingroup\expandafter\endgroup
+ \expandafter\show\csname#1\endcsname
+}
+\skvrobustdef*\skvcomment{%
+ \begingroup
+ \catcode`\{=12 \catcode`\}=12 \catcode`\#=12\relax
+ \skv@c@mment
+}
+\skvrobustdef\skv@c@mment#1\endcomment{\endgroup}
+\skvnewedef*\skv@hashchar{\string#}
+\let\nofilter\relax
+% Don't use '=' at the end of the following definition; the user
+% might have put '=':
+\skvrobustdef*\skvnewlet#1{\skvifdefinable#1\relax\let#1 }
+\skvnewlet\skv@nil\relax
+\skvnewlet\skvrelax\relax
+\skvnewdef*\skv@relaxtoks{\relax}
+\skvnewdef*\skv@nnil{\skv@nil}
+\skvnewdef\skv@car#1#2\car@nil{#1}
+\skvnewdef\skv@car@detok#1#2\car@nil{\detokenize{#1}}
+\skvnewdef\skv@removetonnil#1\skv@nnil{}
+\skvnewdef\skv@catchtonnil#1\skv@nnil{#1}
+\long\def\@gobblethree#1#2#3{}
+\skvnewdef\skv@gobbletoend#1\skv@gobble@nil{}
+\skvnewlet\skv@gobble@nil\relax
+\def\@space{ }
+\skvnewdef\skvswap#1#2{#2#1}
+\skvnewdef*\skv@quark{\@gobble\skv@quark}
+\skvnewlet\skvrom\romannumeral
+\skvnewdef*\skv@rej{^skv^}
+\skvnewdef\skvafterfi#1\fi{\fi#1}
+\skvnewdef\skvafterfifi@inneriscond#1\fi#2\fi{\fi#1\fi}
+\skvnewdef\skvafterfifi#1\fi#2\fi{\fi\fi#1}
+\skvnewdef\skvafterelsei#1\else#2\fi{\fi#1}
+\skvnewlet\skvafterelse\skvafterelsei
+\skvnewdef\skvafterelseii#1\else#2\fi{\fi#2}
+\skvnewedef*\skv@simplearg{\unexpanded{#1}}
+
+\long\def\skv@in@#1#2{%
+ \begingroup
+ \long\def\in@@##1#1##2\in@@{%
+ \edef\in@@{\unexpanded{##2}}%
+ \expandafter\endgroup
+ \ifx\in@@\@empty\in@false\else\in@true\fi
+ }%
+ \in@@#2{\in@@}#1\in@@
+}
+\skvrobustdef*\skvcsnewif#1{%
+ \skvifstrcmp{#1}{x}{%
+ \skv@err{Redefining primitve '\@backslashchar ifx'?}\@ehd
+ }{%
+ \csname newif\expandafter\endcsname\csname if#1\endcsname
+ }%
+}
+\skvnewdef*\skv@zapornot#1{%
+ \ifnum#1=\skvz@
+ \expandafter\@iden
+ \else
+ \expandafter\skvzapspaces
+ \fi
+}
+\skvnewdef\skvzapspaces#1{\skv@zapspaces.#1 \zap@nil}
+\skvnewdef\skv@zapspaces#1 #2\zap@nil{%
+ \skvifblank{#2}{%
+ \@gobble#1%
+ }{%
+ \skv@zapspaces#1#2\zap@nil
+ }%
+}
+\skvnewdef\skvxzapspaces#1#2{%
+ \edef#2{.#1}%
+ \edef#2{\expandafter\skv@zapspaces#2 \zap@nil}%
+}
+
+\newcommand\skvifleadspace[3]{%
+ \romannumeral\csname
+ @\skvifnull{#1}{second}{\iffalse{\fi\skv@ifleadspace.#1 x}}%
+ oftwo\endcsname{0 #2}{0 #3}%
+}
+\skvnewdef\skv@ifleadspace#1 {%
+ \expandafter\skvifnull\expandafter{\@gobble#1}{first}{second}%
+ \expandafter\@gobble\expandafter{\iffalse}\fi
+}
+
+% \skvifldspace{ }{}{} gives <true> as desired.
+\begingroup
+\lccode`\&=0 \catcode`\&=7 \lccode`\!=0 \catcode`\!=8
+\lowercase{\endgroup
+ \skvnewdef\skvifldspace#1{\skv@ifldspace!#1! &}
+ \skvnewdef\skv@ifldspace#1! #2&{\skvifnotblank{#2}}
+ \skvnewdef\skvtrimspace#1{\skv@trimspace@a.#1& &}
+ \skvnewdef\skv@trimspace@a#1 &{\skv@trimspace@b#1&}
+ \skvnewdef\skv@trimspace@b#1&#2{%
+ \unexpanded\expandafter{%
+ \romannumeral0%
+ \expandafter\skvifldspace\expandafter{\@gobble#1}{%
+ \@gobble#1%
+ }{%
+ \expandafter\@space\@gobble#1%
+ }%
+ }%
+ }
+}
+
+\skvrobustdef*\skvdespace#1#2{\edef#2{\skvtrimspace{#1}}}
+\skvrobustdef*\skvdespacecontent#1{%
+ \edef#1{\expandafter\skvtrimspace\expandafter{#1}}%
+}
+\skvnewdef*\skvcsuse#1{%
+ \ifcsname#1\endcsname
+ \csname#1\expandafter\endcsname
+ \fi
+}
+\skvrobustdef*\skvcsdef#1{\expandafter\def\csname#1\endcsname}
+\skvrobustdef*\skvcsgdef#1{\expandafter\gdef\csname#1\endcsname}
+\skvrobustdef*\skvcsedef#1{\expandafter\edef\csname#1\endcsname}
+\skvrobustdef*\skvcsxdef#1{\expandafter\xdef\csname#1\endcsname}
+\skvnewdef\skvaftercsname#1#2{%
+ \expandafter\skvswap\expandafter{\csname#2\endcsname}{#1}%
+}
+\skvnewdef*\skvifdef#1{%
+ \skvifblank{#1}\@secondoftwo{%
+ \skvifx#1\@undefined{%
+ \@secondoftwo
+ }{%
+ \ifx#1\relax
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ }%
+}
+\skvnewdef*\skvifundef#1{\skvifdef{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef*\skvifcsdef#1{%
+ \skvifblank{#1}{%
+ \expandafter\@secondoftwo\@gobble
+ }{%
+ \ifcsname#1\endcsname
+ \expandafter\@firstofone
+ \else
+ \expandafter\expandafter\expandafter
+ \@secondoftwo\expandafter\@gobble
+ \fi
+ }{%
+ \expandafter\ifx\csname#1\endcsname\relax
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+}
+\skvnewdef*\skvifcsundef#1{\skvifcsdef{#1}\@secondoftwo\@firstoftwo}
+\def\skv@ifx@#1#2\skv@ifx@nil{\expandafter#1}
+\skvnewdef*\skvifx#1#2{%
+ \csname @\expandafter\expandafter\expandafter
+ \ifx\skv@ifx@#1\batchmode\skv@ifx@nil\skv@car#2\noboundary\car@nil
+ first\else second\fi oftwo\endcsname
+}
+\skvnewdef*\skvnotifx#1#2{\skvifx{#1}{#2}\@secondoftwo\@firstoftwo}
+\skvnewdef*\skv@ghost{\@gobble\skv@ghost}
+\skvnewdef\skvifempty#1{%
+ \ifx#1\@empty\skv@ghost
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+}
+\skvnewdef\skvifcsempty#1{\expandafter\skvifempty\csname#1\endcsname}
+\skvnewdef\skvifdefempty#1{%
+ \skvifblank{#1}\@secondoftwo{%
+ \skvifntype{#1}{%
+ \skvifdef{#1}{\skvifx#1\@empty}{\@secondoftwo}%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+
+\let\then\iffalse
+\begingroup
+% Keep lccode, in case the test occurs in a table:
+\lccode`\&=0 \catcode`\&=8
+\lowercase{\endgroup
+ \skvnewdef\skvifnull#1{%
+ \csname @\ifcat&\detokenize{#1}&first\else second\fi oftwo\endcsname
+ }
+ \skvnewdef\skviflacus#1\then{\ifcat&\detokenize{#1}&}
+}
+\skvnewdef\skvifblank#1{%
+ \expandafter\skvifnull\expandafter{\@gobble#1.}%
+}
+\skvnewdef\skvifnotblank#1{\skvifblank{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef\iflacuna#1\then{\if\relax\detokenize{#1}\relax}
+
+\skvnewdef*\skvifbool#1{%
+ \skvifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \skvifcsdef{if#1}{%
+ \csname @\csname if#1\endcsname
+ first\else second\fi oftwo\endcsname
+ }{%
+ \skv@err{Undefined boolean '#1'}\@ehd
+ }%
+ }%
+}
+\skvnewdef*\skvifnotbool#1{\skvifbool{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef*\skvifbooltrue#1\then{\csname if#1\endcsname}
+\skvnewdef*\skvifboolfalse#1\then{\csname if#1\endcsname\else}
+\skvnewdef*\skvifdefbool#1{%
+ \csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname
+}
+% \skvlogicalif<bool>"<true>"<false>"
+\skvnewdef*\skvlogicalif#1"#2"#3"{%
+ \skvifbool{#1}{#2}{#3}\skvgobbleleadingspaces
+}
+% \skvifboolval{<toks>}{<true>}{<false>}
+\skvrobustdef*\skvifboolval#1{%
+ \skvxifin{,\expandafter\skvtrimspace\expandafter
+ {\detokenize{#1}},}{,\detokenize{true,false},}%
+}
+% Generate error if <toks> is not a valid boolean value, otherwise
+% execute #2:
+% \skvifvalidboolval{<toks>}{<true>}
+\skvrobustdef*\skvifvalidboolval#1#2{%
+ \skvxifin{,\expandafter\skvtrimspace\expandafter
+ {\detokenize{#1}},}{,\detokenize{true,false},}%
+ {#2}{\skv@badboolerr{#1}}%
+}
+\skvrobustdef*\skvxifboolval#1{%
+ \begingroup
+ \edef\skv@prova{#1}%
+ \skvexpandtwoargs{\endgroup\skvifin}
+ {,\skvoxdetok\skv@prova,}{,\detokenize{true,false},}%
+}
+% Convert bool value (true or false) to switch value (00 or 01):
+\skvrobustdef*\skvbooltoswitch#1#2{%
+ \begingroup
+ \def\reserved@a##1#1##2##3\skv@nil{%
+ \def#2{##2}%
+ \ifx#2\@nnil
+ \skv@err{Bad boolean value '#1' can't be
+ \MessageBreak converted to switch value}\@ehc
+ \fi
+ }%
+ \reserved@a true{00}false{01}#1{\@nil}\skv@nil
+ \skvaftergroupdef#2\endgroup
+}
+\skvrobustdef*\skv@badboolerr#1{%
+ \skv@err{Invalid boolean value '#1'; expected 'true' or 'false'}\@ehd
+}
+
+% All switch functions of skeyval pacakge operate on a command
+% and not on csname.
+\skvnewdef*\skvnewswitch#1{%
+ \skvifcsdef{skv@sw@#1}{%
+ \skv@err{Switch '\detokenize{#1}' already exists}\@ehd
+ }{%
+ \skvcsdef{skv@sw@#1}{01}%
+ }%
+}
+\skvnewdef*\skvifswitch#1{%
+ \if
+ \skvifcsdef{skv@sw@#1}{%
+ \csname skv@sw@#1\endcsname
+ \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+ }{%
+ 01%
+ }%
+}
+\skvnewdef*\skvswitchtrue#1{%
+ \skvifcsdef{skv@sw@#1}{%
+ \skvcsdef{skv@sw@#1}{00}%
+ }{%
+ \skv@err{No switch '\detokenize{#1}'}\@ehd
+ }%
+}
+\skvnewdef*\skvswitchfalse#1{%
+ \skvifcsdef{skv@sw@#1}{%
+ \skvcsdef{skv@sw@#1}{01}%
+ }{%
+ \skv@err{No switch '\detokenize{#1}'}\@ehd
+ }%
+}
+
+\begingroup
+\def\x#1{\endgroup
+ \skvnewdef*\skvnegatesw##1{%
+ 0\ifcase##11#1\or\expandafter1\else\expandafter0\fi
+ }%
+ \skvnewdef*\skvifbothswtrue##1##2{%
+ 0\ifcase##1##2#1\expandafter0\else\expandafter1\fi
+ }%
+ \skvnewdef*\skvifoneswtrue##1##2{%
+ 0\ifnum##1##2<101#1\expandafter0\else\expandafter1\fi
+ }%
+}
+\x{ }
+
+\skvnewdef\skvifcond#1\fi{%
+ \csname @#1first\else second\fi oftwo\endcsname
+}
+\skvnewdef\skvifnotcond#1\fi{\skvifcond{#1}\fi\@secondoftwo\@firstoftwo}
+% Maybe #1 isn't expandable:
+\skvnewdef\skvifcondition#1\fi{%
+ #1\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\skvnewdef*\skvifnum#1#{\skvifcond\ifnum#1\fi}
+\skvnewdef\skvalloftwo#1#2{#1#2}
+% If '#1' is a single, non-space and non-braced token:
+\skvnewdef\skvifntype#1{%
+ \csname @\if0\skv@strcmp
+ {\skvexpandonce{\skvalloftwo#1{}{}}}{\unexpanded{#1{}}}%
+ first\else second\fi oftwo\endcsname
+}
+\skvnewdef\skvxifntype{\skvexpandarg\skvifntype}
+\skvrobustdef*\skvundef#1{\let#1\@undefined}
+\skvrobustdef*\skvgundef#1{\global\let#1\@undefined}
+\skvrobustdef*\skvcsundef#1{\skvcslet{#1}\@undefined}
+\skvrobustdef*\skvcsgundef#1{\global\skvcslet{#1}\@undefined}
+\skvrobustdef*\skvundefcmdlist#1{%
+ \skvcommaparse{#1}\skv@prova{\expandafter\skvundef\skv@prova}%
+}
+\skvrobustdef*\skvemptifycmds#1{%
+ \skvcommaparse{#1}\skv@prova{\expandafter\def\skv@prova{}}%
+}
+\skvifdef\pdfstrcmp{%
+ \let\skv@strcmp\pdfstrcmp
+}{%
+ \RequirePackage{pdftexcmds}%
+ \skvifdef\pdf@strcmp{%
+ \let\skv@strcmp\pdf@strcmp
+ }{%
+ \skv@err{Neither '\string\pdfstrcmp' nor
+ '\string\pdf@strcmp' exists}\@ehd
+ }%
+}
+\skvnewdef\skvifstrcmp#1#2{%
+ \csname @\ifnum\skv@strcmp{\detokenize{#1}}%
+ {\detokenize{#2}}=0first\else second\fi oftwo\endcsname
+}
+\skvnewdef\skvifstreq#1\with#2\then{%
+ \ifnum\skv@strcmp{\detokenize{#1}}{\detokenize{#2}}=\skvz@
+}
+% \ifskvstreq may be used in, eg, \newforeach, where every user-given
+% conditional must start with \if...:
+\skvnewlet\ifskvstreq\skvifstreq
+\skvnewdef\skvoifstrcmp#1#2{%
+ \csname @\ifnum\skv@strcmp{\skvexpandonce{#1}}%
+ {\skvexpandonce{#2}}=0first\else second\fi oftwo\endcsname
+}
+\skvnewdef\skvxifstrcmp#1#2{%
+ \csname @\ifnum\skv@strcmp{#1}{#2}=0first\else
+ second\fi oftwo\endcsname
+}
+\skvrobustdef\skvcslet#1#2{\expandafter\let\csname#1\endcsname#2}
+\skvrobustdef\skvnewcslet#1{%
+ \skvifcsdef{#1}{%
+ \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd
+ }{%
+ \skvcslet{#1}%
+ }%
+}
+\skvrobustdef\skvletcs#1#2{%
+ \begingroup\expandafter\endgroup\expandafter
+ \let\expandafter#1\csname#2\endcsname
+}
+\skvrobustdef\skvnewletcs#1{%
+ \skvifdef{#1}{%
+ \skv@err{Command '\string#1' already defined}\@ehd
+ }{%
+ \skvletcs#1%
+ }%
+}
+\skvrobustdef*\skvcsletcs#1#2{%
+ \begingroup\expandafter\endgroup
+ \expandafter\let\csname#1\expandafter
+ \endcsname\csname#2\endcsname
+}
+\skvrobustdef\skvnewcsletcs#1{%
+ \skvifcsdef{#1}{%
+ \skv@err{Command '\skvnoexpandcs{#1}' already defined}\@ehd
+ }{%
+ \skvcsletcs{#1}%
+ }%
+}
+\skvrobustdef*\skvglobalizecs#1{%
+ \begingroup\expandafter\endgroup\expandafter
+ \global\expandafter\let\csname#1\expandafter\endcsname
+ \csname#1\endcsname
+}
+\skvrobustdef*\skvaftergroupdef#1\endgroup{%
+ \skvexpanded{\endgroup\skvcmdexit#1}%
+}
+\skvrobustdef*\skvaftergroupcsdef#1\endgroup{%
+ \skvexpanded{\endgroup\expandafter\skvcmdexit\csname#1\endcsname}%
+}
+
+% Taking command and booleans out of a local group under \edef:
+\skvnewdef*\skvcmdexit#1{%
+ \edef\noexpand#1{\noexpand\unexpanded{\skvexpandonce{#1}}}%
+}
+\skvnewdef*\skvcsexit#1{%
+ \skvcsedef{#1}{\noexpand\unexpanded{\skvexpandcsonce{#1}}}%
+}
+% \edef\x{\endgroup\skvcmdexitloop{\x\y}}:
+\skvnewdef*\skvcmdexitloop#1{\skv@cmdexitloop#1\end}
+\skvnewdef*\skv@cmdexitloop#1{%
+ \ifx\end#1\else\skvcmdexit{#1}\expandafter\skv@cmdexitloop\fi
+}
+\skvnewdef*\skvboolexit#1{%
+ \expandafter\noexpand\csname\expandafter\@gobblethree
+ \string#1#1true\else false\fi\endcsname
+}
+% \edef\x{\endgroup\skvboolexitloop{\ifboola\ifboolb}}:
+\skvnewdef*\skvboolexitloop#1{\skv@boolexitloop#1\end}
+\skvnewdef*\skv@boolexitloop#1{%
+ \ifx\end#1\else\skvboolexit{#1}\expandafter\skv@boolexitloop\fi
+}
+\skvnewdef*\skvprotect#{%
+ \ifx\protect\@typeset@protect\skv@protect\@firstofone\fi
+ \ifx\protect\@unexpandable@protect\skv@protect\skvunexpandable\fi
+ \ifx\protect\noexpand\skv@protect\unexpanded\fi
+ \ifx\protect\string\skv@protect\detokenize\fi
+ \relax\@firstofone
+}
+\skvnewdef*\skv@protect#1#2\relax\@firstofone{\fi#1}
+\skvnewdef*\skvunexpandable#1{\unexpanded{\skvprotect{#1}}}
+\skvrobustdef\skvifnotnil#1{%
+ \begingroup
+ \edef\skv@prova{\unexpanded{#1}}%
+ \expandafter\endgroup\ifx\skv@prova\skv@nnil
+ \expandafter\@gobble\else\expandafter\@firstofone\fi
+}
+
+\skvrobustdef*\skvsetnumber#1{%
+ \begingroup
+ \def#1{\edef#1{\endgroup\def\noexpand#1{\the\count@}}#1}%
+ \afterassignment#1\count@
+}
+\skvnewlet\skvsetno\skvsetnumber
+\skvrobustdef*\skvadvanceno{\skv@advanceno\relax}
+\skvrobustdef*\skvgadvanceno{\skv@advanceno\global}
+\skvrobustdef*\skv@advanceno#1#2#3{%
+ % Raise error if #3 isn't an integer, \chardef'd or \countdef'd:
+ \begingroup
+ \count@#3\relax
+ \endgroup
+ \skvifdef#2{%
+ #1\edef#2{\the\numexpr#2+#3\relax}%
+ }{%
+ \skv@err{Number '\string#2' is not defined}\@ehd
+ }%
+}
+\skvrobustdef*\skvpushnumber#1{%
+ \skvifdef#1{%
+ \edef#1{\the\numexpr#1+1\relax}%
+ }{%
+ \def#1{0}%
+ }%
+}
+\skvrobustdef*\skvpopnumber#1{%
+ \skvifdef#1{%
+ \edef#1{\the\numexpr#1+1\relax}%
+ }{%
+ \skv@err{Number '\string#1' is not defined}\@ehd
+ }%
+}
+
+\skvrobustdef\skv@testst#1{%
+ \skvifstar{\skv@tempsttrue#1}{\skv@tempstfalse#1}%
+}
+\skvrobustdef\skv@testcl#1{%
+ \skvifnextchar!{\skv@cltrue#1}{\skv@clfalse#1}%
+}
+\skvrobustdef\skv@teststopt#1#2{\skv@testst{\skv@testopt{#1}{#2}}}
+
+
+% Removing spurious spaces before checking for brace.
+% If we were to use \skvtrimspace for \skvifbraced, then the need
+% for double \romannumeral will cause problems of premature expansion.
+\begingroup
+\lccode`\&=0 \catcode`\&=7
+\skvnewgdef\skvifbraced#1{%
+ \expandafter\skv@ifbraced@a\expandafter{%
+ \romannumeral-`\q\skv@ifbraced@b.#1& &%
+ }%
+}
+\skvnewgdef\skv@ifbraced@a#1{\skv@ifbraced@d#1\brace@nil{#1}}
+\skvnewgdef\skv@ifbraced@b#1 &{\skv@ifbraced@c#1&}
+\skvnewgdef\skv@ifbraced@c#1&#2{%
+ \expandafter\skvifldspace\expandafter{\@gobble#1}%
+ {\@gobble#1}{\expandafter\@space\@gobble#1}%
+}
+\skvnewgdef\skv@ifbraced@d#1\brace@nil#2{%
+ \skvifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo
+}
+\endgroup
+
+\skvnewdef\skvifnotbraced#1{\skvifbraced{#1}\@secondoftwo\@firstoftwo}
+
+% \skvstripouterbraces{<nr>}<cmd>
+\skvrobustdef*\skvstripouterbraces#1#2{%
+ \begingroup
+ \@tempcnta\skvz@
+ \expandafter\skv@stripouterbraces#2\strip@nil{#2}{#1}%
+}
+\skvrobustdef*\skv@stripouterbraces#1\strip@nil#2#3{%
+ \advance\@tempcnta\@ne
+ \skvifnum\@tempcnta=#3{%
+ \edef#2{\unexpanded{#1}}%
+ \skvaftergroupdef#2\endgroup
+ }{%
+ \skv@stripouterbraces#1\strip@nil{#2}{#3}%
+ }%
+}
+
+\skvrobustdef*\skvifescaped#1{%
+ \begingroup\escapechar92\relax
+ \edef\x{\expandafter\skv@car\string#1x\car@nil}%
+ \expandafter\endgroup
+ \csname @\ifx\x\@backslashchar first\else second\fi oftwo\endcsname
+}
+\skvnewdef\skvifnotescaped#1{\skvifescaped{#1}\@secondoftwo\@firstoftwo}
+\skvnewdef*\skvremovescape#1{\expandafter\@gobble\string#1}
+\skvnewdef*\skvgobblescape#1{%
+ \skvifblank{#1}{}{%
+ \skvifnum\escapechar>255{\string#1}{%
+ \skvifnum\escapechar<0{\string#1}{%
+ \skvifnum\escapechar=32{%
+ \expandafter\@gobblespace\string#1%
+ }{%
+ \skvremovescape{#1}%
+ }%
+ }%
+ }%
+ }%
+}
+\skvnewdef*\skvoxdetok#1{\detokenize\expandafter{#1}}
+\skvnewdef*\skvexpandonce#1{\unexpanded\expandafter{#1}}
+\skvnewlet\skvxonce\skvexpandonce
+\skvnewlet\skvxaft\expandafter
+\skvnewdef*\skvexpandtwice#1{%
+ \unexpanded\expandafter\expandafter\expandafter{#1}%
+}
+\skvnewdef*\skvexpandthrice#1{%
+ \unexpanded\expandafter\expandafter\expandafter
+ \expandafter\expandafter\expandafter\expandafter{#1}%
+}
+\skvnewdef*\skvnoexpandcs#1{\skvexpandonce{\csname#1\endcsname}}
+\skvnewdef*\skvexpandcsonce#1{%
+ \unexpanded\expandafter\expandafter\expandafter{\csname#1\endcsname}%
+}
+\skvrobustdef\skvexpanded#1{\begingroup\edef\x{\endgroup#1}\x}
+\skvrobustdef\skvexpandarg#1#2{\skvexpanded{\unexpanded{#1}{#2}}}
+\skvrobustdef\skvexpandargonce#1#2{%
+ \skvexpanded{\unexpanded{#1}{\skvexpandonce{#2}}}%
+}
+\skvrobustdef*\skvexpandtwoargs#1#2#3{\skvexpanded{\unexpanded{#1}{#2}{#3}}}
+\skvrobustdef*\skvexpandtwoargsonce#1#2#3{%
+ \skvexpanded{\unexpanded{#1}{\skvexpandonce{#2}}{\skvexpandonce{#3}}}%
+}
+\skvrobustdef\skvexpandsecond#1#2{\skvexpanded{\unexpanded{#1}#2}}
+\skvrobustdef\skvexpandsecondonce#1#2{%
+ \skvexpanded{\unexpanded{#1}\skvexpandonce{#2}}%
+}
+\skvnewdef\skvexpandnext#1#2{\expandafter\skvswap\expandafter{#2}{#1}}
+\skvnewdef\skvexpandbracenext#1#2{%
+ \expandafter\skvswap\expandafter{\expandafter{#2}}{#1}%
+}
+\skvnewlet\skvexpbracenext\skvexpandbracenext
+\skvrobustdef*\skvifin#1#2{%
+ \skv@in@{#1}{#2}%
+ \csname @\ifin@ first\else second\fi oftwo\endcsname
+}
+\skvrobustdef*\skvifnotin#1#2{\skvifin{#1}{#2}\@secondoftwo\@firstoftwo}
+\skvrobustdef*\skvxifin#1#2{\skvexpandtwoargs\skvifin{#1}{#2}}
+\skvrobustdef*\skvxifnotin#1#2{\skvxifin{#1}{#2}\@secondoftwo\@firstoftwo}
+\skvrobustdef*\skvifindetok#1#2#3{%
+ \skvexpandtwoargs\skvifin{#1\skvoxdetok{#2}#1}{#1\skvoxdetok{#3}#1}%
+}
+\skvnewdef\skviffound#1\in#2\then{\skv@in@{#1}{#2}\ifin@}
+\skvnewdef\skvxiffound#1\in#2\then{\skvexpandtwoargs\skv@in@{#1}{#2}\ifin@}
+
+% \skv@kvsplit{<kvpair>}{<parametered.callback>}
+\skvrobustdef*\skv@kvsplit#1#2{%
+ \begingroup
+ \def\skv@tempa##1=##2=##3\skv@kvsplit{%
+ \endgroup#2%
+ }%
+ \skv@tempa#1==\skv@kvsplit
+}
+% \skv@slsplit{<slashlist>}{<parametered.callback>}
+\skvrobustdef*\skv@slsplit#1#2{%
+ \begingroup
+ \def\skv@tempa##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@slsplit{%
+ \endgroup#2%
+ }%
+ \skv@tempa#1/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/\skv@slsplit
+}
+
+\skvrobustdef*\skv@rescan#1{%
+ \begingroup
+ \endlinechar\m@ne\newlinechar\m@ne
+ \catcode`\@=11
+ \everyeof{\skv@rescan@}%
+ \def\reserved@a##1\skv@rescan@{%
+ \endgroup\edef#1{\unexpanded{##1}}%
+ }%
+ \expandafter\reserved@a\scantokens\expandafter{#1}%
+}
+
+\skvnewdef*\skvifdigitpresent#1{%
+ \skvifcond\if0\skvifblank{#1}{1}{\skv@ifdigitpresent#1\skv@nnil}\fi
+}
+\skvnewdef*\skv@ifdigitpresent#1{%
+ \skvifx#1\skv@nnil{%
+ 1%
+ }{%
+ \skvifnum`#1>47{%
+ \skvifnum`#1<58{%
+ 0\skv@removetonnil
+ }{%
+ \skv@ifdigitpresent
+ }%
+ }{%
+ \skv@ifdigitpresent
+ }%
+ }%
+}
+
+\skvnewdef*\skvifalldigit#1{%
+ \skvifcond\if0\skvifblank{#1}{1}{\skv@ifalldigit#1\skv@nnil}\fi
+}
+\skvnewdef*\skv@ifalldigit#1{%
+ \skvifx#1\skv@nnil{0}{%
+ \skvifnum`#1>47{%
+ \skvifnum`#1<58{%
+ \skv@ifalldigit
+ }{%
+ 1\skv@removetonnil
+ }%
+ }{%
+ 1\skv@removetonnil
+ }%
+ }%
+}
+
+\skvnewdef*\skvifalphapresent#1{%
+ \skvifcond\if0\skvifblank{#1}{1}{\skv@ifalphapresent#1\skv@nnil}\fi
+}
+\skvnewdef*\skv@ifalphapresent#1{%
+ \skvifx#1\skv@nnil{%
+ 1%
+ }{%
+ \skvifnum`#1>96{%
+ \skvifnum`#1<123{%
+ 0\skv@removetonnil
+ }{%
+ \skv@ifalphapresent
+ }%
+ }{%
+ \skv@ifalphapresent
+ }%
+ }%
+}
+\skvnewdef*\skvifAlphapresent#1{%
+ \skvifcond\if0\skvifblank{#1}{1}{\skv@ifAlphapresent#1\skv@nnil}\fi
+}
+\skvnewdef*\skv@ifAlphapresent#1{%
+ \skvifx#1\skv@nnil{%
+ 1%
+ }{%
+ \skvifnum`#1>64{%
+ \skvifnum`#1<91{%
+ 0\skv@removetonnil
+ }{%
+ \skv@ifAlphapresent
+ }%
+ }{%
+ \skv@ifAlphapresent
+ }%
+ }%
+}
+\skvnewdef*\skvifprimitive#1{%
+ \expandafter\skv@ifprimitive\meaning#1\relax
+}
+\skvnewdef*\skv@ifprimitive#1#2\relax{%
+ \skvifcond\if#1\@backslashchar\fi{%
+ \skvifdigitpresent{#2}\@secondoftwo\@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+}
+
+\begingroup
+\catcode`\&=7
+\skvnewgdef*\skvdefregistertester#1#2{%
+ \begingroup
+ \def\x##1{\skvnoexpandcs{skv@\skvremovescape#1test@##1}}%
+ \edef\x{\endgroup
+ \def\noexpand#2####1{%
+ \unexpanded{\skvifx#1{##1}\@secondoftwo}{%
+ \unexpanded{\skvifprimitive{##1}\@secondoftwo}%
+ {\noexpand\expandafter\x{a}\noexpand\meaning####1:&}%
+ }%
+ }%
+ \def\x{a}####1:####2&{\x{b}####1\string#1&}%
+ \def\x{b}####1\string#1####2&{\noexpand\skvifblank{####1}}%
+ }\x
+}
+\endgroup
+\skvdefregistertester\skip\skvifskip
+\skvdefregistertester\count\skvifcount
+\skvdefregistertester\dimen\skvifdimen
+\skvdefregistertester\toks\skviftoks
+
+% Converting units.
+% Examples:
+% \edef\x{\skvconvertunit{10pt}{mm}}
+% \edef\x{\skvconvertunit{1in}{bp}}
+\skvnewdef*\skvconvertunit#1#2{%
+ \strip@pt\dimexpr#1*\p@/\dimexpr1#2\relax\relax#2%
+}
+
+% If all the tokens are digits or arithmetic:
+\skvnewdef*\skvifallarithmetic#1{%
+ \begingroup
+ \skv@swatrue
+ \skvifdimensionable{#1}{}{%
+ \ifskv@isinteger\else
+ \def\do##1##2{%
+ \ifx\do##1\else
+ \skvifin{##1}{0123456789.+-*/()}{}{%
+ \skvifin{,##1##2,}{,em,ex,in,pt,pc,cm,mm,dd,cc,nd,nc,bp,sp,}{}{%
+ \skv@swafalse
+ \def\do####1\skvrelax{}%
+ }%
+ }%
+ \expandafter\do
+ \fi
+ ##2%
+ }%
+ \do#1\do\skvrelax
+ \fi
+ }%
+ \expandafter\endgroup\ifskv@swa
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+
+% Test if a token #1 can be assigned to a \dimendef'd register. We assume
+% that #1 isn't a complicated expression and isn't padded with trailing
+% \relax's. A complicated expression will be something like
+%
+% 2pt+3ex-(3pt/4+1.45cc*3)
+%
+% which is much harder to parse and decide on.
+%
+% Examples:
+%
+% \skvifdimensionable{01}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{01pt}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{01abpt}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable\paperwidth{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{\skip0}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{1.2pt}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{1.2\relax pt}{\def\x{T}}{\def\x{F}}
+% \skvifdimensionable{1pt\relax\skvrelax}{\def\x{T}}{\def\x{F}}
+%
+
+\skvnewregister\bool\ifskv@isinteger
+
+% In case the argument of \skvifinteger containes \numexpr:
+\skvnewlet\skv@catch@nil\relax
+% #1: Essence, #2: Test token
+\skvrobustdef*\skvensureinteger#1#2{%
+ \begingroup
+ \def\skv@prova##1\skv@catch@nil{%
+ % If ##1 is empty or contains nothing before a \relax, it's fine:
+ \ifx\relax##1\relax\else
+ \skv@err{Token '#2' for '#1' isn't an integer}\@ehd
+ \fi
+ }%
+ \afterassignment\skv@prova\skv@cnta#2\relax\skv@catch@nil
+ \endgroup
+}
+\skvnewdef*\skv@validunit{em,ex,in,pt,pc,cm,mm,dd,cc,nd,nc,bp,sp}
+\skvrobustdef*\skv@catchremainder#1\skv@catch@nil{%
+ \endgroup\def\skv@elt{#1}%
+}
+\skvrobustdef*\skvifinteger#1{%
+ \begingroup
+ % Don't try '\numexpr0+#1' here:
+ \afterassignment\skv@catchremainder
+ \@tempcnta\numexpr0#1\relax\skv@catch@nil
+ \skvifx\skv@elt\@empty{%
+ \@firstoftwo
+ }{%
+ \skvifx\skv@elt\skv@relaxtoks\@firstoftwo\@secondoftwo
+ }%
+}
+\skvrobustdef\skvoifinteger{\skvexpbracenext\skvifinteger}
+\skvrobustdef\skvifdimensionable#1{%
+ \def\skv@dimunit{}%
+ % Does 'pt' mean 0pt or 1pt? Make it an invalid input:
+ \lowercase{\skvifindetok{,}{#1}}\skv@validunit{%
+ \@latexerr{Illegal step '#1': no number found with it}\@ehd
+ }{}%
+ \skv@isintegerfalse
+ \skvifinteger{#1}{%
+ \skv@isintegertrue\@secondoftwo
+ }{%
+ \expandafter\skv@ifdimensionable\skv@elt\skv@catch@nil
+ }%
+}
+\skvrobustdef\skv@ifdimensionable#1#2\skv@catch@nil{%
+ \skvifx\relax#1{%
+ \skvifblank{#2}{%
+ \skv@isintegertrue\@secondoftwo
+ }{%
+ \expandafter\skv@findunit\skv@elt\skv@catch@nil
+ }%
+ }{%
+ \expandafter\skv@findunit\skv@elt\skv@catch@nil
+ }%
+}
+\skvrobustdef\skv@findunit#1#2#3\skv@catch@nil{%
+ \def\skv@provb{%
+ \ifx\relax#2%
+ \if\relax\detokenize{#3}\relax
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \else
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \fi
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }%
+ \skvifstrcmp{.}{#1}{%
+ % In this case, #1 must have come with a trailing \relax.
+ % Remove it and re-start the test:
+ \def\skv@prova##1##2\relax\skv@catch@nil{%
+ \skvifdimensionable{##1##2}%
+ }%
+ \skv@prova#2#3\skv@catch@nil
+ }{%
+ % Check for a valid unit. May be a \dimendef'd token.
+ \skvifin{,#1,}{,\hsize,\vsize,}{%
+ \skv@provb
+ }{%
+ \skvifdimen{#1}{%
+ \skv@provb
+ }{%
+ \lowercase{\skvifindetok{,}{#1#2}}\skv@validunit{%
+ \def\skv@dimunit{#1#2}%
+ % Check if #3 has only one (leading) \relax:
+ \def\skv@prova##1##2##3\skv@catch@nil{%
+ \def\elt{##1}\def\skv@elt{##2}%
+ }%
+ \skv@prova#3\skv@quark\skv@quark\skv@catch@nil
+ \ifx\elt\skv@relaxtoks
+ \def\skv@prova{\skv@quark}%
+ \ifx\skv@elt\skv@prova
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \else
+ % \skv@elt might contain \relax, but never mind; let us end
+ % the search here. The samething can be said of the tests in
+ % \skv@provb.
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \fi
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ }{%
+ \@secondoftwo
+ }%
+ }%
+ }%
+ }%
+}
+
+% Evaluating a dimensionable expression.
+%
+% 1. This can't parse expressions containing both * and / in one component,
+% eg, in 3pt*3/2. But (3pt*3)/2 or (3pt/2)*3 will pass.
+%
+% Examples:
+%
+% \skvifdimexpr{2bp*3/2}{<T>}{<F>} : fails
+% \skvifdimexpr{1pt-2bp*3+(3cc-2ex)/2}{<T>}{<F>} : true
+% \skvifdimexpr{(1pt-2bp+(3cc-2ex)/2)*5}{<T>}{<F>} : true
+% \skvifdimexpr{1+(1pt-2bp+(3cc-2ex)/2)*5}{<T>}{<F>} : false
+%
+\skvrobustdef*\skvifdimexpr#1{%
+ \begingroup
+ \@tempcnta\skvz@
+ \skv@dimexpr@beg
+ \skv@dimexpr@bgroup#1(\skv@catch@nil
+ \skv@dimexpr@end
+ \skv@dimexpr@end@end
+}
+\skvrobustdef*\skv@dimexpr@beg{\begingroup\@tempcnta\skvz@}
+\skvrobustdef*\skv@dimexpr@end{%
+ \skv@dimexpr@end@end
+ \skv@dimexpr@true\skv@dimexpr@false
+}
+\skvrobustdef*\skv@dimexpr@end@end{%
+ \skvifnum\@tempcnta<\skvz@
+ {\endgroup\@secondoftwo}{\endgroup\@firstoftwo}%
+}
+\skvrobustdef*\skv@dimexpr@true{\advance\@tempcnta\skvz@}
+\skvrobustdef*\skv@dimexpr@false{\advance\@tempcnta\m@ne}
+\skvrobustdef*\skv@dimexpr@bgroup#1(#2\skv@catch@nil{%
+ \skv@dimexpr@egroup#1)\skv@catch@nil
+ \skvifblank{#2}{}{%
+ \skv@dimexpr@beg
+ \skv@dimexpr@bgroup#2\skv@catch@nil
+ }%
+}
+\skvrobustdef*\skv@dimexpr@egroup#1)#2\skv@catch@nil{%
+ \skv@dimexpr@plus#1+\skv@catch@nil
+ \skvifblank{#2}{}{%
+ \skv@dimexpr@end
+ \skv@dimexpr@egroup#2\skv@catch@nil
+ }%
+}
+\skvrobustdef*\skv@dimexpr@plus#1+#2\skv@catch@nil{%
+ \skv@dimexpr@minus#1-\skv@catch@nil
+ \skvifblank{#2}{}{\skv@dimexpr@plus#2\skv@catch@nil}%
+}
+\skvrobustdef*\skv@dimexpr@minus#1-#2\skv@catch@nil{%
+ \skvifblank{#1}{}{%
+ \skvifin{*}{#1}{%
+ \skvifin{/}{#1}{%
+ \skv@err{I can't parse this: both star (*) and slash
+ \MessageBreak (/) are in '#1'}\@ehd
+ }{%
+ \skvifblank{#1}{}{\skv@dimexpr@times#1*\skv@catch@nil}%
+ }%
+ }{%
+ \skvifblank{#1}{}{\skv@dimexpr@divide#1/\skv@catch@nil}%
+ }%
+ }%
+ \skvifblank{#2}{}{\skv@dimexpr@minus#2\skv@catch@nil}%
+}
+% Because of, eg, 2pt*3/2, the test for * is more subtle:
+\skvrobustdef*\skv@dimexpr@times#1*#2\skv@catch@nil{%
+ \skvifblank{#1}{}{%
+ \skvifdimensionable{#1}\skv@dimexpr@true\skv@dimexpr@false
+ }%
+ \skvifblank{#2}{}{%
+ \def\skv@prova##1*##2\skv@catch@nil{##1}%
+ \skvexpbracenext\skv@dimexpr@integer{\skv@prova#2\skv@catch@nil}%
+ }%
+}
+\skvrobustdef*\skv@dimexpr@divide#1/#2\skv@catch@nil{%
+ \skvifblank{#1}{}{%
+ \skvifdimensionable{#1}\skv@dimexpr@true\skv@dimexpr@false
+ }%
+ \skvifblank{#2}{}{%
+ \def\skv@prova##1/##2\skv@catch@nil{##1}%
+ \skvexpbracenext\skv@dimexpr@integer{\skv@prova#2\skv@catch@nil}%
+ }%
+}
+\skvrobustdef*\skv@dimexpr@integer#1{%
+ \skvifblank{#1}{}{%
+ \skvifinteger{#1}\skv@dimexpr@true\skv@dimexpr@false
+ }%
+}
+
+% \skvtrimlastparser{<parser>}<cmd>
+\skvrobustdef\skvtrimlastparser#1#2{%
+ \begingroup
+ % The following \relax will not be cat-12, so it won't appear in #2:
+ \def\skv@trim@a{%
+ \skvxifin{\detokenize{#1}\relax}{\skvoxdetok{#2}\relax}{%
+ \def\skv@trim@b####1#1\normal@nil{%
+ \edef#2{\unexpanded{####1}}%
+ \skv@trim@a
+ }%
+ \expandafter\skv@trim@b#2\normal@nil
+ }{}%
+ }%
+ \skv@trim@a
+ \skvaftergroupdef#2\endgroup
+}
+
+% Generate parameter characters from number #1 to #2:
+\skvnewdef*\skvgenerateparameters#1#2{%
+ \ifnum#1<\numexpr#2+1####\number#1%
+ \expandafter\skvgenerateparameters
+ \expandafter{\number\numexpr#1+1\expandafter}%
+ \expandafter{\number#2\expandafter}%
+ \fi
+}
+
+% Normalize non-parser-separated tokenlist. Preserve outer braces.
+% \edef\x{\skvtsvnormalize{ x y {z}}}
+\skvnewdef*\skvtsvnormalize#1{%
+ \unexpanded\expandafter
+ {\romannumeral-`\q\skv@tsvnormalize.#1 \normal@nil}%
+}
+\skvnewdef*\skv@tsvnormalize#1 #2\normal@nil{%
+ \skvifblank{#2}
+ {\expandafter\expandafter\expandafter\space
+ \expandafter\noexpand\@gobble#1}
+ {\skv@tsvnormalize#1#2\normal@nil}%
+}
+
+
+% \skvnormalize{<csv/kv>}<parser>{<list>}<cmd>
+\skvrobustdef*\skvnormalize#1#2#3#4{%
+ \def\skv@prova##1#1##2##3\skv@nil{%
+ \ifx\skv@nnil##2%
+ \skv@err{Invalid list type '#1' for command \string\skvnormalize}\@ehd
+ \fi
+ \edef#4{\unexpanded{#3}}%
+ ##2[#2]#4%
+ }%
+ \skv@prova csv\skvcsvnormalize kv\skvkvnormalize#1\skv@nnil\skv@nil
+}
+\skvnewswitch{inkv}
+% \skvcsvnormalize[<parser>]<listcmd>
+\skvrobustdef*\skvcsvnormalize{\skv@testopt\skv@csvnormalize,}
+\skvrobustdef*\skv@csvnormalize[#1]#2{%
+ \begingroup
+ \skv@setupnormalizer{#1}%
+ \skvswitchfalse{inkv}%
+ \edef#2{\expandafter\skv@normalizelist\expandafter{#2}}%
+ \skvaftergroupdef#2\endgroup
+}
+% \skvcsvnormalizeset{<cmda>{<token1>,<cmdb2>{<token2>},...}
+\skvrobustdef*\skvcsvnormalizeset{\skv@testopt\skv@csvnormalizeset,}
+\skvrobustdef*\skv@csvnormalizeset[#1]#2{%
+ \begingroup
+ \toks@{}%
+ \skv@setupnormalizer{#1}%
+ \skvswitchfalse{inkv}%
+ \def\do##1##2,{%
+ \skvifnotnil{##1}{%
+ \edef##1{\skv@normalizelist{##2}}%
+ \skvexpanded{\toks@{\the\toks@\skvcmdexit##1}}%
+ \do
+ }%
+ }%
+ \do#2,\skv@nil,%
+ \expandafter\endgroup\the\toks@
+}
+\skvrobustdef*\skvkvnormalize#1{%
+ \begingroup
+ \skv@setupnormalizer{,}%
+ \skvswitchtrue{inkv}%
+ % We put '\skv@kvguard' at the end of #1 to preserve any trailing '='.
+ % This can happen if a key has an empty value. But this can leave
+ % a trailing space or <parser> in #1. We remove the trailing space
+ % with \skvtrimspace.
+ \edef#1{\expandafter\skv@normalizelist\expandafter{#1\skv@kvguard}}%
+ \def\skv@kvnorm##1\skv@kvguard##2\normal@nil{%
+ \skv@parserequalerr##1##2,=\normal@nil
+ \edef#1{\skvtrimspace{##1##2}}%
+ \skvtrimlastparser{,}#1%
+ }%
+ \expandafter\skv@kvnorm#1\normal@nil
+ \skvaftergroupdef#1\endgroup
+}
+
+\begingroup
+\catcode`\~=13 \catcode`\!=13
+\skvrobustgdef\skv@setupnormalizer#1{%
+ \begingroup
+ \lccode`\~=`#1 \lccode`\!=`\=
+ \lowercase{\endgroup
+ \def\skv@normalizelist##1{%
+ \unexpanded\expandafter{\romannumeral-`\q
+ \skv@activeparser#1##1#1~\normal@nil}%
+ }%
+ \def\skv@activeparser##1~##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skvifswitch{inkv}{%
+ \skv@activeequal##1!\normal@nil
+ }{%
+ \skv@spaceparser##1 #1\normal@nil
+ }%
+ }{%
+ \skv@activeparser##1#1##2\normal@nil
+ }%
+ }%
+ \def\skv@activeequal##1!##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skv@spaceparser##1 #1\normal@nil
+ }{%
+ \skv@activeequal##1=##2\normal@nil
+ }%
+ }%
+ }%
+ \def\skv@spaceparser##1 #1##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skv@parserspace##1#1 \normal@nil
+ }{%
+ \skv@spaceparser##1#1##2\normal@nil
+ }%
+ }%
+ \def\skv@parserspace##1#1 ##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skvifswitch{inkv}{%
+ \skv@spaceequal##1 =\normal@nil
+ }{%
+ \skv@doubleparser##1#1#1\normal@nil
+ }%
+ }{%
+ \skv@parserspace##1#1##2\normal@nil
+ }%
+ }%
+ \def\skv@spaceequal##1 =##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skv@equalspace##1= \normal@nil
+ }{%
+ \skv@spaceequal##1=##2\normal@nil
+ }%
+ }%
+ \def\skv@equalspace##1= ##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skv@doubleparser##1#1#1\normal@nil
+ }{%
+ \skv@equalspace##1=##2\normal@nil
+ }%
+ }%
+ \def\skv@doubleparser##1#1#1##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skvifswitch{inkv}{%
+ \skv@doubleequal##1==\normal@nil
+ }{%
+ \skvifblank{##1}{}{%
+ \skv@remleadparser##1\normal@nil
+ }%
+ }%
+ }{%
+ \skv@doubleparser##1#1##2\normal@nil
+ }%
+ }%
+ \def\skv@doubleequal##1==##2\normal@nil{%
+ \skvifblank{##2}{%
+ \skvifblank{##1}{}{%
+ \skv@remleadparser##1\normal@nil
+ }%
+ }{%
+ \skv@doubleequal##1=##2\normal@nil
+ }%
+ }%
+ \def\skv@remleadparser#1##1\normal@nil{%
+ \expandafter\space\noexpand##1%
+ }%
+ \def\skv@parserequalerr##1#1=##2\normal@nil{%
+ \skvifblank{##2}{}{%
+ \skv@err{There is '#1=' in your key-value list}\@ehd
+ }%
+ }%
+}
+\endgroup
+
+% Special slash normalizer, which doesn't replace double slashes with
+% single slash, because a double slash might mean an intentionally
+% missing token/property of a key:
+\begingroup
+\catcode`\~=13 \uccode`\~=`\/
+\uppercase{\endgroup
+ \skvnewdef\skvkeepdoubleslashnormalize#1{%
+ \unexpanded\expandafter{\romannumeral-`\q
+ \skv@activeslash#1~\normal@nil}%
+ }%
+ \skvnewdef\skv@activeslash#1~#2\normal@nil{%
+ \skvifblank{#2}
+ {\skv@spaceslash#1 /\normal@nil}
+ {\skv@activeslash#1/#2\normal@nil}%
+ }%
+}
+\skvnewdef\skv@spaceslash#1 /#2\normal@nil{%
+ \skvifblank{#2}
+ {\skv@slashspace#1/ \normal@nil}
+ {\skv@spaceslash#1/#2\normal@nil}%
+}
+\skvnewdef\skv@slashspace#1/ #2\normal@nil{%
+ \skvifblank{#2}
+ {\skvifblank{#1}{}{\expandafter\space\noexpand#1}}
+ {\skv@slashspace#1/#2\normal@nil}%
+}
+
+
+% \skvmacnormalize[<parser>]<listcmd>
+\skvrobustdef*\skvmacnormalize{\skv@testopt\skv@macnormalize,}
+\skvrobustdef*\skv@macnormalize[#1]#2{%
+ \begingroup
+ \skvsetupmacroparsernormalizer{#1}%
+ \edef#2{\expandafter\skvmacroparsernormalize\expandafter{#2}}%
+ \skvaftergroupdef#2\endgroup
+}
+% This is for normalizing lists like {x\\ y\\\\ z}, where \\ is
+% a control sequence. Such parsers may be commands but we don't
+% expect them to be active characters.
+% Example:
+% \skvsetupmacroparsernormalizer{\\}
+% \edef\x{\skvmacroparsernormalize{x\\ y\\\\ z}}
+\skvrobustdef*\skvsetupmacroparsernormalizer#1{%
+ \long\def\skvmacroparsernormalize##1{%
+ \unexpanded\expandafter{\romannumeral-`\q
+ \skv@mac@spaceparser##1 #1\normal@nil}%
+ }%
+ \long\def\skv@mac@spaceparser##1 #1##2\normal@nil{%
+ \skvifblank{##2}
+ {\skv@mac@parserspace##1#1 \normal@nil}
+ {\skv@mac@spaceparser##1#1##2\normal@nil}%
+ }%
+ \long\def\skv@mac@parserspace##1#1 ##2\normal@nil{%
+ \skvifblank{##2}
+ {\skv@mac@doubleparser##1#1#1\normal@nil}
+ {\skv@mac@parserspace##1#1##2\normal@nil}%
+ }%
+ \long\def\skv@mac@doubleparser##1#1#1##2\normal@nil{%
+ \skvifblank{##2}{ ##1}
+ {\skv@mac@doubleparser##1#1##2\normal@nil}%
+ }%
+}
+% \skvpushfunctions<base-fn>{<fn-list>}<cnt>
+\skvrobustdef*\skvpushfunctions#1#2#3{%
+ \skvgadvanceno#3\@ne
+ \begingroup
+ \def\skv@prova##1{\skvremovescape{##1}@skv@\romannumeral#3}%
+ \def\do##1{\let\noexpand##1\skvnoexpandcs{\skv@prova{##1}}}%
+ \skvifcsdef{\skvremovescape{#1}@skv@stack}{}{%
+ \skvcsdef{\skvremovescape{#1}@skv@stack}{}%
+ }%
+ \skvcsxdef{\skvremovescape{#1}@skv@stack}{%
+ #2{\skvexpandcsonce{\skvremovescape{#1}@skv@stack}}%
+ }%
+ \def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
+ \skvexpanded{\endgroup#2}%
+}
+% \skvpopfunctions<base-fn><counter>
+\skvrobustdef*\skvpopfunctions#1#2{%
+ \begingroup
+ \edef\skv@elt{\skvnoexpandcs{\skvremovescape{#1}@skv@stack}}%
+ \expandafter\skvifdef\skv@elt{%
+ \expandafter\ifx\skv@elt\@empty
+ \skv@err{Stack of '\noexpand#1' is empty}\@ehd
+ \fi
+ }{%
+ \skv@err{Stack of '\noexpand#1' is undefined}\@ehd
+ }%
+ \edef\skv@prova{\skvexpandtwice\skv@elt}%
+ \edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
+ \expandafter\skv@provb\skv@prova
+ \skvgadvanceno#2\m@ne
+}
+
+\chardef\skv@stackdepthlimit=6\relax
+% #1=stack (macro), #2=list, #3=max depth
+\skvrobustdef*\skvbuildmacrostack#1#2#3{%
+ \begingroup
+ \escapechar92\relax
+ \@ifdefinable#1{\def#1{}}%
+ \@tempcnta\skvz@
+ \def\do##1{%
+ \noexpand\skv@elt\noexpand##1%
+ \skvnoexpandcs{\skvremovescape{##1}@skv@\romannumeral\@tempcnta}%
+ }%
+ \def\skv@loop{%
+ \advance\@tempcnta\@ne
+ % Don't use \ifnum here, because #2 may contain booleans.
+ \skvifnum\@tempcnta<\numexpr#3+1\relax{%
+ \edef#1{\skvexpandonce#1.\romannumeral\@tempcnta.{#2}}%
+ \skv@loop
+ }{}%
+ }%
+ \skv@loop
+ \skvaftergroupdef#1\endgroup
+}
+\skvrobustdef*\skvpushstate#1#2{\skv@pushorpopstate{#1}{#2}{+}}
+\skvrobustdef*\skvpopstate#1#2{\skv@pushorpopstate{#1}{#2}{-}}
+% #1: stack (a macro) as built by \skvbuildmacrostack
+% #2: depth counter (macro-defined)
+% #3: stack direction (+/-)
+\skvrobustdef*\skv@pushorpopstate#1#2#3{%
+ \if+#3\relax
+ \skvgadvanceno#2\@ne
+ \def\skv@elt##1##2{\let##2=##1}%
+ \else
+ \ifnum#2<\@ne
+ \skv@err{Can't pop stack: depth currently less than 1}\@ehd
+ \else
+ \def\skv@elt##1##2{\let##1=##2}%
+ \fi
+ \fi
+ \ifnum#2>\skv@stackdepthlimit
+ \skv@err{Stack depth limit '\number\skv@stackdepthlimit' exceeded}\@ehd
+ \fi
+ \def\skv@prova##1{%
+ \def\skv@prova####1.##1.####2####3\skv@nil{####2}%
+ \expandafter\skv@prova#1\skv@nil
+ }%
+ \expandafter\skv@prova\expandafter{\romannumeral#2}%
+ \let\skv@elt\relax
+ \if-#3\skvgadvanceno#2\m@ne\fi
+}
+
+\skvrobustdef*\skvnewbools{\skv@testopt\skv@newbools{}}
+\skvrobustdef*\skv@newbools[#1]#2{%
+ \begingroup
+ \toks@{}%
+ \def\skv@prova{#2}%
+ \skvcsvnormalize\skv@prova
+ \def\do##1,{%
+ \ifx\do##1\else
+ \skvifcsdef{if#1##1}{%
+ \skv@err{Boolean '\skvnoexpandcs{if#1##1}' already exists}\@ehd
+ }{%
+ \toks@\expandafter{\the\expandafter\toks@
+ \csname newif\expandafter\endcsname\csname if#1##1\endcsname}%
+ }%
+ \expandafter\do
+ \fi
+ }%
+ \expandafter\do\skv@prova,\do,%
+ \expandafter\endgroup\the\toks@
+}
+% \ifskv@inoptionsec determines if we're in skeyval options section or not.
+% Some checks are done in that section.
+
+\skvnewbools[skv@]{%
+ inset,st,cl,pl,kf,inpox,prepo,tracingkeys,swa,swb,%
+ intry,insa,success,inoptionsec,inopt,handlerswa,handlerswb%
+}
+
+\skvnewbools{indirkeys}
+\skvnewbools[skv]{indef,novalue,valuebraced}
+\skvnewbools[dirkeys@]{saveunknownkeys}
+
+\skvrobustdef*\skvnewcounts{\skv@testopt\skv@newcounts{}}
+\skvrobustdef*\skv@newcounts[#1]#2{%
+ \begingroup
+ \toks@{}%
+ \def\skv@prova{#2}%
+ \skvcsvnormalize\skv@prova
+ \def\do##1,{%
+ \ifx\do##1\else
+ \skvifcsdef{#1##1}{%
+ \skv@err{Counter '\skvnoexpandcs{#1##1}' already exists}\@ehd
+ }{%
+ \toks@\expandafter{\the\expandafter\toks@
+ \csname newcount\expandafter\endcsname\csname#1##1\endcsname}%
+ }%
+ \expandafter\do
+ \fi
+ }%
+ \expandafter\do\skv@prova,\do,%
+ \expandafter\endgroup\the\toks@
+}
+\skvnewcounts[skv@]{cnta,cntb}
+
+\skvrobustdef*\skvnewnumbers{\skv@testopt\skv@newnumbers{}}
+\skvrobustdef*\skv@newnumbers[#1]#2{%
+ \begingroup
+ \toks@{}%
+ \def\skv@prova{#2}%
+ \skvcsvnormalize\skv@prova
+ \def\do##1,{%
+ \ifx\do##1\else
+ \skvifcsdef{#1##1}{%
+ \skv@err{Number '\skvnoexpandcs{#1##1}' already exists}\@ehd
+ }{%
+ \toks@\expandafter{\the\expandafter\toks@
+ \expandafter\def\csname#1##1\endcsname{0}}%
+ }%
+ \expandafter\do
+ \fi
+ }%
+ \expandafter\do\skv@prova,\do,%
+ \expandafter\endgroup\the\toks@
+}
+
+\skvnewnumbers[skv@]{keydepth,setkeysdepth,makekeysdepth,
+ usekeysdepth,trysetkeysdepth,trysetkeysdepth@b,gendepth}
+\skvnewnumbers{dirkeys@depth}
+\skvnewlet\skv@novalue\relax
+\skvnewdef*\skv@novaluetoks{\skv@novalue}
+
+% A fast key parsing scheme originally designed for \newforeach loop.
+%
+% \quickkeys.define{<family>}[<hp>]{<list>}
+% \quickkeys.set{<family>}[<na>]{<kvlist>}
+%
+% 1. Quickly defines and set command/store keys.
+% 2. Pointers aren't used here, to speed up parsing.
+% 3. Package and class options can't be passed via quick keys.
+% 4. When defining keys, the syntax of <list> is:
+%
+% {<key1,key2,etc>}/{<default>}/{<callback>}/{<choice list>}/{<arg>}
+% ;...;
+% {<key-n>}/{<default>}/{<callback>}/{<choice list>}/{<arg>}
+%
+% Here, keys key1 and key2 will have the same default value, callback,
+% choice list and argument pattern.
+%
+% 5. The special key '.exec' will simply execute the code <default>,
+% without defining anything.
+% 6. Use .na to indicate a missing item that isn't blank.
+%
+% Example:
+% \quickkeys.define{fam}[mp@]{%
+% keya/true/\def\x##1{#1*##1}/true,false;
+% keyb;
+% keyc,keyd/aaa+bbb/\def\x##1{#1*##1*#2}/.na/#1+#2;
+% }
+%
+\skvnewdef*\skv@ifrejorempty#1{%
+ \skvifstrcmp{#1}{^skv^}{%
+ \@firstoftwo
+ }{%
+ \skvifblank{#1}{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+\skvnewdef*\skv@ifrejorna#1{%
+ \skvifstrcmp{#1}{^skv^}{%
+ \@firstoftwo
+ }{%
+ \skvifstrcmp{#1}{.na}{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+\skvnewdef*\skv@ifrejornaorempty#1{%
+ \skvifstrcmp{#1}{^skv^}{%
+ \@firstoftwo
+ }{%
+ \skvifstrcmp{#1}{.na}{%
+ \@firstoftwo
+ }{%
+ \skvifblank{#1}{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }%
+ }%
+}
+
+\skvrobustdef*\quickkeys#1#{%
+ \edef\skv@tempa{\skvtrimspace{#1}}%
+ \skvxifstrcmp{\skvexpandonce\skv@tempa}{.define}{%
+ \begingroup\endlinechar\m@ne
+ \skv@defquickkeys
+ }{%
+ \skvxifstrcmp{\skvexpandonce\skv@tempa}{.set}{%
+ \skv@setquickkeys
+ }{%
+ \skv@err{Unknown task for \string\quickkeys}\@ehd
+ }%
+ }%
+}
+\skvrobustdef*\skv@defquickkeys#1{\skv@testopt{\skv@defquickkeys@a{#1}}{}}
+\skvrobustdef*\skv@defquickkeys@a#1[#2]#3{%
+ \endgroup
+ \edef\skv@tempa{\skvkeepdoubleslashnormalize{#3}}%
+ \def\skv@defquickkeys@b##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@nil{%
+ \skvifin{,##1,}{,.exec,.exec code,}{%
+ ##2\relax
+ }{%
+ % Loop over key list, if there are more than one key:
+ \skvparselist{,}{##1}\skv@tempa{%
+ % If ##2 is empty, the default will be empty:
+ \skv@ifrejorna{##2}{}{%
+ \skvcsedef{#1/\skv@tempa/qkeys.def}{\unexpanded{##2}}%
+ }%
+ \skvcsedef{#1/\skv@tempa/qkeys.cbk}{%
+ % ##3 may be empty:
+ \skv@ifrejorna{##3}{}{\unexpanded{##3}}%
+ }%
+ \skv@ifrejornaorempty{##4}{}{%
+ \skvcsedef{#1/\skv@tempa/qkeys.chc}{\unexpanded{##4}}%
+ }%
+ \skv@ifrejornaorempty{##5}{}{%
+ \skvcsedef{#1/\skv@tempa/qkeys.arg}{\unexpanded{##5}}%
+ }%
+ \skvifblank{#2}{}{%
+ \skvcsedef{#1/\skv@tempa/qkeys.hp}{\unexpanded{#2}}%
+ }%
+ }%
+ }%
+ }%
+ \skvparselist*{;}\skv@tempa\skv@tempa{%
+ \expandafter\skv@defquickkeys@b\skv@tempa
+ /^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@nil
+ }%
+}
+
+\skvnewnumbers[skv@]{setqkeysdepth}
+
+% \quickkeys.set{<family>}[<na>]{<kvlist>}
+
+\skvrobustdef*\skv@setquickkeys#1{\skv@testopt{\skv@setquickkeys@a{#1}}{}}
+\skvrobustdef*\skv@setquickkeys@a#1[#2]#3{%
+ \skvsavestate\skv@setquickkeys{\do\skv@qkeysna}\skv@setqkeysdepth
+ \edef\skv@qkeysna{\unexpanded{#2}}%
+ \skvcsvnormalize\skv@qkeysna
+ \edef\skv@tempa{\unexpanded{#3}}%
+ \skvkvnormalize\skv@tempa
+ \def\skv@setqkeys##1##2{%
+ \skvifcsdef{#1/##1/qkeys.cbk}{}{%
+ \skv@err{Key '#1/##1' is not defined}\@ehd
+ }%
+ \skvifstrcmp{##2}\skv@novalue{%
+ \skvifcsdef{#1/##1/qkeys.def}{%
+ \skvcsletcs{#1/##1/qkeys.val}{#1/##1/qkeys.def}%
+ }{%
+ \skv@err{No user value and no default
+ \MessageBreak for key '#1/##1'}\@ehd
+ }%
+ }{%
+ \skvcsedef{#1/##1/qkeys.val}{\unexpanded{##2}}%
+ }%
+ \skvifcsdef{#1/##1/qkeys.chc}{%
+ \skvletcs\reserved@a{#1/##1/qkeys.chc}%
+ \edef\reserved@b{\skvexpandcsonce{#1/##1/qkeys.val}}%
+ \skvxifin{,\skvoxdetok\reserved@b,}{,\skvoxdetok\reserved@a,}{}{%
+ \skv@err{Value '\detokenize{##2}' for key '##1'
+ \MessageBreak is not in prescribed list
+ \MessageBreak '\skvoxdetok\reserved@a'}\@ehd
+ }%
+ }{}%
+ \skvifcsdef{#1/##1/qkeys.hp}{%
+ \skvletcs\reserved@a{#1/##1/qkeys.hp}%
+ \skvcsletcs{\reserved@a##1}{#1/##1/qkeys.val}%
+ }{}%
+ \skvifcsdef{#1/##1/qkeys.arg}{%
+ \skvletcs\reserved@a{#1/##1/qkeys.arg}%
+ }{%
+ \let\reserved@a\skv@simplearg
+ }%
+ \skvletcs\reserved@b{#1/##1/qkeys.cbk}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter
+ \expandafter\reserved@a\expandafter\reserved@a\expandafter
+ \quickkeyseov\expandafter{\reserved@b}%
+ \expandafter\expandafter\expandafter
+ \reserved@a\csname#1/##1/qkeys.val\endcsname\quickkeyseov
+ }%
+ \def\skv@setquickkeys@c##1=##2=##3\skv@nil{%
+ \skvxifin{,\detokenize{##1},}{,\skvoxdetok\skv@qkeysna,}{}{%
+ \skv@setqkeys{##1}{##2}%
+ }%
+ }%
+ \skvdolist*{,}\skv@tempa\skv@tempa{%
+ \expandafter\skv@setquickkeys@c\skv@tempa=\skv@novalue=\skv@nil
+ }%
+ \skvrestorestate\skv@setquickkeys\skv@setqkeysdepth
+}
+
+% \skvinitializeqkeys{<fam>}[<na>]{<kvlist>}
+\skvrobustdef*\skvinitializeqkeys#1{%
+ \skv@testopt{\skv@initializeqkeys@a{#1}}{}%
+}
+\skvrobustdef*\skv@initializeqkeys@a#1[#2]#3{%
+ \skvindeftrue
+ \skv@setquickkeys{#1}[#2]{#3}%
+ \skvindeffalse
+}
+
+\input skeyval-for
+
+% \skvifcase<comparator>{<teststr>}
+% {<cases>}
+% \elsedo
+% {<no match>}
+% \endif
+%
+% Example:
+%
+% \skvifcase\skvifstrcmp{c}
+% {a}{do a}
+% {b}{do b}
+% {c}{do c}
+% \elsedo
+% no match%
+% \endif
+\skvnewdef\skvifcase#1#2#3\elsedo#4\endif{%
+ \skv@ifcase{#1}{#2}#3{#2}{#4}\skv@casestop
+}
+\skvnewdef\skv@ifcase#1#2#3{%
+ #1{#2}{#3}\skv@ifcase@domatch{\skv@ifcase@a{#1}{#2}}%
+}
+\skvnewdef\skv@ifcase@a#1#2#3{\skv@ifcase{#1}{#2}}
+\skvnewdef\skv@ifcase@domatch#1#2\skv@casestop{\unexpanded{#1}}
+
+% Evaluating a series of boolean expressions.
+%
+% Example:
+%
+% \skvifexpr{%
+% not ( expr { \skvifdef\xa } and expr { \skvifempty\xa } )
+% or ( expr { \skvifbool{@tempswa} } or expr { \skvifx\xa\xb } )
+% }{%
+% \def\x{T}
+% }{%
+% \def\x{F}
+% }
+\skvnewnumbers[skv@]{exprcnt}
+\skvrobustdef*\skvifexpr#1{%
+ \begingroup
+ \def\skv@expr@neg{01}%
+ \skvsetno\skv@exprcnt\skvz@
+ \skv@expr@beg
+ \skv@expr@bgroup#1(\skv@expr@nil
+ \skv@expr@end
+ \skv@expr@end@end
+}
+\skvrobustdef*\skv@expr@beg{%
+ \begingroup
+ \def\skv@expr@neg{01}%
+ \skv@exprcnt\skvz@
+}
+\skvrobustdef*\skv@expr@end{%
+ \skv@expr@end@end\skv@expr@true\skv@expr@false
+}
+\skvrobustdef*\skv@expr@end@end{%
+ \expandafter\endgroup\csname @\ifnum\skv@exprcnt<\skvz@
+ second\else first\fi oftwo\endcsname
+}
+\skvrobustdef*\skv@expr@true{%
+ \skvadvanceno\skv@exprcnt{\if\skv@expr@neg\m@ne\else\skvz@\fi}%
+ \def\skv@expr@neg{01}%
+}
+\skvrobustdef*\skv@expr@false{%
+ \skvadvanceno\skv@exprcnt{\if\skv@expr@neg\skvz@\else\m@ne\fi}%
+ \def\skv@expr@neg{01}%
+}
+\skvrobustdef\skv@expr@bgroup#1(#2\skv@expr@nil{%
+ \skv@expr@egroup#1)\skv@expr@nil
+ \skvifblank{#2}{}{%
+ \skv@expr@beg
+ \skv@expr@bgroup#2\skv@expr@nil
+ }%
+}
+\skvrobustdef\skv@expr@egroup#1)#2\skv@expr@nil{%
+ \skv@expr@and#1and\skv@expr@nil
+ \skvifblank{#2}{}{%
+ \skv@expr@end
+ \skv@expr@egroup#2\skv@expr@nil
+ }%
+}
+\skvrobustdef\skv@expr@and#1and#2\skv@expr@nil{%
+ \skv@expr@or#1or\skv@expr@nil
+ \skvifblank{#2}{}{%
+ \skv@exprcnt\ifnum\skv@exprcnt<\skvz@\m@ne\else\skvz@\fi
+ \skv@expr@and#2\skv@expr@nil
+ }%
+}
+\skvrobustdef\skv@expr@or#1or#2\skv@expr@nil{%
+ \skv@expr@not#1not\skv@expr@nil
+ \skvifblank{#2}{}{%
+ \skv@exprcnt\ifnum\skv@exprcnt<\skvz@\skvz@\else\@ne\fi
+ \skv@expr@or#2\skv@expr@nil
+ }%
+}
+\skvrobustdef\skv@expr@not#1not#2\skv@expr@nil{%
+ \skv@expr@do#1expr\skv@expr@nil
+ \skvifblank{#2}{}{%
+ \def\skv@expr@neg{00}%
+ \skv@expr@not#2\skv@expr@nil
+ }%
+}
+\skvrobustdef\skv@expr@do#1expr#2\skv@expr@nil{%
+ \skvifblank{#1}{}{%
+ \skv@err{Invalid \noexpand\skvifexpr test expression}
+ {The handicapped test part is: '\detokenize{#1}'}%
+ }%
+ \skvifblank{#2}{}{\skv@expr@do@a#2\skv@expr@nil}%
+}
+\skvrobustdef\skv@expr@do@a#1#2\skv@expr@nil{%
+ \ignorespaces#1\skv@expr@true\skv@expr@false
+ \skv@expr@do#2\skv@expr@nil
+}
+
+\skvnewdef\skvwhileexpr#1\do#2{%
+ \skvifcond{#1}\fi{#2\skvwhileexpr{#1}\do{#2}}{}%
+}
+
+\skvbuildmacrostack\skv@keystate{%
+ \do\skv@prefix\do\skvcurrentprefix\do\skv@fams\do\skvcurrentfamily
+ \do\skvcurrentkey\do\skv@header\do\skvcurrentpath\do\skv@na
+ \do\skv@naa\do\ifskv@st\do\ifskv@pl\do\ifskv@kf\do\ifskvnovalue
+ \do\skvcurrentvalue\do\CurrentOption\do\ifskv@intry\do\ifskv@success
+ \do\ifskv@inpox\do\ifskv@prepo
+}\skv@stackdepthlimit
+
+\skvbuildmacrostack\dirkeys@state{%
+ \do\dirkeys@prefixlist\do\dirkeys@familylist\do\dirkeys@holderprefixtoks
+ \do\dirkeys@unknownkeysmacro\do\ifdirkeys@saveunknownkeys
+ \do\ifindirkeys
+}\skv@stackdepthlimit
+
+\skvrobustdef*\skvappendtomacro{\skv@testst{\skv@appendtomacro{app}{e}}}
+\skvrobustdef*\skvgappendtomacro{\skv@testst{\skv@appendtomacro{app}{x}}}
+\skvrobustdef*\skvprependtomacro{\skv@testst{\skv@appendtomacro{pre}{e}}}
+\skvrobustdef*\skvgprependtomacro{\skv@testst{\skv@appendtomacro{pre}{x}}}
+\skvrobustdef\skv@appendtomacro#1#2#3#4{%
+ \skvifescaped{#3}{%
+ \@nameuse{#2def}#3{%
+ \skvifstrcmp{#1}{app}{%
+ \skvifdef#3{\skvexpandonce#3}{}%
+ \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}%
+ }{%
+ \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}%
+ \skvifdef#3{\skvexpandonce#3}{}%
+ }%
+ }%
+ }{%
+ \skv@err{Token '\detokenize{#3}' is not escaped}\@ehd
+ }%
+}
+
+% \skvaddlist{<parser>}{<listitem>}
+% This is usually called under \edef.
+\skvnewdef*\skvaddlist#1#2{%
+ \skvifempty#2{}{\skvexpandonce#2\unexpanded{#1}}%
+}
+% \skvxaddtolist{<parser>}{<listcmd>}{<newitem>}
+\skvrobustdef\skvxaddtolist#1#2#3{%
+ \edef#2{#2\ifx#2\@empty\else#1\fi#3}%
+}
+% \skvaddtolist[<parser>]{<listcmd>}{<newitem>}
+\skvrobustdef*\skvaddtolist{\skv@teststopt{\skv@addtolist{}},}
+\skvrobustdef*\skvgaddtolist{\skv@teststopt{\skv@addtolist{\global}},}
+\skvrobustdef\skv@addtolist#1[#2]#3#4{%
+ #1\edef#3{%
+ \skvifdef#3{%
+ \skvifempty#3{}{\skvexpandonce#3#2}%
+ }{}%
+ \skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#4}%
+ }%
+}
+% \skv@declarefilter{<filter.type>}
+\skvrobustdef*\skv@declarefilter#1{%
+ \edef\skv@filter##1##2{%
+ \skvifblank{#1}{\let##2=##1}{%
+ \skvifx#1\relax{\let##2=##1}{%
+ \skvifstrcmp{#1}\nofilter{\let##2=##1}{%
+ \unexpanded{#1}{##1}{##2}%
+ }%
+ }%
+ }%
+ }%
+}
+
+% \skvfiltermergelist!<cmd>{<sublist>}<filter>
+% The exclamation mark (!) implies that the outcome is globalized.
+% When there is no filter to be applied, \skvmergelist is faster
+% than \skvfiltermergelist.
+\skvrobustdef*\skvfiltermergelist{\skv@testcl\skv@filtermergelist}
+\skvrobustdef*\skv@filtermergelist#1#2#3{%
+ \begingroup
+ \skv@declarefilter{#3}%
+ \skvifdef#1{\skvkvnormalize#1}{\def#1{}}%
+ \edef\skv@merga{\unexpanded{#2}}%
+ \skvkvnormalize\skv@merga
+ \skvcommaloop*\skv@merga\skv@merga{%
+ \@tempswatrue
+ \skv@filter\skv@merga\skv@mergb
+ \let\skv@mergc#1%
+ \let#1\@empty
+ \skvcommaloop*\skv@mergc\skv@mergc{%
+ \skv@filter\skv@mergc\skv@mergd
+ \ifx\skv@mergb\skv@mergd
+ \@tempswafalse
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@merga}%
+ \else
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@mergc}%
+ \fi
+ }%
+ \if@tempswa
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@merga}%
+ \fi
+ }%
+ \skvaftergroupdef#1\endgroup
+ \ifskv@cl\global\let#1#1\fi
+}
+% \skvmergelist!<cmd>{<sublist>}
+% The exclamation mark (!) implies that the outcome is globalized.
+\skvrobustdef*\skvmergelist{\skv@testcl\skv@mergelist}
+\skvrobustdef*\skv@mergelist#1#2{%
+ \begingroup
+ \skvifdef#1{\skvkvnormalize#1}{\def#1{}}%
+ \edef\skv@tempa{\unexpanded{#2}}%
+ \skvkvnormalize\skv@tempa
+ \skvcommaloop*\skv@tempa\skv@tempa{%
+ \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok#1,}{}{%
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempa}%
+ }%
+ }%
+ \skvaftergroupdef#1\endgroup
+ \ifskv@cl\global\let#1#1\fi
+}
+
+% \skvfilterremoveelements!<cmd>{<sublist>}<filter>
+% The exclamation mark (!) implies that the outcome is globalized.
+% When there is no filter to be applied, \skvremoveelements is faster
+% than \skvfilterremoveelements.
+% \if@tempswa can be used to test if, at the end, anything was
+% removed from #1.
+\skvrobustdef*\skvfilterremoveelements{\skv@testcl\skv@filterremoveelements}
+\skvrobustdef*\skv@filterremoveelements#1#2#3{%
+ \begingroup
+ \let\skv@origlist#1%
+ \skv@declarefilter{#3}%
+ \skvifdef#1{\skvkvnormalize#1}{\def#1{}}%
+ \skvcommaparse{#2}\skv@rema\skv@rema{%
+ \skv@filter\skv@rema\skv@remb
+ \let\skv@remc#1\let#1\@empty
+ \skvcommaloop*\skv@remc\skv@remc{%
+ \skv@filter\skv@remc\skv@remd
+ \ifx\skv@remb\skv@remd\else
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@remc}%
+ \fi
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit#1%
+ \ifx#1\@empty
+ \noexpand\@tempswatrue
+ \else
+ \ifx#1\skv@origlist\noexpand\@tempswafalse\else
+ \noexpand\@tempswatrue\fi
+ \fi
+ }%
+ \ifskv@cl\global\let#1#1\fi
+}
+% \skvremoveelements!<cmd>{<sublist>}
+% The exclamation mark (!) implies that the outcome is globalized.
+% \if@tempswa can be used to test if, at the end, anything was
+% removed from #1.
+\skvrobustdef*\skvremoveelements{\skv@testcl\skv@removeelements}
+\skvrobustdef\skv@removeelements#1#2{%
+ \begingroup
+ \let\skv@origlist#1%
+ \skvifdef#1{}{\def#1{}}%
+ \edef\skv@rema{\unexpanded{#2}}%
+ \skvcsvnormalize\skv@rema
+ \let\skv@remb#1\let#1\@empty
+ \skvcommaparse*\skv@remb\skv@tempa{%
+ \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@rema,}{}{%
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempa}%
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit#1%
+ \ifx#1\@empty
+ \noexpand\@tempswatrue
+ \else
+ \ifx#1\skv@origlist\noexpand\@tempswafalse\else
+ \noexpand\@tempswatrue\fi
+ \fi
+ }%
+ \ifskv@cl\global\let#1#1\fi
+}
+
+% \skvfilterreplaceelements!<listcmd>{<replacements>}<filter>
+% <replacements> => {<old-1>}{<new-1>},...,{<old-n>}{<new-n>}
+% An exclamation mark suffix (!) implies that the outcome is globalized.
+% When there is no filter to be applied, \skvreplaceelements is only
+% negligibly faster than \skvfilterreplaceelements. Hence \skvreplaceelements
+% isn't defined in this package. When there is no <filter>, use \nofilter
+% as the filter.
+% Example:
+% \def\cmd{a = 1 , b = 2 , c = 3}
+% \skvfilterreplaceelements\cmd{{a = 1}{x = 1},{c = 3}{z=3}}\skv@getkeyname
+\skvrobustdef*\skvfilterreplaceelements{\skv@testcl\skv@filterreplaceelements}
+\skvrobustdef*\skv@filterreplaceelements#1#2#3{%
+ \begingroup
+ \skv@declarefilter{#3}%
+ \skvifdef#1{\skvkvnormalize#1}{\def#1{}}%
+ \def\do##1##2\skv@nil{%
+ \ifx#3\skv@getkeyname
+ \def\@do####1=####2=####3\skv@nil####4{%
+ \edef####4{\skvtrimspace{####1}=\skvtrimspace{####2}}%
+ }%
+ \@do##1==\skv@nil\skv@old
+ \@do##2==\skv@nil\skv@new
+ \else
+ \edef\skv@old{\unexpanded{##1}}%
+ \edef\skv@new{\unexpanded{##2}}%
+ \fi
+ }%
+ \skvcommaparse{#2}\skv@tempa{%
+ \expandafter\do\skv@tempa\skv@nil
+ \skv@filter\skv@old\skv@oldb
+ \let\skv@tempb#1\let#1\@empty
+ \skvcommaloop*\skv@tempb\skv@tempb{%
+ \skv@filter\skv@tempb\skv@tempc
+ \ifx\skv@tempc\skv@oldb
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@new}%
+ \else
+ \edef#1{\skvaddlist,#1\skvexpandonce\skv@tempb}%
+ \fi
+ }%
+ }%
+ \skvaftergroupdef#1\endgroup
+ \ifskv@cl\global\let#1#1\fi
+}
+\skvrobustdef*\skv@makeprefix#1{%
+ % It is required to first fully expand the prefix:
+ \edef\skvcurrentprefix{#1}%
+ \skvdespacecontent\skvcurrentprefix
+ \edef\skv@prefix{%
+ \ifx\skvcurrentprefix\@empty\else\skvcurrentprefix/\fi
+ }%
+}
+\skvrobustdef*\skv@makeheader#1{%
+ % Fully expand the family, in case it is given as \skvcurrentfamily or
+ % a local/temporary macro:
+ \edef\skvcurrentfamily{#1}%
+ \skvdespacecontent\skvcurrentfamily
+ \edef\skvcurrentpath{\skv@prefix\skvcurrentfamily}%
+ \edef\skv@header{%
+ \skv@prefix\ifx\skvcurrentfamily\@empty\else\skvcurrentfamily/\fi
+ }%
+}
+\skvrobustdef*\skv@testopta#1{%
+ \skvifstar
+ {\skv@sttrue\skv@t@stopta{#1}}{\skv@stfalse\skv@t@stopta{#1}}%
+}
+\skvrobustdef*\skv@t@stopta#1{\skvifplus{\skv@pltrue#1}{\skv@plfalse#1}}
+\skvrobustdef*\skv@testoptb#1{\skv@testopt{\skv@t@stoptb{#1}}{KV}}
+\skvrobustdef*\skv@t@stoptb#1[#2]#3{%
+ \skv@makeprefix{#2}\skv@makeheader{#3}#1%
+}
+\skvrobustdef*\skv@testoptc#1{\skv@testopt{\skv@t@stoptc{#1}}{KV}}
+\skvrobustdef*\skv@t@stoptc#1[#2]#3{%
+ \skvxifin{,}{\detokenize{#2}}{%
+ \skv@err{Only one prefix is allowed here,
+ \MessageBreak but you gave '#2'}\@ehd
+ }{%
+ \skv@makeprefix{#2}%
+ \edef\skv@fams{#3}%
+ \skvxifin{,}{\detokenize{#3}}{%
+ \skvcsvnormalize\skv@fams
+ }{%
+ \skvdespacecontent\skv@fams
+ }%
+ \skv@testopt#1{}%
+ }%
+}
+\skvrobustdef*\skv@testoptd#1#2{%
+ \skv@testoptb{%
+ \edef\skv@provb{#2\skv@header}%
+ \def\skv@prova{\skv@testopt{\skv@t@stoptd{#1}}}%
+ \expandafter\skv@prova\expandafter{\skv@provb}%
+ }%
+}
+\skvrobustdef*\skv@t@stoptd#1[#2]#3{%
+ \skvifnextchar[{\skv@sttrue#1{#2}{#3}}{\skv@stfalse#1{#2}{#3}[]}%
+}
+\skvrobustdef*\skv@getkeyname#1#2{%
+ \expandafter\skv@g@tkeyname#1=\skv@nil#2%
+}
+\skvrobustdef*\skv@g@tkeyname#1=#2\skv@nil#3{%
+ \skv@strippointers{#1}\skvcurrentkey
+ \let#3=\skvcurrentkey
+}
+
+% #1=key-value pairs; #2=result macro
+\skvrobustdef*\skv@getkeynames#1#2{%
+ \begingroup
+ \edef\skv@prova{\unexpanded{#1}}%
+ \skvkvnormalize\skv@prova
+ \let#2\@empty
+ \skvcommaloop*\skv@prova\skv@prova{%
+ \expandafter\expandafter\expandafter
+ \skv@g@tkeyname\skv@prova=\skv@nil\skv@prova
+ \skvaddtolist*#2\skv@prova
+ }%
+ \skvaftergroupdef#2\endgroup
+}
+\skvnewdef*\skv@badkeynames{}
+\skvnewdef*\skvaddbadkeynames{\skvappendtomacro\skv@badkeynames}
+\skvnewdef\skvcurrenttriple{%
+ \skvcurrentprefix/\skvcurrentfamily/\skvcurrentkey
+}
+\skvrobustdef*\skv@definedefault#1#2{%
+ \ifskv@inoptionsec\else
+ \skvxifin{,\skvcurrentprefix,}{,skv,SKV,}{%
+ \skvxifin{,\skvcurrentfamily,}{,skeyval,}{%
+ \skv@err{Prefix/family '\skvcurrentprefix/\skvcurrentfamily'
+ are reserved}\@ehd
+ }{}%
+ }{}%
+ \fi
+ \ifskv@tracingkeys
+ \skvxifin{,#1,}{,\skv@badkeynames,}{%
+ \skv@err{Key name '#1' not allowed}\@ehd
+ }{}%
+ \fi
+ \skvcsedef{\skv@header#1.@defa}{%
+ \skvnoexpandcs{\skv@header#1}{\unexpanded{#2}}%
+ }%
+ \skv@recordkey{#1}{#2}%
+}
+
+% 1. Record key and its initial/default value if the key appears in the
+% 'needini' list of its family. The list 'needini' is made by the
+% command \skvsaveinitialvaluekeys.
+% 2. To 'save initial values of keys', the key names must have been
+% entered by \skvsaveinitialvaluekeys in 'needini' list.
+% 3. If a key has no default, then \skv@definedefault will not be called
+% and hence \skv@recordkey won't be invoked.
+% 4. In \skvdefinekeys, if a key has no default, it won't be entered in
+% the 'needini' list. In \skvdefinekeys, an empty default value should
+% be indicated with a slash, eg, .cmd/keya/, .ord/keyb//,
+% or .ord/keyb/.na/.
+% 5. In \skvdefinekeys, use the key/option '.save initial values' to
+% create 'needini' lists of families.
+\skvrobustdef*\skv@recordkey#1#2{%
+ \begingroup
+ \skvifcsundef{\skv@header.@needini}{%
+ \endgroup\skv@swafalse
+ }{%
+ \skv@swatrue
+ \skvxifin{,#1,}{,\skvexpandcsonce{\skv@header.@needini},}{%
+ \edef\skv@tempa{\skvtrimspace{#2}}%
+ \edef\skv@tempa{%
+ #1=\skvoifstrcmp{\skv@tempa}{true}{false}{\skvexpandonce\skv@tempa}%
+ }%
+ \skvletcs\skv@tempb{\skv@header.@inikv}%
+ \skvifdef\skv@tempb{%
+ \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempb,}{}{%
+ \skvcsedef{\skv@header.@inikv}{%
+ \skvaddlist,\skv@tempb\skvexpandonce\skv@tempa
+ }%
+ }%
+ }{%
+ \skvcsedef{\skv@header.@inikv}{\skvexpandonce\skv@tempa}%
+ }%
+ }{}%
+ }%
+ \ifskv@swa
+ \expandafter\skvaftergroupdef\csname
+ \skv@header.@inikv\expandafter\endcsname
+ \expandafter\endgroup
+ \fi
+}
+
+% Key will be given in the form <pointer>{<key>}. The command
+% \skv@strippointers is called both when defining and setting keys. When
+% setting keys, we also call \skv@replacepointers to replace .usevalue
+% pointer with the value of the key.
+%
+% Notes:
+% 1. The pointer \savevalue (of ltxkeys package) or .save value is
+% not used in the skeyval package, since the key's value is
+% always saved automatically.
+%
+\skvrobustdef*\skv@strippointers#1#2{%
+ \begingroup
+ \edef#2{%
+ \skvifstrcmp{#1}{\skvcurrentkey}
+ {\skvcurrentkey}{\skvtrimspace{#1}}%
+ }%
+ \def\skv@prova{\expandafter\skv@findpointer\expandafter}%
+ % We can't use #1 in place of #2 in the following, since
+ % #2 may have had some pointers stripped in the last call
+ % to \skv@findpointer. Also, we can't \edef #2 here, since
+ % after each call to \skv@findpointer, we want to use the latest
+ % meaning of #2.
+ \def\do{}%
+ \skv@prova{#2}{.need value}#2{%
+ \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}%
+ }{%
+ \skv@prova{#2}{.require value}#2{%
+ \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}%
+ }{%
+ \skv@prova{#2}{.value required}#2{%
+ \def\do{\skvcsdef{\skv@header#2.@ndv}{00}}%
+ }{%
+ \skv@prova{#2}{.forbid value}#2{%
+ \def\do{\skvcsdef{\skv@header#2.@fbv}{00}}%
+ }{%
+ \skv@prova{#2}{.value forbidden}#2{%
+ \def\do{\skvcsdef{\skv@header#2.@fbv}{00}}%
+ }{%
+ \skv@prova{#2}{.expanded}#2{%
+ \edef#2{#2}%
+ }{%
+ \skv@prova{#2}{.expand once}#2{%
+ \edef#2{\skvexpandtwice{#2}}%
+ }{%
+ \skv@prova{#2}{.expand twice}#2{%
+ \edef#2{\skvexpandthrice{#2}}%
+ }{}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit{#2}\do
+ }%
+}
+\skvrobustdef*\skv@findpointer#1#2#3{%
+ \begingroup
+ \def\skv@prova##1#2##2##3\pointer@nil{%
+ \endgroup
+ \skvifstrcmp{##2}{\skv@nil}{%
+ \@secondoftwo
+ }{%
+ \edef#3{\skvtrimspace{##2}}%
+ \@firstoftwo
+ }%
+ }%
+ \skv@prova#1#2{\skv@nil}\pointer@nil
+}
+
+% Extract pseudo key name from a weird key name of the form
+% 'evaluate (\x) as (\y) using (\numexpr\x*2)':
+\skvrobustdef*\skv@extractpntkey#1#2{%
+ \begingroup
+ \@tempcnta\skvz@
+ \def#2{}%
+ \def\skv@prova##1(##2){%
+ \def\skv@provb{##2}%
+ \ifx\skv@provb\@nnil\else
+ \advance\@tempcnta\@ne
+ \edef#2{\skvexpandonce#2\skvtrimspace{##1}}%
+ \expandafter\skv@prova
+ \fi
+ }%
+ \skv@prova#1(\@nil)%
+ \in@false
+ \ifx#2\@empty
+ \edef#2{\unexpanded{#1}}%
+ \else
+ \skvifstreq{#2}\with{\skvcurrentkey}\then
+ \in@true
+ % The number of arguments of the pseudo key is determined by the
+ % number of closed parentheses:
+ \skvcsedef{\skv@header#2.@x0arg}{%
+ \skvgenerateparameters{1}\@tempcnta
+ }%
+ \fi
+ \fi
+ \skvexpanded{\endgroup
+ \skvcmdexit#2%
+ \ifin@
+ \expandafter\skvcmdexit\csname\skv@header#2.@x0arg\endcsname
+ \fi
+ }%
+}
+\skvrobustdef*\skv@extr@ctpntkey#1#2#3{%
+ \begingroup
+ \let\skv@tvalue#3%
+ \def#2{}\def#3{}%
+ \def\skv@prova##1(##2){%
+ \def\skv@provb{##2}%
+ \ifx\skv@provb\@nnil\else
+ \edef#2{\skvexpandonce#2\skvtrimspace{##1}}%
+ \edef#3{\skvexpandonce#3{\skvtrimspace{##2}}}%
+ \expandafter\skv@prova
+ \fi
+ }%
+ \skv@prova#1(\@nil)%
+ \ifx#2\@empty
+ \edef#2{\unexpanded{#1}}%
+ \let#3\skv@tvalue
+ \fi
+ \skvexpanded{\endgroup\skvcmdexit#2\skvcmdexit#3}%
+}
+\skvrobustdef*\skv@replacepointers#1{%
+ \begingroup
+ \let\skvcurrentvalue\@empty
+ \let\skv@tempa\@empty
+ \skvifbraced{#1}{%
+ \skv@r@placepointers{#1}.use value\skv@nil
+ }{%
+ \skv@r@placepointers#1.use value\skv@nil
+ }%
+ \skvaftergroupdef\skvcurrentvalue\endgroup
+}
+% In xkeyval package, if we put, eg,
+%
+% key2=\dimexpr\usevalue{key1}*5\relax
+%
+% \dimexpr will be lost (as part of the value of key2) in pointer
+% replacement. We avoid that deficiency here.
+%
+\skvrobustdef*\skv@r@placepointers#1.use value#2{%
+ \edef\skv@prova{\unexpanded{#2}}%
+ \skvifx\skv@prova\skv@nnil{%
+ \edef\skvcurrentvalue{\unexpanded{#1}}%
+ }{%
+ \skvifcsundef{\skv@header#2.@value}{%
+ \skv@err{No value recorded for key '#2'; ignored}\@ehd
+ \skv@r@placepointers
+ }{%
+ \skvxifin{,\detokenize{#2},}{,\skvoxdetok\skv@tempa,}{%
+ \skv@err{Back linking of pointers;
+ \MessageBreak pointer replacement canceled}\@ehd
+ }{%
+ \edef\skv@tempa{\skvaddlist,\skv@tempa\unexpanded{#2}}%
+ \edef\skv@prova{\skvexpandcsonce{\skv@header#2.@value}}%
+ \skvexpandbracenext\skvifbraced\skv@prova{%
+ \skvexpandbracenext{\skv@r@placepointers#1}\skv@prova
+ }{%
+ \skvexpandnext{\skv@r@placepointers#1}\skv@prova
+ }%
+ }%
+ }%
+ }%
+}
+
+% Assign arguments to keys:
+%
+% \skvassignargs[<prefixes>]{<families>}[<expansion.type>]{<keys>}{<arg>}
+%
+% 1. Valid expansion types are x0 (unexpanded), x1 (expand once),
+% x2 (expand twice), xx (expand fully). The default expansion type is
+% x0 (unexpanded).
+% 2. At set keys (not at define keys), the argument to the listed keys will
+% be expanded using the expansion type.
+% 3. The argument will be assigned whether or not a key already has been
+% defined. This allows the user to define the key later, after its
+% argument has been fixed.
+% 3. Under the macros \skvdefinekeys and \directkeys, there are equally
+% efficient handlers for assigning arguments to keys.
+%
+% Example:
+%
+% \skvassignargs[KV1,KV2]{fam1,fam2}[x1]{keya,keyb}{#1/#2}
+% \skvsetkeys[KV1]{fam2}{keya=vala/valb}
+%
+% For each prefix and family, this will define parameterless functions
+%
+% \<prefix>/<family>/key/.@x1arg.
+%
+% which will be used at setkeys to define and execute the key's callback.
+%
+\skvrobustdef*\skvassignargs{\skv@testopt\skv@assignargs{KV}}
+\skvrobustdef*\skv@assignargs[#1]#2{%
+ \begingroup
+ \skv@testopt{\skv@assignargs@a{#1}{#2}}{^skv^}%
+}
+\skvrobustdef*\skv@assignargs@a#1#2[#3]#4#5{%
+ \edef\skv@tempc{\skvtrimspace{#5}}%
+ \def\skv@tempd{}%
+ \skvifstrcmp{#3}{^skv^}{%
+ \def\skvexpander{x0}%
+ }{%
+ \skv@checkexpander{#3}%
+ \edef\skvexpander{\skvtrimspace{#3}}%
+ }%
+ \def\\{\noexpand\unexpanded}%
+ \skvcommaloop{#1}\skv@tempa{%
+ \skv@makeprefix\skv@tempa
+ \skvcommaloop{#2}\skv@tempa{%
+ \skv@makeheader\skv@tempa
+ \skvcommaparse{#4}\skv@tempa{%
+ \edef\skv@tempd{\skvexpandonce\skv@tempd
+ \skvcsedef{\skv@header\skv@tempa.@\skvexpander arg}{%
+ \\{\\{\skvexpandonce\skv@tempc}}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \skvexpanded{\endgroup\skv@tempd}%
+}
+\skvrobustdef*\skv@checkexpander#1{%
+ \skvxifin{,\expandafter\skvtrimspace\expandafter
+ {\detokenize\expandafter{#1}},}{,\detokenize{x0,x1,x2,xx},}{}{%
+ \skv@err{Illegal expansion type '#1'}\@ehd
+ }%
+}
+
+% Ordinary keys:
+%
+% \skvordkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
+%
+\skvrobustdef*\skvordkey{\skv@testoptb\skv@ordkey}
+\skvrobustdef*\skv@ordkey#1{%
+ \skv@strippointers{#1}\skvcurrentkey
+ \skvexpanded{\skv@testopt{\skv@ordkey@a{\skvcurrentkey}}{^skv^}}%
+}
+\skvrobustdef*\skv@ordkey@a#1[#2]#3{%
+ \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}%
+ \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}%
+}
+\skvrobustdef*\skvordkeys{\skv@testoptb\skv@ordkeys}
+\skvrobustdef*\skv@ordkeys#1{\skv@testopt{\skv@ordkeys@a{#1}}{^skv^}}
+\skvrobustdef*\skv@ordkeys@a#1[#2]#3{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey
+ \skvexpanded{\skv@ordkey@a{\skvcurrentkey}}[#2]{#3}%
+ }%
+}
+
+% \skvvoidkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
+%
+% A void key is an invalid key. A user who tries to set that key will
+% automatically be told that the key is inadmissible. The author of an
+% invalid key can also use <callback> to set a message.
+%
+\skvrobustdef*\skvvoidkey{\skv@testoptb\skv@voidkey}
+\skvrobustdef*\skv@voidkey#1{%
+ \skv@strippointers{#1}\skvcurrentkey
+ \skvexpanded{\skv@testopt{\skv@voidkey@a{\skvcurrentkey}}{^skv^}}%
+}
+\skvrobustdef*\skv@voidkey@a#1[#2]#3{%
+ \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}%
+ % Simply inserting '#3' in the next definition will not work because
+ % of the possible parameter characters in #3:
+ \edef\skv@tempa##1##2{%
+ ##2%
+ \skv@err{Key '#1' of family '\skvcurrentprefix/\skvcurrentfamily'
+ \MessageBreak has been set invalid by its author}\noexpand\@ehd
+ }%
+ \skv@toksa\expandafter{\skv@tempa{##1}{#3}}%
+ \skvcsedef{\skv@header#1.@cbk}{\the\skv@toksa}%
+}
+
+%% Key names with parenthesized tokens.
+%
+% \skvpntkey[<pref>]{<fam>}{<key>}[<defa>]{<callback>}
+%
+% The tokens in parenthesis are removed when building the key name.
+% Each parenthesis gives rise to one argument of the key's callback.
+% When the key is set, the tokens in parenthesis are assigned to the
+% arguments. It is the user's responsibility to catch those argument
+% in the key's callback.
+%
+% Example - a key of three arguments:
+%
+% \skvpntkey[KV]{fam}{evaluate (1) as (2) using (3)}{%
+% \def\oldcmd{#1}\def\newcmd{#2}\def\formula{#3}%
+% \def\x##1{#1*##1}%
+% }
+%
+% \skvpntkey[KV]{fam}{evaluate (1) as (2) using (3)}[%
+% \x\y{\numexpr\x*2}
+% ]{%
+% \edef\x#2{#3}%
+% }
+%
+% \skvshowcs{KV/fam/evaluateasusing/.@x0arg}
+%
+% \skvsetkeys[KV]{fam}{evaluate (\x) as (\y) using (\numexpr\x*2)}
+%
+\skvrobustdef*\skvpntkey{\skv@testoptb\skv@pntkey}
+\skvrobustdef*\skv@pntkey#1{%
+ \skv@strippointers{#1}\skvcurrentkey
+ \skvexpbracenext\skv@extractpntkey\skvcurrentkey\skvcurrentkey
+ \skvexpanded{\skv@testopt{\skv@pntkey@a{\skvcurrentkey}}{^skv^}}%
+}
+\skvrobustdef*\skv@pntkey@a#1[#2]#3{%
+ \skvifstrcmp{#2}{^skv^}{}{\skv@definedefault{#1}{#2}}%
+ \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}%
+}
+
+%% Command keys:
+%
+% \skvcmdkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>}
+%
+\skvrobustdef*\skvcmdkey{%
+ \def\skv@zapnr{0}%
+ \skv@testoptd\skv@cmdkey{cmd}%
+}
+
+% \skvzcmdkey will internally zap the spaces in the key's name, but the
+% key user will not notice that: he can still use the key's name with
+% spaces in it. The key's author could then use the zapped name internally
+% in his code.
+\skvrobustdef*\skvzcmdkey{%
+ \def\skv@zapnr{1}%
+ \skv@testoptd\skv@cmdkey{cmd}%
+}
+% When the key's value has doubled hash characters, xkeyval's definition
+% of \skv@cmdkey fails:
+\skvrobustdef*\skv@cmdkey#1#2[#3]#4{%
+ \skv@strippointers{#2}\skvcurrentkey
+ \skvifdefbool{skv@st}{\skv@definedefault\skvcurrentkey{#3}}{}%
+ % This is to allow the key name to be expanded before possibly zapping
+ % spaces in key name:
+ \edef\skv@prova{#1\skvcurrentkey}%
+ \edef\skv@prova{\expandafter\skv@zapornot\expandafter
+ {\expandafter\skv@zapnr\expandafter}\expandafter{\skv@prova}}%
+ \skvcslet{\skv@header\skvcurrentkey.@hp}\skv@prova
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\unexpanded{#4}}%
+}
+% \skvcmdkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}
+\skvrobustdef*\skvcmdkeys{%
+ \def\skv@zapnr{0}%
+ \skv@testoptd\skv@cmdkeys{cmd}%
+}
+\skvrobustdef*\skvzcmdkeys{%
+ \def\skv@zapnr{1}%
+ \skv@testoptd\skv@cmdkeys{cmd}%
+}
+\skvrobustdef*\skv@cmdkeys#1#2[#3]#4{%
+ \skvcommaparse{#2}\skv@tempa{%
+ \skvexpanded{\skv@cmdkey{#1}{\skv@tempa}}[#3]{#4}%
+ }%
+}
+
+%% Choice keys:
+%
+% \skvchoicekey[<pref>]{<fam>}[<mp>]{<key>}[<bins>]{<choices>}
+% [<defa>]{<callback>}
+%
+% The skeyval package allows holder-macro prefixes for choice keys.
+\skvrobustdef*\skvchoicekey{%
+ \skv@testopta{\skv@testoptb
+ {\skv@testopt\skv@choicekey@a{choice\skv@header}}}%
+}
+\skvrobustdef*\skv@choicekey@a[#1]#2{%
+ \skv@strippointers{#2}\skvcurrentkey
+ \skvcsedef{\skv@header\skvcurrentkey.@hp}{%
+ \skvtrimspace{#1}\skvcurrentkey
+ }%
+ \skv@testopt\skv@choicekey@b{}%
+}
+\skvrobustdef*\skv@choicekey@b[#1]#2{%
+ \def\skv@bins{#1}%
+ \edef\skv@tempa{\unexpanded{#2}}%
+ \skvcsvnormalize\skv@tempa
+ \skv@toksa\expandafter{\skv@tempa}%
+ \skvifnextchar[\skv@choicekey@c{\skv@choicekey@c[^skv^]}%
+}
+\skvrobustdef*\skv@choicekey@c[#1]{%
+ \skvifstrcmp{#1}{^skv^}{}{\skv@definedefault\skvcurrentkey{#1}}%
+ \skvifdefbool{skv@pl}\skv@choicekey@e\skv@choicekey@d
+}
+\skvrobustdef*\skv@choicekey@d#1{\skv@choicekey@f{{#1}}}
+\skvrobustdef*\skv@choicekey@e#1#2{\skv@choicekey@f{{#1}{#2}}}
+\skvrobustdef*\skv@choicekey@f#1{%
+ \edef\skv@tempa##1##2{%
+ \ifskv@st\noexpand\skv@sttrue\else\noexpand\skv@stfalse\fi
+ \ifskv@pl\noexpand\skv@pltrue\else\noexpand\skv@plfalse\fi
+ \skv@checkchoice[\skvexpandonce\skv@bins]{##1}{\the\skv@toksa}##2%
+ }%
+ \skv@toksa\expandafter{\skv@tempa{##1}{#1}}%
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\the\skv@toksa}%
+}
+
+%% Boolean keys:
+%
+% \skvboolkey[<pref>]{<fam>}[<mp>]{<key>}[<defa>]{<callback>}
+%
+% Boolean keys create a store to receive the key's value and also create
+% a boolean internally.
+\skvrobustdef*\skvboolkey{%
+ \def\skv@zapnr{0}%
+ \skv@t@stopta{\skv@testoptd\skv@boolkey{}}%
+}
+% \skvzcmdkey will internally zap the spaces in the key's name and in
+% the boolean that it creates internally, but the key user will not
+% notice that: he will still be able to submit the original key's name
+% with spaces in it. The key's author could then use the zapped key
+% name and boolean in his code (internally).
+\skvrobustdef*\skvzboolkey{%
+ \def\skv@zapnr{1}%
+ \skv@t@stopta{\skv@testoptd\skv@boolkey{}}%
+}
+\skvrobustdef*\skv@boolkey#1#2[#3]{%
+ \skv@strippointers{#2}\skvcurrentkey
+ \skvexpanded{%
+ \ifskv@pl\skv@boolkey@b\else\skv@boolkey@a\fi
+ {\skvcurrentkey}{#1\skvcurrentkey}%
+ }{#3}%
+}
+\skvrobustdef*\skv@boolkey@a#1#2#3#4{%
+ \def\skv@tempa{\skv@boolkey@c{#1}{#2}{#3}}%
+ \expandafter\skv@tempa\expandafter{\expandafter{\expandafter
+ \csname\expandafter\skv@zapornot\expandafter{\skv@zapnr}{#2}%
+ \skv@value\endcsname#4}}%
+}
+\skvrobustdef*\skv@boolkey@b#1#2#3#4#5{%
+ \def\skv@tempa{\skv@boolkey@c{#1}{#2}{#3}}%
+ \expandafter\skv@tempa\expandafter{\expandafter{\expandafter
+ \csname\expandafter\skv@zapornot\expandafter{\skv@zapnr}{#2}%
+ \skv@value\endcsname#4}{#5}}%
+}
+\skvrobustdef*\skv@boolkey@c#1#2#3#4{%
+ \skvcsnewif{\skv@zapornot{\skv@zapnr}{#2}}%
+ \skvifdefbool{skv@st}{\skv@definedefault{#1}{#3}}{}%
+ \edef\skv@tempa##1##2{%
+ \noexpand\skv@sttrue
+ \ifskv@pl\noexpand\skv@pltrue\else\noexpand\skv@plfalse\fi
+ \skv@checkchoice[\noexpand\skv@value]{##1}{true,false}##2%
+ }%
+ \skv@toksa\expandafter{\skv@tempa{##1}{#4}}%
+ \skvcsedef{\skv@header#1.@cbk}{\the\skv@toksa}%
+}
+% \skvboolkeys[<pref>]{<fam>}[<mp>]{<keys>}[<defa>]{<callback>}
+\skvrobustdef*\skvboolkeys{%
+ \def\skv@zapnr{0}%
+ \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}%
+}
+\skvrobustdef*\skvzboolkeys{%
+ \def\skv@zapnr{1}%
+ \skv@t@stopta{\skv@testoptd\skv@boolkeys{}}%
+}
+\skvrobustdef*\skv@boolkeys#1#2[#3]{%
+ \skvifdefbool{skv@pl}\skv@boolkeys@b\skv@boolkeys@a{#2}{#1}{#3}%
+}
+\skvrobustdef*\skv@boolkeys@a#1#2#3#4{\skv@boolkeys@c{#1}{#2}{#3}{#4}{^skv^}}
+\skvrobustdef*\skv@boolkeys@b#1#2#3#4#5{\skv@boolkeys@c{#1}{#2}{#3}{#4}{#5}}
+\skvrobustdef*\skv@boolkeys@c#1#2#3#4#5{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \skvexpbracenext\skv@strippointers\skv@tempa\skvcurrentkey
+ \skvexpanded{%
+ \skvifstrcmp{#5}{^skv^}{%
+ \skv@boolkey@a{\skvcurrentkey}%
+ {#2\skvcurrentkey}\unexpanded{{#3}{#4}}%
+ }{%
+ \skv@boolkey@b{\skvcurrentkey}%
+ {#2\skvcurrentkey}\unexpanded{{#3}{#4}{#5}}%
+ }%
+ }%
+ }%
+}
+
+% Style keys
+%
+% \skvappendstyles[<pref>]{<fam>}{<keys>}{<styles>}[<defa>]{<callback>}
+% \skvprependstyles[<pref>]{<fam>}{<keys>}{<styles>}[<defa>]{<callback>}
+%
+% 1. Style keys will be created if they didn't exist. If they existed,
+% (a) their default values will be overwritten if the option [<defa>]
+% appears in the above syntax; (b) their callbacks will be updated with
+% <callback> and <styles>.
+%
+% 2. If desired, use pointers/handlers .expanded, .expand once, .expand twice
+% on values of styles.
+%
+% Example:
+%
+% \skvordkeys[KV]{fam}{keya,keyb}{\def\x##1{#1*##1}}
+% \skvappendstyles[KV]{fam}{keyd,keye}{keya=.expanded{\vala},keyb=valb}
+% [def-d&e]{\def\y##1{#1*##1}}
+%
+\skvrobustdef*\skvappendstyles{%
+ \def\skv@type{app}%
+ \def\skvexpanderpointer{}%
+ \skv@testoptb\skv@appendstyles
+}
+\skvnewlet\skvstylekeys\skvappendstyles
+\skvrobustdef*\skvprependstyles{%
+ \def\skv@type{prep}%
+ \def\skvexpanderpointer{}%
+ \skv@testoptb\skv@appendstyles
+}
+\skvrobustdef*\skvappendstylesexpanded{%
+ \def\skv@type{app}%
+ \def\skvexpanderpointer{.expanded}%
+ \skv@testoptb\skv@appendstyles
+}
+\skvnewlet\skvstylekeysexpanded\skvappendstylesexpanded
+\skvrobustdef*\skvprependstylesexpanded{%
+ \def\skv@type{prep}%
+ \def\skvexpanderpointer{.expanded}%
+ \skv@testoptb\skv@appendstyles
+}
+\skvrobustdef*\skv@appendstyles#1#2{%
+ \skv@testopt{\skv@appendstyles@a{#1}{#2}}{^skv^}%
+}
+% #2: styles, #3: default, #4: callback
+\skvrobustdef*\skv@appendstyles@a#1#2[#3]#4{%
+ \skvcommaparse{#1}\skv@prova{%
+ \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpanded{%
+ \skvifstrcmp{#3}{^skv^}{}{%
+ \skv@definedefault{\skvcurrentkey}{\unexpanded{#3}}%
+ }%
+ \skv@appendstyles@b{\skvcurrentkey}\unexpanded{{#2}{#4}}%
+ }%
+ }%
+}
+% \skv@appendstyles@b{<parent.key>}{<styles>}{<parent.key.callback>}
+\skvrobustdef*\skv@appendstyles@b#1#2#3{%
+ \def\skv@stylelist{}%
+ \skvkvparse{#2}\skv@provb{%
+ \def\skv@prova##1=##2=##3\skv@nil{%
+ \skvxifstrcmp{#1}{##1}{%
+ \skv@err{Linking key '##1' to itself}\@ehd
+ }{%
+ \skvifcsdef{\skv@header##1.@cbk}{}{%
+ \skv@err{Style key '##1' is undefined}\@ehd
+ }%
+ }%
+ \edef\skv@stylelist{%
+ \skvaddlist,\skv@stylelist\unexpanded{##1}=%
+ \skvexpandonce\skvexpanderpointer{\unexpanded{##2}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@provb==\skv@nil
+ }%
+ \edef\elt{%
+ \skvifcsdef{\skv@header#1.@cbk}
+ {\skvxpandcsonce{\skv@header#1.@cbk}}{}%
+ }%
+ \edef\skv@elt{%
+ \noexpand\skvexpanded{\noexpand\skvsetkeys[\skvcurrentprefix]%
+ {\skvcurrentfamily}{\skvexpandonce\skv@stylelist}}%
+ }%
+ \skvcsedef{\skv@header#1.@cbk}{%
+ \skvxifstrcmp{\skv@type}{prep}{%
+ \skvexpandonce\skv@elt\unexpanded{#3}\skvexpandonce\elt
+ }{%
+ \skvexpandonce\elt\unexpanded{#3}\skvexpandonce\skv@elt
+ }%
+ }%
+}
+%
+% \skvaddstyles[<pref>]{<fam>}{<keys>}{<prepend>}{<append>}[<defa>]{<callback>}
+%
+% Example:
+% \skvordkeys[KV]{fam}{keya1,keyb1,keya2,keyb2}{\def\x##1{#1*##1}}
+% \skvaddstyles[KV]{fam}{keyd,keye}{keya1=vala,keyb1=valb}
+% {keya2=vala,keyb2=.expanded{\valb}}[def-d&e]{\def\y##1{#1*##1}}
+%
+\skvrobustdef*\skvaddstyles{%
+ \def\skvexpanderpointer{}%
+ \skv@testoptb\skv@addstyles
+}
+\skvrobustdef*\skv@addstyles#1#2#3{%
+ \skv@testopt{\skv@addstyles@a{#1}{#2}{#3}}{^skv^}%
+}
+% #2: prepended styles
+% #3: appended styles
+% #4: default
+% #5: callback
+\skvrobustdef*\skv@addstyles@a#1#2#3[#4]#5{%
+ \skvexpanded{%
+ \skvprependstyles[\skvcurrentprefix]{\skvcurrentfamily}%
+ \unexpanded{{#1}{#2}[#4]{#5}}%
+ \skvappendstyles[\skvcurrentprefix]{\skvcurrentfamily}%
+ \unexpanded{{#1}{#3}[#4]{#5}}%
+ }%
+}
+
+%% Checking the admissible values of keys:
+%
+\skvrobustdef*\skvcheckchoice{\skv@testopta{\skv@testopt\skv@checkchoice{}}}
+\skvrobustdef*\skv@checkchoice[#1]#2#3{%
+ \begingroup
+ \edef\skv@tempa{\skvtrimspace{#2}}%
+ \def\skv@tempb{#3}%
+ \skvcsvnormalize\skv@tempb
+ \skvexpanded{%
+ \ifskv@st\lowercase{\fi
+ \ifcat$\detokenize{#1}$%
+ \skv@checkchoice@b\skv@nil
+ {\skvexpandonce\skv@tempa}{\skvexpandonce\skv@tempb}%
+ \else
+ \skv@checkchoice@a\unexpanded{#1}\skv@nil
+ {\skvexpandonce\skv@tempa}{\skvexpandonce\skv@tempb}%
+ \fi
+ \ifskv@st}\fi
+ }%
+}
+\skvrobustdef*\skv@checkchoice@a#1#2\skv@nil#3#4{%
+ \def\skv@tempa{#2}%
+ \skvifx\skv@tempa\@empty{%
+ \skv@checkchoice@b#1{#3}{#4}%
+ }{%
+ \skv@checkchoice@c#1#2{#3}{#4}%
+ }%
+}
+\skvrobustdef*\skv@checkchoice@b#1#2#3{%
+ \def\skv@tempa{#1}%
+ \ifx\skv@tempa\skv@nnil
+ \def\skv@tempa{\endgroup}%
+ \else
+ \def\skv@tempa{\endgroup\def#1{#2}}%
+ \fi
+ \skvifin{,#2,}{,#3,}{%
+ \ifskv@pl
+ \skvappendtomacro\skv@tempa{\@firstoftwo}%
+ \else
+ \skvappendtomacro\skv@tempa{\@firstofone}%
+ \fi
+ }{%
+ \ifskv@pl
+ \skvappendtomacro\skv@tempa{\@secondoftwo}%
+ \else
+ \skv@err{Value '\detokenize{#2}' is not allowed}\@ehd
+ \skvappendtomacro\skv@tempa{\@gobble}%
+ \fi
+ }%
+ \skv@tempa
+}
+\skvrobustdef*\skv@checkchoice@c#1#2#3#4{%
+ \@tempcnta\skvz@
+ \def\skv@tempa{#3}%
+ \edef\skv@tempc{\unexpanded{#4}}%
+ \skvcsvnormalize\skv@tempc
+ \def\skv@prova{\endgroup\skvexpandonce\skv@tempc\noexpand}%
+ \def\skv@tempb##1,{%
+ \def\skv@provb{##1}%
+ \ifx\skv@provb\skv@nnil
+ \def\skv@tempc{\def#1{#3}\def#2{-1}}%
+ \ifskv@pl
+ \edef\skv@tempb{\skv@prova\@secondoftwo}%
+ \else
+ \skv@err{Value '\detokenize{#3}' is not allowed}\@ehd
+ \edef\skv@tempb{\skv@prova\@gobble}%
+ \fi
+ \else
+ \edef\skv@tempc{\def\unexpanded{#1{##1}\def#2}{\the\@tempcnta}}%
+ \ifx\skv@provb\skv@tempa
+ \ifskv@pl
+ \edef\skv@tempb{\skv@prova\skv@checkchoice@d}%
+ \else
+ \edef\skv@tempb{\skv@prova\skv@checkchoice@e}%
+ \fi
+ \else
+ \advance\@tempcnta\@ne
+ \fi
+ \fi
+ \skv@tempb
+ }%
+ \expandafter\skv@tempb\skv@tempc,\skv@nil,%
+}
+\skvrobustdef*\skv@checkchoice@d#1\skv@nil,{\@firstoftwo}
+\skvrobustdef*\skv@checkchoice@e#1\skv@nil,{\@firstofone}
+
+% \skvifkeydef[<prefs>]{<fams>}{key}{<true>}{<false>}
+% 1. The search will stop as soon as the key is found in one combination
+% of prefixes/families.
+% 2. The prefix and header created here may be needed in #5 and #6. Hence
+% we put entry prefix and header on stack before commencing the search.
+\skvrobustdef*\skvifkeydef{\skv@testopt{\skv@ifkeyundef0}{KV}}
+\skvrobustdef*\skvifkeyundef{\skv@testopt{\skv@ifkeyundef1}{KV}}
+\skvrobustdef*\skv@ifkeyundef#1[#2]#3#4#5#6{%
+ \skvpushstate\skv@keystate\skv@keydepth
+ \edef\skv@prefs{#2}%
+ \edef\skv@fams{#3}%
+ \skvdespace{#4}\skvcurrentkey
+ \skv@kffalse
+ % Don't use \skvcurrentprefix in place of \skv@prova here.
+ % We use \skv@prova here because \skv@tempa, \skvcurrentprefix and
+ % \skvcurrentfamily might be in use already.
+ \skvcommaparse*\skv@prefs\skv@prova{%
+ \skv@makeprefix\skv@prova
+ \skv@ifk@yundef
+ \ifskv@kf\skvbreakloop\fi
+ }%
+ \skvexpanded{%
+ \skvifbool{skv@kf}{%
+ \if0#1%
+ \noexpand\@firstoftwo
+ \else
+ \noexpand\@secondoftwo
+ \fi
+ }{%
+ \if0#1%
+ \noexpand\@secondoftwo
+ \else
+ \noexpand\@firstoftwo
+ \fi
+ }%
+ }%
+ {#5}{#6}%
+ \skvpopstate\skv@keystate\skv@keydepth
+}
+\skvrobustdef*\skv@ifk@yundef{%
+ \skvcommaparse*\skv@fams\skv@prova{%
+ \skv@makeheader\skv@prova
+ \skvifcsundef{\skv@header\skvcurrentkey.@cbk}{}{%
+ \skv@kftrue\skvbreakloop
+ }%
+ }%
+}
+% \skvifkeyinfamilies[<prefs>]{<fams>}{key}{<true>}{<false>}
+% The search will be done on all combinations of prefixes/families. The
+% callback <true> or <false> will be executed for all the combinations.
+\skvrobustdef*\skvifkeyinfamilies{%
+ \skv@testopt{\skv@ifkeyinfamilies0}{KV}%
+}
+\skvrobustdef*\skvifkeynotinfamilies{%
+ \skv@testopt{\skv@ifkeyinfamilies1}{KV}%
+}
+\skvrobustdef*\skv@ifkeyinfamilies#1[#2]#3#4#5#6{%
+ \skvpushstate\skv@keystate\skv@keydepth
+ \edef\skv@prefs{#2}%
+ \edef\skv@fams{#3}%
+ \skvdespace{#4}\skvcurrentkey
+ \skvcommaparse*\skv@prefs\skv@prova{%
+ \skv@makeprefix\skv@prova
+ \skv@ifk@yinfamilies{#1}{#5}{#6}%
+ }%
+}
+\skvrobustdef*\skv@ifk@yinfamilies#1#2#3{%
+ \skvcommaparse*\skv@fams\skv@prova{%
+ \skv@makeheader\skv@prova
+ \skvexpanded{%
+ \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{%
+ \if0#1%
+ \noexpand\@firstoftwo
+ \else
+ \noexpand\@secondoftwo
+ \fi
+ }{%
+ \if0#1%
+ \noexpand\@secondoftwo
+ \else
+ \noexpand\@firstoftwo
+ \fi
+ }%
+ }{#2}{#3}%
+ }%
+ \skvpopstate\skv@keystate\skv@keydepth
+}
+% \skvifkeyinfamily{<prefix>/<family>}{<key>}
+\skvnewdef*\skvifkeyinfamily#1#2{%
+ \skvifcsdef{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}%
+}
+% \skvifkeyincurrentfamily{<key>}
+\skvnewdef*\skvifkeyincurrentfamily#1{%
+ \skvifcsdef{\skvcurrentpath/\skvtrimspace{#1}.@cbk}%
+}
+% \skvifonekeyinfamily{<prefix>/<family>}{<keys>}
+% Given a list of keys, test if at least one of them is defined.
+% Example: \edef\x{\skvifonekeyinfamily{KV/fam}{keya,keyb,keyc}{T}{F}}.
+\skvnewdef*\skvifonekeyinfamily#1#2{%
+ \ifnum\numexpr0\skv@ifonekeydef{#1}#2,\@nnil,>\skvz@
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\skvnewdef*\skv@ifonekeydef#1#2,{%
+ \ifx\@nnil#2%
+ \expandafter\@gobble
+ \else
+ \skvifcsndef{\skvtrimspace{#1}/\skvtrimspace{#2}.@cbk}{+1}{+0}%
+ \expandafter\skv@ifonekeydef
+ \fi
+ {#1}%
+}
+
+% \skvvalueof{<pref>}{<family>}{<key>}
+\skvnewdef*\skvvalueof#1#2#3{\skvcsuse{#1/#2/#3.@value}}
+
+% When <pref> isn't given, the following will use 'KV' for <pref>.
+% \skvprintvalue[<pref>]{<family>}{<key>}
+\skvrobustdef*\skvprintvalue{\skv@testoptb\skv@printvalue}
+\skvrobustdef*\skv@printvalue#1{\skvcsuse{\skv@header#1.@value}}
+
+% \skvgetvalue{<pref>}{<family>}{<key>}<cmd>
+\skvrobustdef*\skvgetvalue#1#2#3#4{\skvletcs#4{#1/#2/#3.@value}}
+
+% \skvconveyvalue[<pref>]{<family>}{<key>}<cmd>
+\skvrobustdef*\skvconveyvalue{\skv@testoptb\skv@conveyvalue}
+\skvrobustdef*\skv@conveyvalue#1#2{\skvletcs#2{\skv@header#1.@value}}
+
+% \skvgetinikv{<pref>}{<family>}<cmd>
+\skvrobustdef*\skvgetinikv#1#2#3{\skvletcs#3{#1/#2.@inikv}}
+
+% \skvconveyinikv[<pref>]{<family>}<cmd>
+\skvrobustdef*\skvconveyinikv{\skv@testoptb\skv@conveyinikv}
+\skvrobustdef*\skv@conveyinikv#1{\skvletcs#1{\skv@header.@inikv}}
+
+% \skvkeyslet[<pref>]{<family>}{<list>}
+% <list> -> <new keyname>=<old keyname>
+\skvrobustdef*\skvkeyslet{\skv@testoptb\skv@keyslet}
+\skvnewlet\skvkeylet\skvkeyslet
+\skvrobustdef*\skv@keyslet#1{%
+ \skvletcs\skv@inikv{\skv@header.@inikv}%
+ \skvifundef\skv@inikv{}{%
+ \expandafter\skv@getkeynames\expandafter{\skv@inikv}\skv@inikeys
+ }%
+ \def\skv@k@yslet##1=##2=##3\skv@nil{%
+ \skvifcsundef{\skv@header##2.@cbk}{%
+ \skv@err{Key '\skvcurrentpath/##2' is undefined}\@ehd
+ }{%
+ \skvifcsdef{\skv@header##1.@cbk}{%
+ \skv@err{Key '\skvcurrentpath/##1' is already defined}\@ehd
+ }{}%
+ }%
+ \skvcommaloop{cbk,ndv,fbv}\skv@prova{%
+ \skvcsletcs{\skv@header##1.@\skv@prova}{\skv@header##2.@\skv@prova}%
+ }%
+ \skvifcsdef{\skv@header##2.@defa}{%
+ \edef\skvcurrentkey{##2}%
+ \skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey
+ \skvcurrentvalue
+ \skvcsedef{\skv@header##1.@defa}{%
+ \skvnoexpandcs{\skv@header##1}{\skvexpandonce\skvcurrentvalue}%
+ }%
+ \skv@swatrue
+ }{%
+ \skv@swafalse
+ }%
+ \skvifundef\skv@inikv{}{%
+ \skvxifnotin{,\detokenize{##2},}{,\skvoxdetok\skv@inikeys,}{}{%
+ \skvcsedef{\skv@header.@inikv}{%
+ \expandafter\skvaddlist\expandafter
+ ,\csname\skv@header.@inikv\endcsname
+ ##1\ifskv@swa=\skvexpandonce\skvcurrentvalue\fi
+ }%
+ }%
+ }%
+ \skvcommaloop{ignoredkeys,needini}\skv@prova{%
+ \skvletcs\skv@tempa{\skv@header.@\skv@prova}%
+ \skvifundef\skv@tempa{}{%
+ \skvxifnotin{,\detokenize{##2},}{,\skvoxdetok\skv@tempa,}{}{%
+ \skvcsedef{\skv@header.@\skv@prova}{\skvaddlist,\skv@tempa##1}%
+ }%
+ }%
+ }%
+ }%
+ \skvkvparse{#1}\skv@prova{%
+ \expandafter\skv@k@yslet\skv@prova==\skv@nil
+ }%
+ \let\do\skvundef
+ \do\skv@k@yslet\do\skv@inikv\do\skv@inikeys
+}
+
+\skvrobustdef*\skv@disabledkeywarning#1{%
+ \skv@warn{Key '\skvcurrentpath/#1' has been disabled
+ \MessageBreak You can't set or reset key '#1' at this
+ \MessageBreak late stage. Perhaps you should have set it
+ \MessageBreak earlier \ifskv@inlatex in \noexpand\documentclass or
+ \string\usepackage\fi}%
+}
+\skvrobustdef*\skv@disabledkeyerror#1{%
+ \skv@err{Key '\skvcurrentpath/#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 \ifskv@inlatex in \noexpand\documentclass or
+ \string\usepackage\fi}%
+}
+\skvrobustdef*\skvdisabledkeysmessagetype#1{%
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\@nil{%
+ \ifcase####2\relax
+ \let\skv@disabledmsg\skv@disabledkeywarning
+ \or
+ \let\skv@disabledmsg\skv@disabledkeywarning
+ \or
+ \let\skv@disabledmsg\skv@disabledkeyerror
+ \or
+ \let\skv@disabledmsg\@gobble
+ \else
+ \skv@err{Invalid message type '#1' for disabled keys}\@ehd
+ \fi
+ }%
+ \skv@provb warn{0}warning{1}error{2}nothing{3}##1{10}\@nil
+ }%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
+}
+\skvdisabledkeysmessagetype{warn}
+
+\skvrobustdef*\skvdisablekeys{\skv@testoptb\skv@disablekeys}
+\skvrobustdef*\skv@disablekeys#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \skvifcsdef{\skv@header\skv@tempa.@cbk}{}{%
+ \skv@err{Key '\skv@tempa' is undefined:
+ \MessageBreak couldn't be disabled}\@ehd
+ }%
+ \skvifcsdef{\skv@header\skv@tempa.@defa}{%
+ \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}[]}%
+ }{%
+ \edef\skv@tempb{\noexpand\skv@ordkey{\skv@tempa}}%
+ }%
+ \expandafter\skv@tempb\expandafter{\expandafter\skv@disabledmsg
+ \expandafter{\skv@tempa}}%
+ }%
+}
+
+% We split xkeyval's \presetkeys (which has both head and tail) into
+% \skvpresetkeys (head only) and \skvpostsetkeys (tail only).
+% We strengthen \presetkeys as \skvpreposetkeys.
+%
+% \skvpresetkeys[<pref>]{<fam>}{<keys>}
+% \skvgpresetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvpresetkeys{\skv@testopt\skv@presetkeys{KV}}
+\skvrobustdef*\skv@presetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{#3}{}}
+\skvrobustdef*\skvgpresetkeys{\skv@testopt\skv@gpresetkeys{KV}}
+\skvrobustdef*\skv@gpresetkeys[#1]#2#3{\skvgpreposetkeys[#1]{#2}{#3}{}}
+\skvrobustdef*\skvpostsetkeys{\skv@testopt\skv@postsetkeys{KV}}
+\skvrobustdef*\skv@postsetkeys[#1]#2#3{\skvpreposetkeys[#1]{#2}{}{#3}}
+\skvrobustdef*\skvgpostsetkeys{\skv@testopt\skv@gpostsetkeys{KV}}
+\skvrobustdef*\skv@gpostsetkeys[#1]#2#3{\skvgpreposetkeys[#1]{#2}{}{#3}}
+\skvrobustdef*\skvpreposetkeys{\skv@clfalse\skv@testoptb\skv@preposetkeys}
+\skvrobustdef*\skvgpreposetkeys{\skv@cltrue\skv@testoptb\skv@preposetkeys}
+\skvrobustdef*\skv@preposetkeys#1#2{%
+ \skvifblank{#1}{}{\skv@pr@posetkeys{#1}{preset}}%
+ \skvifblank{#2}{}{\skv@pr@posetkeys{#2}{postset}}%
+}
+\skvrobustdef*\skv@pr@posetkeys#1#2{%
+ \skvifcsundef{\skv@header.@#2}{%
+ \skvnormalize{csv}{,}{#1}\skv@tempa
+ \ifskv@cl\expandafter\global\fi
+ \expandafter\def\csname\skv@header.@#2\expandafter
+ \endcsname\expandafter{\skv@tempa}%
+ }{%
+ % Don't change \skv@filtermergelist to \skvfiltermergelist:
+ \expandafter\skv@filtermergelist\csname\skv@header
+ .@#2\endcsname{#1}\skv@getkeyname
+ }%
+}
+% \skvremovepresetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremovepresetkeys{%
+ \skv@clfalse\skv@testoptb\skv@removepresetkeys
+}
+% \skvgremovepresetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgremovepresetkeys{%
+ \skv@cltrue\skv@testoptb\skv@removepresetkeys
+}
+\skvrobustdef*\skv@removepresetkeys#1{%
+ \skvifcsdef{\skv@header.@preset}{%
+ \expandafter\skv@filterremoveelements\csname\skv@header
+ .@preset\endcsname{#1}\skv@getkeyname
+ }{%
+ \skv@err{No preset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }%
+}
+% \skvundefpresetkeys[<pref>]{<fam>}
+\skvrobustdef*\skvundefpresetkeys{%
+ \skv@clfalse\skv@testoptb\skv@undefpresetkeys
+}
+\skvrobustdef*\skvgundefpresetkeys{%
+ \skv@cltrue\skv@testoptb\skv@undefpresetkeys
+}
+\skvrobustdef*\skv@undefpresetkeys{%
+ \skvifcsundef{\skv@header.@preset}{%
+ \skv@err{No preset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header.@preset}%
+ }%
+}
+
+% \skvremovepostsetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremovepostsetkeys{%
+ \skv@clfalse\skv@testoptb\skv@removepostsetkeys
+}
+% \skvgremovepostsetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgremovepostsetkeys{%
+ \skv@cltrue\skv@testoptb\skv@removepostsetkeys
+}
+\skvrobustdef*\skv@removepostsetkeys#1{%
+ \skvifcsdef{\skv@header.@postset}{%
+ \expandafter\skv@filterremoveelements\csname\skv@header
+ .@postset\endcsname{#1}\skv@getkeyname
+ }{%
+ \skv@err{No postset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }%
+}
+% \skvundefpostsetkeys[<pref>]{<fam>}
+\skvrobustdef*\skvundefpostsetkeys{%
+ \skv@clfalse\skv@testoptb\skv@undefpostsetkeys
+}
+\skvrobustdef*\skvgundefpostsetkeys{%
+ \skv@cltrue\skv@testoptb\skv@undefpostsetkeys
+}
+\skvrobustdef*\skv@undefpostsetkeys{%
+ \skvifcsundef{\skv@header.@postset}{%
+ \skv@err{No postset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header.@postset}%
+ }%
+}
+
+% \skvremovepreposetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremovepreposetkeys{%
+ \skv@clfalse\skv@testoptb\skv@removepreposetkeys
+}
+% \skvgremovepreposetkeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgremovepreposetkeys{%
+ \skv@cltrue\skv@testoptb\skv@removepreposetkeys
+}
+\skvrobustdef*\skv@removepreposetkeys#1#2{%
+ \skv@r@movepreposetkeys{#1}{preset}%
+ \skv@r@movepreposetkeys{#2}{postset}%
+}
+\skvrobustdef*\skv@r@movepreposetkeys#1#2{%
+ \skvifcsdef{\skv@header.@#2}{%
+ \expandafter\skv@filterremoveelements\csname\skv@header
+ .@#2\endcsname{#1}\skv@getkeyname
+ }{%
+ \skv@err{No preset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }%
+}
+% \skvundefpreposetkeys[<pref>]{<fam>}
+\skvrobustdef*\skvundefpreposetkeys{%
+ \skv@clfalse\skv@testoptb\skv@undefpreposetkeys
+}
+\skvrobustdef*\skvgundefpreposetkeys{%
+ \skv@cltrue\skv@testoptb\skv@undefpreposetkeys
+}
+\skvrobustdef*\skv@undefpreposetkeys{%
+ \skvifcsundef{\skv@header.@preset}{%
+ \skv@err{No preset keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header.@preset}%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header.@postset}%
+ }%
+}
+
+%% Note about the absence of '(g)save-value-keys':
+% All keys have their values saved in the macro '<header>.@value'.
+% The value can be accessed via \skvgetvalue of \skvconveyvalue. When
+% needed, the value can be taken outside a local group by using \global
+% on the macro that has inherited the key's value via these commands.
+
+% \skvneedvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvneedvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@needvaluekeys
+}
+\skvrobustdef*\skvgneedvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@needvaluekeys
+}
+\skvrobustdef*\skv@needvaluekeys#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsdef{\skv@header\skv@tempa.@ndv}{}%
+ }%
+}
+% \skvremoveneedvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremoveneedvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@removeneedvaluekeys
+}
+\skvrobustdef*\skvgremoveneedvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@removeneedvaluekeys
+}
+\skvrobustdef*\skv@removeneedvaluekeys#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header\skv@tempa.@ndv}%
+ }%
+}
+
+% \skvforbidvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvforbidvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@forbidvaluekeys
+}
+\skvrobustdef*\skvgforbidvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@forbidvaluekeys
+}
+\skvrobustdef*\skv@forbidvaluekeys#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsdef{\skv@header\skv@tempa.@fbv}{}%
+ }%
+}
+% \skvremoveforbidvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremoveforbidvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@removeforbidvaluekeys
+}
+\skvrobustdef*\skvgremoveforbidvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@removeforbidvaluekeys
+}
+\skvrobustdef*\skv@removeforbidvaluekeys#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \ifskv@cl\expandafter\global\fi
+ \skvcsundef{\skv@header\skv@tempa.@fbv}%
+ }%
+}
+
+% Save the default/initial values of keys:
+% \skvsaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvsaveinitialvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@saveinitialvaluekeys
+}
+% \skvgsaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgsaveinitialvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@saveinitialvaluekeys
+}
+\skvrobustdef*\skv@saveinitialvaluekeys#1{%
+ \skvifcsundef{\skv@header.@needini}{%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize\skv@tempa
+ \ifskv@cl\expandafter\global\fi
+ \skvcsedef{\skv@header.@needini}{\skvexpandonce\skv@tempa}%
+ }{%
+ \expandafter\skv@filtermergelist\csname
+ \skv@header.@needini\endcsname{#1}\skv@getkeyname
+ }%
+}
+% \skvremovesaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremovesaveinitialvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@removesaveinitialvaluekeys
+}
+% \skvgremovesaveinitialvaluekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgremovesaveinitialvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@removesaveinitialvaluekeys
+}
+\skvrobustdef*\skv@removesaveinitialvaluekeys#1{%
+ \skvifcsundef{\skv@header.@needini}{%
+ \skv@err{No save-initial keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \expandafter\skv@filterremoveelements\csname
+ \skv@header.@needini\endcsname{#1}\skv@getkeyname
+ }%
+}
+% \skvundefsaveinitialvaluekeys[<pref>]{<fam>}
+\skvrobustdef*\skvundefsaveinitialvaluekeys{%
+ \skv@clfalse\skv@testoptb\skv@undefsaveinitialvaluekeys
+}
+% \skvgundefsaveinitialvaluekeys[<pref>]{<fam>}
+\skvrobustdef*\skvgundefsaveinitialvaluekeys{%
+ \skv@cltrue\skv@testoptb\skv@undefsaveinitialvaluekeys
+}
+\skvrobustdef*\skv@undefsaveinitialvaluekeys{%
+ \skvifcsundef{\skv@header.@needini}{%
+ \skv@err{No save-initial keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \csname skv\ifskv@cl g\fi csundef\endcsname{\skv@header.@needini}%
+ }%
+}
+
+% While setting keys, ignore the listed keys.
+% \skvignorekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvignorekeys{\skv@clfalse\skv@testoptb\skv@ignorekeys}
+\skvrobustdef*\skvgignorekeys{\skv@cltrue\skv@testoptb\skv@ignorekeys}
+\skvrobustdef*\skv@ignorekeys#1{%
+ \skvifcsdef{\skv@header.@ignoredkeys}{%
+ \expandafter\skv@filtermergelist\csname
+ \skv@header.@ignoredkeys\endcsname{#1}\skv@getkeyname
+ }{%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[,]\skv@tempa
+ \ifskv@cl\expandafter\global\fi
+ \skvcsedef{\skv@header.@ignoredkeys}{\skvexpandonce\skv@tempa}%
+ }%
+}
+% \skvremoveignorekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvremoveignorekeys{%
+ \skv@clfalse\skv@testoptb\skv@removeignorekeys
+}
+% \skvgremoveignorekeys[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\skvgremoveignorekeys{%
+ \skv@cltrue\skv@testoptb\skv@removeignorekeys
+}
+\skvrobustdef*\skv@removeignorekeys#1{%
+ \skvifcsundef{\skv@header.@ignoredkeys}{%
+ \skv@err{No ignore keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \expandafter\skv@filterremoveelements\csname
+ \skv@header.@ignoredkeys\endcsname{#1}\skv@getkeyname
+ }%
+}
+% \skvundefignorekeys[<pref>]{<fam>}
+\skvrobustdef*\skvundefignorekeys{%
+ \skv@clfalse\skv@testoptb\skv@undefignorekeys
+}
+% \skvgundefignorekeys[<pref>]{<fam>}
+\skvrobustdef*\skvgundefignorekeys{%
+ \skv@cltrue\skv@testoptb\skv@undefignorekeys
+}
+\skvrobustdef*\skv@undefignorekeys{%
+ \skvifcsundef{\skv@header.@ignoredkeys}{%
+ \skv@err{No ignore keys defined for
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ \csname skv\ifskv@cl g\fi csundef\endcsname
+ {\skv@header.@ignoredkeys}%
+ }%
+}
+
+% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+% To add (2012/08/08):
+% \skvoptionkeys
+% \skvnotoptionkeys
+% \skvnewlet\skvnonoptionkeys\skvnotoptionkeys
+%---------------------------------------------------------------
+
+% \skvaddkeycode[<pref>]{<fam>}{<key>}{<precode>}{<postcode>}
+\skvrobustdef*\skvaddkeycode{\skv@testoptb\skv@addkeycode}
+\skvrobustdef*\skv@addkeycode#1#2#3{%
+ \skv@prependkeycode{prep}{#1}{#2}%
+ \skv@prependkeycode{app}{#1}{#3}%
+}
+\skvnewlet\skvaddtocallback\skvaddkeycode
+% \skvprependkeycode[<pref>]{<fam>}{<key>}{<code>}
+\skvrobustdef*\skvprependkeycode{\skv@testoptb{\skv@prependkeycode{prep}}}
+\skvrobustdef*\skvappendkeycode{\skv@testoptb{\skv@prependkeycode{app}}}
+\skvnewlet\skvprependtocallback\skvprependkeycode
+\skvnewlet\skvapendtocallback\skvappendkeycode
+\skvrobustdef*\skv@prependkeycode#1#2#3{%
+ \edef\skvcurrentkey{\skvtrimspace{#2}}%
+ \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{%
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{%
+ \skvifstrcmp{#1}{prep}{%
+ \skvtrimspace{#3}%
+ \skvexpandcsonce{\skv@header\skvcurrentkey.@cbk}%
+ }{%
+ \skvexpandcsonce{\skv@header\skvcurrentkey.@cbk}%
+ \skvtrimspace{#3}%
+ }%
+ }%
+ }{%
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\skvtrimspace{#3}}%
+ }%
+}
+
+% Initialize remaining-keys to empty, for the listed prefixes and families:
+% \skvinitializermkeys{<prefixes>}{<families>}
+\skvrobustdef*\skvinitializermkeys{%
+ \skv@clfalse\skv@testst\skv@initializermkeys
+}
+\skvrobustdef*\skvginitializermkeys{%
+ \skv@cltrue\skv@testst\skv@initializermkeys
+}
+\skvrobustdef*\skv@initializermkeys#1#2{%
+ \skv@usetempst{#1}\skv@tempa
+ \skv@usetempst{#2}\skv@tempb
+ \skvcommaparse*\skv@tempa\skv@tempa{%
+ \skv@makeprefix\skv@tempa
+ \skvcommaparse*\skv@tempb\skv@tempb{%
+ \skv@makeheader\skv@tempb
+ \skvcslet{\skv@header.@rmkeys}\@empty
+ \ifskv@cl\skvglobalizecs{\skv@header.@rmkeys}\fi
+ }%
+ }%
+}
+
+% \skvgetrmkeys[<pref>]{<fam>}<cmd>
+\skvrobustdef*\skvgetrmkeys{\skv@clfalse\skv@testoptb\skv@getrmkeys}
+\skvrobustdef*\skvggetrmkeys{\skv@cltrue\skv@testoptb\skv@getrmkeys}
+\skvrobustdef*\skv@getrmkeys#1{%
+ \skvifcsdef{\skv@header.@rmkeys}{%
+ \skvletcs#1{\skv@header.@rmkeys}%
+ \ifskv@cl\global\let#1=#1\fi
+ }{%
+ \skv@err{No 'rmkeys' for family
+ '\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }%
+}
+\skvrobustdef*\skvsetkeys{%
+ \skv@testopta{\skv@testoptc\skv@setkeys@a}%
+}
+% \skv@setkeys@a[<ignore.list>]{<kvlist>}
+\skvrobustdef*\skv@setkeys@a[#1]#2{%
+ % \skvexecuteoptions calls \skv@setkeys@a. So this is the place for
+ % \skv@insettrue:
+ \skv@insettrue
+ % \skv@testoptc has created \skvcurrentprefix and \skv@fams.
+ \ifskv@intry\else\skvafterfi
+ \skv@getkeynames{#2}\skv@naa
+ \fi
+ % Both #1 and #2 will be normalized in \skv@setkeys@b.
+ \skv@setprepokeys{#1}{preset}%
+ \skv@setkeys@b{#2}{#1}%
+ \skv@setprepokeys{#1}{postset}%
+ \ifnum\skv@setkeysdepth=\skvz@
+ \skv@insetfalse
+ \fi
+ % Don't set \let\CurrentOption\@empty here.
+}
+\skvrobustdef*\skv@setprepokeys#1#2{%
+ \skv@prepotrue
+ \skvecommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ \skvifcsundef{\skv@header.@#2}{}{%
+ \skv@toksa\expandafter\expandafter\expandafter
+ {\csname\skv@header.@#2\endcsname}%
+ \skvexpandtwoargs\skv@setkeys@b{\the\skv@toksa}%
+ {\skvexpandonce\skv@naa\ifx\skv@naa\@empty\else,\fi
+ \unexpanded{#1}}%
+ }%
+ }%
+ \skv@prepofalse
+}
+
+% \skv@keydepth is called in places other than by \skvsetkeys. Hence we
+% need an independent \skv@setkeysdepth here.
+% \skv@setkeys@b{<kvlist>}{<ignore.list>}
+\skvrobustdef*\skv@setkeys@b#1#2{%
+ % \skv@setprepokeys calls \skv@setkeys@b. So this is the place to
+ % advance \skv@setkeysdepth.
+ \skvgadvanceno\skv@setkeysdepth\@ne
+ \ifskv@st
+ \ifnum\skv@setkeysdepth=\@ne
+ \skvinitializermkeys*\skvcurrentprefix\skv@fams
+ \fi
+ \fi
+ \ifnum\skv@setkeysdepth>\skv@stackdepthlimit\relax
+ \skv@err{\noexpand\skvsetkeys is nested too deeply.
+ \MessageBreak Maybe there has been infinite reentry}\@ehd
+ \fi
+ % \skv@na can't be anywhere else, not in \skv@setkeys@a.
+ \edef\skv@na{\unexpanded{#2}}%
+ \skvifempty\skv@na{}{\skvcsvnormalize\skv@na}%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvifempty\skv@tempa{}{\skvkvnormalize\skv@tempa}%
+ \def\skv@setkeys@c##1={%
+ \skvxifin{(}{\detokenize{##1}}{%
+ \skvxifin{)}{\detokenize{##1}}{%
+ \def\skv@ispntkey{00}%
+ \skv@extr@ctpntkey{##1}\skvcurrentkey\skvcurrentvalue
+ \ifx\skvcurrentvalue\@empty
+ \skvnovaluetrue
+ \else
+ \skvnovaluefalse
+ \fi
+ }{%
+ \skv@err{Key value has '(' but no ')'}
+ {The value of a parenthesized key must have both opening
+ '(' and closing ')'}%
+ }%
+ }{%
+ \def\skv@ispntkey{01}%
+ \skv@g@tkeyname##1=\skv@nil\skvcurrentkey
+ }%
+ \def\skv@prova####1=####2\skv@nil{%
+ \skvifcond\if\skv@ispntkey\fi{}{%
+ \edef\skvcurrentvalue{\skvexpandonce{\@gobble####1}}%
+ \ifx\skvcurrentvalue\skv@novaluetoks
+ \skvnovaluetrue
+ \def\skvcurrentvalue{}%
+ \else
+ \skvnovaluefalse
+ \fi
+ \skvexpbracenext\skvifbraced\skvcurrentvalue{%
+ \skvvaluebracedtrue
+ }{%
+ % Strip and use pointers from key value:
+ \skvexpbracenext\skv@strippointers\skvcurrentvalue
+ \skvcurrentvalue
+ }%
+ }%
+ \ifx\skvcurrentkey\@empty
+ \ifx\skvcurrentvalue\@empty\else
+ \skv@err{Current key is nil, but you have a value for it:
+ \MessageBreak\skvoxdetok\skvcurrentvalue}\@ehd
+ \fi
+ \fi
+ \edef\CurrentOption{%
+ \skvcurrentkey
+ \ifx\skvcurrentvalue\@empty\else\skvafterfi
+ =\skvxonce\skvcurrentvalue
+ \fi
+ }%
+ \skv@setkeys@d
+ }%
+ \skv@prova.%
+ }%
+ \skvcommaloop*\skv@tempa\CurrentOption{%
+ \skvvaluebracedfalse
+ % Expand the key name twice, in case the key and its value
+ % are hidden in a macro. A maverick might do just that.
+ \expandafter\expandafter\expandafter
+ \skv@setkeys@c\CurrentOption=\skv@novalue=\skv@nil
+ }%
+ \skvgadvanceno\skv@setkeysdepth\m@ne
+}
+
+\skvrobustdef*\skv@setkeys@d{%
+ \skv@cnta\@ne
+ \skvletcs\skv@tempa{\skv@header.@ignoredkeys}%
+ \skvifdef\skv@tempa{%
+ \skvxifin{,\skvcurrentkey,}{,\skv@tempa,}{%
+ \skv@cnta\skvz@
+ }{%
+ \skvxifin{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}%
+ }%
+ }{%
+ \skvxifin{,\skvcurrentkey,}{,\skv@na,}{\skv@cnta\skvz@}{}%
+ }%
+ \skvifnum\skv@cnta=\skvz@{}{%
+ \skv@kffalse
+ \skvifdefbool{skv@prepo}{%
+ \skv@setkeys@e
+ }{%
+ \skvifdefbool{skv@intry}{%
+ \skv@setkeys@e
+ }{%
+ \skvifdefbool{skv@pl}{%
+ \skvecommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ \skv@setkeys@e
+ % If we don't save rm keys here, the family may change before
+ % we get to the next call of \skv@setkeys@f:
+ \ifskv@kf\else
+ \ifskv@st
+ \expandafter\expandafter\expandafter\skv@setkeys@f
+ \fi
+ \fi
+ }%
+ }{%
+ \skvcommaloop*\skv@fams\skvcurrentfamily{%
+ \skv@makeheader\skvcurrentfamily
+ \skv@setkeys@e
+ \ifskv@kf\skvbreakloop\fi
+ }%
+ }%
+ }%
+ }%
+ \skvifdefbool{skv@kf}{%
+ \ifskv@inpox\skvafterfifi@inneriscond
+ \ifx\skv@testclass\skv@documentclass\skvafterfi
+ \expandafter\skv@useoption\expandafter{\CurrentOption}%
+ \fi
+ \fi
+ }{%
+ \skvifdefbool{skv@inpox}{%
+ \skvifcsdef{\skv@header.@famhandler}{%
+ \begingroup
+ \let\elt\skvexpandonce
+ \skvexpanded{\endgroup
+ \skvnoexpandcs{\skv@header.@famhandler}%
+ {\elt\skvcurrentprefix}{\elt\skvcurrentfamily}%
+ {\elt\skvcurrentkey}{\elt\skvcurrentvalue}%
+ }%
+ }{%
+ \skvifcsdef{skv@dox@\@currname @\@currext}{%
+ \skvcsuse{skv@dox@\@currname @\@currext}%
+ }{%
+ \ifx\@currext\@clsextension\else
+ \let\CurrentOption\skvcurrentkey\@unknownoptionerror
+ \fi
+ }%
+ }%
+ }{%
+ \skvifdefbool{skv@intry}{%
+ % Continue in remaining families. When all the families have
+ % been searched and the key isn't found, toggle 'intry' false
+ % and raise error.
+ }{%
+ \skvifdefbool{skv@st}{%
+ \ifskv@pl
+ % In this case we've already saved any rm keys.
+ \relax
+ \else
+ \expandafter\skv@setkeys@f
+ \fi
+ }{%
+ \skvifcsdef{\skv@header.@famhandler}{%
+ \begingroup
+ \let\elt\skvexpandonce
+ \skvexpanded{\endgroup
+ \skvnoexpandcs{\skv@header.@famhandler}%
+ {\elt\skvcurrentprefix}{\elt\skvcurrentfamily}%
+ {\elt\skvcurrentkey}{\elt\skvcurrentvalue}%
+ }%
+ }{%
+ \skv@err{Key '\skvcurrenttriple' is undefined}
+ {I have come across an undefined key '\skvcurrentkey'.}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+}
+\skvrobustdef*\skv@setkeys@e{%
+ \skvifcsundef{\skv@header\skvcurrentkey.@cbk}{%
+ \ifskv@intry\skv@successfalse\fi
+ }{%
+ \skv@kftrue
+ \ifskv@intry\skv@successtrue\fi
+ \ifskvnovalue
+ \skvifcsdef{\skv@header\skvcurrentkey.@ndv}{%
+ \skv@err{Key '\skvcurrenttriple' requires
+ \MessageBreak a user value}\@ehd
+ }{%
+ \skvifcsdef{\skv@header\skvcurrentkey.@defa}{%
+ \skv@getdefault\skvcurrentprefix\skvcurrentfamily\skvcurrentkey
+ \skvcurrentvalue
+ % Check if the default value is braced:
+ \skvexpbracenext\skvifnotbraced\skvcurrentvalue{}{%
+ \skvvaluebracedtrue
+ }%
+ }{%
+ \skv@err{No value specified for key
+ \MessageBreak'\skvcurrenttriple'
+ \MessageBreak and no default value}\@ehd
+ }%
+ }%
+ \else
+ \skvifcsdef{\skv@header\skvcurrentkey.@fbv}{%
+ \skv@err{Key '\skvcurrenttriple' doesn't
+ \MessageBreak accept a user value}\@ehd
+ }{}%
+ \fi
+ \skvifempty\skvcurrentvalue{}{%
+ \expandafter\skv@replacepointers\expandafter{\skvcurrentvalue}%
+ }%
+ % Use argument type to possibly expand the argument:
+ \def\do##1##2##3{%
+ \skvifcsdef{\skv@header\skvcurrentkey.@##1arg}{%
+ {\noexpand##2}%
+ {\skvexpandcsonce{\skv@header\skvcurrentkey.@##1arg}}%
+ }{%
+ ##3%
+ }%
+ }%
+ % Get key's argument and its expander type:
+ \edef\skv@prova{%
+ % This ordering is important:
+ \do{xx}{\@firstofone}{%
+ \do{x2}{\expandcstwice}{%
+ \do{x1}{\skvexpandonce}{%
+ \do{x0}{\unexpanded}{%
+ \do{}{\unexpanded}{{\noexpand\unexpanded}{####1}}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \def\skv@provb##1##2\skv@arg@nil{%
+ \edef\skv@temparg{\unexpanded{##2}}%
+ \skvstripouterbraces{2}\skv@temparg
+ % Apply expander ##1:
+ \edef\skvcurrentvalue{\expandafter##1\expandafter{\skvcurrentvalue}}%
+ % Strip outer braces of weird arguments, so that the argument can be
+ % grabbed by the, possibly multiparametered, callback function:
+ \ifx\skv@temparg\skv@simplearg\else\skvafterfi
+ \skvstripouterbraces{2}\skvcurrentvalue
+ \skvvaluebracedfalse
+ \fi
+ }%
+ \expandafter\skv@provb\skv@prova\skv@arg@nil
+ \skvcslet{\skv@header\skvcurrentkey.@value}\skvcurrentvalue
+ \skvifcsdef{\skv@header\skvcurrentkey.@hp}{%
+ \skvexpanded{\skvcslet{\skvexpandcsonce
+ {\skv@header\skvcurrentkey.@hp}}}\skvcurrentvalue
+ }{}%
+ \skvpushstate\skv@keystate\skv@keydepth
+ \skvletcs\skv@prova{\skv@header\skvcurrentkey.@cbk}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter
+ \expandafter\skv@tempcbk\expandafter\skv@temparg\expandafter
+ \skeyvaleov\expandafter{\skv@prova}%
+ \ifx\skv@temparg\skv@simplearg\skvafterelsei
+ \expandafter\skv@tempcbk\expandafter{\skvcurrentvalue}\skeyvaleov
+ \else\skvafterfi
+ \expandafter\skv@tempcbk\skvcurrentvalue\skeyvaleov
+ \fi
+ \skvpopstate\skv@keystate\skv@keydepth
+ }%
+}
+% Save rm keys:
+\skvrobustdef*\skv@setkeys@f{%
+ \edef\skv@prova{%
+ \skvcurrentkey
+ \ifskvnovalue\else\skvafterfi
+ =\skvexpandonce\skvcurrentvalue
+ \fi
+ }%
+ \skvexpanded{%
+ \skvmergelist\skvnoexpandcs{\skv@header.@rmkeys}%
+ {\skvexpandonce\skv@prova}%
+ % The boolean \ifdirkeys@saveunknownkeys is, by default, false.
+ % The default value of \dirkeys@unknownkeysmacro is \skvfaillist.
+ \ifdirkeys@saveunknownkeys
+ \skvmergelist\skvexpandonce\dirkeys@unknownkeysmacro
+ {{\skvcurrentprefix}/{\skvcurrentfamily}/%
+ {\skvexpandonce\skv@prova}}%
+ \fi
+ }%
+}
+\skvrobustdef*\skvsetrmkeys{\skv@testopta{\skv@testoptc\skv@setrmkeys}}
+\skvrobustdef*\skv@setrmkeys[#1]{%
+ % Only one prefix is allowed. \skv@testoptc has created
+ % \skvcurrentprefix and \skv@fams.
+ \skvcommaloop*\skv@fams\skv@tempa{%
+ \skv@makeheader\skv@tempa
+ \skvletcs\skv@prova{\skv@header.@rmkeys}%
+ \skvifdef\skv@prova{%
+ \skvexpandbracenext{\skv@setkeys@a[#1]}\skv@prova
+ }{}%
+ }%
+}
+% \skv@getdefault{<pref>}{<fam>}{<key>}{<return.macro>}
+\skvrobustdef*\skv@getdefault#1#2#3#4{%
+ \begingroup
+ \let\elt\relax
+ \edef\skv@prova{\elt{#1}/\elt{#2}/\elt{#3}}%
+ \let\elt\skvtrimspace
+ \edef\skv@prova{\skv@prova}%
+ \def\skv@g@tdefault##1##2\skv@nil{%
+ \edef\skv@provb{\skvremovescape{##1}}%
+ \@onelevel@sanitize\skv@prova
+ \ifx\skv@prova\skv@provb
+ \skvcsdef{\skv@prova}####1{\edef#4{\unexpanded{####1}}}%
+ \csname\skv@prova.@defa\endcsname
+ \else
+ \skv@err{The default value syntax of key
+ \MessageBreak '\skv@prova' doesn't conform to
+ \MessageBreak skeyval format. Maybe another package
+ \MessageBreak has abused the format}
+ {I can't extract the default value of key '\skv@prova'.}%
+ \fi
+ }%
+ % <default.macro><key.macro>
+ \expandafter\expandafter\expandafter\skv@g@tdefault
+ \csname\skv@prova.@defa\endcsname\skv@nil
+ \skvaftergroupdef#4\endgroup
+}
+% Set keys using their default values:
+% \skvinitializekeys[<pref>]{<fams>}[<ignored.keys>]
+\skvrobustdef*\skvinitializekeys{\skv@testoptc\skv@initializekeys}
+% #1: ignored keys
+\skvrobustdef*\skv@initializekeys[#1]{%
+ \begingroup
+ \def\skv@tempe{}%
+ % \skv@testoptc has created \skvcurrentprefix and \skv@fams.
+ \skvcommaloop*\skv@fams\skv@tempa{%
+ \skv@makeheader\skv@tempa
+ \skvletcs\skv@tempa{\skv@header.@inikv}%
+ \skvifundef\skv@tempa{%
+ \skv@err{No 'save initial value' keys defined in family
+ \MessageBreak'\skvcurrentprefix/\skvcurrentfamily'}\@ehd
+ }{%
+ % '\skv@header.@poxkeys' is the list of keys that have been
+ % instantiated as current pacakge options.
+ \skvletcs\skv@tempc{\skv@header.@poxkeys}%
+ \skvifundef\skv@tempc{%
+ \edef\skv@tempe{%
+ \skvexpandonce\skv@tempe
+ \skvsetkeys[\skvcurrentprefix]{\skvcurrentfamily}%
+ [#1]{\skvexpandonce\skv@tempa}%
+ }%
+ }{%
+ % Filter pox (instantiated package/article options) list members:
+ \def\skv@tempd{}%
+ \skvcommaloop*\skv@tempa\skv@tempa{%
+ \expandafter\skv@g@tkeyname\skv@tempa=\skv@nil\skv@tempb
+ \skvxifin{,\skvoxdetok\skv@tempb,}{,\skvoxdetok\skv@tempc,}{}{%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd\ifx\skv@tempd\@empty\else,\fi
+ \skvexpandonce\skv@tempa
+ }%
+ }%
+ }%
+ \edef\skv@tempe{%
+ \skvexpandonce\skv@tempe
+ \skvsetkeys[\skvcurrentprefix]{\skv@fams}[#1]%
+ {\skvexpandonce\skv@tempd}%
+ }%
+ }%
+ }%
+ }%
+ \expandafter\endgroup\skv@tempe
+}
+
+%+++++++++++++++++++++ Compactly define keys +++++++++++++++++++++++++%
+%
+% \skvdefinekeys*+[<pref>]{<fams>}[<hp>]{<list>}
+% * -> define only new keys.
+% + -> define across the given families.
+%
+% The only difference between \skvedefinekeys and \skvdefinekeys is the
+% value of \endlinechar.
+%
+% Examples:
+%
+% \skvdefinekeys*+[KVA]{fam1,fam2}[thp@]{%
+% .ords/{keya,keyb}/{default-a},
+% .cmds/{keyc,keyd}/,
+% .zcmd/key e/\def\cmde##1{##1}/
+% \edef\y{\detokenize\expandafter{\thp@keye}}\def\x##1{#1*key e*##1},
+% .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right},
+% .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi},
+% .args/{key1,key2}/{#1/#2},
+% .arg/key3/{#1+#2},
+% .exec/\def\x##1{##1},
+% }
+% \skvshowcs{KVA/fam1/keyb.@defa}
+% \def\keybval{xx}
+% \skvsetkeys[KVA]{fam1}{keyb=.expand once{\keybval}}
+%
+\skvnewbools[skvdfk@]{saveinitialvalues,initialize}
+% '.initialize' means set the keys with their default values after
+% they've been defined. Leave this as ordinary keys, not zbool keys,
+% since the key names contain dot (.). Zapping the spaces in the
+% key name will not lead to a boolean of the \ifhp@key:
+\skvordkey[SKV]{definekeys}{.initialize}[true]{%
+ \skvifvalidboolval{#1}{%
+ \csname skvdfk@initialize#1\endcsname
+ }%
+}
+% Save default values as a kv list in macro <header>.@needini:
+\skvordkey[SKV]{definekeys}{.save initial values}[true]{%
+ \skvifvalidboolval{#1}{%
+ \csname skvdfk@saveinitialvalues#1\endcsname
+ }%
+}
+%\skvsetkeys[SKV]{definekeys}{.initialize=false,.save initial values=false}
+
+\skvnewdef*\skv@keyparser{,}
+\skvnewdef*\skvdfk@afterdefinekeys{}
+\skvrobustdef*\AfterDefineKeys{\skvgappendtomacro\skvdfk@afterdefinekeys}
+\skvrobustdef*\skvdfk@testopta#1{%
+ \skvifstar{%
+ \skv@sttrue\skvifplus
+ {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}%
+ }{%
+ \skv@stfalse\skvifplus
+ {\skv@pltrue\skvdfk@testoptb#1}{\skv@plfalse\skvdfk@testoptb#1}%
+ }%
+}
+\skvrobustdef*\skvdfk@testoptb#1{\skv@testopt{\skvdfk@t@stoptb{#1}}{KV}}
+\skvrobustdef*\skvdfk@t@stoptb#1[#2]#3{%
+ \skvxifin{,}{\detokenize{#2}}{%
+ \skv@err{Only one prefix is allowed when calling
+ \MessageBreak \noexpand\skvdefinekeys or similar commands,
+ \MessageBreak but you gave '#2'}\@ehd
+ }{%
+ % The prefix and families here deserve separate names, to avoid
+ % confusing them with those required for setting the keys of the
+ % macro \skvdefinekeys.
+ \edef\skv@checkkeyexist{\ifskv@st00\else01\fi}%
+ \edef\skvdfk@pref{#2}%
+ \skvxifin{,}{\detokenize{#3}}{%
+ \edef\skvdfk@fams{#3}%
+ \skvcsvnormalize\skvdfk@fams
+ }{%
+ \edef\skvdfk@fams{#3}%
+ \skvdespacecontent\skvdfk@fams
+ }%
+ \skv@testopt#1{userhp@}%
+ }%
+}
+\skvnewnumbers{skvdfk@depth}
+\skvrobustdef*\skv@pushdefinekeys{%
+ \skvpushfunctions\skvdefinekeys{%
+ \do\skvdfk@pref\do\skvdfk@fams\do\skvdfk@currlist\do\skv@accumulated
+ \do\skv@acc@mulated\do\skv@igkeys\do\skvdfk@keys\do\skvdfk@keyvals
+ \do\skv@itemfour\do\skv@itemfive\do\skv@checkkeyexist\do\skv@hp
+ \do\skv@type\do\skv@typenr\do\skv@default\do\skv@isarg
+ \do\ifskvdfk@initialize\do\ifskvdfk@saveinitialvalues\do\ifskv@st
+ \do\ifskv@pl\do\skvcurrentprefix\do\skvcurrentfamily\do\skvcurrentkey
+ }\skvdfk@depth
+}
+\skvrobustdef*\skvedefinekeys{%
+ \skv@pushdefinekeys
+ \begingroup
+ \endlinechar\m@ne
+ \skvdfk@testopta\skv@definekeys
+}
+\skvrobustdef*\skvdefinekeys{%
+ \skv@pushdefinekeys
+ \begingroup
+ \skvdfk@testopta\skv@definekeys
+}
+\skvrobustdef*\skv@definekeys[#1]#2{%
+ \skvexpanded{\endgroup
+ \skvcmdexitloop{\skv@checkkeyexist\skvdfk@pref\skvdfk@fams}%
+ \skvboolexit\ifskv@pl
+ }%
+ \skvindeftrue
+ \edef\skv@hp{#1}%
+ \skvdespacecontent\skv@hp
+ \def\skv@accumulated{}%
+ \skv@makeprefix\skvdfk@pref
+ \edef\skvdfk@currlist{\skvkeepdoubleslashnormalize{#2}}%
+ \def\skv@d@finekeys##1{%
+ \skv@makeheader{##1}%
+ \def\skv@acc@mulated{}%
+ \def\skvdfk@keys{}%
+ \def\skvdfk@keyvals{}%
+ \expandafter\skv@d@f@nekeys\expandafter{\skvdfk@currlist}%
+ }%
+ % If the plus variant is not specified, just take and use the first
+ % family.
+ \skvifdefbool{skv@pl}{%
+ \skvcommaloop*\skvdfk@fams\skv@tempa{%
+ \expandafter\skv@d@finekeys\expandafter{\skv@tempa}%
+ }%
+ }{%
+ \def\skv@prova##1,##2\skv@nil{%
+ \skv@d@finekeys{##1}%
+ }%
+ \expandafter\skv@prova\skvdfk@fams,\skv@nil
+ }%
+ \skv@accumulated
+ \skvpopfunctions\skvdefinekeys\skvdfk@depth
+ \skvindeffalse
+ \skvdfk@afterdefinekeys\relax
+ \def\skvdfk@afterdefinekeys{}%
+}
+\skvrobustdef*\skv@d@f@nekeys#1{%
+ \edef\skv@igkeys{%
+ \skvifcsdef{\skv@header.@ignoredkeys}{%
+ \skvexpandcsonce{\skv@header.@ignoredkeys}%
+ }{}%
+ }%
+ \def\skv@splita##1/##2/{\skv@splitb##1/##2/.}%
+ \def\skv@splitb##1/##2/##3/##4/##5/##6/##7/##8/##9\skv@split@nil{%
+ \let\skv@gobble\relax
+ \edef\skv@type{\unexpanded{##1}}%
+ % Take the default early: it is needed in splitting multiple keys of
+ % the same type. In this case, the default value will not change
+ % until the splitting is completed.
+ \edef\skv@default{\skvexpandonce{\@gobble##3}}%
+ \def\skv@isarg{01}%
+ \def\skv@prova####1{%
+ \def\skv@prova########1####1########2########3\skv@nil{%
+ \def\skv@typenr{########2}%
+ \ifx\skv@typenr\skv@nnil
+ \skv@err{Invalid key type '####1'}\@ehd
+ \else
+ \ifnum\skv@typenr>6\relax
+ \ifnum\skv@typenr<11\relax
+ \def\skv@isarg{00}%
+ \fi
+ \fi
+ \fi
+ }%
+ \skv@prova .ord{0}.cmd{1}.zcmd{2}.bool{3}.zbool{4}.choice{5}%
+ .exec{6}.arg{7}.arg expanded{8}.arg expanded once{9}%
+ .arg expanded twice{10}.ords{11}.cmds{12}.zcmds{13}.bools{14}%
+ .zbools{15}.choices{16}.args{17}####1{\skv@nil}\skv@nil
+ }%
+ \expandafter\skv@prova\expandafter{\skv@type}%
+ \skvxifin{,\skv@typenr,}{,11,12,13,14,15,16,17,}{%
+ % Accumulate multiple keys of the same type:
+ \def\skv@prova####1s{\def\skv@type{####1}}%
+ \expandafter\skv@prova\skv@type
+ \skvcommaparse{##2}\skv@tempa{%
+ \skvexpanded{%
+ \noexpand\skv@splita
+ \skv@type/\skv@tempa/\skvexpandonce\skv@default/%
+ \unexpanded{##4/##5/##6/##7/##8/##9}\noexpand\skv@split@nil
+ }%
+ }%
+ % Skip the rest of \skv@splitb:
+ \let\skv@gobble\skv@gobbletoend
+ }{%
+ \skvifnum\skv@typenr=6{%
+ ##2%
+ \let\skv@gobble\skv@gobbletoend
+ }{%
+ % There may be multiple keys in ##2. So keep findpointers here,
+ % where multiple keys would have been split into separate units.
+ % For example, we can't check for ignored keys without first
+ % stripping the pointers:
+ \skv@strippointers{##2}\skvcurrentkey
+ \skvxifin{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@igkeys,}{%
+ \let\skv@gobble\skv@gobbletoend
+ }{%
+ \if\skv@isarg
+ \skvdfk@definearg\skv@type\skvcurrentkey\skv@default
+ \let\skv@gobble\skv@gobbletoend
+ \else
+ \let\skv@gobble\relax
+ \fi
+ }%
+ }%
+ }%
+ \skv@gobble
+ \edef\skv@itemfour{\unexpanded{##4}}%
+ \edef\skv@itemfive{\unexpanded{##5}}%
+ \skvxifin{\skv@hashchar}{\detokenize{##2}}{%
+ \skv@err{Key name '\detokenize{##2}' contains hash character}\@ehc
+ }{}%
+ \if\skv@checkkeyexist
+ \skvifcsdef{\skv@header\skvcurrentkey.@cbk}{%
+ \skv@err{Key '\skvcurrenttriple' already exists}\@ehd
+ }{}%
+ \fi
+ \ifnum\skv@typenr=5\relax
+ \edef\skv@prova{%
+ 0\ifx\skv@itemfour\@empty 1\else\ifx\skv@itemfour\skv@rej 1\fi\fi
+ }%
+ \ifcase\skv@prova\relax
+ \def\skv@altlista{}\def\skv@altlistb{}%
+ % \skv@itemfour is need here to hide unbalanced conditionals in ##4:
+ \expandafter\skv@getaltlist\expandafter{\skv@itemfour}%
+ \else
+ \skv@err{Empty alternate list for choice key '\skvcurrentkey'}\@ehd
+ \fi
+ \fi
+ \edef\skvdfk@keys{\skvaddlist,\skvdfk@keys\skvcurrentkey}%
+ \skvxifboolval{\skvexpandonce\skv@default}\in@true\in@false
+ \edef\skvdfk@keyvals{%
+ \skvaddlist,\skvdfk@keyvals
+ % If a key has no default, then it can't be initialized. An empty
+ % default value should be indicated with a slash, eg, keya below:
+ % .cmd/keya/, .bool/keyb/true.
+ \expandafter\skv@ifrejorna\expandafter{\skv@default}{}{%
+ \skvcurrentkey=\skvifdefbool{in@}{false}{\skvxonce\skv@default}%
+ }%
+ }%
+ \edef\skv@acc@mulated{%
+ \skvexpandonce\skv@acc@mulated
+ \skvnoexpandcs{skv\expandafter\@gobble\skv@type key}%
+ \ifnum\skv@typenr=5*\fi
+ \ifnum\skv@typenr>2\ifnum\skv@typenr<6+\fi\fi
+ [\skvcurrentprefix]{\skvcurrentfamily}%
+ % ##2 should be inserted below instead of \skvcurrentkey, because
+ % \skvcurrentkey has had any possible pointer stripped:
+ \ifnum\skv@typenr>0\ifnum\skv@typenr<6[\skv@hp]\fi\fi
+ {##2}%
+ \ifnum\skv@typenr=5% no \relax here.
+ [\unexpanded{\skvuserinput\skvorder}]{\skvexpandonce\skv@altlista}%
+ \fi
+ % default:
+ \expandafter\skv@ifrejorna\expandafter{\skv@default}{}{%
+ [{\skvexpandonce\skv@default}]%
+ }%
+ {%
+ % Key callback. If choice key, then the callback is item 5,
+ % otherwise it's item 4:
+ \skvifnum\skv@typenr=5{%
+ \skvifx\skv@itemfive\skv@rej{}{\skvexpandonce\skv@itemfive}%
+ \skv@executealt{########1}{\skvexpandonce\skv@altlistb}%
+ }{%
+ \skvifx\skv@itemfour\skv@rej{}{\skvexpandonce\skv@itemfour}%
+ }%
+ }%
+ % Second branch of callback for '+' variants, now used for all
+ % boolean and choice keys:
+ \ifnum\skv@typenr>2\ifnum\skv@typenr<6{\skvkeyvalueerror}\fi\fi
+ }%
+ \skv@gobble@nil
+ }%
+ \skvexpanded{\skvparselist{\skv@keyparser}}{#1}\skv@prova{%
+ \expandafter\skv@splita\skv@prova
+ /^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^/^skv^\skv@split@nil
+ }%
+ % 1. \skv@accumulated is a two-layer stack: there're loops on families
+ % and keys.
+ % 2. To save initial values of keys, the key names should be
+ % entered by \skvsaveinitialvaluekeys in 'needini' list. This is
+ % the case even when the boolean '.initialize' is true. See below.
+ % 3. The boolean '.save initial values' is the one that will invoke
+ % \skvsaveinitialvaluekeys below.
+ \edef\skv@accumulated{%
+ \skvexpandonce\skv@accumulated % looping on families
+ \skvifdefbool{skvdfk@saveinitialvalues}{%
+ \noexpand\skvsaveinitialvaluekeys[\skvcurrentprefix]%
+ {\skvcurrentfamily}{\skvexpandonce\skvdfk@keys}%
+ }{}%
+ \skvexpandonce\skv@acc@mulated % looping on keys
+ \skvifdefbool{skvdfk@initialize}{%
+ \noexpand\skvsetkeys[\skvcurrentprefix]%
+ {\skvcurrentfamily}{\skvexpandonce\skvdfk@keyvals}%
+ }{}%
+ }%
+}
+%
+% Assigning arguments within \skvdefinekeys:
+%
+% Eg, .args/{key1,key2}/{#1/#2}
+%
+\skvrobustdef*\skvdfk@definearg#1#2#3{%
+ \begingroup
+ \toks@\expandafter{#3}%
+ \def\skv@prova.arg##1\skv@nil{%
+ \if\relax\detokenize{##1}\relax
+ \def\skv@prova{x0}%
+ \else
+ \edef\skv@provb{\skvtrimspace{##1}}%
+ \def\skv@prova####1{%
+ \def\skv@prova########1####1########2########3\skv@nil{%
+ \def\skv@prova{########2}%
+ \ifx\skv@prova\skv@nnil
+ \def\skv@prova{x0}%
+ \fi
+ }%
+ \skv@prova
+ expanded{xx}expand once{x1}expand twice{x2}####1{\skv@nil}\skv@nil
+ }%
+ \expandafter\skv@prova\expandafter{\skv@provb}%
+ \fi
+ }%
+ \expandafter\skv@prova#1\skv@nil
+ \skvcsedef{\skv@header#2.@\skv@prova arg}{\the\toks@}%
+ \expandafter\skvaftergroupdef
+ \csname\skv@header#2.@\skv@prova arg\endcsname\endgroup
+}
+
+%+++++++++++++++++++++++ Keys for \skvmakekeys +++++++++++++++++++++++%
+% Example:
+% \skvmakekeys[
+% prefix=KVA, families={fam1,fam2}, hp=thp@, all new,
+% define in all families, initialize=true, endlinechar=-1
+% ]{%
+% .ords/{keya,keyb}/{default-a},
+% .cmds/{keyc,keyd}/,
+% .zcmd/key e/\def\cmde##1{##1}/
+% \edef\y{\detokenize\expandafter{\thp@keye}}\def\x##1{#1*key e*##1},
+% .choice/keyf/center/{center.do=\def\x##1{#1*##1},left,right},
+% .zbool/show center/true/\edef\cmd{\ifthp@showcenter Yes\else No\fi}
+% }
+% \skvshowcs{KVA/fam1/keyb.@defa}
+% \def\keybval{xx}
+% \skvsetkeys[KVA]{fam1}{keyb=.expand once{\keybval}}
+
+\skvedefinekeys*[SKV]{makekeys}[skvmk@]{%
+ .ords/{.new,.all new,.all are new}/true/
+ \edef\skvmk@allnew{\skvifstrcmp{#1}{true}{00}{01}}
+ ,
+ .ords/{.initialize,.initialize after define}/true/
+ \skvifvalidboolval{#1}{%
+ \csname skvdfk@initialize#1\endcsname
+ }%
+ ,
+ .ord/.save initial values/true/
+ \skvifvalidboolval{#1}{%
+ \csname skvdfk@saveinitialvalues#1\endcsname
+ }%
+ ,
+ .ords/{.endlinechar,.endline character}/13/
+ \def\skvmk@endlinechar{#1},
+ .ords/{.define in all families,.in all families}/true/
+ \edef\skvmk@inallfams{\skvifstrcmp{#1}{true}{00}{01}}
+ ,
+ .ord/.prefix/KV/
+ \skviflacus#1\then
+ \def\skvmk@pref{KV}%
+ \else
+ \edef\skvmk@pref{#1}%
+ \skvstripouterbraces{2}\skvmk@pref
+ \fi
+ ,
+ .ords/{.holder prefix,.hp}/userhp@/\edef\skvmk@hp{#1},
+ .ords/{.family,.families}/^skv^/
+ \skviflacus#1\then
+ \skv@err{Key family is empty\on@line}\@ehd
+ \else
+ \edef\skvmk@fams{#1}%
+ \skvstripouterbraces{2}\skvmk@fams
+ \fi
+ ,
+}
+% Default settings for keys of \skvmakekeys. Presetting keys will be
+% inefficient here, since many of the keys have complements. It will be
+% necessary to include all the complements in the preset list, but doing
+% this will be inefficient.
+\skvsetkeys[SKV]{makekeys}{%
+ .prefix,.family=^skv^,.hp,.new=false,.define in all families=false,
+ .endlinechar=13,.initialize=false,.save initial values=false
+}
+
+\skvrobustdef*\skvmakekeys{\skv@testopt\skv@makekeys{}}
+\skvrobustdef*\skv@makekeys[#1]#2{%
+ \skvpushfunctions\skvmakekeys{%
+ \do\skvmk@pref\do\skvmk@fams\do\skvmk@allnew\do\skvmk@hp
+ \do\skvmk@endlinechar\do\skvmk@inallfams\do\ifskvdfk@initialize
+ \do\ifskvdfk@saveinitialvalues
+ }\skv@makekeysdepth
+ \skvsetkeys[SKV]{makekeys}{#1}%
+ \ifx\skvmk@fams\skv@rej
+ \skv@err{No family specified for \string\skvmakekeys}\@ehd
+ \fi
+ % Push the stack of \skvdefinekeys:
+ \skv@pushdefinekeys
+ % The following \begingroup is ended in \skv@definekeys:
+ \begingroup
+ \skvexpanded{%
+ \endlinechar=\skvmk@endlinechar\relax
+ \skvdfk@testopta\skv@definekeys
+ \if\skvmk@allnew*\fi\if\skvmk@inallfams+\fi
+ [\skvmk@pref]{\skvmk@fams}%
+ [\ifx\skvmk@hp\@empty skvhp@\else\skvmk@hp\fi]%
+ }%
+ {#2}%
+ \skvpopfunctions\skvmakekeys\skv@makekeysdepth
+}
+
+\skvrobustdef*\skvkeyvalueerror{%
+ \skv@getinnoval\CurrentOption
+ \skv@err{Erroneous value '\skv@ival' for key or option
+ \MessageBreak'\skvcurrentkey'}
+ {Invalid key value encountered.}%
+}
+\skvrobustdef*\skv@getaltlist#1{%
+ \begingroup
+ \def\skv@g@taltlist##1.do=##2.do=##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvoxdetok\skv@prova{\skvtrimspace{##2}}}%
+ \skvaddtolist*\skv@altlista\skv@prova
+ \skvaddtolist*\skv@altlistb\skv@provb
+ }%
+ \skvcommaparse{#1}\skv@prova{%
+ \expandafter\skv@g@taltlist\skv@prova.do=.do=\skv@nil
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexitloop{\skv@altlista\skv@altlistb}%
+ }%
+}
+\skvrobustdef*\skv@executealt#1#2{%
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \edef\skv@prova{\skvoxdetok\skv@prova}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\skv@nil{%
+ \edef\skv@prova{\unexpanded{####2}}%
+ \skvifx\skv@prova\skv@nnil{%
+ \skv@err{No alternate list match for key '\skvcurrentkey'}\@ehd
+ }{%
+ ####2%
+ }%
+ }%
+ }%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
+ \skvexpandsecond{\skv@provb#2}\skv@prova{\skv@nil}\skv@nil
+}
+
+\skvrobustdef*\skv@getinnoval#1{%
+ \begingroup
+ \def\skv@prova##1=##2=##3\skv@nil{%
+ \edef\skv@provb{\detokenize{##2}}%
+ \skvifx\skv@provb\@empty{%
+ \def\skv@ival{???}%
+ }{%
+ \skv@getbasetoks{30}\skv@provb\skv@ival
+ }%
+ }%
+ \expandafter\skv@prova#1==\skv@nil
+ \skvaftergroupdef\skv@ival\endgroup
+}
+% \skv@getbasetoks{<nr>}{<toks.cmd>}{<result.cmd>}
+\skvrobustdef*\skv@getbasetoks#1#2#3{%
+ \begingroup
+ \edef\skv@prova{\detokenize\expandafter{#2}}%
+ \def#3{}\@tempcnta\skvz@
+ \def\do##1{%
+ \def\skv@prova{##1}%
+ \skvifx\skv@prova\skv@nnil{}{%
+ \advance\@tempcnta\@ne
+ \ifnum\@tempcnta<#1\relax
+ \edef#3{#3\ifx\next\@sptoken\@space\fi##1}%
+ \else
+ \def\@do####1\skv@nil{}%
+ \fi
+ \@do
+ }%
+ }%
+ \def\@do{\futurelet\next\do}%
+ \expandafter\@do\skv@prova\skv@nil
+ \skvaftergroupdef#3\endgroup
+}
+
+% +++++++++++ User-defined handlers for unknown keys. +++++++++++++%
+%
+% \skvunknownkeyhandler[<prefixes>]{<families>}{<handler>}
+%
+% Note: See skeyval.sty for \skvunknownoptionhandler.
+%
+% Eg, for keya undefined in KV/fam:
+%
+% \skvunknownkeyhandler[KV]{fam}{%
+% \skvordkey[#1]{#2}{#3}[#4]{\def\x##1{##1xx#4}}%
+% }
+% \skvsetkeys[KV]{fam}{unknownkey=val}
+%
+\skvrobustdef*\skvunknownkeyhandler{\skv@testopt\skv@unknownkeyhandler{KV}}
+% For each prefix and family, this will define the functions
+% \<prefix>/<family>/.@famhandler of 4 parameters (prefix, family,
+% key name, current value).
+\skvrobustdef*\skv@unknownkeyhandler[#1]#2#3{%
+ \skvcommaloop{#1}\skv@tempa{%
+ \skv@makeprefix\skv@tempa
+ \skvcommaloop{#2}\skv@tempb{%
+ \skv@makeheader\skv@tempb
+ \skvcsdef{\skv@header.@famhandler}##1##2##3##4{#3}%
+ }%
+ }%
+}
+
+%%++++++++++++++++++++++ Keys for \skvusekeys: +++++++++++++++++++++++%%
+% Example:
+% \skvusekeys[
+% .prefix=KVA,.families={fam1,fam2},.set in all families,
+% .save rm keys
+% ]{%
+% key1,key2
+% }
+
+\skvmakekeys[
+ .prefix=SKV,.family=usekeys,.hp=skvuk@,.endlinechar=-1
+]{%
+ .ords/{.save rm,.save rm keys,.save unknown keys}/true/
+ \edef\skvuk@saverm{\skvifstrcmp{#1}{true}{00}{01}}
+ ,
+ .ords/{.set in all families,.in all families}/true/
+ \edef\skvuk@inallfams{\skvifstrcmp{#1}{true}{00}{01}}
+ ,
+ .ord/.prefix/KV/
+ \skviflacus#1\then
+ \def\skvuk@pref{KV}%
+ \else
+ \edef\skvuk@pref{#1}%
+ \skvstripouterbraces{2}\skvuk@pref
+ \fi
+ ,
+ .ords/{.family,.families}/^skv^/
+ \skviflacus#1\then
+ \skv@err{Key family is empty\on@line}\@ehd
+ \else
+ \edef\skvuk@fams{#1}%
+ \skvstripouterbraces{2}\skvuk@fams
+ \fi
+ ,
+}
+% Default settings for keys of \skvusekeys:
+\skvsetkeys[SKV]{usekeys}{%
+ .prefix,.family=^skv^,.set in all families=false,.save rm=false
+}
+
+\skvrobustdef*\skvusekeys{\skv@testopt\skv@usekeys{}}
+\skvrobustdef*\skv@usekeys[#1]#2{%
+ \skvpushfunctions\skvusekeys{%
+ \do\skvuk@fams\do\skvuk@pref\do\skvuk@inallfams\do\skvuk@saverm
+ }\skv@usekeysdepth
+ \skvsetkeys[SKV]{usekeys}{#1}%
+ \ifx\skvuk@fams\skv@rej
+ \skv@err{No family specified for \string\skvusekeys}\@ehd
+ \fi
+ \skvexpanded{%
+ \noexpand\skvsetkeys\if\skvuk@saverm*\fi\if\skvuk@inallfams+\fi
+ [\skvuk@pref]{\skvuk@fams}{\unexpanded{#2}}%
+ }%
+ \skvpopfunctions\skvusekeys\skv@usekeysdepth
+}
+
+%++++++++++ Utilities for handlers of the macro \directkeys +++++++++++%
+
+\skvnewlet\handlereov\relax
+\skvrobustdef*\directkeys{\skv@testst\dirkeys@parse}
+\skvnewlet\dirkeys\directkeys
+\skvrobustdef*\dirkeys@parse{%
+ \begingroup
+ \ifskv@tempst\endlinechar\m@ne\fi
+ \dirkeys@parse@a
+}
+\skvrobustdef*\dirkeys@parse@a#1{%
+ \endgroup
+ \skvpushstate\dirkeys@state\dirkeys@depth
+ \indirkeystrue
+ % Note 1: Initialise all lists to empty. This note is referred to
+ % somewhere: don't delete its number.
+ \def\dirkeys@prefixlist{}%
+ \def\dirkeys@familylist{}%
+ \def\dirkeys@holderprefixtoks{}%
+ \dirkeys@saveunknownkeysfalse
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvkvnormalize\skv@tempa
+ \def\dirkeys@do##1=##2=##3\dirkeys@nil{%
+ \edef\skv@tempa{\unexpanded{##2}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvdespacecontent\skv@tempa
+ % Get the first token, to test if it's \dirkeys. If it is, then
+ % we have a nested \dirkeys:
+ \expandafter\skvifx\skv@car##1x\car@nil\dirkeys{%
+ \skvifempty\skv@tempa{%
+ ##1\relax
+ }{%
+ \skv@err{Something wrong with use of \string\dirkeys:
+ \MessageBreak equals ('=') found after \string\dirkeys}\@ehd
+ }%
+ }{%
+ \skv@ensurehandlerdot{##1}%
+ \skvifcsdef{dirkeys@handler@##1}{%
+ \csname dirkeys@handler@##1\expandafter\endcsname
+ \skv@tempa\handlereov
+ }{%
+ \skv@err{Unknown handler '\detokenize{##1}'\MessageBreak
+ in command \string\dirkeys; or no '=' sign}\@ehd
+ }%
+ }%
+ }%
+ \skvexpanded{\skvparselist*{\skv@keyparser}}\skv@tempa\skv@tempa{%
+ \expandafter\dirkeys@do\skv@tempa==\dirkeys@nil
+ }%
+ \indirkeysfalse
+ \skvpopstate\dirkeys@state\dirkeys@depth
+}
+\skvrobustdef*\dirkeys@setdefaultroot{%
+ \ifx\dirkeys@familylist\@empty
+ \ifskv@inopt
+ \edef\dirkeys@familylist{\@currname.\@currext}%
+ \else
+ \skv@err{No key's family can be empty}\@ehd
+ \fi
+ \fi
+ \ifx\dirkeys@prefixlist\@empty
+ \def\dirkeys@prefixlist{KV}%
+ \fi
+ \ifx\dirkeys@holderprefixtoks\@empty
+ \def\dirkeys@holderprefixtoks{user@}%
+ \fi
+}
+\skvrobustdef*\dirkeys@getrootlist{%
+ \def\skv@rootlist{}%
+ \def\do##1##2{%
+ \edef\skv@rootlist{%
+ \skvexpandonce\skv@rootlist
+ \noexpand\skv@doonroot{##1}{##2}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+}
+\skvrobustdef*\dirkeys@getcurrentroots#1{%
+ \begingroup
+ \dirkeys@setdefaultroot
+ \def\skv@tempa{}%
+ \skvcommaloop*\dirkeys@prefixlist\skv@prova{%
+ \skvcommaloop*\dirkeys@familylist\skv@provb{%
+ \edef\skv@tempa{\skvexpandonce\skv@tempa
+ \unexpanded{#1}{\skv@prova}{\skv@provb}}%
+ }%
+ }%
+ \expandafter\endgroup\skv@tempa
+}
+
+\skvrobustdef*\dirkeys@dodefinekeys#1{%
+ \begingroup
+ % #1 may contain parameter characters that may be confused with
+ % ##1 and ##2 below. Hence we put it in the macro \skv@tempb.
+ % Ignored keys are always defined. This saves resources and has
+ % so far been harmless.
+ \edef\skv@tempb{\unexpanded{#1}}%
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvdefinekeys\ifskv@handlerswa*\fi[##1]{##2}%
+ [\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+}
+\skvrobustdef*\dirkeys@dosetkeys#1#2{%
+ \begingroup
+ % #1 may contain parameter characters that may be confused with
+ % ##1 and ##2 below. Hence we put it in the macro \skv@tempb:
+ \edef\skv@tempb{\unexpanded{#1}}%
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ #2\ifdirkeys@saveunknownkeys*\else\ifskv@handlerswa*\fi\fi
+ [##1]{##2}[\skvcsuse{##1/##2/.@ignoredkeys}]%
+ % #1 may contain unbalanced conditionals; hence the need for
+ % \skvifdefbool here. When setting 'rm keys', then no
+ % key list is needed here.
+ \skvifdefbool{skv@handlerswb}{}{{\skvexpandonce\skv@tempb}}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+}
+
+% This is used by prepostsetkeys, etc.
+% \dirkeys@dolistedkeys@a{<key.list>}{<callback>}
+\skvrobustdef*\dirkeys@dolistedkeys@a#1#2{%
+ \begingroup
+ \def\skv@tempd{}%
+ % ##1=prefix, ##2=family
+ \def\do##1##2{%
+ \def\skv@tempb{}%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvcommaparse{#1}\skv@tempa{%
+ \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@igkeys,}{}{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb\ifx\skv@tempb\@empty\else,\fi
+ \skvexpandonce\skv@tempa
+ }%
+ }%
+ }%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ \skvifempty\skv@tempb{}{%
+ \noexpand#2[##1]{##2}{\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempd
+}
+
+% \dirkeys@dolistedkeys@b{<callback>}
+\skvrobustdef*\dirkeys@dolistedkeys@b#1{%
+ \begingroup
+ % ##1=prefix, ##2=family
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \unexpanded{\skv@makeprefix{##1}\skv@makeheader{##2}#1}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+}
+\skvrobustdef*\skv@getexpander#1{%
+ \begingroup
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \def\skv@provb##1{%
+ \def\skv@provb####1##1####2####3\skv@nil{%
+ \endgroup
+ % Don't use \let for the next definition:
+ \def\skvexpander{####2}%
+ \ifx\skvexpander\@nnil
+ \skv@err{Unknown expansion type '\detokenize{##1}'}\@ehd
+ \fi
+ }%
+ \skv@provb x0{\unexpanded}x1{\skvexpandonce}x2{\skvexpandtwice}%
+ xx{\@iden}##1{\@nil}\skv@nil
+ }%
+ \expandafter\skv@provb\expandafter{\skv@prova}%
+}
+\skvrobustdef*\skv@getmaintoks#1#2{%
+ \def\skv@prova##1#2##2#2##3\skv@nil{%
+ \edef\skvcurrentmaintoks{\skvtrimspace{##1}}%
+ \skvstripouterbraces{2}\skvcurrentmaintoks
+ \ifx\skvcurrentmaintoks\@empty
+ \skv@err{No main key in '\detokenize{#1}'}\@ehd
+ \fi
+ \edef\skvcurrentsub{\unexpanded{##2}}%
+ \ifx\skvcurrentsub\skv@novaluetoks
+ \def\skvcurrentsub{}%
+ \else\skvafterfi
+ \skvdespacecontent\skvcurrentsub
+ \skvstripouterbraces{2}\skvcurrentsub
+ \fi
+ }%
+ \skv@prova#1#2\skv@novalue#2\skv@nil
+}
+
+% Assigning admissible values to keys. The handlers here are:
+%
+% .choice, .choice expanded, .choice expanded once, .choice expanded twice.
+%
+% \dirkeys@savechoice{<list>}{<expander.type>}
+%
+% 1. <list> has the form
+%
+% <key1>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}},...,
+% <key-n>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}}
+%
+% 2. If it didn't exist, the main key (eg, the above <key1>) will be
+% defined with an empty default value and an empty callback.
+%
+\skvrobustdef*\dirkeys@savechoice#1#2{%
+ \begingroup
+ \dirkeys@getrootlist
+ \def\skv@tempd{}%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[/]\skv@tempa
+ \skvcommaparse*\skv@tempa\skv@tempa{%
+ \skvexpbracenext\dirkeys@s@vechoice\skv@tempa{#2}%
+ }%
+ \expandafter\endgroup\skv@tempd
+}
+\skvrobustdef*\dirkeys@s@vechoice#1#2{%
+ \skv@getmaintoks{#1}{/}%
+ \skvkvnormalize\skvcurrentsub
+ \def\skv@doonroot##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvxifin{,\skvcurrentmaintoks,}{,\skv@igkeys,}{}{%
+ \skvifcsdef{##1/##2/\skvcurrentmaintoks.@cbk}{}{%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ \skvordkey[##1]{##2}{\skvcurrentmaintoks}[]{}%
+ }%
+ }%
+ \def\skv@choicelist{}%
+ \skvcommaloop*\skvcurrentsub\skv@tempa{%
+ \def\skv@prova####1.do=####2.do=####3\skv@nil{%
+ \edef\skv@choicelist{%
+ \skvexpandonce\skv@choicelist
+ {\skvtrimspace{####1}}{\skvtrimspace{####2}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa.do=.do=\skv@nil
+ }%
+ }%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ \skvappendkeycode[##1]{##2}{\skvcurrentmaintoks}%
+ {\dirkeys@executechoice{#2}{########1}%
+ {\skvexpandonce\skv@choicelist}}%
+ }%
+ }%
+ \skv@rootlist
+}
+% \dirkeys@executechoice{<expansion.type>}{<curr.value>}{<choices.and.cbks>}
+\skvrobustdef*\dirkeys@executechoice#1#2#3{%
+ \skv@getexpander{#1}%
+ \edef\skv@prova{\skvexpander{#2}}%
+ \skvdespacecontent\skv@prova
+ \def\do##1##2##3\skv@nil{%
+ \edef\skv@provb{\unexpanded{##1}}%
+ \skvifx\skv@provb\skv@prova{%
+ ##2%
+ }{%
+ \skvifblank{##3}{%
+ \skv@err{No choice match found for key '\skvcurrentkey'}\@ehd
+ }{%
+ \do##3\skv@nil
+ }%
+ }%
+ }%
+ \do#3\skv@nil
+}
+
+% The handlers here are:
+%
+% .style, .style expanded, .style expanded once, .style expanded twice.
+%
+% Note that the handlers are preceded by 'append' or 'prepend'.
+%
+% \dirkeys@savestyle{<list>}{<append.or.prepend>}{<expander.type>}
+%
+% 1. <list> has the form
+%
+% {<main key1>,...,<main key-n>}/{<style1=val1>,...,<style-n=val-n>}
+% ,...,
+% {<main key1>,...,<main key-n>/{<style1=val1>,...,<style-n=val-n>}
+%
+% 2. Here the styles are linked with each main key. When the main key is
+% set, the associated styles will be set with the given values.
+%
+% 3. Examples:
+%
+% a) The following example means that keyc and keyd are representations
+% for the actions on their right (ie, for setting 'keya=\someright,
+% keyb=\keybval') when keyc or keyd is set. The values of keya and
+% keyb will be expanded twice before the keys are set:
+%
+% .append style expand twice={keyc,keyd}/{keya=\someright,keyb=\keybval}.
+%
+% b) In the following example, #1 will be the value of keye and/or keyf
+% when they're set. The values of keye and keyf will be fully expanded
+% before they're assigned to keyc and keyd:
+%
+% .prepend style expanded={keye,keyf}/{keyc=#1,keyd=#1}
+%
+\skvrobustdef\dirkeys@savestyle#1#2#3{%
+ \begingroup
+ \dirkeys@getrootlist
+ \skv@getexpander{#3}%
+ \def\skv@tempd{}%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[/]\skv@tempa
+ \skvcommaparse*\skv@tempa\skv@tempa{%
+ \skvexpbracenext\dirkeys@s@vestyle\skv@tempa{#2}%
+ }%
+ \expandafter\endgroup\skv@tempd
+}
+\skvrobustdef\dirkeys@s@vestyle#1#2{%
+ \skv@getmaintoks{#1}{/}%
+ \skvcsvnormalize\skvcurrentmaintoks
+ \skvkvnormalize\skvcurrentsub
+ \def\skv@doonroot##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvcommaloop*\skvcurrentmaintoks\skv@maintoks{%
+ \skvxifin{,\skv@maintoks,}{,\skv@igkeys,}{}{%
+ \skvifcsdef{##1/##2/\skv@maintoks.@cbk}{}{%
+ % Link keys should always be set with a value. If they were
+ % undefined before being designated as a link key, then
+ % clearly they should have no default.
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ \skvordkey[##1]{##2}{.value required{\skv@maintoks}}{}%
+ }%
+ }%
+ \def\skv@stylelist{}%
+ \skvcommaloop*\skvcurrentsub\skv@tempa{%
+ \def\skv@prova####1=####2=####3\skv@nil{%
+ \skvxifstrcmp{\skv@maintoks}{####1}{%
+ \skv@err{Linking key '####1' to itself}\@ehd
+ }{%
+ \skvifcsdef{##1/##2/####1.@cbk}{}{%
+ \skv@err{Style key '####1' is undefined}\@ehd
+ }%
+ }%
+ \skvxifin{,####1,}{,\skv@igkeys,}{}{%
+ \edef\skv@stylelist{%
+ \skvaddlist,\skv@stylelist\unexpanded{####1}=%
+ \skvexpandonce\skvexpander{\unexpanded{####2}}%
+ }%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa==\skv@nil
+ }%
+ }%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd
+ % The styles contain value expanders \@firstofone, \unexpanded, etc.
+ % They will be expanded by the next \skvexpanded when the main key
+ % is set.
+ \skvifstrcmp{#2}{app}\skvappendkeycode\skvprependkeycode
+ [##1]{##2}{\skv@maintoks}%
+ {\skvexpanded{\skvsetkeys[##1]{##2}%
+ {\skvexpandonce\skv@stylelist}}}%
+ }%
+ }%
+ }%
+ \skv@rootlist
+}
+
+%% +++++++++++++++ Linking keys:
+%
+% The handlers here are:
+%
+% .link, .link expanded, .link expanded once, .link expanded twice.
+%
+% \dirkeys@savestyle{<list>}{<append.or.prepend>}{<expander.type>}
+%
+% 1. <list> has the form
+%
+% {<linkkey-1>,..,<linkkey-n>}/{<parentkey-1>,...,<parentkey-n>}
+%
+% 2. The parent key will be set (with the value of link key) whenever the
+% link key is set.
+% 3. If the link key didn't exist, it will be defined as an ordinary key
+% with the default value of the parent key. In this way, setting a
+% link key without value won't give rise to a 'no value and no default
+% error'.
+% 4. Example: Link keyb and keyc to existing keya:
+%
+% .link={keyb,keyc}/keya
+%
+% This is equivalent to:
+%
+% .style={{keyb,keyc}/keya=#1}
+%
+% This will link keyb and keyc to keya, such that when keyb and
+% keyc are set, keya too will be set with their values.
+%
+\skvrobustdef\dirkeys@savelink#1#2#3{%
+ \begingroup
+ \def\skv@tempe{}%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvcsvnormalize[/]\skv@tempa
+ \skvcommaparse*\skv@tempa\skv@tempa{%
+ \skvexpbracenext\skv@getmaintoks\skv@tempa{/}%
+ \skvcsvnormalize\skvcurrentmaintoks
+ \def\skv@tempd{}%
+ \skvcommaparse*\skvcurrentsub\skv@tempb{%
+ \edef\skv@tempd{%
+ \skvexpandonce\skv@tempd\ifx\skv@tempd\@empty\else,\fi
+ \skvexpandonce\skv@tempb=####1%
+ }%
+ }%
+ \edef\skv@tempe{%
+ \skvexpandonce\skv@tempe\ifx\skv@tempe\@empty\else,\fi
+ {\skvexpandonce\skvcurrentmaintoks}/{\skvexpandonce\skv@tempd}%
+ }%
+ }%
+ \expandafter\endgroup\expandafter\dirkeys@savestyle
+ \expandafter{\skv@tempe}{#2}{#3}%
+}
+
+% #1: <key-1>=<arg-1>,...,<key-n>=<arg-n>
+% #2: <arg.expander.type>
+%
+\skvrobustdef*\dirkeys@assignarg#1#2{%
+ \begingroup
+ % Don't take #1 inside \skv@doonroot because it contains parameters:
+ \edef\skv@tempd{\unexpanded{#1}}%
+ \def\skv@tempe{}%
+ \skvkvnormalize\skv@tempd
+ \def\skv@doonroot##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvcommaloop*\skv@tempd\skv@tempa{%
+ \def\skv@prova####1=####2=####3\skv@nil{%
+ \skvxifin{,####1,}{,\skv@igkeys,}{}{%
+ \skvifcsdef{##1/##2/####1.@cbk}{%
+ \skvifblank{####2}{}{%
+ \edef\skv@tempe{%
+ \skvexpandonce\skv@tempe\unexpanded{%
+ \skvcsedef{##1/##2/####1.@#2arg}{\unexpanded{####2}}%
+ }%
+ }%
+ }%
+ }{%
+ \skv@err{Key '####1' is undefined in family '##1/##2'}\@ehd
+ }%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa==\skv@nil
+ }%
+ }%
+ \dirkeys@getcurrentroots\skv@doonroot
+ \expandafter\endgroup\skv@tempe
+}
+
+% Use the default values of <keys> to set the keys.
+% \dirkeys@setwithdefaults[<pref>]{<fam>}{<keys>}
+\skvrobustdef*\dirkeys@setwithdefaults[#1]#2#3{%
+ \begingroup
+ \def\skv@defaultlist{}%
+ \skvcommaparse{#3}\skvcurrentkey{%
+ \skvletcs\skv@prova{#1/#2/\skvcurrentkey.@defa}%
+ \skvifdef\skv@prova{%
+ \skv@getdefault{#1}{#2}\skvcurrentkey\skvcurrentvalue
+ \edef\skv@defaultlist{%
+ \skvaddlist,\skv@defaultlist
+ \skvcurrentkey=\skvexpandonce\skvcurrentvalue
+ }%
+ }{%
+ \skv@err{No default value for key '\skvcurrentkey'
+ \MessageBreak in family '#1/#2'}\@ehd
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvsetkeys*+[#1]{#2}{\skvexpandonce\skv@defaultlist}%
+ }%
+}
+
+\skvrobustdef*\dirkeys@dounknownkeyhandler#1{%
+ \begingroup
+ \def\skv@tempa{}\def\skv@tempb{}%
+ \def\do##1##2{%
+ \skvxifin{,##1,}{,\skv@tempa,}{}{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \ifx\skv@tempa\@empty\else,\fi##1%
+ }%
+ }%
+ \skvxifin{,##2,}{,\skv@tempb,}{}{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \ifx\skv@tempb\@empty\else,\fi##2%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \skvexpanded{\endgroup
+ \skvunknownkeyhandler\ifskv@handlerswa+\fi[\skv@tempa]{\skv@tempb}%
+ }{#1}%
+}
+
+%%++++++++++++++++++++++++++ Try setting keys +++++++++++++++++++++++%%
+%
+% \skvtrysetkeys[<options>]{<keyvals>}
+% .try set keys={<options>}{<keyvals>}
+%
+% Try to set a given key-value list on the paths given by the independent
+% options '.prefix/.prefixes' and '.family/.families' of \skvtrysetkeys. If
+% called within \directkeys (via the handler '.try set keys'), \skvtrysetkeys
+% will ignore the paths that are currently prevailing within \directkeys.
+% That is, within \directkeys, the handler '.try set keys' acts independent
+% of local circumstances of \directkeys.
+%
+% Save the known/found keys in the macro suggested by the option
+% <success list macro>. The user can inspect this macro to see the found
+% keys. When many families are given by the user, the success list is likely
+% to be smaller than failed list.
+%
+% Raise an error if the number of successful families is less than
+% the minimum threshold <min success>. The default value of <min success>
+% is 1. The options <min success> and <lower goal> are synonymous.
+%
+% \skvtrysetkeys is similar to \skvsetkeys*+ (ie, \skvsetkeys with the
+% options *+), but in this case we have <try> (ie, the maximum total number
+% of attempts - families to search for a given key) before backing off,
+% and <upper goal> (the maximum number of successful families in which a key
+% should be set).
+%
+% \skvtrysetkeys too will set existing preset and postset keys in the
+% given families.
+%
+% The options of \skvtrysetkeys are:
+%
+% .try:
+% The maximum number of the sum of successful and unsuccessful
+% attempts that should be made to set a key in the given SFs. The
+% default value of <try> is 12.
+% .upper goal/.max success:
+% The max. number of search families (SF) in which a given key should
+% be set/executed, if the key existed in those families. The number of
+% SFs may be more than <upper goal>, but the key may not need to be
+% executed in all of them. The default value of <upper goal> is 1.
+% .lower goal/.min success:
+% The min. number of search families (SF) in which a given key should
+% be set/executed. For any key, if <hits> is less than <lower goal>
+% an error will be flagged.
+% .prefix/.prefixes:
+% The prefixes in which the keys should be set (default=KV).
+% .families/.family:
+% Families to search.
+% .ignore keys:
+% Ignored keys. These keys will not be set even if they are found.
+% .save known keys:
+% The boolean that directs that known/found keys should be saved
+% in a macro.
+% .save known keys in/success list macro/success list:
+% The macro into which to save known keys. Each known key is
+% saved in the format: <pref>/<fam>/<key>. The user can
+% inspect this macro to see the found keys. The default macro is
+% \skvsuccesslist.
+%
+% NOTE:
+%
+% When the paths are many, the user has to be right in choosing the
+% options '.try', '.upper goal' and '.lower goal', otherwise not enough paths
+% will be searched. For example, if you want some 'keya' to be set on
+% paths KV1/fam1, KV1/fam2, KV2/fam1, KV2/fam2, and you set '.try=2' or
+% '.upper goal=2', then only 2 paths will be traversed; not the desired 4.
+
+\skvedefinekeys[SKV]{skvtryset}[skvtry@]{%
+ .ords/{.try,.max attempt,.max attempts,.total}/12/
+ \edef\skvtry@maxattempts{\number#1}%
+ \skvensureinteger{.max attempt}\skvtry@maxattempts
+ \ifnum#1<\@ne
+ \skv@err{The max. number of attempts ('try')
+ \MessageBreak can't be less than 1}\@ehd
+ \fi
+ ,
+ .ords/{.upper goal,.max success,.max hits}/1/
+ \edef\skvtry@maxsuccess{\number#1}%
+ \skvensureinteger{upper goal}\skvtry@maxsuccess
+ \ifnum#1<\@ne
+ \skv@err{The max. number of successful attempts
+ \MessageBreak ('upper goal') can't be less than 1}\@ehd
+ \fi
+ ,
+ .ords/{.min success,.lower goal,.goal}/1/
+ \edef\skvtry@minsuccess{\number#1}%
+ \skvensureinteger{lower goal}\skvtry@minsuccess
+ \ifnum#1<\@ne
+ \skv@err{The min. number of successful attempts
+ \MessageBreak ('lower goal') can't be less than 1}\@ehd
+ \fi
+ ,
+ .ords/{.prefix,.prefixes,.add prefix,.add prefixes}/KV/
+ \edef\skvtry@prefs{#1}
+ \skvstripouterbraces{2}\skvtry@prefs
+ \edef\skvtry@prefs{\skvifempty\skvtry@prefs{KV}{\skvtry@prefs}}%
+ \ifskv@insa
+ \skvexpbracenext{\skvmergelist\skvtry@prefs}\dirkeys@prefixlist
+ \fi
+ \skvcsvnormalize\skvtry@prefs
+ ,
+ .ords/{.family,.families,.add family,.add families}/^skv^/
+ \edef\skvtry@fams{#1}
+ \ifx\skvtry@fams\skv@rej\else
+ \skvstripouterbraces{2}\skvtry@fams
+ \ifskv@insa
+ \skvexpbracenext{\skvmergelist\skvtry@fams}\dirkeys@familylist
+ \fi
+ \skvcsvnormalize\skvtry@fams
+ \fi
+ ,
+ .ords/{.path,.paths,.add path,.add paths,.root,.roots}/^skv^/
+ \edef\skv@tempa{\skvtrimspace{#1}}
+ \skvstripouterbraces{2}\skv@tempa
+ \ifcase0\ifx\skv@tempa\skv@rej1\else
+ \ifx\skv@tempa\@empty1\fi\fi\relax\skvafterfi
+ \skvexpbracenext\skvtry@fixpaths\skv@tempa
+ \fi
+ ,
+ .ords/{.ignore keys,.filter keys}//
+ \def\skvtry@igkeys{#1}
+ \skvstripouterbraces{2}\skvtry@igkeys
+ ,
+ .ords/{.save known keys,.save success}/true/
+ \edef\skvtry@savesuccess{0\skvifstrcmp{#1}{true}01}
+ ,
+ .ords/{.save known keys in,.success list,.success list macro}/
+ \skvsuccesslist/\def\skvtry@successlistmacro{#1}
+ ,
+}
+\skvrobustdef*\skvtry@fixpaths#1{%
+ \def\skvtry@prefs{}%
+ \def\skvtry@fams{}%
+ \def\skv@tempc##1/##2/##3\skv@nil{%
+ \def\skv@tempa{##1}%
+ \def\skv@tempb{##2}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvstripouterbraces{2}\skv@tempb
+ \edef\skvtry@prefs{%
+ \skvtry@prefs\ifx\skvtry@prefs\@empty\else,\fi\skv@tempa
+ }%
+ \edef\skvtry@fams{%
+ \skvtry@fams\ifx\skvtry@fams\@empty\else,\fi\skv@tempb
+ }%
+ }%
+ \skvcommaparse{#1}\skv@prova{%
+ \expandafter\skv@tempc\skv@prova//\skv@nil
+ }%
+ \ifskv@insa
+ \skvexpbracenext{\skvmergelist\skvtry@prefs}\dirkeys@prefixlist
+ \skvexpbracenext{\skvmergelist\skvtry@fams}\dirkeys@familylist
+ \fi
+ \skvcsvnormalize\skvtry@prefs
+ \skvcsvnormalize\skvtry@fams
+}
+\skvsetkeys[SKV]{skvtryset}{.try,.upper goal,.lower goal,.prefix,
+ .family=^skv^,.ignore keys,.save success,.success list macro
+}
+
+% \skvtrysetkeys[<options>]{<kvlist>}
+\skvrobustdef*\skvtrysetkeys{\skv@testopt\skv@trysetkeys{}}
+\skvrobustdef*\skv@trysetkeys[#1]#2{%
+ \skvpushfunctions\skvtrysetkeys{%
+ % Don't include \skvsuccesslist here!
+ \do\skvtry@fams\do\skvtry@prefs\do\skvtry@maxattempts
+ \do\skvtry@minsuccess\do\skvtry@maxsuccess\do\skvtry@igkeys
+ \do\skvtry@successlistmacro\do\skvtry@savesuccess
+ }\skv@trysetkeysdepth
+ \skvsetkeys[SKV]{skvtryset}{#1}%
+ \ifx\skvtry@fams\skv@rej
+ \skv@err{No families in which to 'try' to set keys}\@ehd
+ \fi
+ \skv@getkeynames{#2}\skv@naa
+ \ifnum\skv@trysetkeysdepth=\@ne
+ \expandafter\def\skvtry@successlistmacro{}%
+ \def\skv@tempsuccesslist{}%
+ \fi
+ \skv@intrytrue
+ \skvcommaparse{#2}\CurrentOption{%
+ \expandafter\skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey
+ \skvxifin{,\skvcurrentkey,}{,\skvtry@igkeys,}{}{%
+ \skv@successfalse
+ % Don't use \chardef here; it won't printed in the error message
+ % if it wasn't incremented:
+ \def\skv@attempts{0}%
+ \def\skv@hits{0}%
+ \def\skv@breakprefloop{01}%
+ \skvcommaloop*\skvtry@prefs\skvcurrentprefix{%
+ \skvcommaloop*\skvtry@fams\skvcurrentfamily{%
+ \skvpushfunctions\skv@trysetkeys@istate{%
+ \do\CurrentOption\do\skvcurrentkey\do\skvcurrentprefix
+ \do\skvcurrentfamily\do\skv@attempts\do\skv@hits
+ \do\skv@breakprefloop\do\ifskv@success
+ }\skv@trysetkeysdepth@b
+ \skvexpanded{%
+ % Don't use \skv@setkeys@a here: \skv@fams, etc.
+ % will be mixed up.
+ \skvsetkeys[\skvcurrentprefix]{\skvcurrentfamily}%
+ {\skvexpandonce\CurrentOption}%
+ }%
+ \skvpopfunctions\skv@trysetkeys@istate\skv@trysetkeysdepth@b
+ \edef\skv@attempts{\the\numexpr\skv@attempts+1}%
+ \ifskv@success
+ \edef\skv@hits{\the\numexpr\skv@hits+1}%
+ \if\skvtry@savesuccess
+ \edef\skv@tempsuccesslist{%
+ \skvaddlist,\skv@tempsuccesslist\skvcurrenttriple
+ }%
+ \fi
+ \fi
+ \ifnum\skv@hits<\skvtry@maxsuccess\relax
+ \ifnum\skv@attempts<\skvtry@maxattempts\relax\else
+ \skvbreakloop
+ \def\skv@breakprefloop{00}%
+ \fi
+ \else
+ \skvbreakloop
+ \def\skv@breakprefloop{00}%
+ \fi
+ }%
+ \if\skv@breakprefloop
+ \skvbreakloop
+ \fi
+ }%
+ \ifnum\skv@hits<\skvtry@minsuccess\relax
+ \skv@err{Success target '\skvtry@minsuccess' wasn't reached
+ \MessageBreak for key '\skvcurrentkey' by
+ \ifskv@insa'.search also set'\else
+ \noexpand\skvtrysetkeys\fi.
+ \MessageBreak Actual hits were '\skv@hits'}\@ehd
+ \fi
+ }%
+ }%
+ \expandafter\let\skvtry@successlistmacro\skv@tempsuccesslist
+ \ifnum\skv@trysetkeysdepth=\@ne
+ \skv@intryfalse\skv@insafalse
+ \let\do\skvundef
+ \do\skv@breakprefloop\do\skv@attempts\do\skv@hits
+ \do\skv@tempsuccesslist
+ \fi
+ \skvpopfunctions\skvtrysetkeys\skv@trysetkeysdepth
+}
+
+%%+++++++++++++++++++++++++ 'search also' set keys +++++++++++++++++++%%
+%
+% \skvsasetkeys[<options>]{<keyvals>}
+% .sa set keys={<options>}{<keyvals>}
+%
+% 1. The only difference between \skvsasetkeys and \skvtrysetkeys is that,
+% when in \directkeys, the values of the options <prefix/prefixes> and
+% <family/families> of \skvsasetkeys are added to the current
+% active prefixes and families from the lists \dirkeys@prefixlist and
+% \dirkeys@familylist. Outside of \directkeys, the commands
+% \skvsasetkeys and \skvtrysetkeys are the same.
+%
+% 2. All the options of \skvtrysetkeys apply to \skvsasetkeys.
+
+\skvnewlet\skvsasetkeys\skvtrysetkeys
+\skvrobustdef*\dirkeys@dosasetkeys#1{%
+ \skv@insatrue
+ \skvifundef\dirkeys@familylist{\def\dirkeys@familylist{}}{}%
+ \skvifundef\dirkeys@prefixlist{\def\dirkeys@prefixlist{}}{}%
+ \skv@trysetkeys[#1]%
+}
+
+% \dirkeys@addorremoveroots{<list>}{<operator>}
+\skvrobustdef*\dirkeys@addorremoveroots#1#2{%
+ \edef\skv@prova{\unexpanded{#1}}%
+ \skvcsvnormalize[/]\skv@prova
+ \def\skv@tempa{}\def\skv@tempb{}%
+ \skvcommaparse*\skv@prova\skv@prova{%
+ \def\skv@provb##1/##2/##3\skv@nil{%
+ \skvxifin{,##1,}{,\skv@tempa,}{}{%
+ \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}%
+ }%
+ \skvxifin{,##2,}{,\skv@tempb,}{}{%
+ \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}%
+ }%
+ }%
+ \expandafter\skv@provb\skv@prova//\skv@nil
+ }%
+ \skv@clfalse
+ \skvexpbracenext{#2\dirkeys@prefixlist}\skv@tempa
+ \skvexpbracenext{#2\dirkeys@familylist}\skv@tempb
+}
+
+
+% \dirkeys@addtocodeorvalue{app/pre}{cbk/value}{<list>}
+\skvrobustdef*\dirkeys@addtocodeorvalue#1#2#3{%
+ \begingroup
+ % Hid the list from the parameters of \do:
+ \edef\skv@tempa{\unexpanded{#3}}%
+ \def\skv@tempb{}%
+ % ##1=prefix, ##2=family
+ \def\do##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvkvparse*\skv@tempa\skv@tempa{%
+ \expandafter\skv@kvsplit\expandafter{\skv@tempa}{%
+ \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
+ \skvletcs\skv@prova{##1/##2/####1.@#2}%
+ \skvifundef\skv@prova{%
+ \skv@err{Key '####1' isn't in family '##1/##2'}\@ehd
+ }{%
+ \skvcsedef{##1/##2/####1.@#2}{%
+ \skvifstrcmp{#1}{pre}{%
+ \skvtrimspace{####2}\skvexpandonce\skv@prova
+ }{%
+ \skvexpandonce\skv@prova\skvtrimspace{####2}%
+ }%
+ }%
+ % To take the new macros outside the group:
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \noexpand\skvcsexit{##1/##2/####1.@#2}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \skvexpanded{\endgroup\skv@tempb}%
+}
+
+% \dirkeys@assigndefault{<kvlist>}
+\skvrobustdef*\dirkeys@assigndefault#1{%
+ \begingroup
+ % Hid the list from the parameters of \do:
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \def\skv@tempb{}%
+ % ##1=prefix, ##2=family
+ \def\do##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvkvparse*\skv@tempa\skv@tempa{%
+ \expandafter\skv@kvsplit\expandafter{\skv@tempa}{%
+ \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
+ \skvifcsdef{##1/##2/####1.@cbk}{%
+ \skvcsedef{##1/##2/####1.@defa}{%
+ \skvnoexpandcs{##1/##2/####1}{\skvtrimspace{####2}}%
+ }%
+ % To take the new defaults outside the group:
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \noexpand\skvcsexit{##1/##2/####1.@defa}%
+ }%
+ }{%
+ \skv@err{Key '####1' is not in family '##1/##2'}\@ehd
+ }%
+ }%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \skvexpanded{\endgroup\skv@tempb}%
+}
+
+% \dirkeys@assignvalue{<kvlist>}
+\skvrobustdef*\dirkeys@assignvalue#1{%
+ \begingroup
+ % Hid the list from the parameters of \do:
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \def\skv@tempb{}%
+ % ##1=prefix, ##2=family
+ \def\do##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvkvparse*\skv@tempa\skv@tempa{%
+ \expandafter\skv@kvsplit\expandafter{\skv@tempa}{%
+ \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
+ \skvifcsdef{##1/##2/####1.@cbk}{%
+ \skvcsedef{##1/##2/####1.@value}{\skvtrimspace{####2}}%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb
+ \noexpand\skvcsexit{##1/##2/####1.@value}%
+ }%
+ }{%
+ \skv@err{Key '####1' isn't in family '##1/##2'}\@ehd
+ }%
+ }%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \skvexpanded{\endgroup\skv@tempb}%
+}
+
+% \dirkeys@inherit{value/cbk/defa}{<list>}
+\skvrobustdef*\dirkeys@inherit#1#2{%
+ % Hid the list from the parameters of \do:
+ \edef\skv@tempa{\unexpanded{#2}}%
+ % ##1=prefix, ##2=family
+ \def\do##1##2{%
+ \skvletcs\skv@igkeys{##1/##2/.@ignoredkeys}%
+ \skvifdef\skv@igkeys{}{\def\skv@igkeys{}}%
+ \skvkvparse*\skv@tempa\skv@tempa{%
+ \expandafter\skv@slsplit\expandafter{\skv@tempa}{%
+ \skvxifin{,\detokenize{####1},}{,\skvoxdetok\skv@igkeys,}{}{%
+ \ifcase\skvifcsdef{##1/##2/####1.@cbk}{0}{1}%
+ \skvifcsdef{##1/##2/####2.@cbk}{0}{1}\relax
+ \skvcsletcs{##1/##2/####1.@#1}{##1/##2/####2.@#1}%
+ \else
+ \skv@err{Key '####1' or '####2' isn't in family '##1/##2'}\@ehd
+ \fi
+ }%
+ }%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+}
+
+% \dirkeys@setbooleanhandler{<handler>}{<boolean>}{<bool value>}
+\skvrobustdef*\dirkeys@setbooleanhandler#1#2#3{%
+ \skvifblank{#3}{%
+ \csname#2true\endcsname
+ }{%
+ \skvifboolval{#3}{%
+ \csname#2#3\endcsname
+ }{%
+ \skv@err{Invalid value '\detokenize{#3}' for handler '#1':
+ \MessageBreak its expects either 'true' or 'false'}\@ehd
+ }%
+ }%
+}
+
+\skvrobustdef*\skv@ensurehandlerdot#1{%
+ \if.\skv@car@detok#1x\car@nil\else
+ \skv@err{A dot (.) must lead handler name '#1'}\@ehd
+ \fi
+}
+\skvrobustdef*\skv@handlerloop#1{%
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \skvkvparse*\skv@tempa
+}
+
+% \dirkeys@defhandlers{<marker>}{<list>}
+% <marker> indicates if we're in <new> or <define> handler.
+\skvrobustdef*\dirkeys@defhandlers#1#2{%
+ \def\do##1=##2=##3\handler@nil{%
+ \skv@ensurehandlerdot{##1}%
+ \if0#1%
+ \skvcsdef{dirkeys@handler@##1}####1{##2}%
+ \else
+ \skvifcsdef{dirkeys@handler@##1}{%
+ \skv@err{Handler '##1' arealdy exists}\@ehd
+ }{%
+ \skvcsdef{dirkeys@handler@##1}####1\handlereov{##2}%
+ }%
+ \fi
+ }%
+ \skv@handlerloop{#2}\skv@tempa{%
+ \expandafter\do\skv@tempa==\handler@nil
+ }%
+}
+
+% Define handlers of more than one argument. This is slightly more
+% expensive than '.new handlers':
+% \dirkeys@defnarghandlers{<marker>}{<list>}
+% <marker> indicates if we're in <new> or <define> handler.
+\skvrobustdef*\dirkeys@defnarghandlers#1#2{%
+ \def\do##1=##2=##3\handler@nil{%
+ \skv@ensurehandlerdot{##1}%
+ \def\skv@tempa####1####2\handler@nil{%
+ % ####2 must be hidden in a macro for later use in defining the
+ % handler:
+ \edef\skv@prova{\unexpanded{####2}}%
+ \edef\skv@tempa{\skvgenerateparameters{1}{####1}\handlereov}%
+ \def\skv@provb{%
+ \edef\skv@tempb{\protected\def\skvnoexpandcs{dirkeys@handler@##1}}%
+ \expandafter\expandafter\expandafter\skv@tempb\expandafter
+ \skv@tempa\expandafter{\skv@prova}%
+ }%
+ \if0#1%
+ \skv@provb
+ \else
+ \skvifcsdef{dirkeys@handler@##1}{%
+ \skv@err{Handler '##1' arealdy exists}\@ehd
+ }{%
+ \skv@provb
+ }%
+ \fi
+ }%
+ \skv@tempa##2\handler@nil
+ }%
+ \skv@handlerloop{#2}\skv@tempa{%
+ \expandafter\do\skv@tempa==\handler@nil
+ }%
+}
+\skvrobustdef*\skvusehandler#1#2{%
+ \skv@ensurehandlerdot{#1}%
+ \skvifcsdef{dirkeys@handler@#1}{%
+ \csname dirkeys@handler@#1\endcsname#2\handlereov
+ }{%
+ \skv@err{Handler '#1' is undefined}\@ehd
+ }%
+}
+
+% The macro that contains the default command in which unknown keys
+% will be saved by some handlers of \dirkeys:
+\skvnewdef*\dirkeys@unknownkeysmacro{\skvfaillist}
+
+% Notes:
+% 1. '.new handlers' must be defined outsied \dirkeys, since it is
+% the one that defines every other handler.
+% 2. It defines definable handlers of one or more arguments. See also
+% '.define handlers' later on (within the next call of \dirkeys).
+\skvrobustcsdef*{dirkeys@handler@.new handlers}#1\handlereov{%
+ \dirkeys@defhandlers{1}{#1}%
+}
+% In case one gives no value to a handler:
+\skvundef\dirkeys@
+\dirkeys*{%
+ .new handlers={%
+ .exec code=#1,
+ .define handlers=\dirkeys@defhandlers{0}{#1},
+ .define narg handlers=\dirkeys@defnarghandlers{0}{#1},
+ .new narg handlers=\dirkeys@defnarghandlers{1}{#1},
+ .kill handlers={%
+ \skv@handlerloop{#1}\skv@tempa{%
+ \skvifcsdef{dirkeys@handler@\skv@tempa}{%
+ \skvcsundef{dirkeys@handler@\skv@tempa}%
+ }{%
+ \skv@err{Handler '\skv@tempa' is undefined}\@ehd
+ }%
+ }%
+ },
+ .use handler=\skvusehandler{#1},
+ .handler let={%
+ \def\do##1=##2=##3\handler@nil{%
+ \skvifcsdef{dirkeys@handler@##1}{%
+ \skv@err{Handler '##1' arealdy exists}\@ehd
+ }{%
+ \skvifcsundef{dirkeys@handler@##2}{%
+ \skv@err{Handler '##2' doesn't exist}\@ehd
+ }{%
+ \skvifblank{##1}{%
+ \skv@err{No child handler}\@ehd
+ }{%
+ \skvcsletcs{dirkeys@handler@##1}{dirkeys@handler@##2}%
+ }%
+ }%
+ }%
+ }%
+ \skv@handlerloop{#1}\skv@tempa{%
+ \expandafter\do\skv@tempa==\handler@nil
+ }%
+ },
+ .prefixes={%
+ \def\dirkeys@prefixlist{}%
+ \skvusehandler{.add prefixes}{#1}%
+ },
+ .add prefixes={%
+ \skv@clfalse\skv@mergelist\dirkeys@prefixlist{#1}%
+ },
+ .families={%
+ \def\dirkeys@familylist{}%
+ \skvusehandler{.add families}{#1}%
+ },
+ .add families={%
+ \skv@clfalse\skv@mergelist\dirkeys@familylist{#1}%
+ },
+ .roots={%
+ \def\dirkeys@prefixlist{}%
+ \def\dirkeys@familylist{}%
+ \skvusehandler{.add roots}{#1}%
+ },
+ .add roots={%
+ \dirkeys@addorremoveroots{#1}\skvmergelist
+ },
+ .ignore roots={%
+ \dirkeys@addorremoveroots{#1}\skvremoveelements
+ },
+ .restore roots={%
+ \skvusehandler{.add roots}{#1}%
+ },
+ .ignore prefixes=\skvremoveelements\dirkeys@prefixlist{#1},
+ .restore prefixes=\skvmergelist\dirkeys@prefixlist{#1},
+ .ignore families=\skvremoveelements\dirkeys@familylist{#1},
+ .restore families=\skvmergelist\dirkeys@familylist{#1},
+ .ignore keys={%
+ \def\skv@doonroot##1##2{%
+ \expandafter\skvmergelist
+ \csname##1/##2/.@ignoredkeys\endcsname{#1}%
+ }%
+ \dirkeys@getcurrentroots\skv@doonroot
+ },
+ .restore keys={%
+ \def\skv@doonroot##1##2{%
+ \expandafter\skvremoveelements
+ \csname##1/##2/.@ignoredkeys\endcsname{#1}%
+ }%
+ \dirkeys@getcurrentroots\skv@doonroot
+ },
+ .holder prefix=\def\dirkeys@holderprefixtoks{#1},
+ .push prefixes=\dirkeys@pushmeta{prefix},
+ .pop prefixes=\dirkeys@popmeta{prefix},
+ .push families=\dirkeys@pushmeta{family},
+ .pop families=\dirkeys@popmeta{family},
+ .push roots=\dirkeys@pushmeta{root},
+ .pop roots=\dirkeys@popmeta{root},
+ .push holder prefix=\dirkeys@pushmeta{hp},
+ .pop holder prefix=\dirkeys@popmeta{hp},
+ .save unknown keys={%
+ \dirkeys@setbooleanhandler
+ {.save unknown keys}{dirkeys@saveunknownkeys}{#1}%
+ },
+ .save unknown keys in={%
+ \skvifblank{#1}{}{%
+ \skvifescaped{#1}{%
+ \dirkeys@saveunknownkeystrue
+ \def\dirkeys@unknownkeysmacro{#1}%
+ }{%
+ \skv@err{Token '\detokenize{#1}' is not escaped}\@ehd
+ }%
+ }%
+ },
+ .define keys=\skv@handlerswafalse\dirkeys@dodefinekeys{#1},
+ .new keys=\skv@handlerswatrue\dirkeys@dodefinekeys{#1},
+ .initialize keys after define={%
+ \skvusehandler{.set boolean handler}{%
+ {.initialize keys after define}{skvdfk@initialize}{#1}%
+ }%
+ },
+ .save initial values of keys={%
+ \dirkeys@setbooleanhandler
+ {.save initial values of keys}{skvdfk@saveinitialvalues}{#1}%
+ },
+ .set keys={%
+ \skv@handlerswafalse\skv@handlerswbfalse
+ \dirkeys@dosetkeys{#1}\skvsetkeys
+ },
+ .set keys*={%
+ \skv@handlerswatrue\skv@handlerswbfalse
+ \dirkeys@dosetkeys{#1}\skvsetkeys
+ },
+ .set rmkeys={%
+ \skvifblank{#1}{%
+ \skv@handlerswafalse\skv@handlerswbtrue
+ \dirkeys@dosetkeys{}\skvsetrmkeys
+ }{%
+ \skv@err{Key 'set rmkeys' can't have value:
+ \MessageBreak Instead use the key 'ignore keys'
+ \MessageBreak to suggest keys to be ignored
+ \MessageBreak when setting 'rmkeys'}\@ehd
+ }%
+ },
+ .set rmkeys*={%
+ \skvifblank{#1}{%
+ \skv@handlerswatrue\skv@handlerswbtrue
+ \dirkeys@dosetkeys{}\skvsetrmkeys
+ }{%
+ \skv@err{Key 'set rmkeys*' can't have value:
+ \MessageBreak Instead use the key 'ignore keys' to suggest keys
+ \MessageBreak to be ignored when setting rmkeys}\@ehd
+ }%
+ },
+ .preset keys=\dirkeys@dolistedkeys@a{#1}\skv@presetkeys,
+ .gpreset keys=\dirkeys@dolistedkeys@a{#1}\skv@gpresetkeys,
+ .remove preset keys=
+ \dirkeys@dolistedkeys@a{#1}\skvremovepresetkeys,
+ .gremove preset keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgremovepresetkeys,
+ .undefine preset keys=
+ \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
+ .gundefine preset keys=
+ \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
+ .postset keys=\dirkeys@dolistedkeys@a{#1}\skv@postsetkeys,
+ .gpostset keys=\dirkeys@dolistedkeys@a{#1}\skv@gpostsetkeys,
+ .remove postset keys=\dirkeys@dolistedkeys@a{#1}\skvremovepostsetkeys,
+ .gremove postset keys=\dirkeys@dolistedkeys@a{#1}\skvgremovepostsetkeys,
+ .undefine postset keys=
+ \skv@clfalse\dirkeys@dolistedkeys@b\skv@undefpostsetkeys,
+ .gundefine postset keys=
+ \skv@cltrue\dirkeys@dolistedkeys@b\skv@undefpresetkeys,
+ .need value keys=\dirkeys@dolistedkeys@a{#1}\skvneedvaluekeys,
+ .gneed value keys=\dirkeys@dolistedkeys@a{#1}\skvgneedvaluekeys,
+ .remove need value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvremoveneedvaluekeys,
+ .gremove need value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgremoveneedvaluekeys,
+ .forbid value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvforbidvaluekeys,
+ .gforbid value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgforbidvaluekeys,
+ .remove forbid value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvremoveforbidvaluekeys,
+ .gremove forbid value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgremoveforbidvaluekeys,
+ .save initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvsaveinitialvaluekeys,
+ .gsave initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgsaveinitialvaluekeys,
+ .remove save initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvremovesaveinitialvaluekeys,
+ .gremove save initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgremovesaveinitialvaluekeys,
+ .undefine save initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvundefsaveinitialvaluekeys,
+ .gundefine save initial value keys=
+ \dirkeys@dolistedkeys@a{#1}\skvgundefsaveinitialvaluekeys,
+ .disable keys=\dirkeys@dolistedkeys@a{#1}\skvdisablekeys,
+ .disabled key message type={\skvdisabledkeysmessagetype{#1}},
+ % Choices are always appended; never prepended, since the parent
+ % key must first be set before choices are executed.
+ % <key1>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}},...,
+ % <key-n>/{<ch1>.do={<act1>},...,<ch-n>.do={<act-n>}}
+ .choice=\dirkeys@savechoice{#1}{x0},
+ .choice expand once=\dirkeys@savechoice{#1}{x1},
+ .choice expand twice=\dirkeys@savechoice{#1}{x2},
+ .choice expanded=\dirkeys@savechoice{#1}{xx},
+ % {<key-i>,...,<key-j>}/{<stylelist-ij>},...,
+ % {<key-n>,...,<key-m>}/{<stylelist-nm>}:
+ .append style=\dirkeys@savestyle{#1}{app}{x0},
+ .prepend style=\dirkeys@savestyle{#1}{prep}{x0},
+ .append style expanded=\dirkeys@savestyle{#1}{app}{xx},
+ .prepend style expanded=\dirkeys@savestyle{#1}{prep}{xx},
+ .append style expand once=\dirkeys@savestyle{#1}{app}{x1},
+ .prepend style expand once=\dirkeys@savestyle{#1}{prep}{x1},
+ .append style expand twice=\dirkeys@savestyle{#1}{app}{x2},
+ .prepend style expand twice=\dirkeys@savestyle{#1}{prep}{x2},
+ % {<linklist-1>}/<mainkeylist-1>,...,{<linklist-n>}/<mainkeylist-n>:
+ .append link=\dirkeys@savelink{#1}{app}{x0},
+ .prepend link=\dirkeys@savelink{#1}{prep}{x0},
+ .append link expanded=\dirkeys@savelink{#1}{app}{xx},
+ .prepend link expanded=\dirkeys@savelink{#1}{prep}{xx},
+ .append link expand once=\dirkeys@savelink{#1}{app}{x1},
+ .prepend link expand once=\dirkeys@savelink{#1}{prep}{x1},
+ .append link expand twice=\dirkeys@savelink{#1}{app}{x2},
+ .prepend link expand twice=\dirkeys@savelink{#1}{prep}{x2},
+ .list break=\skvbreaklooptrue,
+ .args=\dirkeys@assignarg{#1}{x0},
+ % Expand arguments of keys at key setting time, not at key definition:
+ .args expanded=\dirkeys@assignarg{#1}{xx},
+ .args expanded once=\dirkeys@assignarg{#1}{x1},
+ .args expanded twice=\dirkeys@assignarg{#1}{x2},
+ .set with defaults={
+ \dirkeys@dolistedkeys@a{#1}\dirkeys@setwithdefaults
+ },
+ .unknown key handler={
+ \dirkeys@dounknownkeyhandler{#1}
+ },
+ % Redefine the default value macros of keys.
+ % .default values={keya=vala,...,keyn=valn}
+ .default values={%
+ \dirkeys@assigndefault{#1}
+ },
+ % Change the current values of keys.
+ % .assign values={keya=vala,...,keyn=valn}
+ .assign values={%
+ \dirkeys@assignvalue{#1}
+ },
+ % A key inherits value from a key.
+ % .inherit values={keya1/keya2,...,keyn1/keyn2}
+ .inherit values={%
+ \dirkeys@inherit{value}{#1}
+ },
+ .inherit callback={%
+ \dirkeys@inherit{cbk}{#1}
+ },
+ .inherit defaults={%
+ \dirkeys@inherit{defa}{#1}
+ },
+ % .prepend values={keya=vala,...,keyn=valn}
+ .prepend values={%
+ \dirkeys@addtocodeorvalue{pre}{value}{#1}
+ },
+ .append values={%
+ \dirkeys@addtocodeorvalue{app}{value}{#1}
+ },
+ % .prepend code={keya=codea,...,keyn=coden}
+ .prepend code={%
+ \dirkeys@addtocodeorvalue{pre}{cbk}{#1}
+ },
+ .append code={%
+ \dirkeys@addtocodeorvalue{app}{cbk}{#1}
+ },
+ },
+ .new narg handlers={%
+ .no such key={4}{%
+ % All the parameters would have been despaced when this handler
+ % is called. #1=prefix, #2=family, #3=key, #4=value.
+ \skvifcsdef{#1@#2@handler}{%
+ \csname#1@#2@handler\endcsname{#1}{#2}{#3}{#4}
+ }{%
+ \skv@err{Key '#3' is not in family '#1/#2'}\@ehd
+ }%
+ },
+ .add style={2}{%
+ \skvusehandler{.prepend style}{#1}%
+ \skvusehandler{.append style}{#2}%
+ },
+ .add code={2}{%
+ \skvusehandler{.prepend code}{#1}%
+ \skvusehandler{.append code}{#2}%
+ },
+ .add value={2}{%
+ \skvusehandler{.prepend value}{#1}%
+ \skvusehandler{.append value}{#2}%
+ },
+ % .get value={<pref>}{<fam>}{<key>}<cmd>
+ .get value={4}{%
+ \skvifcsdef{#1/#2/#3.@value}{%
+ \skvifescaped{#4}{%
+ \skvletcs#4{#1/#2/#3.@value}%
+ }{%
+ \skv@err{Token '\detokenize{#4}' isn't escaped}\@ehd
+ }%
+ }{%
+ \skv@err{Key '#3' isn't defined or has
+ \MessageBreak no value in '#1/#2'}\@ehd
+ }%
+ },
+ % '.try set keys' doesn't use the active prefixes and families within
+ % \dirkeys. The prefix, families and other options are to be supplied
+ % in the argument #1.
+ % .try set keys={<options>}{<kvlist>}
+ .try set keys={2}{%
+ \skv@trysetkeys[{#1}]{#2}
+ },
+ % 'search also' set keys.
+ % .sa set keys={<options>}{<kvlist>}
+ .sa set keys={2}{%
+ \dirkeys@dosasetkeys{#1}{#2}
+ },
+ % .set boolean handler={<handler>}{<boolean>}{<value>}
+ .set boolean handler={3}{%
+ \dirkeys@setbooleanhandler{#1}{#2}{#3}
+ },
+ },
+ .handler let={%
+ .exec=.exec code,
+ .handlers let=.handler let,
+ .prefix=.prefixes, .change prefix=.prefix, .cp=.prefix,
+ .add prefix=.add prefixes,
+ .ignore prefix=.ignore prefixes,
+ .restore prefix=.restore prefixes,
+ .hp=.holder prefix,
+ .family=.families, .change family=.family, .cf=.family,
+ .add family=.add families,
+ .ignore family=.ignore families,
+ .restore family=.restore families,
+ .root=.roots, .change root=.roots, .cd=.roots,
+ .path=.roots, .paths=.roots, .change path=.roots,
+ .add root=.add roots,
+ .add path=.add roots, .add paths=.add roots,
+ .ignore root=.ignore roots,
+ .ignore path=.ignore roots, .ignore paths=.ignore roots,
+ .restore root=.restore roots,
+ .restore path=.restore roots, .restore paths=.restore roots,
+ .ignore key=.ignore keys, .restore key=.restore keys,
+ .define key=.define keys, .new key=.new keys,
+ .initialize after define=.initialize keys after define,
+ .save initial values=.save initial values of keys,
+ .set=.set keys, .setkeys=.set keys,
+ .set*=.set keys*, .setkeys*=.set keys*,
+ .setkeys save unknown=.set keys*,
+ .setrmkeys=.set rmkeys,
+ .set remaining keys=.set rmkeys,
+ .setrmkeys*=.set rmkeys*,
+ .set remaining keys*=.set rmkeys*,
+ .presetkeys=.preset keys, .initial values=.preset keys,
+ .postsetkeys=.postset keys,
+ .try set=.try set keys,
+ .sa set=.sa set keys, .search also set keys=.sa set keys,
+ .use defaults=.set with defaults,
+ .echoice=.choice expanded,
+ .style=.append style,
+ .styles=.append style,
+ .estyle=.append style expanded,
+ .style expand once=.append style expand once,
+ .style expand twice=.append style expand twice,
+ .link=.append link,
+ .links=.append link,
+ .elink=.append link expanded,
+ .link expand once=.append link expand once,
+ .link expand twice=.append link expand twice,
+ .listbreak=.list break, .break list=.list break,
+ .new handler=.new handlers, .define handler=.define handlers,
+ .kill handler=.kill handlers,
+ .initial value=.initial values,
+ .default value=.default values,.default=.default values,
+ .defaults=.default values,
+ .assign value=.assign values,
+ .inherit value=.inherit values,
+ .inherit default=.inherit defaults,
+ .inherit code=.inherit callback,
+ .prepend value=.prepend values,
+ .append value=.append values,
+ .disabled option message type=.disabled key message type,
+ .message type when disabled key is invoked=.disabled key message type,
+ .message type when disabled option is invoked=.disabled key message type,
+ .unknown option handler=.unknown key handler,
+ },
+}
+
+% \skvpatchcmd[<prefix>]{<cmd>}{<search>}{<replace>}{<succeed>}{<fail>}
+\skvrobustdef*\skvpatchcmd{%
+ \begingroup
+ \@makeother{\#}\endlinechar\m@ne
+ \skv@testopt\skv@patchcmd{########1}%
+}
+\skvrobustdef*\skv@patchcmd[#1]#2#3#4{%
+ \ifskv@tracingkeys
+ \typeout{^^J** Debugging patches: command '\string#2'}%
+ \fi
+ \skv@p@tchcmd{#1}{#2}{#3}{#4}%
+}
+\skvrobustdef*\skv@p@tchcmd#1#2#3#4{%
+ \skvifpatchable{#2}{#3}{#4}{%
+ \skv@patchdebug{++}{Command is patchable}%
+ \skv@patchdebug{==}{Patching has begun}%
+ \begingroup
+ \edef\skv@tempa##1##2{%
+ \def##1####1\detokenize{macro:}####2->####3\skvrelax{%
+ #1\def\string#2####2{##2####3\skvrelax}%
+ }%
+ \def##2####1\detokenize{#3}####2\skvrelax{####1\detokenize{#4}####2}%
+ \edef##1{##1\meaning#2\skvrelax}%
+ }%
+ \skv@tempa\skv@tempa\skv@tempb
+ \skv@scantoksd\endgroup\skv@tempa
+ \skv@patchdebug{==}{Patching completed successfully}%
+ \@firstoftwo
+ }{%
+ \skv@patchdebug{--}{Patching couldn't be completed}%
+ \@secondoftwo
+ }%
+}
+\skvrobustdef*\skv@patchdebug#1#2{%
+ \ifskv@tracingkeys\typeout{[debug] #1 #2}\fi
+}
+\skvrobustdef*\skvifpatchable#1#2#3{%
+ \endgroup
+ \skvifundef{#1}{%
+ \skv@patchdebug{--}{Command not defined}%
+ \@secondoftwo
+ }{%
+ \skv@patchdebug{++}{Command is defined}%
+ \skvifmacro{#1}{%
+ \skv@patchdebug{++}{Command is a macro}%
+ \skvifscannable{#1}{%
+ \skv@patchdebug{++}{Macro can be retokenized safely after patching}%
+ \skvifpattern{#2}{#1}{%
+ \skv@patchdebug{++}{Requested search pattern found}%
+ \@firstoftwo
+ }{%
+ \skv@patchdebug{--}{Requested search pattern not found}%
+ \@secondoftwo
+ }%
+ }{%
+ \skv@patchdebug{--}{Nested commands or parameters}%
+ \@secondoftwo
+ }%
+ }{%
+ \skv@patchdebug{--}{Macro can't be retokenized safely after patching}%
+ \@secondoftwo
+ }%
+ }%
+}
+\skvrobustdef*\skveveryscan{%
+ \everyeof{\noexpand}%
+ \endlinechar\m@ne
+ \makeatletter
+ \catcode`\ =10
+ \catcode`\\=0
+ \catcode`\{\@ne
+ \catcode`\}\tw@
+}
+\skvrobustdef*\skv@scantoksd#1#2{%
+ \skvexpandsecond{#1\skveveryscan\scantokens}{%
+ {#2}\everyeof{\the\everyeof}%
+ \noexpand\endlinechar\the\endlinechar\relax
+ \catcode`\noexpand\@=\the\catcode`\@\relax
+ \catcode`\noexpand\ =\the\catcode`\ \relax
+ \catcode`\noexpand\\=\the\catcode`\\\relax
+ \catcode`\noexpand\{=\the\catcode`\{\relax
+ \catcode`\noexpand\}=\the\catcode`\}\relax
+ }%
+}
+\skvrobustdef*\skvifscannable#1{%
+ % Fails if the content of #1 is already detokenized.
+ \begingroup
+ \edef\skv@tempa##1{%
+ \def##1####1\detokenize{macro}:####2->####3\skvrelax{%
+ ####1\def\string\skv@tempa####2{####3}%
+ }%
+ \edef##1{##1\meaning#1\skvrelax}%
+ }%
+ \skv@tempa\skv@tempa
+ \makeatletter\everyeof{\noexpand}\endlinechar\m@ne
+ \scantokens\expandafter{\skv@tempa}\relax
+ \expandafter\endgroup
+ \ifx#1\skv@tempa
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+\skvrobustdef\skvifpattern#1#2{%
+ \begingroup
+ \edef\skv@tempa##1{\def##1####1\detokenize{#1}####2\skvrelax}%
+ \skv@tempa\skv@tempa{%
+ \expandafter\endgroup\ifx\\##2\\%
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ \edef\skv@tempb##1{##1\detokenize{#1}\skvrelax}%
+ \skv@tempb{\expandafter\skv@tempa\meaning#2}%
+}
+\skvrobustdef*\skvifmacro#1{%
+ \begingroup
+ \edef\skv@tempa##1{\def##1####1\detokenize{macro}:####2\skvrelax}%
+ \skv@tempa\skv@tempa{%
+ \expandafter\endgroup\ifx\@nnil##2\@nnil
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi
+ }%
+ \edef\skv@tempb##1{##1\detokenize{macro}:\skvrelax}%
+ \skv@tempb{\expandafter\skv@tempa\meaning#1}%
+}
+%\skvxzapspaces{\detokenize{\begin{\document}}}\skv@begindoc@string
+\edef\skv@begindoc@string{\string\begin\string{\string\document\string}}
+
+\skv@core@restorecodes
+\endinput
+
+%% End of file 'skeyval-core.tex'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
new file mode 100644
index 00000000000..b02ed4f91ed
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
@@ -0,0 +1,2583 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-for', version 1.1, October 2012. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\csname skeyval-for-loaded\endcsname
+\expandafter\let\csname skeyval-for-loaded\endcsname\endinput
+
+\edef\skv@for@restorecatcodes{%
+ \catcode`\noexpand\@\the\catcode`\@\relax
+ \let\noexpand\skv@for@restorecatcodes\relax
+}
+\catcode`\@=11\relax
+
+\ifx\ProvidesFile\@undefined
+ \message{File 'skeyval-for.tex' 2012/10/15 v1.1
+ Loops for skeyval package (AM)}
+\else
+ \ProvidesFile{skeyval-for.tex}
+ [2012/10/15 v1.1 Loops for skeyval package (AM)]
+ \@addtofilelist{skeyval-for.tex}
+\fi
+
+\skvrobustdef*\skv@nostackerr{\skv@err{You've called empty stack}\@ehd}
+% \skvsavestate<base-fn>{<fn-list>}<counter>
+\skvrobustdef*\skvsavestate#1#2#3{%
+ \skvgadvanceno#3\@ne
+ \begingroup
+ \let\s\string\escapechar\m@ne
+ \def\skv@prova##1{\s##1@skv@\romannumeral#3}%
+ \def\do##1{\let\noexpand##1\skvnoexpandcs{\skv@prova{##1}}}%
+ \skvifcsdef{\s#1@skv@stack}{}{\skvcsdef{\s#1@skv@stack}{\nostack}}%
+ \skvcsxdef{\s#1@skv@stack}{#2{\skvexpandcsonce{\s#1@skv@stack}}}%
+ \def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
+ \edef\reserved@a{\endgroup#2}\reserved@a
+}
+% \skvrestorestate<base-fn><counter>
+\skvrobustdef*\skvrestorestate#1#2{%
+ \begingroup
+ \let\nostack\skv@nostackerr
+ \edef\skv@elt{\skvnoexpandcs{\skvremovescape#1@skv@stack}}%
+ \expandafter\ifx\skv@elt\relax
+ \skv@err{Stack of '\noexpand#1' is undefined}\@ehd
+ \fi
+ \edef\skv@prova{\skvexpandtwice\skv@elt}%
+ \edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
+ \expandafter\skv@provb\skv@prova
+ \skvgadvanceno#2\m@ne
+}
+
+\skvnewregisters\bool{\ifskvbreakloop\ifforeachlastitem
+ \ifskvprocessempty\ifskv@tempst\ifskv@foreach@swa
+ \ifskv@foreach@swb\ifskv@foreach@parenth
+}
+\skvnewnumbers[skv@]{csvdepth,dolistcnt}
+
+\skvrobustdef*\skv@usetempst#1#2{%
+ \edef#2{\skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#1}}%
+}
+%
+% \skvdolist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvdolist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+%
+% 1. This can be nested to any depth, with different parsers on each
+% level.
+% 2. This will not process an empty list; see \skvecommaloop.
+% 3. For comma lists, \skvcommaloop and \skvcommaparse are faster.
+% See later.
+% 4. For processing kv lists, use \skvkvparse.
+%
+\skvrobustdef*\skvdolist{\skv@testst\skv@dolist}
+\skvrobustdef*\skv@dolist#1#2#3#4{%
+ \skvgadvanceno\skv@dolistcnt\@ne
+ \skv@usetempst{#2}#3%
+ \def\skv@dolist@a{skv@dolist@\skvrom\skv@dolistcnt}%
+ \skvcsdef{\skv@dolist@a}##1##2##3#1{%
+ \skvifstrcmp{##3}{\skv@dolist@nil}{%
+ % To allow nesting of loop:
+ \skvbreakloopfalse
+ }{%
+ \edef##1{\unexpanded{##3}}%
+ ##2\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \skvcsdef{\skv@dolist@a}####1\skv@dolist@nil#1{\endgroup}%
+ \fi
+ \@nameuse{\skv@dolist@a}##1{##2}%
+ }%
+ }%
+ \skvifempty#3{}{%
+ \edef\reserved@a{\unexpanded{\@nameuse{\skv@dolist@a}#3{#4}}}%
+ \expandafter\reserved@a#3#1\skv@dolist@nil#1%
+ }%
+ \skvgadvanceno\skv@dolistcnt\m@ne
+}
+
+% First normalize the list before parsing.
+%
+% \skvparselist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvparselist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+%
+\skvrobustdef*\skvparselist{\skv@testst\skv@parselist}
+\skvrobustdef*\skv@parselist#1#2#3{%
+ \skv@usetempst{#2}#3%
+ \skvcsvnormalize[#1]#3%
+ \skv@tempsttrue
+ \skv@dolist{#1}#3#3%
+}
+
+\skvifdefinable\listbreaker{\let\listbreaker\relax}
+\skvifdefinable\listpauser{\let\listpauser\relax}
+\skvnewdef*\skv@listbreakertoks{\listbreaker}
+\skvnewdef*\skv@listpausertoks{\listpauser}
+
+\skvnewlet\skvprocessempty\skvprocessemptytrue
+\skvletmanytocmd{\skvbreakloop\interruptloop\skvbreakforeach
+ \interruptforeach}\skvbreaklooptrue
+
+% Reversing tokens:
+\skvnewdef*\skvreverse#1{\skv@reverse#1\skv@reverse@stop}
+\skvnewdef*\skv@reverse#1#2\skv@reverse@stop{%
+ \if\relax\detokenize{#2}\relax\skv@reverse@stop\fi
+ \skv@reverse#2\skv@reverse@stop\skvreversedo{#1}%
+}
+\skvnewdef*\skv@reverse@stop#1\skv@reverse@stop{\fi}
+\let\skvreversedo\@iden
+
+\skvrobustdef*\skv@removetrailingparser#1#2{%
+ \skvxifin{\detokenize{#1}\relax}{\skvoxdetok#2\relax}{%
+ \def\skv@prova##1#1\skv@trim@nil{\unexpanded{##1}}%
+ \edef#2{\expandafter\skv@prova#2\skv@trim@nil}%
+ }{}%
+}
+
+% \skvrecurse<body>\while<\if...>\fi
+%
+% On entry, the condition is checked before the body is executed.
+%
+% \@tempcnta\z@
+% \skvrecurse{
+% \advance\@tempcnta\@ne
+% \@tempcntb\z@
+% \skvrecurse
+% \advance\@tempcntb\@ne
+% \typeout{Doing \the\@tempcnta,\the\@tempcntb}
+% \while
+% \ifnum\@tempcntb<3
+% \fi
+% }
+% \while
+% \ifnum\@tempcnta<4
+% \fi
+%
+\skvrobustdef\skvrecurse#1\while#2\fi{%
+ \@expandtwoargs\skv@dobody{\skvtrimspace{#2}}{\skvtrimspace{#1}}%
+}
+\skvrobustdef\skv@dobody#1#2{%
+ #1\relax\expandafter\@iden\else\expandafter\@gobble\fi
+ {#2\relax\skv@dobody{#1}{#2}}%
+}
+
+% A version of LaTeX's \@tfor that can parse undoubled parameter
+% characters.
+%
+% \skvtfor<holder.cmd>{<list>}\do{<callback>}
+% \skvtfor*<holder.cmd>{<listcmd>}\do{<callback>}
+%
+% Example:
+%
+% \skvnewregister\count\nr
+% \skvtfor\x:=a \ifx {\def\x#1{#1}} \fi\do{%
+% \nr\z@
+% \skvtfor\y:=12345\do{%
+% \typeout{Doing: \detokenize\expandafter{\x}--\y}%
+% \advance\nr\@ne
+% \ifnum\nr>\tw@\skvbreakloop\fi
+% }
+% }
+%
+\skvnewdef*\skv@tfor@nil{\skv@tfor@nil}
+\skvrobustdef*\skvtfor{\skv@testst\skv@tfor}
+\skvrobustdef*\skv@tfor#1:={\skv@tf@r#1 }
+\skvrobustdef\skv@tf@r#1#2\do#3{%
+ \edef#1{\skvtrimspace{#2}}%
+ \edef#1{\skvifbool{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
+ \skvifempty#1{}{%
+ \skvbreakloopfalse
+ \expandafter\skv@tforloop#1\skv@tfor@nil\skv@tfor#1{#3}%
+ }%
+}
+\skvrobustdef\skv@tforloop#1#2\skv@tfor#3#4{%
+ \edef#3{\unexpanded{#1}}%
+ \skvifx#3\skv@tfor@nil{%
+ \skvbreakloopfalse
+ }{%
+ #4\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \def\skv@tforloop##1\skv@tfor@nil\skv@tfor##2##3{%
+ \endgroup
+ \edef\skvremainder{\unexpanded{##1}}%
+ }%
+ \fi
+ \skv@tforloop#2\skv@tfor#3{#4}%
+ }%
+}
+
+% Non-expandable comma loops
+%
+% 1. These follow from \skvdolist and \skvparselist, but they are
+% specialized for comma lists and they are faster.
+% 2. They can be nested.
+% 3. \skvecommaloop needs \skv@c@mmaloop.
+%
+% \skvcommaloop{<list>}<holder-cmd>{<callback>}
+% \skvcommaloop*{<listcmd>}<holder-cmd>{<callback>}
+%
+\skvrobustdef*\skvcommaloop{\skv@testst\skv@commaloop}
+\skvrobustdef\skv@commaloop#1#2#3{%
+ \skv@usetempst{#1}#2%
+ % Don't put \skvcsvnormalize#2 here. Use \skvcommaparse instead.
+ % Some callers of \skvcommaloop already have their lists normalized.
+ \skvifx#2\@empty{}{%
+ \skvexpandnext{\skv@c@mmaloop#2{#3}}#2,\skv@commaloop@nil,%
+ }%
+}
+\skvrobustdef\skv@c@mmaloop#1#2#3,{%
+ \skvifstrcmp{#3}{\skv@commaloop@nil}{%
+ \skvbreakloopfalse
+ }{%
+ \edef#1{\unexpanded{#3}}%
+ #2\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \long\def\skv@c@mmaloop##1\skv@commaloop@nil,{\endgroup}%
+ \fi
+ \skv@c@mmaloop#1{#2}%
+ }%
+}
+%
+% \skvecommaloop{<list>}<cmd>{<callback>}
+% \skvecommaloop*{<listcmd>}<cmd>{<callback>}
+%
+% \skvecommaloop is as \skvcommaloop but will execute <callback>
+% once when <list> is empty. This is needed for processing empty
+% families.
+%
+\skvrobustdef\skvecommaloop{\skv@testst\skv@ecommaloop}
+\skvrobustdef\skv@ecommaloop#1#2#3{%
+ \edef#2{\unexpanded{\skv@c@mmaloop#2{#3}}}%
+ \ifskv@tempst\expandafter\expandafter\fi#2#1,\skv@commaloop@nil,%
+}
+%
+% \skvcommaparse{<list>}<cmd>{<callback>}
+% \skvcommaparse*{<listcmd>}<cmd>{<callback>}
+%
+% \skvcommaparse is as \skvcommaloop but will first normalize <list>
+% using \skvcsvnormalize.
+%
+\skvrobustdef*\skvcommaparse{\skv@testst\skv@commaparse}
+\skvrobustdef\skv@commaparse#1#2#3{%
+ \skv@usetempst{#1}#2%
+ \skvcsvnormalize#2%
+ \skvcommaloop*#2#2{#3}%
+}
+%
+% \skvkvparse{<list>}<cmd>{<callback>}
+% \skvkvparse*{<listcmd>}<cmd>{<callback>}
+%
+% \skvkvparse is as \skvcommaloop but will first normalize <list> using
+% \skvkvnormalize.
+%
+\skvrobustdef*\skvkvparse{\skv@testst\skv@kvparse}
+\skvnewlet\skvparsekeyvals\skvkvparse
+\skvrobustdef\skv@kvparse#1#2#3{%
+ \skv@usetempst{#1}#2%
+ \skvkvnormalize#2%
+ \skvcommaloop*#2#2{#3}%
+}
+%
+
+% \skv@foreach@normalize[<parser>]<listcmd>
+\skvrobustdef*\skv@foreach@normalize{\skv@testopt\skv@foreach@norm@lize,}
+\skvrobustdef*\skv@foreach@norm@lize[#1]#2{%
+ \skvxifntype{\detokenize{#1}}\skvcsvnormalize\skvmacnormalize[#1]#2%
+}
+
+% \newforeach[<options>] <holders> {<list>} {<callback>}
+% \newforeach*[<options>] <holders> {<listcmd>} {<callback>}
+% \newforeach[<options>] <holders> in {<list>} do {<callback>}
+% \newforeach*[<options>] <holders> in {<listcmd>} do {<callback>}
+% \newforeach[<options>] <holders> in {<list>} <callback> ;
+% \newforeach*[<options>] <holders> in {<listcmd>} <callback> ;
+%
+% 1. <callback> is the code that will be executed for each element
+% of the list. It will refer to the holder macros <holders>.
+%
+% 3. Elements of the form (a,b) and [a,b] are grabbed together.
+%
+% 4. Use \interruptforeach to break out of the loop prematurely.
+%
+% 5. \newforeach can be nested.
+
+% \skv@foreach@sisterdepth must be different from \foreachdepth,
+% to avoid confusing two different stacks.
+\skvnewnumbers{foreachdepth,skv@foreach@sisterdepth,skv@foreach@nra,%
+ skv@warnsubparser}
+\skvnewdef*\skv@foreach@onlyinitially{}
+\skvrobustdef*\skv@foreach@assignonce#1{%
+ \edef\skv@foreach@onlyinitially{%
+ \skvexpandonce\skv@foreach@onlyinitially
+ \unexpanded{#1}%
+ }%
+}
+% \skv@foreach@addtocallback{<pre.or.post>}{<code.to.add>}
+\skvrobustdef*\skv@foreach@addtocallback#1#2{%
+ \skvcsedef{skv@foreach@#1callback}{%
+ \skvifcsundef{skv@foreach@#1callback}{}{%
+ \skvexpandcsonce{skv@foreach@#1callback}%
+ }%
+ % No \unexpanded for #2 here, since #2 is to be expanded:
+ #2%
+ }%
+}
+
+\skvnewlet\skv@foreach@codemark\relax
+\skvrobustdef*\skv@foreach@addtohook#1#2#3{%
+ \begingroup
+ \skvifdef#2{}{\def#2{}}%
+ \edef\x{\detokenize{\skv@foreach@codemark#3\skv@foreach@codemark}}%
+ \skvxifin\x{\skvoxdetok#2}{}{%
+ \edef#2{%
+ \skvifstrcmp{#1}{pre}{%
+ \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
+ \skvexpandonce{#2}%
+ }{%
+ \skvexpandonce{#2}%
+ \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
+ }%
+ }%
+ }%
+ \skvaftergroupdef#2\endgroup
+}
+
+% \prependtobeginforeach[<depths>]{<code>}
+\skvrobustdef*\prependtobeginforeach{%
+ \skv@testopt{\skv@atbeginforeach{pre}}{}%
+}
+% \appendtobeginforeach[<depths>]{<code>}
+\skvrobustdef*\appendtobeginforeach{%
+ \skv@testopt{\skv@atbeginforeach{app}}{}%
+}
+\skvnewlet\atbeginforeach\appendtobeginforeach
+\skvrobustdef*\skv@atbeginforeach#1[#2]#3{%
+ \skvifblank{#2}{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atbeginhook@\skvrom\@ne}{#3}%
+ }{%
+ \skvcommaloop{#2}\skv@tempa{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atbeginhook@\skvrom\number\skv@tempa}{#3}%
+ }%
+ }%
+}
+% \prependtoendforeach[<depths>]{<code>}
+\skvrobustdef*\prependtoendforeach{%
+ \skv@testopt{\skv@atendforeach{pre}}{}%
+}
+% \appendtoendforeach[<depths>]{<code>}
+\skvrobustdef*\appendtoendforeach{%
+ \skv@testopt{\skv@atendforeach{app}}{}%
+}
+\skvnewlet\atendforeach\appendtoendforeach
+\skvrobustdef*\skv@atendforeach#1[#2]#3{%
+ \skvifblank{#2}{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atendhook@\skvrom\@ne}{#3}%
+ }{%
+ \skvcommaloop{#2}\skv@tempa{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atendhook@\skvrom\number\skv@tempa}{#3}%
+ }%
+ }%
+}
+% \atbeginforeachondepth{<depths>}{<code>}
+\skvrobustdef*\atbeginforeachondepth#1#2{%
+ \appendtobeginforeach[#1]{#2}%
+}
+% \atendforeachondepth{<depths>}{<code>}
+\skvrobustdef*\atendforeachondepth#1#2{%
+ \appendtoendforeach[#1]{#2}%
+}
+
+% \skv@foreach@fi must use \detokenize. Don't change to \string!
+\skvnewedef*\skv@foreach@fi{\detokenize{\fi}}
+\skvnewedef*\skv@foreach@if{\string\if}
+
+% \skv@foreach@ifacceptkv and \skv@foreach@maketester must come
+% before the initialization of keys:
+\skvrobustdef*\skv@foreach@ifacceptkv#1#2{%
+ \def\next{}%
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifnum0>\numexpr0\ifx\skv@prova\@empty-1\else
+ \ifx\skv@prova\@nnil-1\else+0\fi\fi\relax\relax
+ \skv@err{Invalid syntax '\detokenize{#1}'}\@ehd
+ \else
+ \edef\next{\unexpanded{#2}}%
+ \fi
+ \fi
+ \next
+}
+\skvrobustdef*\skv@foreach@ifholderisonecmd#1#2#3{%
+ \skvifntype{#2}{%
+ \skvifescaped{#2}{%
+ #3%
+ }{%
+ \skv@err{Value of key '#1' must
+ \MessageBreak be escaped: the holder macro
+ \MessageBreak to be evaluated}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key '#1' must
+ \MessageBreak be only one token: the holder
+ \MessageBreak macro to be evaluated}\@ehd
+ }%
+}
+% \skv@foreach@maketester{<cond>}<cond.tester.cmd>{<flag>}
+%
+% 1. Only balanced conditionals beginning with \if...\fi are allowed.
+% Restricting the type of allowed conditionals is necessary for
+% auto syntax checking.
+% 2. <flag> is either 0 or 1, signifying whether or not the condition
+% should be entered in postcallback.
+%
+% Examples: \ifnum\x>10\fi, \ifx\x\cmd\fi.
+%
+\skvrobustdef*\skv@foreach@maketester#1#2#3{%
+ % Make '#1' innocent in a macro, in case it contains parameter
+ % characters. \skv@prova will appear only in the error message.
+ \begingroup
+ \edef\skv@prova{\detokenize{#1}}%
+ \skvifblank{#1}{%
+ \skv@err{A blank conditional given in \string\newforeach}\@ehd
+ }{%
+ \skvxifin{\skv@foreach@fi\relax}{\detokenize{#1}\relax}{%
+ \skvxifin{\relax\skv@foreach@if}{\relax\detokenize{#1}}{%
+ \edef#2{\noexpand\skvifcondition\unexpanded{#1}}%
+ \ifnum#3=\@ne
+ \skv@foreach@addtocallback{post}{%
+ \unexpanded{\skvifcondition#1}{\noexpand\skvbreakloop}{\relax}%
+ }%
+ \fi
+ }{%
+ \skv@err{Illegal conditional '\skv@prova'}
+ {Invalid, possibly unbalanced, conditional '\skv@prova'}%
+ }%
+ }{%
+ \skv@err{Illegal conditional '\skv@prova'}\@ehd
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit#2%
+ \ifnum#3=\@ne
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+\begingroup
+\catcode`P=12 \lccode`P=112
+\catcode`T=12 \lccode`T=116
+\lowercase{\endgroup
+ \def\skv@foreach@strippoint#1#2{%
+ \def\reserved@a##1#1\relax{\def#2{##1}}%
+ \def\do##1.##2PT#1{%
+ \ifx\do##1\else##1%
+ \if\skv@foreach@keephighdecimals
+ \ifdim.##2pt>.5pt\relax##2\fi
+ \else
+ \if\skv@foreach@keepdecimals
+ \ifnum##2>\skvz@.##2\fi
+ \fi
+ \fi
+ \unexpanded{#1}%
+ \expandafter\do
+ \fi
+ }%
+ \edef#2{\expandafter\do#2#1\do.PT#1}%
+ \expandafter\reserved@a#2\relax
+ }
+}
+
+\quickkeys.define{skvforeach}{%
+ .exec/
+ \def\skv@foreach@parser{,}
+ \def\skv@foreach@subparser{/}
+ ;
+ parser/{,}/
+ \ifskvindef\else
+ \edef\skv@foreach@parser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@parser
+ \skvxifntype{\detokenize{#1}}{%
+ \begingroup
+ % It is assumed that every n-type parser and subparser
+ % must have catcode 12:
+ \skvexpandnext{\catcode`}\skv@foreach@parser=12\relax
+ \skv@rescan\skv@foreach@parser
+ \skvaftergroupdef\skv@foreach@parser\endgroup
+ }{}
+ \fi
+ ;
+ subparser/{/}/
+ \ifskvindef\else
+ \edef\skv@foreach@subparser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@subparser
+ \skvxifntype{\detokenize{#1}}{
+ \begingroup
+ \skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
+ \skv@rescan\skv@foreach@subparser
+ \skvaftergroupdef\skv@foreach@subparser\endgroup
+ }{}
+ \fi
+ ;
+ terminator,callback terminator/{;}/
+ \edef\skv@foreach@terminator{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@foreach@terminator
+ ;
+ list is a macro,macro list/true/
+ \edef\skv@foreach@listismacro{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % process up to = <nr>
+ % Maximum number of items to process:
+ process up to,process up to number/\@nil/
+ \ifskvindef\else
+ \def\skv@foreach@processupto{#1}%
+ \ifx\skv@foreach@processupto\@nnil\else
+ \skv@ensureinteger{process up to}{#1}%
+ \fi
+ \fi
+ ;
+ process empty list/true/
+ \edef\skv@foreach@processempty{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % Eg, exit when=\ifnum\x=20\fi
+ .exec/\let\skv@foreach@exittester\@secondoftwo;
+ loop stopper,exit when/\if01\fi/
+ \ifskvindef\else
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \expandafter\skv@foreach@maketester\expandafter
+ {\skv@tempa}\skv@foreach@exittester\@ne
+ \fi
+ ;
+ % Eg, 'evaluate = \x as \z using \numexpr\x*2'. 'as' and 'using', and the
+ % tokens after them, can be missing, but the formula must be complete.
+ evaluate/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parseevaluate{#1}%
+ }%
+ ;
+ % The evaluator \numexpr will invariably be used internally for this key.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ evaluate num,evaluate number/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{evaluate number}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using\numexpr#1}%
+ }%
+ }%
+ ;
+ % The evaluator \dimexpr will invariably be used internally for this key.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ evaluate dim,evaluate dimension/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{evaluate dimension}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using\dimexpr#1}%
+ }%
+ }%
+ ;
+ % Eg, 'expand=\x'.
+ % Fully expand holder macro. This is equivalent to, eg, edef\x{\x}.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ expand,expanded/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{expand}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using#1}%
+ }%
+ }%
+ ;
+ % Eg, 'pgf parse = \x as \xe using \x*3'. 'as' and 'using', and the
+ % tokens after them, can be present or missing.
+ % \pgfmathparse is always used for this key.
+ pgf evaluate,pgf parse,pgfmath parse/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parsepgfmathparse{#1}%
+ }%
+ ;
+ % count in = \y all \x satisfying <condition> initially <value>
+ % Eg,
+ % count in = \p all \x satisfying \ifnum\x>4\fi, or
+ % count in = \p all \x satisfying \skvifnum\x>4
+ % The counting is not additive, meaning that the counter is initialized
+ % to zero on each depth.
+ count in,count/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parsecountin{#1}%
+ }%
+ ;
+ % Eg, 'remember=\x as \y initially A':
+ remember/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parseremember{#1}%
+ }%
+ ;
+ % Eg, 'recall=\x initially A'.
+ % 'recall' is as 'remember', but will save the value of the holder macro
+ % in \<foreachlast><holder>. 'as' is invalid/illegal here, since a
+ % retainer macro is built internally:
+ retain,recall,call up/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parserecall{#1}%
+ }%
+ ;
+ item counter,counter/\@nil/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@nnil
+ \skv@err{Invalid empty value for key 'item counter'}\@ehd
+ \else
+ \skvifescaped{#1}{%
+ \let\skv@foreach@itemcounter\skv@prova
+ }{%
+ \skv@err{Non-escaped value '\detokenize{#1}'
+ \MessageBreak for key 'item counter'}\@ehd
+ }%
+ \fi
+ \fi
+ ;
+ list breaker/\listbreaker/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list breaker'}\@ehd
+ \else
+ \let\skv@listbreakertoks\skv@prova
+ \fi
+ \fi
+ ;
+ list pauser/\listpauser/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list pauser'}\@ehd
+ \else
+ \let\skv@listpausertoks\skv@prova
+ \fi
+ \fi
+ ;
+ % Remember outside the loop the holder values. Of course, this
+ % means remembering only the latest values.
+ recover holder values,recover holder values after loop/true/
+ \edef\skv@foreach@recoverholders{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % This default value of 'link' is required by \skv@foreach@filllist:
+ .exec/\def\skv@foreach@link{\@nil};
+ link/\@nil/
+ \ifskvindef\else
+ \edef\skv@foreach@link{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@foreach@link
+ \ifnum0>\numexpr0\ifx\skv@foreach@link\@empty-1\else
+ \ifx\skv@foreach@link\@nnil-1\else+0\fi\fi\relax\relax
+ \skv@err{The key 'link' doesn't accept empty/blank values}\@ehd
+ \fi
+ \fi
+ ;
+ grow/\@nil/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@nnil
+ \skv@err{Value required for key 'grow'}\@ehd
+ \else
+ \skvcsedef{skv@foreach@grow#1}{00}
+ \edef\skv@prova{\skvifstrcmp{#1}{left}{right}{left}}%
+ \skvcsedef{skv@foreach@grow\skv@prova}{01}%
+ \fi
+ \fi
+ /left,right
+ ;
+ .exec/
+ \def\skv@foreach@growleft{01}
+ \def\skv@foreach@growright{01}
+ ;
+ grow left/true/
+ \ifskvindef\else
+ \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}10}
+ \fi
+ /true,false
+ ;
+ grow right/true/
+ \ifskvindef\else
+ \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}10}
+ \fi
+ /true,false
+ ;
+ % Keep the decimals in rounded numbers or dimensions when list is
+ % auto-completed. The value value of this key is 'true'.
+ keep decimals/true/
+ \edef\skv@foreach@keepdecimals{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ keep high decimals,keep only high decimals/true/
+ \edef\skv@foreach@keephighdecimals{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ % This key means that, eg, for \x/\y, do \let\y=\x if \y has no
+ % user value, ie, if the user gives as an item 'a' instead of
+ % 'a/b' or 'a/a'.
+ inherit/true/
+ \edef\skv@foreach@inherit{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ expand before fill/true/
+ \edef\skv@foreach@expandbeforefill{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+}
+
+% The following keys don't need a default value:
+%
+% link,evaluate,*evaluate,evaluate num,*evaluate num,
+% evaluate dim,*evaluate dim,expand,*expand,count in,*count in,
+% loop stopper,process up to,grow
+%
+\skvinitializeqkeys{skvforeach}{%
+ parser,
+ subparser,
+ callback terminator,
+ list is a macro=false,
+ process up to,
+ process empty list=false,
+ item counter,
+ list breaker,
+ list pauser,
+ recover holder values=false,
+ grow left=false,
+ grow right=false,
+ keep decimals=true,
+ keep high decimals=false,
+ inherit=false,
+ expand before fill=false,
+}
+
+\skvnewdef*\skv@foreach@kvlist{}
+% \setupforeach{<kvlist>}
+\skvrobustdef*\setupforeach#1{%
+ \skvifblank{#1}{}{%
+ \skvaddtolist\skv@foreach@kvlist{#1}%
+ }%
+}
+\skvrobustdef*\skv@foreach@setkeys#1{%
+ \def\reserved@a{\quickkeys.set{skvforeach}}%
+ \expandafter\reserved@a\expandafter{\skv@foreach@kvlist,#1}%
+}
+
+% evaluate=<holder.macro> as <child.macro> using <formula>
+%
+% 1. Evaluation is done with \edef unless \pgfmathparse is present
+% in <formula>.
+%
+% 2. <formula> must be a valid formula, eg,
+%
+% \pgfmathparse\x*2
+% \pgfmathparse{exp(50)*\x*2+sin(.5*pi)*60}
+% \numexpr\x*2
+% \skvexpandonce\x
+%
+% or simply
+%
+% 'evaluate \x as \x using <empty>'
+%
+% The latter is equivalent to asking for full expansion. See also
+% the keys 'evaluate num', 'evaluate dim', and 'expand'.
+%
+% 3. This allows <formula> to be generic.
+%
+\skvrobustdef*\skv@foreach@parseevaluate#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@foreach@swafalse
+ \def\skv@tempd{}%
+ \def\skv@tempa##1as##2using##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find child macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provc\@empty
+ \skv@err{Value of key 'evaluate' has no formula or
+ \MessageBreak holder macro to be expanded}\@ehd
+ \fi
+ \skv@tempxifin{\pgfmathparse}{##3}{%
+ \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
+ \ifx\@nnil####1\@nnil
+ \skv@foreach@swatrue
+ \else
+ \skv@err{Invalid token \detokenize{####1}
+ \MessageBreak before \string\pgfmathparse}\@ehd
+ \fi
+ }%
+ \skv@tempc##3\skv@nil
+ }{%
+ \skv@tempxifin{\numexpr}{##3}{%
+ \def\skv@tempd{\relax}%
+ }{%
+ \skv@tempxifin{\dimexpr}{##3}{%
+ \def\skv@tempd{\relax}%
+ }{%
+ \def\skv@tempd{}%
+ }%
+ }%
+ }%
+ }%
+ \skv@tempxifin{using}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ % 'as' and 'using' are present: maybe there is a formula.
+ \skv@foreach@swbtrue
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak there is 'using', but no 'as'}\@ehd
+ }%
+ }{%
+ % No formula given. Maybe the key is 'expand' or still 'evaluate'
+ % but without formula.
+ \skv@foreach@swbfalse
+ \skv@tempxifin{as}{#1}{%
+ \def\skv@tempb##1as##2##3\skv@nil{%
+ \ifx\@nnil##1\@nnil
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \ifx\@nnil##2%
+ \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \else
+ \skv@tempa##1as##2using##1\skv@nil
+ \fi
+ \fi
+ }%
+ \skv@tempb#1{\@nnil}\skv@nil
+ }{%
+ % No 'as' or 'using': #1 should be only the holder macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ % Expand the holder macro:
+ \skv@tempa#1as#1using#1\skv@nil
+ }{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \skv@foreach@addtocallback{afterpre}{%
+ \ifskv@foreach@swa
+ % <formula> has the syntax \pgfmathparse{\x}.
+ \skvexpandonce\skv@provc
+ \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
+ \else
+ % <formula> has the syntax \numexpr\x*2 or \dimexpr\x*2.
+ % \ifskv@foreach@swb is true when a formula has been given.
+ \edef\skvexpandonce\skv@provb{%
+ \ifskv@foreach@swb\noexpand\the\fi
+ \skvexpandonce\skv@provc\skv@tempd
+ }%
+ \fi
+ }%
+ \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
+}
+
+% pgfmath parse=<holder.macro> as <child.macro> using <formula>
+%
+% 1. Evaluation is always done with \pgfmathparse.
+%
+% 2. <formula> must be \pgfmathparse-able.
+%
+\skvrobustdef*\skv@foreach@parsepgfmathparse#1{%
+ \begingroup
+ \ifdefined\pgfmathparse\else
+ \skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\@ehd
+ \fi
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@foreach@swafalse
+ \def\skv@tempa##1as##2using##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find child macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provc\@empty
+ \skv@err{Value of key 'pgfmath parse' has no formula or
+ \MessageBreak holder macro to be expanded}\@ehd
+ \fi
+ \skv@tempxifin{\pgfmathparse}{##3}{%
+ \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
+ \ifx\@nnil####1\@nnil
+ \skv@foreach@swatrue
+ \else
+ \skv@err{Invalid token \detokenize{####1}
+ \MessageBreak before \string\pgfmathparse}\@ehd
+ \fi
+ }%
+ \expandafter\skv@tempc\skv@provc\skv@nil
+ }{%
+ \skv@tempxifin{\numexpr}{##3}{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak\noexpand\numexpr not allowed}\@ehd
+ }{%
+ \skv@tempxifin{\dimexpr}{##3}{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak\noexpand\dimexpr not allowed}\@ehd
+ }{%
+ \skv@foreach@swatrue
+ \edef\skv@provc{\noexpand\pgfmathparse{\skvexpandonce\skv@provc}}%
+ }%
+ }%
+ }%
+ }%
+ \skv@tempxifin{using}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ % 'as' and 'using' are present: maybe there is a formula.
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak there is 'using', but no 'as'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{as}{#1}{%
+ \def\skv@tempb##1as##2##3\skv@nil{%
+ \ifx\@nnil##1\@nnil
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \ifx\@nnil##2%
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \else
+ \skv@tempa##1as##2using##1\skv@nil
+ \fi
+ \fi
+ }%
+ \skv@tempb#1{\@nnil}\skv@nil
+ }{%
+ % No 'as' or 'using': #1 should be only the holder macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ % Evaluate the holder macro:
+ \skv@tempa#1as#1using#1\skv@nil
+ }{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \skv@foreach@addtocallback{afterpre}{%
+ \ifskv@foreach@swa
+ \skvexpandonce\skv@provc
+ \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
+ \fi
+ }%
+ \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
+}
+
+% count in = \y all \x satisfying <condition> initially <value>
+%
+% 1. <condition> must be a balanced and valid TeX conditional, like
+%
+% \ifnum\x>2\fi, \ifx\x\@empty\fi
+%
+% 2. The aim is to allow general conditions (not only those involving
+% numerals) to be submitted.
+%
+% 3. PGF's \foreach doesn't have this feature; it has only a general
+% counter, eg,
+%
+% '\foreach \x [count=\xi] in {a,...,e}'.
+%
+% Generic counting is available in \newforeach by default, without
+% user request. The macros \foreachcurrentitem, \foreachitemcount,
+% \foreachnextitem are always available on each nesting level. The
+% boolean \ifforeachlastitem is also always available, to indicate when
+% the last item of the list has been reached:
+%
+% \ifforeachlastitem \typeout{Processing last entry of the list} \fi
+%
+% 4. Counting is done from 1 (zero) unless <value> is given after
+% 'initially'.
+%
+\skvrobustdef*\skv@foreach@parsecountin#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \def\skv@tempa##1\skv@nil{%
+ \skv@tempxifin{initially}{##1}{%
+ \skv@tempb##1\skv@nil
+ }{%
+ \skv@tempb##1initially\skv@nil
+ }%
+ }%
+ \def\skv@tempb##1all##2satisfying##3initially##4\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \edef\skv@provd{\skvtrimspace{##4}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find counter macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ counter macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provd\@empty
+ \expandafter\def\skv@prova{0}%
+ \else
+ \skvifinteger\skv@provd{%
+ \expandafter\let\skv@prova\skv@provd
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ initial \skvoxdetok\skv@provd not an integer}\@ehd
+ }%
+ \fi
+ \skv@foreach@swafalse
+ \ifx\skv@provc\@empty
+ % No tester but there may be a holder macro to test. The holder
+ % macro, on its own, isn't sufficient to conduct a test:
+ \let\skv@foreach@itemcounter\skv@prova
+ \else
+ \ifx\skv@provb\@empty\else
+ % If there isn't a holder macro or quantity to test, then no
+ % test is possible:
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ holder macro \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \skv@foreach@swatrue
+ % \skv@tester is the second argument of \skv@foreach@maketester.
+ % \skv@tester is used in pushing the item counter:
+ \skvexpbracenext\skv@foreach@maketester\skv@provc\skv@tester\skvz@
+ \fi
+ \fi
+ }%
+ \skv@tempxifin{satisfying}{#1}{%
+ \skv@tempxifin{all}{#1}{%
+ % 'all' and 'satisfying' are present:
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'count':
+ \MessageBreak there is 'satisfying', but no 'all'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{all}{#1}{%
+ \skv@tempa#1satisfying\skv@nil
+ }{%
+ % No 'all' or 'satisfying': #1 should be only the counter macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ \skv@tempa#1all satisfying\skv@nil
+ }{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find counter macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \ifskv@foreach@swa
+ \skv@foreach@addtocallback{afterpre}{%
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \def\skvexpandonce\skv@prova{\number\skv@prova}%
+ \noexpand\fi
+ \skvexpandonce\skv@tester{%
+ \noexpand\skvpushnumber\skvexpandonce\skv@prova
+ }{}%
+ }%
+ \fi
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@afterprecallback
+ \else
+ \skvcmdexit\skv@foreach@itemcounter
+ \fi
+ }%
+}
+
+% remember=<holder.macro> as <child.macro> initially <value>
+%
+\skvrobustdef*\skv@foreach@parseremember#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@tempxifin{(}{#1}{%
+ \skv@err{Value of key 'remember': '(' found.
+ \MessageBreak I don't accept this PGF format.
+ \MessageBreak remove the parenthesis '()'}\@ehd
+ }{}%
+ \def\skv@tempa##1as##2initially##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \skv@foreach@swafalse
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'remember' has no holder macro:
+ \MessageBreak i.e., no macro that holds input}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'remember' has no child macro;
+ \MessageBreak i.e., no macro after 'as'}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \skv@foreach@swatrue
+ }{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak Child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ }%
+ \skv@tempxifin{initially}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak There is 'initially', but no 'as'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{as}{#1}{%
+ \skv@tempa#1initially\skv@nil
+ }{%
+ % No 'as' and 'initially':
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \ifx\skv@prova\@empty\else
+ \skv@tempa#1as initially\skv@nil
+ \fi
+ }%
+ }%
+ \ifskv@foreach@swa
+ % Initially:
+ \skv@foreach@addtocallback{pre}{%
+ % Don't remove this \ifnum, otherwise the initial assignment
+ % will be overwritten on subsequent returns:
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \edef\skvexpandonce\skv@provb{%
+ \noexpand\unexpanded{\skvexpandonce\skv@provc}%
+ }%
+ \noexpand\fi
+ }%
+ \skv@foreach@addtocallback{post}{%
+ \let\skvexpandonce\skv@provb\skvexpandonce\skv@prova
+ }%
+ \fi
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@precallback
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+% recall=<holder.macro> initially <value>.
+%
+% This builds a retainer macro of the form \<foreachlast><holder.name>.
+%
+% 'as' is invalid/illegal here, since a retainer macro is built internally.
+%
+\skvrobustdef*\skv@foreach@parserecall#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@tempxifin{(}{#1}{%
+ \skv@err{Value of key 'recall': '(' found.
+ \MessageBreak I don't accept this PGF format.
+ \MessageBreak remove the parenthesis '()'}\@ehd
+ }{}%
+ \skv@foreach@swafalse
+ \def\skv@tempa##1initially##2\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'recall' has no holder macro:
+ \MessageBreak i.e., no macro that holds input}\@ehd
+ \else
+ \expandafter\skvifntype\expandafter{\skv@prova}{%
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
+ \skv@foreach@swatrue
+ % Initially:
+ \skv@foreach@addtocallback{pre}{%
+ % Don't remove this \ifnum, otherwise the initial assignment
+ % will be overwritten on subsequent returns:
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \skvcsedef{foreachlast\skv@elt}{%
+ \noexpand\unexpanded{\skvexpandonce\skv@provb}%
+ }%
+ \noexpand\fi
+ }%
+ \skv@foreach@addtocallback{post}{%
+ \skvcslet{foreachlast\skv@elt}\skvexpandonce\skv@prova
+ }%
+ }{%
+ \skv@err{Value of key 'recall':
+ \MessageBreak \detokenize{#1} is not escaped}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'recall':
+ \MessageBreak \detokenize{#1} is not one token}\@ehd
+ }%
+ \fi
+ }%
+ \skv@tempxifin{as}{#1}{%
+ \skv@err{Value of key 'recall': invalid 'as' found.
+ \MessageBreak This key doesn't expect 'as' since
+ \MessageBreak it automatically builds a retainer macro
+ \MessageBreak of the form \<foreachlast><holder.name>}\@ehd
+ }{%
+ \skv@tempxifin{initially}{#1}{%
+ \skv@tempa#1\skv@nil
+ }{%
+ \ifx\@nnil#1\@nnil\else
+ \skv@tempa#1initially\skv@nil
+ \fi
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@precallback
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+% Eg, \skv@dots@in<value>\skv@nil...\skv@nnil\skv@stop
+\skvnewdef*\skv@dots@in#1...#2#3\skv@stop{%
+ \ifx\skv@nnil#2\in@false\else\in@true\fi
+}
+
+\skvrobustdef*\skv@foreach@latehookerr{%
+ \def\skv@foreach@latehook{%
+ \begingroup
+ \let\s\string
+ \skv@err{A \noexpand\newforeach hook (\s\prependtobeginforeach,
+ \MessageBreak\s\appendtobeginforeach, \s\atbeginforeach,
+ \MessageBreak\s\prependtoendforeach, \s\appendtoendforeach,
+ \MessageBreak or \s\atendforeach) has been illegally
+ \MessageBreak issued within \s\newforeach}
+ {\s\newforeach\space hook command shouldn't be issued
+ within \s\newforeach.}%
+ \endgroup
+ }%
+ \skvletmanytocmd{%
+ \prependtobeginforeach\appendtobeginforeach\atbeginforeach
+ \prependtoendforeach\appendtoendforeach\atendforeach
+ }\skv@foreach@latehook
+}
+
+\skvrobustdef*\skv@foreach@pushstate{%
+ \skvsavestate\skv@foreach@stack{%
+ \do\skv@foreach@parser\do\skv@foreach@subparser
+ \do\skv@foreach@listismacro
+ \do\skv@foreach@processupto\do\skv@foreach@processempty
+ \do\skv@foreach@exittester
+ \do\skv@foreach@grow\do\skv@foreach@growleft
+ \do\skv@foreach@growright
+ \do\skv@foreach@terminator\do\skv@foreach@recoverholders
+ \do\skv@foreach@callback
+ \do\skv@foreach@auxcallback
+ \do\skv@foreach@precallback
+ \do\skv@foreach@afterprecallback
+ \do\skv@foreach@postcallback
+ \do\skv@foreach@onlyinitially
+ \do\foreachlistremainder\do\skv@foreach@mainloop
+ \do\skv@foreach@getnext\do\skv@foreach@getrm
+ \do\skv@foreach@do@a\do\skv@foreach@do@b
+ \do\skv@foreach@holderlist
+ \do\skv@foreach@userlist
+ \do\skv@foreach@inherit
+ \do\skv@foreach@keepdecimals
+ \do\skv@foreach@keephighdecimals
+ \do\skv@foreach@itemcounter
+ \do\skv@foreach@link\do\skv@foreach@expandbeforefill
+ \do\skv@listbreakertoks\do\skv@listpausertoks
+ \do\foreachcurrentitem
+ \do\foreachnextitem
+ \do\foreachitemcount
+ \do\foreachprevitem
+ % The following commands are disabled on entry into the loop.
+ % Hence they need to be stacked:
+ \do\prependtobeginforeach
+ \do\appendtobeginforeach
+ \do\atbeginforeach
+ \do\prependtoendforeach
+ \do\appendtoendforeach
+ \do\atendforeach
+ }\foreachdepth
+}
+\skvrobustdef*\skv@foreach@popstate{%
+ \skvrestorestate\skv@foreach@stack\foreachdepth
+}
+\skvnewdef*\foreachnestdepth{\foreachdepth}
+\skvnewlet\skv@foreach@nil\relax
+\skvnewdef*\skv@foreach@nnil{\skv@foreach@nil}
+\skvrobustdef*\newforeach{\skv@testst\skv@newforeach@beginprescan}
+\skvrobustdef*\skv@newforeach@beginprescan{%
+ \edef\skv@foreach@st{0\ifskv@tempst0\else1\fi}%
+ \begingroup
+ \def\skv@tempa{%
+ \skvexpanded{\endgroup
+ \noexpand\skv@foreach@endprescan{\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ \def\skv@tempb{}%
+ \let\bgroup\relax
+ \skvifnextchar[{%
+ \endgroup
+ \skv@foreach@scanarg
+ }{%
+ \skvifnextchar i{%
+ \endgroup
+ \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ }{%
+ \skvifnextchar\skv@orig@bgroup{%
+ \endgroup
+ \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ }{%
+ \skv@foreach@collectholders
+ }%
+ }%
+ }%
+}
+\skvrobustdef*\skv@foreach@collectholders#1{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb\skvtrimspace{#1}%
+ }%
+ \skvifnextchar[{%
+ \skv@tempa
+ }{%
+ \skvifnextchar i{%
+ \skv@tempa[]%
+ }{%
+ \skvifnextchar\skv@orig@bgroup{%
+ \skv@tempa[]%
+ }{%
+ \skv@foreach@collectholders
+ }%
+ }%
+ }%
+}
+\skvrobustdef*\skv@foreach@endprescan#1[#2]{%
+ \skvifblank{#1}{%
+ \skv@err{\string\newforeach: no holder macros seen}\@ehd
+ }{%
+ \skv@foreach@scanarg[#2]#1%
+ }%
+}
+\skvrobustdef*\skv@foreach@scanarg{\skv@testopt\skv@foreach@a{}}
+\skvrobustdef*\skv@foreach@a[#1]{%
+ \skv@foreach@pushstate
+ \skv@foreach@latehookerr
+ % \foreachitemcount must be a macro, not a counter, because it is stacked:
+ \def\foreachitemcount{0}%
+ % Don't confuse item counters of various depths:
+ \skvundef\skv@foreach@itemcounter
+ \skvundef\skv@foreach@processupto
+ \def\skv@foreach@callback{}%
+ \def\skv@foreach@auxcallback{}%
+ \def\skv@foreach@precallback{}%
+ \def\skv@foreach@afterprecallback{}%
+ \def\skv@foreach@postcallback{}%
+ \def\skv@foreach@onlyinitially{}%
+ % The keys have to be set here, to determine if the list is a macro, etc.
+ % Since \skv@foreach@precallback are initialized in each nest, the
+ % keys have to be reset here.
+ \skv@foreach@setkeys{#1}%
+ \begingroup
+ % Collect item holders. Don't confuse explicit \bgroup for left brace:
+ \skv@cnta\skvz@
+ \def\skv@tempb{}%
+ \let\bgroup\relax
+ \skvifnextchar i\skv@foreach@c{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ }%
+}
+% #1: one holer macro or subparser.
+\skvrobustdef*\skv@foreach@b#1{%
+ \ifnum\skv@cnta=\skvz@
+ \skvifescaped{#1}{}{%
+ \skv@err{Token '\noexpand#1' is not escaped
+ \MessageBreak and can't be a holder macro}\@ehd
+ }%
+ \else
+ \ifnum\skv@cnta=\@ne
+ \skvifescaped{#1}{%
+ \skv@err{Token '\noexpand#1' cannot be a subparser;
+ \MessageBreak it seems to be a holder macro.
+ \MessageBreak I expected the subparser to be the
+ \MessageBreak second token here.}\@ehd
+ }{%
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \let\elt\skvexpandonce
+ \def\skv@elt{\elt\skv@foreach@subparser}%
+ \if\elt\skv@prova\skv@elt\else
+ % Don't stack \skv@warnsubparser:
+ \ifnum\skv@warnsubparser=\skvz@
+ \skvgadvanceno\skv@warnsubparser\@ne
+ \skv@warn{Scanned subparser '\elt\skv@prova' is different from
+ \MessageBreak the default or user-supplied subparser '\skv@elt'.
+ \MessageBreak I have used '\elt\skv@prova', but please submit
+ \MessageBreak '\elt\skv@prova' as the value of the key
+ 'subparser'
+ }%
+ \fi
+ \let\skv@foreach@subparser\skv@prova
+ \fi
+ }%
+ \fi
+ \fi
+ \advance\skv@cnta\@ne
+ \edef\skv@tempb{\skvexpandonce\skv@tempb\skvtrimspace{#1}}%
+ \skvifnextchar i\skv@foreach@c{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ }%
+}
+\skvrobustdef*\skv@foreach@c#1#2{%
+ \skvifstrcmp{#1#2}{in}{%
+ \skv@foreach@d
+ }{%
+ \skv@err{I have seen 'i' but no expected 'in'}\@ehd
+ }%
+}
+\skvrobustdef*\skv@foreach@d{%
+ \ifx\skv@tempb\@empty
+ \skv@err{No item holder macros before 'in'
+ \MessageBreak or before left brace}\@ehd
+ \fi
+ \skvifnextchar\skv@orig@bgroup{%
+ \skv@foreach@e
+ }{%
+ \if\skv@foreach@listismacro
+ \expandafter\skv@foreach@e
+ \else
+ \if\skv@foreach@st
+ \expandafter\expandafter\expandafter\skv@foreach@e
+ \else
+ \def\reserved@a##1{%
+ \skvifmacro{##1}{%
+ \def\skv@ehd{Maybe a star (*) suffix or key 'list is
+ a macro' is missing.}%
+ }{%
+ \let\skv@ehd\@ehd
+ }%
+ \skv@err{I expected a left brace for beginning of list,
+ \MessageBreak since you haven't told me that your
+ \MessageBreak list is a macro. Instead I found '\detokenize{##1}'.
+ \MessageBreak If your list is indeed a macro, you can
+ \MessageBreak either put star (*) after \noexpand\newforeach
+ \MessageBreak or use the key 'list is a macro'%
+ }{%
+ \skv@ehd
+ }%
+ }%
+ \expandafter\expandafter\expandafter\reserved@a
+ \fi
+ \fi
+ }%
+}
+% #1: <list> or <listcmd>
+\skvrobustdef*\skv@foreach@e#1{%
+ \edef\skv@tempc{\unexpanded{#1}}%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@h{%
+ \skvifnextchar d\skv@foreach@f\skv@foreach@g
+ }%
+}
+\skvrobustdef*\skv@foreach@f#1#2{%
+ \skvifstrcmp{#1#2}{do}{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@h\skv@foreach@g
+ }{%
+ \skv@err{I have seen 'd' but no the expected 'do'}\@ehd
+ }%
+}
+% We've exhausted all options for grabbing the callback, so now
+% look for terminator (default ;). If there is no terminator ahead,
+% the use of \skv@prova will trigger 'the use of ... does not match
+% its definition' or 'runaway argument ...'.
+\skvrobustdef*\skv@foreach@g{%
+ \def\skv@prova##1{%
+ \def\skv@prova####1##1{%
+ % Look out for a case like 'parser=<parser>'.
+ % Eg, \newforeach[parser=;]. In this case, the value ';' of
+ % key 'parser' will mistakenly be assumed to be the callback
+ % terminator. It should be enclosed in braces.
+ \skvxifin{\detokenize{parser=}\relax}{\detokenize{####1}\relax}{%
+ \skvxifin{[}{\detokenize{####1}}{%
+ \skv@err{Put '##1' in braces for key 'parser=##1'.
+ \MessageBreak Try [parser={##1}]}
+ {Maybe parser '##1' is the value of a key/option of
+ \noexpand\newforeach and needs to be enclosed in braces.
+ The '##1' I have just encountered doesn't seem to be the
+ one ending a TikZ object. Maybe you need to do [parser={##1}].}%
+ }{%
+ % Otherwise, let's try continue:
+ \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ }%
+ }{%
+ \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ }%
+ }%
+ \skv@prova
+ }%
+ % In case callback terminator is currently active:
+ \skv@rescan\skv@foreach@terminator
+ \expandafter\skv@prova\expandafter{\skv@foreach@terminator}%
+}
+% #1: callback
+\skvrobustdef*\skv@foreach@h#1{%
+ \skvexpanded{\endgroup
+ % The subparser may have changed along the way (see \skv@foreach@b):
+ \skvcmdexit\skv@foreach@subparser
+ \skv@foreach@i{\skvexpandonce\skv@tempb}{\skvexpandonce\skv@tempc}%
+ }{#1}%
+}
+% #1: holder macros
+% #2: List or list command
+% #3: Callback
+\skvrobustdef*\skv@foreach@i#1#2#3{%
+ \if\skv@foreach@st\else
+ \if\skv@foreach@listismacro
+ \def\skv@foreach@st{00}%
+ \else
+ \def\skv@foreach@st{01}%
+ \fi
+ \fi
+ \edef\skv@foreach@userlist{%
+ \if\skv@foreach@st
+ \expandafter\skvexpandonce
+ \else
+ \expandafter\unexpanded
+ \fi
+ {#2}%
+ }%
+ % Initial code, if any:
+ \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachdepth}%
+ \skvifdef\foreachprevitem{}{\def\foreachprevitem{}}%
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@parser]\skv@foreach@userlist
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@subparser]\skv@foreach@userlist
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ \def\skv@foreach@lookahead@a##1{%
+ \def\skv@foreach@continue{##1.}%
+ \futurelet\skv@foreach@next\skv@foreach@lookahead@b
+ }%
+ \def\skv@foreach@lookahead@b{%
+ \ifx\skv@foreach@next[%
+ \expandafter\skv@foreach@lookahead@c
+ \else
+ \ifx\skv@foreach@next(%
+ \expandafter\expandafter\expandafter\skv@foreach@lookahead@d
+ \else
+ \expandafter\expandafter\expandafter\skv@foreach@continue
+ \fi
+ \fi
+ }%
+ \def\skv@foreach@lookahead@c[##1]{\skv@foreach@continue[{##1}]}%
+ \def\skv@foreach@lookahead@d(##1){\skv@foreach@continue({##1})}%
+ \def\skv@foreach@mainloop##1{%
+ \def\skv@foreach@getnext####1##1####2\skv@foreach@stop{%
+ \edef\foreachnextitem{\skvexpandonce{\@gobble####1}}%
+ \ifx\foreachnextitem\skv@foreach@nnil
+ \foreachlastitemtrue
+ \def\foreachnextitem{}%
+ \fi
+ }%
+ \def\skv@foreach@do@a####1##1####2\skv@foreach@stop{%
+ \edef\foreachcurrentitem{\skvexpandonce{\@gobble####1}}%
+ \skvifx\foreachcurrentitem\skv@foreach@nnil{%
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ }{%
+ \skvifx\foreachcurrentitem\skv@listbreakertoks{%
+ \skv@foreach@getrm{####2}%
+ }{%
+ \skvifx\foreachcurrentitem\skv@listpausertoks{%
+ \message{^^J! List pause:
+ ^^JType x or X to quit, or <RETURN> to proceed^^J}%
+ \begingroup
+ \endlinechar\m@ne\global\read-1 to\@gtempa
+ \endgroup
+ \skvexpandarg\lowercase{\def\noexpand\@gtempa{\@gtempa}}%
+ \skvxifstrcmp\@gtempa{x}{%
+ \skv@foreach@getrm{####2}%
+ }{%
+ \skv@foreach@do@b{####2}%
+ }%
+ }{%
+ \skv@foreach@do@b{####2}%
+ }%
+ }%
+ }%
+ }%
+ \def\skv@foreach@do@b####1{%
+ \edef\foreachitemcount{\the\numexpr\foreachitemcount+1}%
+ \ifnum0=\numexpr
+ \ifx\skv@foreach@itemcounter\@undefined-1\else+0\fi
+ \ifx\skv@foreach@itemcounter\@empty-1\else+0\fi
+ \ifx\skv@foreach@itemcounter\@nnil-1\else+0\fi\relax\relax
+ \expandafter\let\skv@foreach@itemcounter\foreachitemcount
+ \fi
+ \skv@foreach@lookahead@a\skv@foreach@getnext####1\skv@foreach@stop
+ % In case the user decides to continue after \listpauser:
+ \skvifx\foreachcurrentitem\skv@listpausertoks{}{%
+ \expandafter\skv@foreach@callback\expandafter{\foreachcurrentitem}%
+ }%
+ \let\foreachprevitem\foreachcurrentitem
+ \ifx\skv@foreach@processupto\@undefined\else
+ \ifx\skv@foreach@processupto\@nnil\else
+ \ifnum\foreachitemcount<\skv@foreach@processupto\relax\else
+ \skvbreakloop
+ \fi
+ \fi
+ \fi
+ \skvifdefbool{skvbreakloop}{%
+ \skv@foreach@getrm{####1}%
+ }{%
+ \skv@foreach@lookahead@a\skv@foreach@do@a####1\skv@foreach@stop
+ }%
+ }%
+ \def\skv@foreach@getrm####1{%
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ \def\skv@prova########1\skv@foreach@nil##1{%
+ \edef\foreachlistremainder{\unexpanded{########1}}%
+ \skv@removetrailingparser{##1}\foreachlistremainder
+ }%
+ \skv@prova####1%
+ }%
+ \skvifx\skv@foreach@userlist\@empty{%
+ \if\skv@foreach@processempty\skv@foreach@callback{}\fi
+ }{%
+ \expandafter\skv@foreach@filllist\expandafter
+ {\skv@foreach@parser}\skv@foreach@userlist
+ \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do@a
+ \skv@foreach@userlist##1\skv@foreach@nil##1\skv@foreach@stop
+ }%
+ }%
+ \skv@foreach@makeprecode{#1}%
+ \if\skv@foreach@recoverholders\else
+ \expandafter\skvsavestate\expandafter\skv@foreach@holderstate
+ \expandafter{\skv@foreach@holderlist}\skv@foreach@sisterdepth
+ \fi
+ \skv@foreach@makeauxcallback{#3}%
+ \skvexpandbracenext\skv@foreach@mainloop\skv@foreach@parser
+ \skvcsuse{skv@foreach@atendhook@\skvrom\foreachdepth}%
+ \if\skv@foreach@recoverholders\else
+ \skvrestorestate\skv@foreach@holderstate\skv@foreach@sisterdepth
+ \fi
+ \skv@foreach@popstate
+}
+
+% \skv@foreach@makeprecode{<holder.list>}
+%
+% 'Holder macro' here means, eg, \x and \y in
+%
+% \newforeach \x/\y in {1/a,2/b,3/c}{<code>}
+%
+\skvrobustdef*\skv@foreach@makeprecode#1{%
+ \begingroup
+ \skv@cnta\skvz@
+ \def\skv@foreach@holderlist{}%
+ \def\skv@foreach@paramlist{}%
+ \def\skv@prevholder{}%
+ \def\skv@tempa{#1}%
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@subparser]\skv@tempa
+ \skvtfor*\skv@prova:=\skv@tempa\do{%
+ \ifx\skv@prova\skv@foreach@subparser
+ \ifnum\skv@cnta=\skvz@
+ \skv@err{Subparser '\skvoxdetok\skv@foreach@subparser' can't come
+ first in the list\MessageBreak of holder macros}\@ehd
+ \else
+ % Eg, if subparser is slash (/), \skv@foreach@paramlist will have
+ % the syntax: ##1/##2/...:
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist\skvexpandonce\skv@prova
+ }%
+ \fi
+ \else
+ \advance\skv@cnta\@ne
+ \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
+ \edef\skv@foreach@precallback{%
+ \skvexpandonce\skv@foreach@precallback
+ % Each given item-holder macro is now defined in terms of
+ % parameters of skv@foreach@auxcallback:
+ \edef\skvexpandonce\skv@prova{%
+ \noexpand\unexpanded{####\number\skv@cnta}%
+ }%
+ % If the current holder has no value, use the value of last holder:
+ \ifnum\skv@cnta>\@ne
+ \if\skv@foreach@inherit
+ \noexpand\ifx\skvexpandonce\skv@prova\noexpand\@empty
+ \let\skvexpandonce\skv@prova\skvexpandonce\skv@prevholder
+ \noexpand\fi
+ \fi
+ \fi
+ }%
+ \edef\skv@foreach@holderlist{%
+ \skvexpandonce\skv@foreach@holderlist
+ % The \do is for the individual entries of the stack of
+ % \skv@foreach@holderlist. It is required for stacking the
+ % holder list:
+ \noexpand\do\skvexpandonce\skv@prova
+ }%
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist########\number\skv@cnta
+ }%
+ \let\skv@prevholder\skv@prova
+ \fi
+ }%
+ % Add one extra parameter character to absorb extra subparsers that are
+ % added for incomplete list items:
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist
+ \skvexpandonce\skv@foreach@subparser
+ ########\number\numexpr\skv@cnta+1\relax
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit\skv@foreach@holderlist
+ \skvcmdexit\skv@foreach@paramlist
+ \skvcmdexit\skv@foreach@precallback
+ }%
+}
+
+% #1: callback
+\skvrobustdef*\skv@foreach@makeauxcallback#1{%
+ \begingroup
+ \def\skv@generatesubparser##1{%
+ \ifnum##1<10\skvexpandonce\skv@foreach@subparser
+ \expandafter\skv@generatesubparser
+ \expandafter{\number\numexpr##1+1\expandafter}%
+ \fi
+ }%
+ % Add extra subparsers in case some items aren't subparser-complete:
+ \edef\skv@tempa{\skv@generatesubparser{1}}%
+ \let\foreacheov\relax
+ \skvexpanded{\endgroup
+ % Define auxiliary callback:
+ \def\noexpand\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
+ % Holder macro assignments:
+ \skvexpandonce\skv@foreach@precallback
+ % User tests/tasks, eg, if requested from 'evaluate' key:
+ \skvexpandonce\skv@foreach@afterprecallback
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \noexpand\skv@foreach@onlyinitially
+ \noexpand\fi
+ \unexpanded{#1}%
+ % User tests/tasks, eg, if requested from the keys 'remember',
+ % 'exit when', etc:
+ \skvexpandonce\skv@foreach@postcallback
+ }%
+ % Define the real callback:
+ \def\noexpand\skv@foreach@callback####1{%
+ \noexpand\skv@foreach@auxcallback####1\skv@tempa\foreacheov
+ }%
+ }%
+}
+\skvnewdef*\skv@ucalpha#1{%
+ \ifcase#1\or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or
+ K\or L\or M\or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or
+ X\or Y\or Z\else?\fi
+}
+\skvnewdef*\skv@lcalpha#1{%
+ \ifcase#1\or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or
+ k\or l\or m\or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or
+ x\or y\or z\else?\fi
+}
+\skvnewdef*\skv@alphamap{%
+ {A}{a}{1}{B}{b}{2}{C}{c}{3}{D}{d}{4}{E}{e}{5}{F}{f}{6}{G}{g}{7}{H}{h}{8}%
+ {I}{i}{9}{J}{j}{10}{K}{k}{11}{L}{l}{12}{M}{m}{13}{N}{n}{14}{O}{o}{15}%
+ {P}{p}{16}{Q}{q}{17}{R}{r}{18}{S}{s}{19}{T}{t}{20}{U}{u}{21}{V}{v}{22}%
+ {W}{w}{23}{X}{x}{24}{Y}{y}{25}{Z}{z}{26}%
+}
+% \skv@foreach@addtolist<parser><add.new><listcmd>
+\skvrobustdef*\skv@foreach@addtolist#1#2#3{%
+ \edef#3{\skvexpandonce#3\ifx#3\@empty\else\unexpanded{#1}\fi#2}%
+}
+\skvrobustdef*\skv@reverselumap#1{%
+ \def\skv@prova##1##2##3##4\skv@nil{%
+ \ifx\@nnil##1%
+ \expandafter\@gobble
+ \else
+ \expandafter\@iden
+ \fi
+ {\skv@prova##4\skv@nil{##1}{##2}{##3}}%
+ }%
+ \edef#1{\expandafter\skv@prova\skv@alphamap\@nnil{}{}\skv@nil}
+}
+
+\skvnewdef*\skv@foreach@ifloweralpha#1{%
+ \skvifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \skvifntype{#1}{%
+ \skvifnum`#1>96{%
+ \skvifnum`#1<123{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+\skvnewdef*\skv@foreach@ifupperalpha#1{%
+ \skvifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \skvifntype{#1}{%
+ \skvifnum`#1>64{%
+ \skvifnum`#1<91{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+
+% Parse list for 1,2,...,n,1,...,m. Return value in #1:
+%
+% \skv@foreach@filllist{<parser>}<listcmd>
+\skvrobustdef*\skv@foreach@filllist#1#2{%
+ \def\skv@inalphabetic{01}%
+ \def\skv@isupperalpha{01}%
+ % If the list is alphabetic, original unit is nil:
+ \def\skv@foreach@origunit{}%
+ \def\skv@foreach@filledlist{}%
+ \edef\skv@foreach@parser{\skvtrimspace{#1}}%
+ \ifx\skv@foreach@parser\@undefined
+ \def\skv@foreach@parser{,}%
+ \fi
+ \def\skv@foreach@iflinkgiven{%
+ \skvifdef\skv@foreach@link{%
+ \skvnotifx\skv@foreach@link\@nnil
+ }{%
+ \skv@err{List auto-completion: 'link' is undefined}\@ehd
+ }%
+ }%
+ \skvexpanded{%
+ \noexpand\skv@foreach@filllist@a
+ {\skvexpandonce\skv@foreach@parser}{\skvexpandonce{#2}}%
+ }%
+ \let#2\skv@foreach@filledlist
+}
+\skvnewlet\skvautofilllist\skv@foreach@filllist
+% \skv@foreach@filllist@a{<parser>}{<list>}
+\skvrobustdef*\skv@foreach@filllist@a#1#2{%
+ \edef\skv@tempa{\unexpanded{#2}}%
+ \skv@foreach@normalize[#1]\skv@tempa
+ \def\skv@prova##1{%
+ \skvxifin{...}{\detokenize{##1}}{%
+ \if\skv@foreach@expandbeforefill
+ \edef\skv@tempa{##1}%
+ \skv@foreach@normalize[#1]\skv@tempa
+ \else
+ \edef\skv@tempa{\unexpanded{##1}}%
+ \fi
+ \skvexpandargonce{\skv@foreach@filllist@b{#1}}{\skv@tempa}%
+ \skv@foreach@normalize[#1]\skv@foreach@filledlist
+ }{%
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \skvtrimspace{##1}%
+ }%
+ }%
+ }%
+ \expandafter\skv@prova\expandafter{\skv@tempa}%
+}
+% \skv@foreach@filllist@b{<parser>}{<list>}
+\skvrobustdef*\skv@foreach@filllist@b#1#2{%
+ \skvxiffound{\relax...}\in{\relax\detokenize{#2}}\then
+ \skv@err{I can't find lower limit before '...'}\@ehd
+ \else
+ \skvxiffound{\relax\detokenize{#1}...}\in{\relax\detokenize{#2}}\then
+ \skv@err{I can't find lower limit before '...'}\@ehd
+ \fi
+ \fi
+ % \newforeach format is '<parser>...<parser>':
+ \skvxifin{\detokenize{#1...#1}}{\detokenize{#2}}{%
+ \skv@foreach@splitonguide{#1}{#2}%
+ \def\skv@prova##1#1##2#1...#1##3#1##4#1##5\skv@nil{%
+ \skvifblank{##3}{%
+ \skv@err{I can't find upper limit number or dimension,
+ \MessageBreak i.e., after symbool '...'}\@ehd
+ }{%
+ % \skv@foreach@filllist@a may be reentered. Hence accumulate
+ % filled list:
+ \skviflacus{##1}\then\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist\unexpanded{##1}%
+ }%
+ \fi
+ % Complete the list:
+ \skv@foreach@filllist@c{#1}{##1}{##2}{##3}%
+ % In case the list is folded on ellipsis (...):
+ \skvifblank{##4}{}{\skv@foreach@filllist@a{#1}{##4#1##5}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa#1#1\skv@nil
+ }{%
+ % Not \newforeach format: try PGF's \foreach format:
+ \skv@foreach@trypgfformat{#1}{#2}%
+ }%
+}
+
+% \skv@foreach@zerostepwarn{<lower>}{<upper>}{<pt.or.nil>}
+\skvrobustdef*\skv@foreach@zerostepwarn#1#2#3{%
+ \skv@warn{The tokens '\detokenize{#1}', '\detokenize{#2}'
+ give nil step; '1#3' used. \MessageBreak
+ Maybe you used the font-dependent units \MessageBreak
+ 'ex' or 'em' before \skv@begindoc@string}%
+}
+
+% skv@foreach@filllist@c{<parser>}{<lower1>}{<lower2>}{<upperbound>}
+%
+% 1. No <guide> here.
+%
+\skvrobustdef*\skv@foreach@filllist@c#1#2#3#4{%
+ \skv@foreach@iflinkgiven{%
+ % <link> has been given by the user:
+ \skv@foreach@splitandgrow{#1}{#2}{#3}{#4}%
+ }{%
+ % No <link> has been given. The list has '...' but presumably no link.
+ % Note: If there're more than 1 alpha/Alpha character, both
+ % \skv@foreach@ifloweralpha and \skv@foreach@ifupperalpha will
+ % return false, since double aphabetic characters can't be grown.
+ % \skv@foreach@filllist@d{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+ \skv@foreach@filllist@d{#1}{}{#2}{#3}{#4}%
+ }%
+}
+
+% skv@foreach@fsplitandgrow{<parser>}{<lower1>}{<lower2>}{<upperbound>}
+%
+% {0\pi,0.5\pi,...,3\pi} : link = \pi ; grow left
+% {1--,4--,...,10--} : link = -- ; grow left
+% {2pt,4pt,...,10pt} : link = pt ; grow left (or no additional info.)
+% {A_1,C_1,...,Q_1} : link = _ ; grow left
+% {2^a,2^c,...,2^q} : link = ^ ; grow right
+%
+% 1. Automatically split and grow.
+% 2. We already know that the key 'link' will reject empty values.
+%
+\skvrobustdef*\skv@foreach@splitandgrow#1#2#3#4{%
+ \ifx\skv@foreach@growleft\skv@foreach@growright
+ \skv@err{I can't grow the list in both directions.
+ \MessageBreak Maybe you haven't indicated the
+ \MessageBreak direction of growth (left or right),
+ \MessageBreak or both directions are 'true'.}
+ {Try one of the keys 'grow=left or right',
+ \MessageBreak 'grow left=true or false',
+ 'grow right=true or false'}\@ehd
+ \fi
+ \begingroup
+ \def\skv@prova##1{%
+ \skv@foreach@swatrue
+ \skviflacus#2\then\else
+ \skvifin{##1}{#2}{}\skv@foreach@swafalse
+ \fi
+ \skvifin{##1}{#3}{}\skv@foreach@swafalse
+ \skvifin{##1}{#4}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa\else
+ \edef\skv@provb{\ifx\@nnil#2\@nnil\else\unexpanded{#2}, \fi}%
+ \skv@err{No link '##1' in one of
+ '\detokenize\expandafter{\skv@provb#3, #4}'}\@ehd
+ \fi
+ \def\skv@prova####1##1####2\skv@nil{%
+ \if\skv@foreach@growright
+ \edef\skv@prova{\skvtrimspace{####1##1}}%
+ \else
+ \edef\skv@prova{\skvtrimspace{##1####2}}%
+ \fi
+ \def\do########1{{\skvtrimspace{########1}}}%
+ % \skv@foreach@trypgfformat@a<parser><guide><lower1><lower2><upper>
+ \skvexpanded{\endgroup
+ \noexpand\skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}{\skvexpandonce\skv@prova}\do{#2}\do{#3}\do{#4}%
+ }%
+ }%
+ \skv@prova#3\skv@nil
+ }%
+ \expandafter\skv@prova\expandafter{\skv@foreach@link}%
+}
+%
+% \skv@foreach@splitonguide{<parser>}{<list>}
+%
+% Get the two elements before '...' or '<guide>,...'. In the case of skeyval
+% format, get the two elements before '...'. The PGF format uses <guide>,
+% shown in the following examples:
+%
+% PGF formats:
+% {a^1,a^3,a^...,a^9} : <guide> = a^
+% {A_1,B_1,..._1,E_1} : <guide> = _1
+% {1--,4--,...--,16--} : <guide> = --
+% {1pt,4pt,...pt,10pt} : <guide> = pt
+% {A_2pt,A_4pt,A_...pt,A_10pt} : <guide> = A_, pt
+%
+% skeyval formats:
+% {a^1,a^3,a^...,a^9} : no additional info. required
+% {A_1,B_1,..._1,E_1} : no additional info. required
+% {1--,4--,...--,16--} : no additional info. required
+% {1pt,4pt,...pt,10pt} : no additional info. required
+% {A_2pt,A_4pt,A_...,A_10pt} : no additional info. required
+%
+% {a^1,a^3,...,a^9} : link = ^, grow = right
+% {A_1,B_1,...,E_1} : link = _, grow = left
+% {1--,4--,...,16--} : link = --, grow = left
+% {1pt,4pt,...,10pt} : link = pt, grow = left (or addit. info.)
+% {A_2pt,A_4pt,...,A_10pt} : link = _, grow = right
+%
+% The items prior to the last 2 items before '<guide>...' or before '...'
+% are called 'before-the-last-2' (BL2). Collect in \skv@tempa BL2 items,
+% together with the rest of the list. Save in \skv@foreach@filledlist
+% the BL2 items.
+%
+% Return \skv@foreach@filledlist and \skv@tempa.
+%
+\skvrobustdef*\skv@foreach@splitonguide#1#2{%
+ % First count all the elements before '<guide>,...'. We're already
+ % sure that #2 contains '<guide>,...' or '...':
+ \begingroup
+ \skv@cnta\skvz@
+ \def\do##1#1{%
+ \skvifin{...}{##1}{%
+ \def\do####1\skv@nil{}%
+ }{%
+ \advance\skv@cnta\@ne
+ }%
+ \do
+ }%
+ \do#2#1\skv@nil
+ \ifnum\skv@cnta>\tw@
+ \skvsetno\skv@foreach@nra\m@ne
+ \def\do##1#1{%
+ \skvadvanceno\skv@foreach@nra\@ne
+ \ifnum\skv@foreach@nra=\numexpr\skv@cnta-\tw@\relax
+ \def\do####1\skv@nil{\def\skv@tempa{##1#1####1}}%
+ \else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist\unexpanded{##1}%
+ }%
+ \fi
+ \do
+ }%
+ \do#2#1\skv@nil
+ \else
+ \ifnum\skv@cnta=\@ne
+ \def\skv@tempa{#1#2}%
+ \else
+ \ifnum\skv@cnta=\tw@
+ \def\skv@tempa{#2}%
+ \else
+ \ifnum\skv@cnta=\skvz@
+ \skv@err{List <<\detokenize{#2}>>\MessageBreak
+ contains symbol '...' but not a lowerbound}\@ehd
+ \fi
+ \fi
+ \fi
+ \fi
+ \skvexpanded{\endgroup
+ \skvcmdexit\skv@foreach@filledlist\skvcmdexit\skv@tempa
+ }%
+}
+
+% \skv@foreach@trypgfformat{<parser>}{<list>}
+%
+% When we say, 'try PGF format', we don't actually mean the PGF format with
+% left and right guides, but the syntax '<guide>...' (ie, having only the
+% left-hand-side or only the right-hand-side guide). For example,
+% {A_2pt,A_4pt,A_...,A_10pt}. \skv@foreach@trypgfformat will auto-complete
+% this list without knowledge of the values of the keys 'link' and 'grow'.
+%
+% skeyval formats:
+%
+% {1pt,4pt,...pt,10pt} : no additional info. required
+% {A_2pt,A_4pt,A_...,A_10pt} : no additional info. required
+% {1pt,4pt,...,10pt} : link = pt, grow=right (or no addit. info.)
+% {A_2pt,A_4pt,...,A_10pt} : link =_, grow=right
+%
+% The general PGF format (with left and right guides) is illegal here,
+% because the skeyval-for package uses the location of the guide (left or
+% right of ...) to determine the direction of growth.
+%
+% {A_2pt,A_4pt,A_...pt,A_10pt}
+%
+\skvrobustdef*\skv@foreach@trypgfformat#1#2{%
+ \skv@foreach@splitonguide{#1}{#2}%
+ \def\skv@prova##1#1##2#1##3...##4#1##5#1##6#1##7\skv@nil{%
+ \skvifblank{##5}{%
+ \skv@err{I can't find upper limit number or dimension,
+ \MessageBreak i.e., after symbool '...'}\@ehd
+ }{%
+ % \skv@foreach@filllist@a may be reentered. Hence
+ \if\relax\detokenize{##1}\relax\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \skvtrimspace{##1}%
+ }%
+ \fi
+ \def\do####1{{\skvtrimspace{####1}}}%
+ \skvifblank{##3}{%
+ \skvifblank{##4}{%
+ \skv@err{No direction of growth before and/or after
+ \MessageBreak symbol '...'}\@ehd
+ }{%
+ \def\skv@foreach@growleft{00}%
+ \def\skv@foreach@growright{01}%
+ \skvexpanded{%
+ \skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}\do{##4}\do{##1}\do{##2}\do{##5}%
+ }%
+ }%
+ }{%
+ \skvifblank{##4}{%
+ \def\skv@foreach@growright{00}%
+ \def\skv@foreach@growleft{01}%
+ \skvexpanded{%
+ \skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}\do{##3}\do{##1}\do{##2}\do{##5}%
+ }%
+ }{%
+ \skv@err{Having both '\detokenize{##3 and ##4}' in an
+ \MessageBreak ellipsis list is illegal in
+ \MessageBreak\noexpand\newforeach and \noexpand\newforeach.
+ \MessageBreak I know that PGF's \noexpand\foreach needs it,
+ \MessageBreak but I don't need it. I can
+ \MessageBreak auto-fill your list without it.}\@ehd
+ }%
+ }%
+ % In case the list is folded on ellipsis (...):
+ \skvifblank{##6}{}{\skv@foreach@filllist@a{#1}{##6#1##7}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa#1#1#1\skv@nil
+}
+%
+% \skv@foreach@trypgfformat@a{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+%
+% 1. Use the <guide> to get the contant and variable parts of the
+% elements.
+% 2. Use the variable parts to determine if the list is Alpah, alpha or
+% number type. In this format, the unit in dimension type of list may
+% appear in <guide>.
+% 3. Use the variable parts to work out the <step>.
+% 4. Call the relevant macro to fill the list.
+% 5. <lower1> has already been saved in \skv@foreach@filledlist.
+%
+\skvrobustdef*\skv@foreach@trypgfformat@a#1#2#3#4#5{%
+ \skv@foreach@swafalse
+ \skviflacus#3\then\else
+ \skvxifin{#2}{#3}{}\skv@foreach@swatrue
+ \fi
+ \skvxifin{#2}{#4}{}\skv@foreach@swatrue
+ \skvxifin{#2}{#5}{}\skv@foreach@swatrue
+ \ifskv@foreach@swa
+ \skv@err{Guide token '\detokenize{#2}' not found in some
+ \MessageBreak of the elements: I can't complete
+ \MessageBreak the current list. This may be
+ \MessageBreak due to wrong direction of growth}\@ehd
+ \fi
+ % Get from the left or right of 'link' (#2) the components that should be
+ % grown, without the link:
+ \def\skv@prova##1#2##2\skv@nil##3{%
+ \edef##3{\if\skv@foreach@growleft##1\else##2\fi}%
+ }%
+ % <lower1> is empty when there is only one element before ellipsis:
+ \skviflacus#3\then
+ \def\skv@tempa{}%
+ \else
+ \skv@prova#3\skv@nil\skv@tempa
+ \fi
+ \skv@prova#4\skv@nil\skv@tempb
+ \skv@prova#5\skv@nil\skv@tempc
+ \let\do\skvexpandonce
+ \skvexpandsecond
+ {\skv@foreach@filllist@d{#1}{#2}}%
+ {{\do\skv@tempa}{\do\skv@tempb}{\do\skv@tempc}}%
+}
+
+% \skv@foreach@filllist@d{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+%
+% 1. Use the variable parts to determine if the list is Alpah, alpha or
+% number type. In this format, the unit in dimension type of list may
+% appear in <guide>.
+% 2. Use the variable parts to work out the <step>.
+% 3. Call the relevant macro to fill the list.
+% 4. <lower1> has already been saved in \skv@foreach@filledlist.
+%
+\skvrobustdef*\skv@foreach@filllist@d#1#2#3#4#5{%
+ \begingroup
+ \def\skv@templist{}%
+ \edef\skv@lowerlower{\ifx\@nnil#3\@nnil\else\unexpanded{#3}, \fi}%
+ \skv@foreach@ifloweralpha{#4}{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skv@foreach@ifloweralpha{#3}{}\skv@foreach@swafalse
+ \fi
+ \skv@foreach@ifloweralpha{#5}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1}%
+ \else
+ \edef\skv@foreach@step{\the\numexpr\lccode`#4-\lccode`#3}%
+ \ifnum\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1}%
+ \skv@foreach@zerostepwarn{#3}{#4}{}%
+ \fi
+ \fi
+ \def\skv@isupperalpha{01}%
+ % \skv@foreach@origunit remains nil on this branch:
+ \skv@foreach@fillalphabetic{#1}{#4}{#5}\skv@templist
+ % Also update the items already entered in \skv@foreach@filledlist.
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak aren't of the same type}\@ehd
+ \fi
+ }{%
+ \skv@foreach@ifupperalpha{#4}{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skv@foreach@ifupperalpha{#3}{}\skv@foreach@swafalse
+ \fi
+ \skv@foreach@ifupperalpha{#5}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1}%
+ \else
+ \edef\skv@foreach@step{\the\numexpr\uccode`#4-\uccode`#3}%
+ \ifnum\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1}%
+ \skv@foreach@zerostepwarn{#3}{#4}{}%
+ \fi
+ \fi
+ \def\skv@isupperalpha{00}%
+ % \skv@foreach@origunit remains nil on this branch:
+ \skv@foreach@fillalphabetic{#1}{#4}{#5}\skv@templist
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak aren't of the same type}\@ehd
+ \fi
+ }{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skvifdimensionable{#3}{}\skv@foreach@swafalse
+ \fi
+ \skvifdimensionable{#4}{}\skv@foreach@swafalse
+ \let\skv@foreach@origunit\skv@dimunit
+ \skvifdimensionable{#5}{}\skv@foreach@swafalse
+ \ifx\skv@foreach@origunit\skv@dimunit\else
+ \skv@err{The units on \detokenize{'#4', '#5'} are different}\@ehd
+ \fi
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1pt}%
+ \else
+ \edef\skv@foreach@step{\the\dimexpr#4-#3}%
+ \ifdim\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1pt}%
+ \skv@foreach@zerostepwarn{#3}{#4}{pt}%
+ \fi
+ \fi
+ \skvexpandsecond{%
+ \skv@foreach@fillnumordim{#1}%
+ }{%
+ {#4}{#5}%
+ }\skv@templist
+ \skv@foreach@strippoint{#1}\skv@templist
+ % Attach the constant part to the elements of the completed list.
+ % <lower1> was saved earlier in \skv@foreach@trypgfformat, and
+ % <lower2> and <upper> have been saved while filling the list.
+ % Always strip point and restore original unit here.
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skvifdimensionable{#3pt}{}\skv@foreach@swafalse
+ \fi
+ \skvifdimensionable{#4pt}{}\skv@foreach@swafalse
+ \skvifdimensionable{#5pt}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1pt}%
+ \else
+ \edef\skv@foreach@step{\the\dimexpr#4pt-#3pt}%
+ \ifdim\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1pt}%
+ \skv@foreach@zerostepwarn{#3}{#4}{pt}%
+ \fi
+ \fi
+ % \skv@foreach@origunit remains nil on this branch:
+ \skvexpandsecond{%
+ \skv@foreach@fillnumordim{#1}%
+ }{%
+ {#4pt}{#5pt}%
+ }\skv@templist
+ \skv@foreach@strippoint{#1}\skv@templist
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{Sorry, the tokens
+ '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak are unparsable. I have given up on them.
+ \MessageBreak Did you miss something syntactic?
+ \MessageBreak See manual for acceptable syntaxes}\@ehd
+ \fi
+ \fi
+ }%
+ }%
+ \skvaftergroupdef\skv@foreach@filledlist\endgroup
+}
+
+% Restore guide and, in the case of numerical sequences, 'original unit'.
+%
+% \skv@foreach@restoreguideandunit{<parser>}{<guide>}{<listcmd>}
+\skvrobustdef*\skv@foreach@restoreguideandunit#1#2#3{%
+ \def\do##1#1{%
+ \ifx\do##1\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \if\skv@foreach@growleft
+ ##1\skv@foreach@origunit\unexpanded{#2}%
+ \else
+ \unexpanded{#2}##1\skv@foreach@origunit
+ \fi
+ }%
+ \expandafter\do
+ \fi
+ }%
+ \expandafter\do#3#1\do#1%
+}
+
+
+\skvrobustdef*\skv@foreach@getcomparator{%
+ \begingroup
+ % 'unit' isn't required in alphabetic sequences:
+ \if\skv@inalphabetic\else
+ \let\skvreversedo\@iden
+ \edef\skv@provb{\skvexpbracenext\skvreverse{\skv@foreach@step}}%
+ \def\skv@prova##1##2##3\skv@nil{%
+ \skvxifin{,\detokenize{##2##1},}{,\skvoxdetok\skv@validunit,}{%
+ \def\skv@foreach@unit{}%
+ }{%
+ \def\skv@foreach@unit{pt}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@provb\skv@nil
+ \fi
+ \def\skv@prova##1##2\skv@nil{%
+ \edef\skv@foreach@stepisneg{0\if-##10\else1\fi}%
+ }%
+ \expandafter\skv@prova\skv@foreach@step\skv@nil
+ \edef\skv@comparator{\if\skv@foreach@stepisneg>\else<\fi}%
+ \let\do\skvcmdexit
+ \skvexpanded{\endgroup
+ \do\skv@foreach@stepisneg\do\skv@comparator
+ \if\skv@inalphabetic\else\do\skv@foreach@unit\fi
+ }%
+}
+% \skv@foreach@fillnumordim<parser><lower><upper><listcmd>
+\skvrobustdef*\skv@foreach@fillnumordim#1#2#3#4{%
+ \begingroup
+ \skv@foreach@getcomparator
+ \if\skv@foreach@stepisneg
+ \ifdim#3\skv@foreach@unit>#2\skv@foreach@unit\relax
+ \skv@err{Step '\skv@foreach@step' is negative but upperbound
+ \MessageBreak '\detokenize{#3}' is greater than lowerbound
+ '\detokenize{#2}'}\@ehd
+ \fi
+ \else
+ \ifdim#3\skv@foreach@unit<#2\skv@foreach@unit\relax
+ \skv@err{Step '\skv@foreach@step' is nonnegative but upperbound
+ \MessageBreak '\detokenize{#3}' is less than lowerbound
+ '\detokenize{#2}'}\@ehd
+ \fi
+ \fi
+ % The bounds may have decimal places. So the calculation has to be
+ % done with \dimexpr:
+ \skv@foreach@addtolist{#1}{\the\dimexpr#2\skv@foreach@unit}#4%
+ % Upper number:
+ \edef\skv@tempa{\the\dimexpr#3\skv@foreach@unit}%
+ % Lower number:
+ \edef\skv@tempb{\the\dimexpr#2\skv@foreach@unit}%
+ \ifdim\skv@tempa=\skv@tempb\relax\else
+ \def\do{%
+ \edef\skv@tempb{%
+ \the\dimexpr\skv@tempb+\skv@foreach@step\skv@foreach@unit\relax
+ }%
+ \ifdim\skv@tempb\skv@comparator\skv@tempa\relax
+ \skv@foreach@addtolist{#1}{\skvexpandonce\skv@tempb}#4%
+ \expandafter\do
+ \fi
+ }%
+ \do
+ % The last item has to in 'pt', so that 'pt' can be stripped:
+ \skv@foreach@addtolist{#1}{\the\dimexpr#3\skv@foreach@unit}#4%
+ \fi
+ \skvaftergroupdef#4\endgroup
+}
+
+% Fill Alpha or alpha:
+% \skv@foreach@fillalphabetic<parser><lower><upper><listcmd>
+\skvrobustdef*\skv@foreach@fillalphabetic#1#2#3#4{%
+ \begingroup
+ \def\skv@inalphabetic{00}%
+ \skv@foreach@getcomparator
+ \edef\skv@type{%
+ \if\skv@isupperalpha Upper\else Lower\fi case alphabetic%
+ }%
+ \edef\reserved@a{\if-\skv@foreach@step\else\skv@foreach@step\fi}%
+ \skvoifinteger\reserved@a{}{%
+ \skv@err{List is '\skv@type' type but\MessageBreak
+ step '\skv@foreach@step' isn't an integer}\@ehd
+ }%
+ \skv@foreach@addtolist{#1}{#2}#4%
+ \skvifstrcmp{#2}{#3}{}{%
+ \edef\skv@lowerlimit{#2}%
+ \edef\skv@upperlimit{#3}%
+ \skvexpandnext{\chardef\skv@lowerlimit`}\skv@lowerlimit\relax
+ \skvexpandnext{\chardef\skv@upperlimit`}\skv@upperlimit\relax
+ \edef\skv@lowerlimit{%
+ \the\numexpr\skv@lowerlimit-\if\skv@isupperalpha 64\else 96\fi
+ }%
+ \edef\skv@upperlimit{%
+ \the\numexpr\skv@upperlimit-\if\skv@isupperalpha 64\else 96\fi
+ }%
+ \edef\skv@charcase{\the\numexpr\skv@lowerlimit+\skv@foreach@step}%
+ \skvrecurse
+ \if\skv@isupperalpha
+ \edef\skv@tempa{\skv@ucalpha\skv@charcase}%
+ \else
+ \edef\skv@tempa{\skv@lcalpha\skv@charcase}%
+ \fi
+ \skv@foreach@addtolist{#1}\skv@tempa#4%
+ \edef\skv@charcase{\the\numexpr\skv@charcase+\skv@foreach@step}%
+ \while
+ \ifnum\skv@charcase\skv@comparator\skv@upperlimit\relax
+ \fi
+ \skv@foreach@addtolist{#1}{#3}#4%
+ }%
+ \skvaftergroupdef#4\endgroup
+}
+
+\skv@for@restorecatcodes
+\endinput
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex
new file mode 100644
index 00000000000..dbdb14df6cf
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxcmds.tex
@@ -0,0 +1,266 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-ltxcmds.tex', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\csname skeyval-ltxcmds-loaded\endcsname
+\expandafter\let\csname skeyval-ltxcmds-loaded\endcsname\endinput
+
+\edef\skv@ltxcmds@restorecatcodes{%
+ \catcode`\noexpand\@\the\catcode`\@\relax
+ \let\noexpand\skv@ltxcmds@restorecatcodes\relax
+}
+\catcode`\@=11\relax
+
+\message{skeyval-ltxcmds 2012/10/15 v1.1 skeyval TeX header (AM)}
+
+\def\@nnil{\@nil}
+\def\@empty{}
+\long\def\@firstofone#1{#1}
+\long\def\@firstoftwo#1#2{#1}
+\long\def\@secondoftwo#1#2{#2}
+\long\def\@gobble#1{}
+\long\def\@gobbletwo#1#2{}
+\lowercase{\def\@gobblespace} {}
+\def\@nameuse#1{\csname#1\endcsname}
+\let\l@ngrel@x\relax
+\protected\def\newif#1{%
+ \count@\escapechar\escapechar\m@ne
+ \let#1\iffalse
+ \ltx@booldef#1\iftrue
+ \ltx@booldef#1\iffalse
+ \escapechar\count@
+}
+\protected\def\ltx@booldef#1#2{%
+ \expandafter\def\csname\expandafter\@gobbletwo\string#1%
+ \expandafter\@gobbletwo\string#2\endcsname{\let#1#2}%
+}
+\long\protected\def\@ifnextchar#1#2#3{%
+ \let\reserved@d=#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch
+}
+\def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c
+}
+\lowercase{\lowercase{\let\@sptoken= } }
+\lowercase{\def\@xifnch} {\futurelet\@let@token\@ifnch}
+\let\kernel@ifnextchar\@ifnextchar
+\long\def\@testopt#1#2{\kernel@ifnextchar[{#1}{#1[{#2}]}}
+\protected\def\@expandtwoargs#1#2#3{%
+ \edef\reserved@a{\noexpand#1{#2}{#3}}\reserved@a
+}
+\edef\@backslashchar{\expandafter\@gobble\string\\}
+\newif\ifin@
+\def\strip@prefix#1>{}
+\protected\def\@onelevel@sanitize#1{%
+ \edef#1{\expandafter\strip@prefix\meaning#1}%
+}
+\long\protected\def\g@addto@macro#1#2{%
+ \begingroup
+ \toks@\expandafter{#1#2}%
+ \xdef#1{\the\toks@}%
+ \endgroup
+}
+
+% In case we call \@latex@error, etc, without LaTeX:
+\newwrite\@unused
+\def\typeout#1{%
+ \begingroup
+ \let\protect\string
+ \immediate\write\@unused{#1}%
+ \endgroup
+}
+\let\MessageBreak\relax
+\protected\def\GenericInfo#1#2{%
+ \begingroup
+ \def\MessageBreak{^^J#1}%
+ \let\protect\string
+ \immediate\write\m@ne{#2\on@line.}%
+ \endgroup
+}
+\protected\def\GenericWarning#1#2{%
+ \begingroup
+ \def\MessageBreak{^^J#1}%
+ \let\protect\string
+ \immediate\write\@unused{^^J#2\on@line.^^J}%
+ \endgroup
+}
+
+\begingroup
+\lccode`\@=`\ %
+\lccode`\~=`\ %
+\lccode`\}=`\ %
+\lccode`\{=`\ %
+\lccode`\T=`\T%
+\lccode`\H=`\H%
+\catcode`\ =11\relax%
+\lowercase{\endgroup%
+\protected\def\GenericError#1#2#3#4{%
+\begingroup%
+\immediate\write\@unused{}%
+\def\MessageBreak{^^J}%
+\let\protect\string%
+\edef%
+\@err@ % \@err@
+{{#4}}%
+\errhelp
+\@err@ % \@err@
+\let
+\@err@ % \@err@
+\@empty
+\def\MessageBreak{^^J#1}%
+\def~{\errmessage{%
+#2.^^J^^J%
+#3^^J%
+Type H <return> for immediate help%
+\@err@ % \@err@
+}}%
+~%
+\endgroup}}%
+
+\def\PackageError#1#2#3{%
+ \GenericError{%
+ (#1)\@spaces\@spaces\@spaces\@spaces
+ }{%
+ Package #1 Error: #2%
+ }{%
+ See the #1 package documentation for explanation.%
+ }{#3}%
+}
+\def\PackageWarning#1#2{%
+ \GenericWarning{%
+ (#1)\@spaces\@spaces\@spaces\@spaces
+ }{%
+ Package #1 Warning: #2%
+ }%
+}
+\def\PackageWarningNoLine#1#2{%
+ \PackageWarning{#1}{#2\@gobble}%
+}
+\def\PackageInfo#1#2{%
+ \GenericInfo{%
+ (#1) \@spaces\@spaces\@spaces
+ }{%
+ Package #1 Info: #2%
+ }%
+}
+\def\ClassError#1#2#3{%
+ \GenericError{%
+ (#1) \space\@spaces\@spaces\@spaces
+ }{%
+ Class #1 Error: #2%
+ }{%
+ See the #1 class documentation for explanation.%
+ }{#3}%
+}
+\def\ClassWarning#1#2{%
+ \GenericWarning{%
+ (#1) \space\@spaces\@spaces\@spaces
+ }{%
+ Class #1 Warning: #2%
+ }%
+}
+\def\ClassWarningNoLine#1#2{%
+ \ClassWarning{#1}{#2\@gobble}%
+}
+\def\ClassInfo#1#2{%
+ \GenericInfo{%
+ (#1) \space\space\@spaces\@spaces
+ }{%
+ Class #1 Info: #2%
+ }%
+}
+\def\@latex@error#1#2{%
+ \GenericError{%
+ \space\space\space\@spaces\@spaces\@spaces
+ }{%
+ LaTeX Error: #1%
+ }{%
+ See the LaTeX manual or LaTeX Companion for explanation.%
+ }{#2}%
+}
+\let\@latexerr\@latex@error
+\def\@latex@warning#1{%
+ \GenericWarning{%
+ \space\space\space\@spaces\@spaces\@spaces
+ }{%
+ LaTeX Warning: #1%
+ }%
+}
+\let\@warning\@latex@warning
+\def\@warningnoline#1{\@latex@warning{#1\@gobble}}
+\def\@latex@info#1{%
+ \GenericInfo{%
+ \@spaces\@spaces\@spaces
+ }{%
+ LaTeX Info: #1%
+ }%
+}
+\def\@infonoline#1{\@latex@info{#1\@gobble}}
+
+\errorcontextlines=\m@ne
+\ifnum\inputlineno=\m@ne
+ \let\on@line\@empty
+\else
+ \def\on@line{ on input line \the\inputlineno}
+\fi
+
+\def\@spaces{\space\space\space\space}
+\def\@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\showoverfull{\tracingonline\@ne}
+\def\loggingoutput{%
+ \tracingoutput\@ne\showboxbreadth\maxdimen
+ \showboxdepth\maxdimen\errorstopmode
+}
+\def\loggingall{%
+ \tracingcommands\tw@\tracingstats\tw@
+ \tracingpages\@ne\tracinglostchars\@ne
+ \tracingmacros\tw@\tracingparagraphs\@ne
+ \tracingrestores\@ne\errorcontextlines\maxdimen
+ \loggingoutput
+}
+\def\tracingall{\loggingall\showoverfull}
+
+\skv@ltxcmds@restorecatcodes
+\endinput
+
+%% End of file 'skeyval-ltxcmds.tex'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty
new file mode 100644
index 00000000000..e44d3b50f7b
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-ltxpatch.sty
@@ -0,0 +1,437 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-ltxpatch.sty', version 1.1, 2012/10/15. %
+% %
+% The rationale for this package: the patch in 'xkvltxp' package isn't %
+% strong enough. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.sty, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\begingroup
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode044 12 % ,
+\def\skv@prova{\endgroup
+ \def\do##1,{%
+ \ifx\do##1\else
+ \catcode##1\string=\the\catcode##1\relax
+ \expandafter\do
+ \fi
+ }%
+ \edef\skvltxp@restorecodes{\do035,064,123,125,061,059,\do,}%
+}
+\skv@prova
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode061 12 % =
+\catcode044 12 % ,
+\def\do#1=#2,{%
+ \ifx\do#1\else
+ \edef\skvltxp@restorecodes{%
+ \skvltxp@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,\do=,%
+
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+\ProvidesPackage{skeyval-ltxpatch}
+ [2012/10/15 v1.1 Patches for LaTeX2e kernel options processing (AM)]
+
+\def\@space{ }
+\protected\def\skvltxptracingall{%
+ \tracinggroups\@ne\tracingifs\@ne\loggingall\tracingassigns\@ne
+ \tracingonline\z@\tracingifs\z@
+}
+\let\skvltxploggingall\skvltxptracingall
+
+\def\skvltxp@cmptwo#1#2\@@a#3#4\@@b#5{%
+ \csname @#5#1#3first\else second\fi oftwo\endcsname
+}
+
+\begingroup
+\lccode`\&=0 \catcode`\&=7 \lccode`\!=0 \catcode`\!=8
+\lowercase{\endgroup
+ \def\skvltxp@ifleadspace#1{\skvltxp@ifl@adspace!#1! &}%
+ \def\skvltxp@ifl@adspace#1! #2&{%
+ \skvltxp@ifnull{#2}\@secondoftwo\@firstoftwo
+ }
+ \def\skvltxp@ifnull#1{\skvltxp@cmptwo#1&\@@a&\@@b\ifx}
+ \def\skvltxp@ifx#1#2{\skvltxp@cmptwo#1&\@@a#2!\@@b\ifx}
+ \def\skvltxp@trimspace#1{\skvltxp@trimspace@a.#1& &}
+ \def\skvltxp@trimspace@a#1 &{\skvltxp@trimspace@b#1&}
+ \def\skvltxp@trimspace@b#1&#2{%
+ \unexpanded\expandafter{%
+ \romannumeral0%
+ \expandafter\skvltxp@ifleadspace\expandafter{\@gobble#1}{%
+ \@gobble#1%
+ }{%
+ \expandafter\@space\@gobble#1%
+ }%
+ }%
+ }
+}
+\protected\def\skvltxp@despacecontent#1{%
+ \edef#1{\expandafter\skvltxp@trimspace\expandafter{#1}}%
+}
+
+% \skvltxp@normalize isn't meant for normalizing keyval lists.
+\protected\def\skvltxp@setupnormalizer#1{%
+ \begingroup
+ \lccode`\~=`#1\relax
+ \lowercase{\endgroup
+ \def\skvltxp@normalize##1{%
+ \unexpanded\expandafter
+ {\romannumeral\skvltxp@activeparser#1##1#1~\skv@nil}%
+ }%
+ \def\skvltxp@activeparser##1~##2\skv@nil{%
+ \skvltxp@ifnull{##2}
+ {\skvltxp@spaceparser##1 #1\skv@nil}
+ {\skvltxp@activeparser##1#1##2\skv@nil}%
+ }%
+ }%
+ \def\skvltxp@spaceparser##1 #1##2\skv@nil{%
+ \skvltxp@ifnull{##2}
+ {\skvltxp@parserspace##1#1 \skv@nil}
+ {\skvltxp@spaceparser##1#1##2\skv@nil}%
+ }%
+ \def\skvltxp@parserspace##1#1 ##2\skv@nil{%
+ \skvltxp@ifnull{##2}
+ {\skvltxp@doubleparser##1#1#1\skv@nil}
+ {\skvltxp@parserspace##1#1##2\skv@nil}%
+ }%
+ \def\skvltxp@doubleparser##1#1#1##2\skv@nil{%
+ \skvltxp@ifnull{##2}{%
+ \skvltxp@ifnull{##1}{0 }{0\expandafter\@space\@gobble##1}%
+ }{%
+ \skvltxp@doubleparser##1#1##2\skv@nil
+ }%
+ }%
+}
+\def\skvltxp@commanormalize#1{%
+ \skvltxp@setupnormalizer{,}%
+ \edef#1{\expandafter\skvltxp@normalize\expandafter{#1}}%
+}
+
+\newif\ifbreakkerpaloop
+\def\kerpaloopdepth{0}
+% \kerpaloop{<parser>}{<list>}{<1.parameter.callback>}
+% \kerpaloop*{<parser>}{<listcmd>}{<1.parameter.callback>}
+\protected\def\kerpaloop{\@ifstar{\skv@kerpaloop1}{\skv@kerpaloop0}}
+\def\skv@kerpaloop#1#2#3#4{%
+ \xdef\kerpaloopdepth{\the\numexpr\kerpaloopdepth+1}%
+ \def\skv@k@rpaloop{kerpaloop@\romannumeral\kerpaloopdepth}%
+ \breakkerpaloopfalse
+ \@namedef{\skv@k@rpaloop}##1#2{%
+ \skvltxp@ifx{##1}\kerpaloop{%
+ \breakkerpaloopfalse
+ }{%
+ #4\relax
+ \ifbreakkerpaloop
+ \breakkerpaloopfalse
+ \begingroup
+ \@namedef\skv@k@rpaloop####1\kerpaloop#2{\endgroup}%
+ \fi
+ \@nameuse\skv@k@rpaloop
+ }%
+ }%
+ \edef\reserved@a{%
+ \if0#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
+ {\unexpanded{#3}}{\unexpanded\expandafter{#3}}%
+ }%
+ \ifx\reserved@a\@empty\expandafter\@gobble\else\expandafter\@iden\fi
+ {%
+ \csname\skv@k@rpaloop\expandafter\endcsname
+ \reserved@a#2\kerpaloop#2%
+ }%
+ \xdef\kerpaloopdepth{\the\numexpr\kerpaloopdepth-1}%
+}
+\def\skvltxp@getoptionnames#1#2{%
+ \def#2{}%
+ \skvltxp@commanormalize#1%
+ \def\do##1=##2\skv@nil{%
+ \edef#2{\ifx#2\@empty\else#2,\fi##1}%
+ }%
+ \kerpaloop*{,}#1{\do##1=\skv@nil}%
+}
+\def\@ptionlist#1{%
+ \@ifundefined{opt@#1}{}{\unexpanded\expandafter
+ \expandafter\expandafter{\csname opt@#1\endcsname}}%
+}
+\def\@if@ptions#1#2#3{%
+ \@expandtwoargs\@if@pti@ns{\@ptionlist{#2.#1}}{\unexpanded{#3}}%
+}
+\def\@if@pti@ns#1#2{%
+ \skvltxp@setupnormalizer{,}%
+ \edef\skv@options@i{\skvltxp@normalize{#1}}%
+ \edef\skv@options@ii{\skvltxp@normalize{#2}}%
+ \ifx\skv@options@i\skv@options@ii
+ \def\skv@tempa{\expandafter\@firstoftwo\@gobbletwo}%
+ \else
+ \ifx\skv@options@ii\@empty
+ \ifx\skv@options@i\@empty
+ \def\skv@tempa{\expandafter\@firstoftwo\@gobbletwo}%
+ \else
+ \def\skv@tempa{\expandafter\@secondoftwo\@gobbletwo}%
+ \fi
+ \else
+ \let\skv@tempa\@iden
+ \fi
+ \fi
+ \skv@tempa{%
+ \let\skv@tempa\@firstoftwo
+ \def\do##1{%
+ \@expandtwoargs\in@{,\detokenize{##1},}%
+ {,\detokenize\expandafter{\skv@options@i},}%
+ \ifin@\else\let\skv@tempa\@secondoftwo\breakkerpalooptrue\fi
+ }%
+ \kerpaloop*{,}\skv@options@ii{\do{##1}}%
+ }%
+ \skv@tempa
+}
+\def\@onefilewithoptions#1[#2][#3]#4{%
+ \@pushfilename
+ \xdef\@currname{#1}%
+ \global\let\@currext#4%
+ \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
+ \let\CurrentOption\@empty
+ \@reset@ptions
+ \makeatletter
+ \@ifl@aded\@currext{#1}{%
+ \@if@ptions\@currext{#1}{#2}{}{%
+ % Merge the two options lists:
+ \let\skv@tempa\skv@options@i
+ \skvltxp@ifnull{#2}{}{%
+ \def\do##1{%
+ \@expandtwoargs\in@{,\detokenize{##1},}%
+ {,\detokenize\expandafter{\skv@tempa},}%
+ \ifin@\else
+ \edef\skv@tempa{%
+ \ifx\skv@tempa\@empty\else
+ \detokenize\expandafter{\skv@tempa},\fi
+ \detokenize{##1}%
+ }%
+ \fi
+ }%
+ \kerpaloop*{,}\skv@options@ii{\do{##1}}%
+ }%
+ \@onelevel@sanitize\skv@options@i
+ \@onelevel@sanitize\skv@options@ii
+ \@latex@error{Option clash for \@cls@pkg\@space #1}{%
+ The package '#1' has already been loaded
+ with \ifx\skv@options@i\@empty no options\MessageBreak\else
+ options:\MessageBreak\@space\@space[\skv@options@i]\fi.
+ \MessageBreak There has now been an attempt to load it with
+ \ifx\skv@options@ii\@empty no options\else options
+ \MessageBreak\@space\@space[\skv@options@ii]\fi.
+ \MessageBreak Adding the global options\MessageBreak
+ \@space\@space'\skv@tempa'\MessageBreak
+ to your \noexpand\documentclass declaration may fix this problem.
+ }%
+ }%
+ }{%
+ \@pass@ptions\@currext{#2}{#1}%
+ \global\expandafter
+ \let\csname ver@\@currname.\@currext\endcsname\@empty
+ \InputIfFileExists{\@currname.\@currext}{}{%
+ \@missingfileerror\@currname\@currext
+ }%
+ \let\@unprocessedoptions\@@unprocessedoptions
+ \csname\@currname.\@currext-h@@k\endcsname
+ \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@undefined
+ \@unprocessedoptions
+ }%
+ \def\skv@tempa##1 v##2 ##3\@nil##4{%
+ \edef##4{'##1\ifx\\##2\\\else\@space v##2\fi'}%
+ }%
+ \skv@tempa#3 v \@nil\skv@tempb
+ \expandafter\expandafter\expandafter\skv@tempa
+ \csname ver@#1.\@currext\expandafter\endcsname
+ \@space v \@nil\skv@tempc
+ \@ifl@ter\@currext{#1}{#3}{}{%
+ \@expandtwoargs\AtEndDocument{%
+ \noexpand\@latex@warning@no@line{%
+ You requested,\on@line, version\MessageBreak
+ \skv@tempb\@space of \@cls@pkg\@space #1,\MessageBreak
+ but only version \skv@tempc\MessageBreak is available
+ }%
+ }{}%
+ }%
+ \ifx\@currext\@clsextension
+ \let\LoadClass\@twoloadclasserror
+ \fi
+ \@popfilename
+ \@reset@ptions
+}
+\protected\def\ProcessOptions{%
+ \let\ds@\@empty
+ \edef\@curroptions{\@ptionlist{\@currname.\@currext}}%
+ \ifx\@classoptionslist\relax
+ \let\@classoptionslist@a\relax
+ \else
+ % LaTeX can't process options with values. So we filter out
+ % option values:
+ \skvltxp@getoptionnames\@classoptionslist\@classoptionslist@a
+ \fi
+ \skvltxp@getoptionnames\@curroptions\@curroptions@a
+ \@ifstar\@xprocess@ptions\@process@ptions
+}
+\def\@process@ptions{%
+ \@for\CurrentOption:=\@declaredoptions\do{%
+ \ifx\CurrentOption\@empty\else
+ \@expandtwoargs\in@{,\CurrentOption,}{%
+ ,\ifx\@currext\@clsextension\else
+ \ifx\@classoptionslist@a\relax\else\@classoptionslist@a,\fi\fi
+ \@curroptions@a,}%
+ \ifin@
+ \@use@ption
+ \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
+ \fi
+ \fi
+ }%
+ \@process@pti@ns
+}
+\def\@xprocess@ptions{%
+ \ifx\@currext\@clsextension\else
+ \@for\CurrentOption:=\@classoptionslist@a\do{%
+ \ifx\CurrentOption\@empty\else
+ \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}%
+ \ifin@
+ \@use@ption
+ \expandafter\let\csname ds@\CurrentOption\endcsname\@empty
+ \fi
+ \fi
+ }%
+ \fi
+ \@process@pti@ns
+}
+\def\@process@pti@ns{%
+ \@for\CurrentOption:=\@curroptions@a\do{%
+ \@ifundefined{ds@\CurrentOption}{\@use@ption\default@ds}{\@use@ption}%
+ }%
+ \@for\CurrentOption:=\@declaredoptions\do{%
+ \expandafter\let\csname ds@\CurrentOption\endcsname\relax
+ }%
+ \let\CurrentOption\@empty
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+}
+\def\@pass@ptions#1#2#3{%
+ \def\reserved@a{#2}%
+ \def\reserved@b{\CurrentOption}%
+ \ifx\reserved@a\reserved@b
+ \@ifundefined{opt@#3.#1}{%
+ \@temptokena\expandafter{#2}%
+ }{%
+ \@temptokena\expandafter\expandafter\expandafter
+ {\csname opt@#3.#1\endcsname}%
+ \@temptokena\expandafter\expandafter\expandafter{%
+ \expandafter\the\expandafter\@temptokena\expandafter,#2}%
+ }%
+ \else
+ \@ifundefined{opt@#3.#1}{%
+ \@temptokena{#2}%
+ }{%
+ \@temptokena\expandafter\expandafter\expandafter
+ {\csname opt@#3.#1\endcsname}%
+ \@temptokena\expandafter{\the\@temptokena,#2}%
+ }%
+ \fi
+ \expandafter\xdef\csname opt@#3.#1\endcsname{\the\@temptokena}%
+}
+\def\OptionNotUsed{%
+ \ifx\@currext\@clsextension
+ \let\reserved@a\CurrentOption
+ \@onelevel@sanitize\reserved@a
+ \xdef\@unusedoptionlist{%
+ \@unusedoptionlist
+ \ifx\@unusedoptionlist\@empty\else,\fi
+ \reserved@a
+ }%
+ \fi
+}
+
+\def\@use@ption{%
+ \begingroup
+ \skvltxp@despacecontent\CurrentOption
+ \@onelevel@sanitize\reserved@a
+ \@onelevel@sanitize\@unusedoptionlist
+ \def\skv@tempa{}%
+ \def\do##1=##2=##3\@nil{%
+ \edef\reserved@a{\skvltxp@trimspace{##1}}%
+ }%
+ \kerpaloop*{,}\@unusedoptionlist{%
+ \do##1==\@nil
+ \ifx\reserved@a\CurrentOption\else
+ \edef\skv@tempa{%
+ \skv@tempa\ifx\skv@tempa\@empty\else,\fi##1%
+ }%
+ \fi
+ }%
+ \global\let\@unusedoptionlist\skv@tempa
+ \endgroup
+ \csname ds@\CurrentOption\endcsname
+}
+\def\@fileswith@pti@ns#1[#2]#3[#4]{%
+ \ifx\@clsextension#1%
+ \ifx\@classoptionslist\relax
+ \@temptokena{#2}%
+ \xdef\@classoptionslist{\the\@temptokena}%
+ \def\reserved@a{%
+ \@onefilewithoptions#3[#2][#4]#1\@documentclasshook
+ }%
+ \else
+ \def\reserved@a{\@onefilewithoptions#3[#2][#4]#1}%
+ \fi
+ \else
+ \@temptokena{#2}%
+ \def\reserved@b##1,{%
+ \ifx\@nnil##1\relax\else
+ \ifx\relax##1\relax\else
+ \noexpand\@onefilewithoptions##1%
+ [\the\@temptokena][#4]\noexpand\@pkgextension
+ \fi
+ \expandafter\reserved@b
+ \fi
+ }%
+ \edef\reserved@a{\zap@space#3 \@empty}%
+ \edef\reserved@a{\expandafter\reserved@b\reserved@a,\@nnil,}%
+ \fi
+ \reserved@a
+}
+\let\@@fileswith@pti@ns\@fileswith@pti@ns
+
+\skvltxp@restorecodes
+\endinput
+
+%% End of file `skeyval-ltxpatch.sty'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty
new file mode 100644
index 00000000000..155b5b56b02
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.sty
@@ -0,0 +1,44 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-pstkey.sty', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+\ProvidesPackage{skeyval-pstkey}
+ [2012/10/15 v1.1 LaTeX/package wrapper for skeyval-pstkey.tex (AM)]
+
+\expandafter\ifx\csname skeyval-pstkey-loaded\endcsname
+\endinput\else
+ \input skeyval-pstkey
+\fi
+\skvdeclareoption*{%
+ \PackageWarning{skeyval-pstkey}{Unknown option
+ '\CurrentOption' ignored}%
+}
+\skvprocessoptions
+\endinput
+
+%% End of file `skeyval-pstkey.sty'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex
new file mode 100644
index 00000000000..83fd3dfff44
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-pstkey.tex
@@ -0,0 +1,70 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-pstkey.tex', version 1.0, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\csname skeyval-pstkey-loaded\endcsname
+\expandafter\let\csname skeyval-pstkey-loaded\endcsname\endinput
+
+\edef\skv@pst@restorecatcodes{%
+ \catcode`\noexpand\@\the\catcode`\@\relax
+ \let\noexpand\skv@pst@restorecatcodes\relax
+}
+\catcode`\@=11\relax
+
+\def\skv@@afterfi#1\fi{\fi#1}
+\def\skv@@afterelse#1\else#2\fi{\fi#1}
+
+\ifx\ProvidesFile\@undefined\skv@@afterelse
+ \message{File 'skeyval-pstkey.tex' 2012/10/15 v1.1
+ PSTricks specialization of skeyval package (AM)}
+ \input skeyval-core
+\else\skv@@afterfi
+ \ProvidesFile{skeyval-pstkey.tex}
+ [2012/10/15 v1.1 PSTricks specialization of skeyval (AM)]
+ \@addtofilelist{skeyval-pstkey.tex}
+ \@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
+\fi
+
+\def\pst@famlist{}
+\def\pst@addfams#1{%
+ \skvcommaloop{#1}\skvtempa{%
+ \skvxifin{,\skvtempa,}{,\pst@famlist,}{}{%
+ \edef\pst@famlist{\pst@famlist,\skvtempa}%
+ }%
+ }%
+}
+\def\psset{\skvexpandbracenext{\skv@testopt\pss@t}\pst@famlist}
+\def\pss@t[#1]#2{\skvsetkeys+[psset]{#1}{#2}\ignorespaces}
+\def\@psset#1,\@nil{%
+ \edef\skvtempa{\skvsetkeys+[psset]{\pst@famlist}}%
+ \skvtempa{#1}%
+}
+
+\skv@pst@restorecatcodes
+\endinput
+
+%% End of file 'skeyval-pstkey.tex'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty
new file mode 100644
index 00000000000..fc078fd2378
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-view.sty
@@ -0,0 +1,352 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-view.sty', version 1.1, 2012/10/15. %
+% %
+% 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. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\begingroup
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode044 12 % ,
+\def\skv@prova{\endgroup
+ \def\do##1,{%
+ \ifx\do##1\else
+ \catcode##1\string=\the\catcode##1\relax
+ \expandafter\do
+ \fi
+ }%
+ \edef\skvv@restorecodes{\do035,064,123,125,061,059,\do,}%
+}
+\skv@prova
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode061 12 % =
+\catcode044 12 % ,
+\def\do#1=#2,{%
+ \ifx\do#1\else
+ \edef\skvv@restorecodes{%
+ \skvv@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,\do=,%
+
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+\ProvidesPackage{skeyval-view}
+ [2012/10/15 v1.1 Viewer utility for skeyval package (AM)]
+\@ifpackageloaded{skeyval}{}{\RequirePackage{skeyval}}
+\directkeys*{%
+ .prefix=SKVV,
+ .family=skvview,
+ .holder prefix=skvv@,
+ .initialize keys after define,
+ .every unknown option={
+ \PackageWarning{skeyval-view}{Unknown option '\CurrentOption'}%
+ },
+ .new options={
+ % LaTeX's options processor will zap the option names. So these keys
+ % can't have spaces between their parts.
+ .ords/{xcolor-options,load-xcolor-with}//
+ \edef\skvv@xcoloroptions{\unexpanded{#1}}
+ \skvstripouterbraces{1}\skvv@xcoloroptions,
+ },
+ .copy class options and process options,
+}
+\AtEndOfPackage{%
+ \skvdisablekeys[SKVV]{skvview}{%
+ xcolor-options,load-xcolor-with
+ }%
+}
+
+\@ifpackageloaded{longtable}{}{\RequirePackage{longtable}}
+\@ifpackageloaded{xcolor}{}{\RequirePackage[\skvv@xcoloroptions]{xcolor}}
+\skvnewbools[skvv@]{colii,coliii,coliv,colv}
+\newwrite\skvv@out
+\skvnewnumbers[skvv@]{depth,nra}
+
+\directkeys*{
+ .prefix=SKVV,
+ .family=skvview,
+ .holder prefix=skvv@,
+ .initialize after define=false,
+ .define keys={
+ .ords/{file,wcolsep,weol}/\@nil/
+ \skvcsedef{skvv@\skvcurrentkey}{\unexpanded{#1}}
+ \skvaftercsname{\skvstripouterbraces{1}}{skvv@\skvcurrentkey}
+ \skvaftercsname\skvdespacecontent{skvv@\skvcurrentkey}
+ ,
+ .ords/{prefix,family,type,default,columns}/\@nil/
+ \skvcsedef{skvv@\skvcurrentkey}{\unexpanded{#1}}
+ \skvaftercsname{\skvstripouterbraces{1}}{skvv@\skvcurrentkey}
+ \skvaftercsname\skvcsvnormalize{skvv@\skvcurrentkey}
+ ,
+ .bools/{view,vlabels,wlabels}/true,
+ .ord/length of default/20/\def\skvv@lod{#1},
+ .cmd/color/black,
+ },
+ .set keys={
+ prefix,family,type,default,file,columns,wcolsep=&,weol=\\,
+ view,vlabels=false,wlabels=false,color,length of default
+ },
+ .links={
+ show/view,
+ key type/type,
+ {prefixes,only those with prefix,only those with prefixes}/prefix,
+ {families,only those in family,only those in families}/family,
+ {defaults,only those with default,only those with defaults}/default,
+ view output/view,
+ write to file/file,
+ {view labels,show labels}/vlabels,
+ {view wlabels,show wlabels}/wlabels,
+ wend of line/weol,
+ wcolumn separation/wcolsep,
+ word length of default/length of default
+ },
+ .style={
+ only those without default/default=[none],
+ },
+}
+
+% Use \setupviewkeys to change viewing specifications without actually
+% displaying (or writing to file) the key list:
+%
+\skvrobustdef*\setupviewkeys{\skvsetkeys[SKVV]{skvview}}
+
+\let\skvv@db\@empty
+\skvrobustdef*\skvv@tabulate#1#2#3{%
+ \edef\skv@tempa{\detokenize{#3}}%
+ \skv@getbasetoks\skvv@lod\skv@tempa\skv@ival
+ \skvxaddtolist{,}\skvv@db{%
+ #1=\ifx\skvcurrentprefix\@empty\else
+ \skvcurrentprefix\fi=\skvcurrentfamily=#2=\skv@ival
+ }%
+}
+\protected\def\skv@ordkey@a#1[#2]#3{%
+ \skvifstrcmp{#2}{^skv^}{%
+ \skvv@tabulate{#1}{ordinary}{[none]}%
+ }{%
+ \skv@definedefault{#1}{#2}%
+ \skvv@tabulate{#1}{ordinary}{#2}%
+ }%
+ \skvcsedef{\skv@header#1.@cbk}{\unexpanded{#3}}%
+}
+\protected\def\skv@cmdkey#1#2[#3]#4{%
+ \skv@strippointers{#2}\skvcurrentkey
+ \skvifdefbool{skv@st}{%
+ \skv@definedefault\skvcurrentkey{#3}%
+ \skvv@tabulate\skvcurrentkey{command}{#3}%
+ }{%
+ \skvv@tabulate\skvcurrentkey{command}{[none]}%
+ }%
+ % This is to allow the key name to be expanded before possibly zapping
+ % spaces in key name:
+ \edef\skv@prova{#1\skvcurrentkey}%
+ \edef\skv@prova{\expandafter\skv@zapornot\expandafter
+ {\expandafter\skv@zapnr\expandafter}\expandafter{\skv@prova}}%
+ \skvcslet{\skv@header\skvcurrentkey.@hp}\skv@prova
+ \skvcsedef{\skv@header\skvcurrentkey.@cbk}{\unexpanded{#4}}%
+}
+\protected\def\skv@choicekey@c[#1]{%
+ \skvifstrcmp{#1}{^skv^}{%
+ \skvv@tabulate\skvcurrentkey{choice}{[none]}%
+ }{%
+ \skv@definedefault\skvcurrentkey{#1}%
+ \skvv@tabulate\skvcurrentkey{choice}{#1}%
+ }%
+ \skvifdefbool{skv@pl}\skv@choicekey@e\skv@choicekey@d
+}
+\protected\def\skv@boolkey@c#1#2#3#4{%
+ \skvcsnewif{\skv@zapornot{\skv@zapnr}{#2}}%
+ \skvifdefbool{skv@st}{%
+ \skv@definedefault{#1}{#3}%
+ \skvv@tabulate{#1}{bool}{#3}%
+ }{%
+ \skvv@tabulate{#1}{bool}{[none]}%
+ }%
+ \edef\skv@tempa##1##2{%
+ \noexpand\skv@sttrue
+ \ifskv@pl\noexpand\skv@pltrue\else\noexpand\skv@plfalse\fi
+ \skv@checkchoice[\noexpand\skv@value]{##1}{true,false}##2%
+ }%
+ \skv@toksa\expandafter{\skv@tempa{##1}{#4}}%
+ \skvcsedef{\skv@header#1.@cbk}{\the\skv@toksa}%
+}
+% #2: styles, #3: default, #4: callback
+\protected\def\skv@appendstyles@a#1#2[#3]#4{%
+ \skvcommaparse{#1}\skv@prova{%
+ \skvexpbracenext\skv@strippointers\skv@prova\skvcurrentkey
+ \skvexpanded{%
+ \skvifstrcmp{#3}{^skv^}{%
+ \skvv@tabulate{\skvcurrentkey}{style}{[none]}%
+ }{%
+ \skv@definedefault{\skvcurrentkey}{\unexpanded{#3}}%
+ \skvv@tabulate{\skvcurrentkey}{style}{\unexpanded{#3}}%
+ }%
+ \skv@appendstyles@b{\skvcurrentkey}\unexpanded{{#2}{#4}}%
+ }%
+ }%
+}
+
+\skvbuildmacrostack\skvv@state{%
+ \do\skvv@prefix\do\skvv@family\do\skvv@type\do\skvv@default
+ \do\skvv@file\do\skvv@columns\do\skvv@wcolsep\do\skvv@weol
+ \do\skvv@color\do\ifskvv@view\do\ifskvv@vlabels\do\ifskvv@wlabels
+}{2}
+
+\skvrobustdef*\skvv@skvview@a#1{%
+ \skvsetkeys[SKVV]{skvview}{#1}%
+ \ifx\skvv@default\@nnil\else\@onelevel@sanitize\skvv@default\fi
+ \ifx\skvv@columns\@nnil
+ \skvsetnumber\skvv@nra5\relax
+ \skvv@coliitrue\skvv@coliiitrue\skvv@colivtrue\skvv@colvtrue
+ \else
+ \skvsetnumber\skvv@nra\@ne
+ \@expandtwoargs\skv@in@{,prefix,}{,\skvv@columns,}%
+ \ifin@\skvadvanceno\skvv@nra\@ne\skvv@coliitrue\else\skvv@coliifalse\fi
+ \@expandtwoargs\skv@in@{,family,}{,\skvv@columns,}%
+ \ifin@\skvadvanceno\skvv@nra\@ne\skvv@coliiitrue\else\skvv@coliiifalse\fi
+ \@expandtwoargs\skv@in@{,type,}{,\skvv@columns,}%
+ \ifin@
+ \skvadvanceno\skvv@nra\@ne\skvv@colivtrue
+ \else
+ \@expandtwoargs\skv@in@{,key type,}{,\skvv@columns,}%
+ \ifin@\skvadvanceno\skvv@nra\@ne\skvv@colivtrue\else\skvv@colivfalse\fi
+ \fi
+ \@expandtwoargs\skv@in@{,default,}{,\skvv@columns,}%
+ \ifin@\skvadvanceno\skvv@nra\@ne\skvv@colvtrue\else\skvv@colvfalse\fi
+ \fi
+ \ifskvv@view
+ \protected@edef\skv@prova{%
+ \noexpand\begin{longtable}[l]{*\skvv@nra l}%
+ \\\noexpand\hline
+ \normalfont Key
+ \ifskvv@colii&\normalfont Prefix\fi
+ \ifskvv@coliii&\normalfont Family\fi
+ \ifskvv@coliv&\normalfont Type\fi
+ \ifskvv@colv&\normalfont Default\fi
+ \\\noexpand\hline
+ \noexpand\endfirsthead\noexpand\multicolumn{\skvv@nra}{l}{%
+ \normalfont\emph{Continued from previous page}}%
+ \\\noexpand\hline
+ \normalfont Key
+ \ifskvv@colii&\normalfont Prefix\fi
+ \ifskvv@coliii&\normalfont Family\fi
+ \ifskvv@coliv&\normalfont Type\fi
+ \ifskvv@colv&\normalfont Default\fi
+ \\\noexpand\hline\noexpand
+ \endhead\noexpand\hline
+ \noexpand\multicolumn{\skvv@nra}{r}{%
+ \normalfont\emph{Continued on next page}}%
+ \\\noexpand\endfoot\noexpand\hline
+ \noexpand\endlastfoot
+ }%
+ \skv@toksa\expandafter{\skv@prova}%
+ \fi
+ \ifx\skvv@file\@nnil\else\immediate\openout\skvv@out\skvv@file\fi
+ \skvcommaloop*\skvv@db\skv@prova{%
+ \skv@swatrue
+ \expandafter\skvv@skvview@b\skv@prova\skv@nil
+ }%
+ \ifskvv@view
+ \addto@hook\skv@toksa{\end{longtable}}%
+ \begingroup
+ \color{\skvv@color}%
+ \ttfamily\the\skv@toksa
+ \endgroup
+ \fi
+ \ifx\skvv@file\@nnil\else\immediate\closeout\skvv@out\fi
+}
+\skvnewdef*\skvv@skvview@b#1=#2=#3=#4=#5\skv@nil{%
+ \skvv@ifin{#2}\skvv@prefix
+ \skvv@ifin{#3}\skvv@family
+ \skvv@ifin{#4}\skvv@type
+ \skvv@ifin{#5}\skvv@default
+ \ifskv@swa
+ \ifskvv@view
+ \edef\skv@prova{%
+ #1\ifskvv@colii&#2\fi\ifskvv@coliii&#3\fi
+ \ifskvv@coliv&#4\fi\ifskvv@colv&#5\fi
+ \ifskvv@vlabels\noexpand\label{#2/#3/#1}\fi
+ }%
+ \skv@toksa\expandafter{\the\expandafter\skv@toksa\skv@prova\\}%
+ \fi
+ \ifx\skvv@file\@nnil\else
+ \immediate\write\skvv@out{%
+ #1\ifskvv@colii\skvv@wcolsep#2\fi
+ \ifskvv@coliii\skvv@wcolsep#3\fi
+ \ifskvv@coliv\skvv@wcolsep#4\fi
+ \ifskvv@colv\skvv@wcolsep#5\fi
+ \ifskvv@wlabels\string\label{#2/#3/#1}\fi
+ \skvexpandonce\skvv@weol
+ }%
+ \fi
+ \fi
+}
+\skvrobustdef*\skvv@ifin#1#2{%
+ \ifx#2\@nnil\else
+ \skvxifin{,\detokenize{#1},}{,\skvoxdetok{#2},}{}\skv@swafalse
+ \fi
+}
+
+\directkeys*{
+ .prefix=SKVV,
+ .family=skvvshow,
+ .holder prefix=skvvs@,
+ .initialize keys after define,
+ .new keys={
+ .ords/{.show,.show table}//
+ \skvifdefbool{skvindef}{}{
+ \edef\skvvs@show{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skvvs@show
+ \ifx\skvvs@show\@empty\else\skvafterfi
+ \skvpushstate\skvv@state\skvv@depth
+ \skvexpbracenext\skvv@skvview@a\skvvs@show
+ \skvpopstate\skvv@state\skvv@depth
+ \fi
+ },
+ .ord/.exec code/\@nil/
+ \edef\skvvs@execcode{\unexpanded{#1}}
+ \ifx\skvvs@execcode\@nnil\else
+ \expandafter\skvvs@execcode
+ \fi
+ },
+}
+
+\skvrobustdef*\skvviewkeys{\skvsetkeys[SKVV]{skvvshow}}
+\skvnewlet\skvshowkeys\skvviewkeys
+
+\skvv@restorecodes
+
+\endinput
+
+%% End of file 'skeyval-view.sty'.
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
index e82d269e76f..38871851cd1 100644
--- a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty
@@ -1,6 +1,5 @@
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
-% %
-% This is file 'skeyval.sty', version 0.72. %
+% This is file 'skeyval.sty', version 1.1, 2012/10/15. %
% %
% This package and accompanying files may be distributed and/or %
% modified under the conditions of the LaTeX Project Public License, %
@@ -16,3167 +15,790 @@
% implied warranties of merchantability and fitness for a particular %
% purpose. %
% %
-% Copyright (c) 2010 Ahmed Musa (a.musa@rocketmail.com). %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
\begingroup
-\catcode064 11% @
-\catcode123 01% {
-\catcode125 02% }
-\def\SKV@tempa{\endgroup
- \edef\SKV@restorecodes{%
- \catcode035 \the\catcode035% #
- \catcode064 \the\catcode064% @
- \catcode123 \the\catcode123% {
- \catcode125 \the\catcode125% }
- \catcode061 \the\catcode061% =
- }%
-}
-\SKV@tempa
-\catcode035 06% #
-\catcode061 12% =
-\catcode064 11% @
-\catcode123 01% {
-\catcode125 02% }
-\def\SKV@setcode#1#2{%
- \edef\SKV@restorecodes{%
- \SKV@restorecodes
- \catcode#1 \the\catcode#1\relax
- }%
- \catcode#1 #2\relax
-}
-\AtEndOfPackage{%
- \SKV@AfterPackageEnd{%
- \SKV@restorecodes
- \SKV@Undef!{\SKV@setcode\SKV@restorecodes}%
- }%
-}
-\SKV@setcode{010}{12}% ^^J
-\SKV@setcode{032}{10}% SP
-\SKV@setcode{033}{12}% !
-\SKV@setcode{036}{03}% $
-\SKV@setcode{038}{03}% &
-\SKV@setcode{040}{12}% (
-\SKV@setcode{041}{12}% )
-\SKV@setcode{042}{12}% *
-\SKV@setcode{043}{12}% +
-\SKV@setcode{044}{12}% ,
-\SKV@setcode{045}{12}% -
-\SKV@setcode{047}{12}% /
-\SKV@setcode{058}{12}% :
-\SKV@setcode{059}{12}% ;
-\SKV@setcode{060}{12}% >
-\SKV@setcode{062}{12}% <
-\SKV@setcode{063}{12}% ?
-\SKV@setcode{091}{12}% [
-\SKV@setcode{093}{12}% ]
-\SKV@setcode{096}{12}% `
-\SKV@setcode{126}{13}% ~
-\def\SKV@rcsid$#1: #2 #3 #4 #5${#4 v#3}
-\ProvidesPackage{skeyval}[%
- \SKV@rcsid $Id: skeyval.sty,v 0.72 2010/05/21 09:00:00 Ahmed Musa $
- Extensions to the xkeyval parser (AM)
-]
-\NeedsTeXFormat{LaTeX2e}[1996/12/01]
-\ifnum0=0%
- \ifx\eTeXversion\SKV@undefined1\else\ifnum\eTeXversion<\tw@1\fi\fi
-\else
- \PackageError{skeyval}{eTeX not loaded or old version}%
- {This package requires eTeX version 2 or later.}%
- \endinput
-\fi
-\newtoks\SKV@toks
-\newcount\SKV@depth
-\protected\def\@nil{\@nil}
-\def\@nnil{\@nil}
-\def\@space{ }
-\long\def\@firstofthree#1#2#3{#1}
-\long\def\@secondofthree#1#2#3{#2}
-\long\def\@thirdofthree#1#2#3{#3}
-\long\def\@gobblethree#1#2#3{}
-\long\def\SKV@car#1#2\@nil{#1}
-\long\def\SKV@cdr#1#2\@nil{#2}
-\long\def\SKV@carcube#1#2#3#4\@nil{#1#2#3}
-\def\SKV@threexp{\expandafter\expandafter\expandafter}
-\def\SKV@aftercs#1#2{\expandafter#1\csname#2\endcsname}
-\def\SKV@xaftercs#1#2{\SKV@threexp#1\csname#2\endcsname}
-\SKV@aftercs\let{SKV@1of1}\@firstofone
-\SKV@aftercs\let{SKV@1of2}\@firstoftwo
-\SKV@aftercs\let{SKV@2of2}\@secondoftwo
-\SKV@aftercs\let{SKV@1of3}\@firstofthree
-\SKV@aftercs\let{SKV@2of3}\@secondofthree
-\SKV@aftercs\let{SKV@3of3}\@thirdofthree
-\def\SKV@ifx#1#2{\@nameuse{SKV@\ifx#1#21\else2\fi of2}}
-\def\SKV@unifx#1#2{\@nameuse{SKV@\ifx#1#22\else1\fi of2}}
-\def\SKV@csifx#1#2{\begingroup\expandafter\endgroup\expandafter
- \SKV@ifx\csname#1\endcsname#2}
-\def\SKV@uncsifx#1#2{\begingroup\expandafter\endgroup\expandafter
- \SKV@unifx\csname#1\endcsname#2}
-\def\SKV@ifxcs#1#2{\begingroup\expandafter\endgroup\expandafter
- \SKV@ifx\expandafter#1\csname#2\endcsname}
-\def\SKV@unifxcs#1#2{\begingroup\expandafter\endgroup\expandafter
- \SKV@unifx\expandafter#1\csname#2\endcsname}
-\def\SKV@ifdefined#1{\@nameuse{SKV@\ifdefined#11\else2\fi of2}}
-\def\SKV@oifdefined#1{\@nameuse{SKV@\expandafter\SKV@ifdefined#1{1}{2}of2}}
-\def\SKV@unifdefined#1{\@nameuse{SKV@\SKV@ifdefined{#1}{2}{1}of2}}
-\def\SKV@ifcsname#1{\@nameuse{SKV@\ifcsname#1\endcsname1\else2\fi of2}}
-\def\SKV@unifcsname#1{\@nameuse{SKV@\SKV@ifcsname{#1}{2}{1}of2}}
-\def\SKV@ifnum#1#2#3{\@nameuse{SKV@\ifnum#1#2#3 1\else2\fi of2}}
-\protected\def\SKV@AtEndAfterPackageEnd#1{\AtEndOfPackage
- {\SKV@AfterPackageEnd{#1}}}
-\begingroup
-\def\SKV@tempa{%
- \def\SKV@nodocerr{%
- \PackageError{skeyval}{'skeyval' package loaded before
- \string\documentclass}{Load skeyval package after
- \string\documentclass.}%
- \endinput
- }%
- \def\SKV@tempb##1\@nil,{}%
- \def\SKV@tempa##1,{%
- \def\@currname{##1}%
- \SKV@ifx\SKV@documentclass\SKV@undefined{%
- \SKV@ifx\@currname\@nnil{}{%
- \filename@parse\@currname
- \SKV@unifx\filename@ext\@clsextension{}{%
- \SKV@unifcsname{opt@\filename@area\filename@base.%
- \filename@ext}{}{%
- \edef\SKV@documentclass{\filename@area%
- \filename@base.\filename@ext}%
- }%
- }%
- \SKV@tempa
- }%
- }{%
- \let\SKV@tempa\SKV@tempb\SKV@tempa
- }%
- }%
- \SKV@ifx\@filelist\relax\SKV@nodocerr{%
- \SKV@ifx\@filelist\@gobble\SKV@nodocerr{%
- \expandafter\SKV@tempa\@filelist,\@nil,%
- }%
- }%
- \SKV@ifx\SKV@documentclass\SKV@undefined\SKV@nodocerr\relax
-}
-\SKV@tempa\endgroup
-\def\SKV@notdefinable{%
- \PackageError{skeyval}%
- {Command '\@backslashchar\resvd@a' not definable,
- \MessageBreak or name '\@backslashchar\@qend...' illegal}%
- {Command '\@backslashchar\resvd@a' already defined.}%
-}
-\def\SKV@ifdefinable#1{%
- \begingroup
- \escapechar92\relax
- \xdef\resvd@a{\expandafter\@gobble\string#1}%
- \edef\resvd@b{\expandafter\SKV@car\string#1\@nil}%
- \SKV@ifx\resvd@b\@backslashchar{}{%
- \PackageError{skeyval}{Backslash required}{Backslash
- required in argument of '\string\SKV@ifdefinable'.}%
- }%
- \SKV@ifdefined#1{%
- \SKV@ifx{#1}\relax{\aftergroup\@firstofone}%
- {\aftergroup\SKV@notdefinable}%
- }{%
- \edef\resvd@b{\unexpanded\expandafter{\csname end\resvd@a\endcsname}}%
- \expandafter\SKV@ifx\resvd@b\relax{%
- \SKV@ifx\resvd@a\@qrelax{\aftergroup\SKV@notdefinable}%
- {\aftergroup\@firstofone}
- }{\aftergroup\SKV@notdefinable}%
- }%
- \endgroup
-}
-\def\SKV@csifdefinable#1{\begingroup\expandafter\endgroup
- \expandafter\SKV@ifdefinable\csname#1\endcsname}
-\newcommand*\@ifpackagecurrent[2]{%
- \@nameuse{SKV@\ifnum\SKV@threexp\@parse@version
- \csname ver@#1.\@pkgextension\endcsname//00\@nil
- <\expandafter\@parse@version#2//00\@nil2\else1\fi of2}%
-}
-\newcommand*\@ifpackagenotcurrent[2]{%
- \@nameuse{SKV@\@ifpackagecurrent{#1}{#2}{2}{1}of2}}
-\newcommand*\@ifloadedandcurrent[2]{%
- \begingroup
- \@ifpackageloaded{#1}{%
- \@ifpackagecurrent{#1}{#2}{\aftergroup\@firstofthree}{%
- \aftergroup\@secondofthree}}{\aftergroup\@thirdofthree}%
- \endgroup
-}
-\@ifloadedandcurrent{xkeyval}{2008/08/13}{}{%
- \PackageError{skeyval}%
- {Your loaded version of xkeyval package is not current}%
- {You need version 2.6a (or higher) of xkeyval package.}%
- \endinput
-}{\RequirePackage{xkeyval}[2008/08/13]}
-\newcommand*\SKV@ifdefinable@n[1]{%
- \XKV@sp@deflist\SKV@tempa{#1}%
- \XKV@for@o\SKV@tempa\SKV@tempa{%
- \edef\resvd@a{\SKV@threexp\SKV@car
- \expandafter\string\SKV@tempa\@nil}%
- \SKV@unifx\resvd@a\@backslashchar{}{%
- \PackageError{skeyval}{Backslash not allowed}{Backslash not
- allowed in argument of '\string\SKV@ifdefinable@n'.}%
- }%
- \SKV@csifdefinable\SKV@tempa\relax
- }%
-}
-\SKV@ifdefinable@n{SKV@def,SKV@d@f,SKV@pdef,SKV@pd@f}
-\protected\def\SKV@def{\@star@or@long\SKV@d@f}
-\def\SKV@d@f#1{\SKV@ifdefinable#1{\l@ngrel@x\def#1}}
-\protected\def\SKV@pdef{\@star@or@long\SKV@pd@f}
-\def\SKV@pd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\def#1}}
-\SKV@pdef*\SKV@gdef{\@star@or@long\SKV@gd@f}
-\SKV@def*\SKV@gd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\gdef#1}}
-\SKV@pdef*\SKV@edef{\@star@or@long\SKV@ed@f}
-\SKV@def*\SKV@ed@f#1{\SKV@ifdefinable#1{\l@ngrel@x\edef#1}}
-\SKV@pdef*\SKV@pgdef{\@star@or@long\SKV@pgd@f}
-\SKV@def*\SKV@pgd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\gdef#1}}
-\SKV@pdef*\SKV@pedef{\@star@or@long\SKV@ped@f}
-\SKV@def*\SKV@ped@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\edef#1}}
-\SKV@pdef*\SKV@pxdef{\@star@or@long\SKV@pxd@f}
-\SKV@def*\SKV@pxd@f#1{\SKV@ifdefinable#1{\l@ngrel@x\protected\xdef#1}}
-\SKV@pdef*\SKV@redef{\@star@or@long\SKV@red@f}
-\SKV@def*\SKV@red@f#1{%
- \SKV@ensurescape{#1}%
- \SKV@unifdefined{#1}{}{%
- \SKV@ifx{#1}\relax{}{%
- \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
- }%
- }%
- \l@ngrel@x\def#1%
-}
-\SKV@pdef*\SKV@csredef{\SKV@aftercs\SKV@redef}
-\SKV@pdef*\SKV@predef{\@star@or@long\SKV@pred@f}
-\SKV@def*\SKV@pred@f#1{%
- \SKV@ensurescape{#1}%
- \SKV@unifdefined{#1}{}{%
- \SKV@ifx{#1}\relax{}{%
- \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
- }%
- }%
- \l@ngrel@x\protected\def#1%
-}
-\SKV@pdef*\SKV@cspredef{\SKV@aftercs\SKV@predef}
-\SKV@def*\SKV@vbmsg#1#2{%
- \begingroup
- \def\@i{info}\def\@ii{warn}\def\@iii{#1}%
- \@nameuse{SKV@\ifSKV@verbose1\else2\fi of2}%
- {\SKV@ifx\@i\@iii
- {\SKV@info{#2}}%
- {\SKV@ifx\@ii\@iii{\SKV@warn{#2}}{}}%
- }{}%
- \endgroup
-}
-\define@boolkeys[KV]{skeyval@i}[SKV@]{st,pl,cl,rt,
- lt,sw,sk,loc,uv}[true]
-\setkeys[KV]{skeyval@i}{st,pl,cl,rt,lt,sw,sk,loc,uv}
-\define@boolkey+[KV]{skeyval}[SKV@]{verbose}[true]{}{%
- \SKV@inputerr{#1}{verbose}%
-}
-\setkeys[KV]{skeyval}{verbose=false}
-\SKV@pdef\SKV@info#1{\PackageInfo{skeyval}{#1\@gobble}}
-\SKV@pdef\SKV@warn#1{\PackageWarningNoLine{skeyval}{#1}}
-\SKV@pdef\SKV@err#1#2{\PackageError{skeyval}{#1}{#2}}
-\SKV@def*\SKV@MB{\MessageBreak}
-\SKV@pdef\SKV@afterfi#1\fi{\fi#1}
-\SKV@pdef\SKV@afterelsefi#1\else#2\fi{\fi#1}
-\SKV@pdef\SKV@afterfifi#1\fi#2\fi{\fi#2\fi#1}
-\SKV@def*\SKV@badargerr#1#2{%
- \SKV@err{Invalid #2 argument for command '\@backslashchar#1'}%
- {Bad #2 argument for command '\@backslashchar#1'.\SKV@MB
- You need to look again at user instruction\SKV@MB
- for command '\@backslashchar#1'.}%
-}
-\SKV@def*\SKV@state#1#2#3{%
- \ifcase#1\relax
- \def\SKV@ste{XKV@prefix,XKV@fams,XKV@tkey,XKV@na,ifXKV@st,%
- ifXKV@pl,ifXKV@knf,CurrentOption,ifSKV@sk}%
- \SKV@ifempty{#3}{\advance\XKV@depth\@ne}{}%
- \or
- \def\SKV@ste{ifSKV@st,ifSKV@pl,ifSKV@cl,ifSKV@rt,ifSKV@lt}%
- \SKV@ifempty{#3}{\advance\SKV@depth\@ne}{}%
- \else
- \SKV@err{Unknown state identifier '#1'}%
- {I expected '\string#1' to be number 0 or 1.}%
- \fi
- \XKV@for@o\SKV@ste\SKV@ste{%
- \SKV@aftercs\let{\SKV@ste#2\SKV@aftercs}{\SKV@ste#3}%
- }%
- \ifcase#1\relax
- \SKV@ifempty{#2}{\advance\XKV@depth\m@ne}{}%
- \or
- \SKV@ifempty{#2}{\advance\SKV@depth\m@ne}{}%
- \fi
-}
-\SKV@def*\XKV@savstate{\SKV@state{0}{@\romannumeral\XKV@depth}{}}
-\SKV@def*\XKV@resstate{\SKV@state{0}{}{@\romannumeral\XKV@depth}}
-\SKV@def*\SKV@savstate{\SKV@state{1}{@\romannumeral\SKV@depth}{}}
-\SKV@def*\SKV@resstate{\SKV@state{1}{}{@\romannumeral\SKV@depth}}
-\def\XKV@srstate#1#2{\SKV@state{0}{#1}{#2}}
-\SKV@def*\SKV@scantoksa{\SKV@savstate\SKV@testoptf\SKV@sc@ntoksa}
-\SKV@def\SKV@sc@ntoksa[#1]#2{%
- \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
- \SKV@for[#1]{#2}\SKV@resvda{%
- \ifSKV@pl
- \SKV@ifcsdef\SKV@resvda{}{%
- \SKV@err{Command '\SKV@csexpox\SKV@resvda' undefined}%
- {I can't scan contents of undefined command
- '\SKV@csexpox\SKV@resvda'}%
- }%
- \SKV@expnext\SKV@ensurenoscape\SKV@resvda
- \expandafter\let\expandafter\SKV@resvdb%
- \csname\SKV@resvda\endcsname
- \else
- \expandafter\SKV@ifdef\SKV@resvda{}{%
- \SKV@err{Command '\SKV@expox\SKV@resvda' undefined}%
- {I can't scan contents of undefined command
- '\SKV@expox\SKV@resvda'}%
- }%
- \SKV@expnext\SKV@ensurescape\SKV@resvda
- \expandafter\let\expandafter\SKV@resvdb\SKV@resvda
- \fi
- \SKV@noexpparse\SKV@resvdb
- \begingroup
- \edef\SKV@resvdb##1##2{##1{##2{\SKV@expox\SKV@resvdb}}}%
- \everyeof{\noexpand}\endlinechar\m@ne\makeatletter
- \SKV@resvdb{\xdef\SKV@resvdb}{\scantokens\expandafter}%
- \endgroup
- \ifSKV@pl
- \gl@l@x\SKV@aftercs\let\SKV@resvda\SKV@resvdb
- \else
- \gl@l@x\expandafter\let\SKV@resvda\SKV@resvdb
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode044 12 % ,
+\def\skv@prova{\endgroup
+ \def\do##1,{%
+ \ifx\do##1\else
+ \catcode##1\string=\the\catcode##1\relax
+ \expandafter\do
\fi
}%
- \SKV@resstate
-}
-\SKV@def*\SKV@emptycmds{\SKV@savstate\SKV@testoptf\SKV@em@tycmds}
-\SKV@def\SKV@em@tycmds[#1]#2{%
- \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
- \SKV@for[#1]{#2}\SKV@resvda{%
- \ifSKV@pl
- \SKV@expnext\SKV@ensurenoscape\SKV@resvda
- \gl@l@x\SKV@aftercs\let\SKV@resvda\@empty
- \else
- \SKV@expnext\SKV@ensurescape\SKV@resvda
- \gl@l@x\expandafter\let\SKV@resvda\@empty
- \fi
- }%
- \SKV@resstate
-}
-\SKV@pdef*\SKV@csdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\def}}
-\SKV@pdef*\SKV@csgdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\gdef}}
-\SKV@pdef*\SKV@csedef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\edef}}
-\SKV@pdef*\SKV@csxdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\xdef}}
-\SKV@def*\SKV@newcs#1#2{%
- \ifSKV@st\let\l@ngrel@x\relax\else\let\l@ngrel@x\long\fi
- \ifSKV@pl
- \let\SKV@next\SKV@n@wcs
- \else
- \def\SKV@next{\l@ngrel@x\SKV@aftercs}%
- \fi
- \SKV@resstate\SKV@next#1{#2}%
-}
-\SKV@def*\SKV@n@wcs#1#2{%
- \SKV@ifcsname{#2}%
- {\SKV@csifx{#2}\relax{}{\def\resvd@a{#2}\SKV@notdefinable}}%
- {\l@ngrel@x\SKV@aftercs{#1}{#2}}%
-}
-\SKV@def*\SKV@csuse#1{\SKV@ifcsname{#1}{\@nameuse{#1}}{}}
-\SKV@pdef\SKV@expargs#1#2#3#4\@nil{%
- \begingroup
- \protected@edef\SKV@tempa{\endgroup
- \ifcase#1\relax
- \unexpanded{#2}{#3}%
- \or
- \unexpanded{#2#3}{#4}%
- \or
- \unexpanded{#2}{#3}{#4}%
- \or
- \unexpanded{#2}#3\unexpanded{#4}%
- \else
- \SKV@err{Unknown expansion type '\string#1' for
- \string\SKV@expargs}{I expected your first
- argument '\string#1' to be between 0 and 3.}%
- \fi
- }%
- \SKV@tempa
-}
-\SKV@def*\SKV@findescape#1{%
- \begingroup\escapechar92\relax
- \edef\resvd@a{\expandafter\SKV@car\string#1\@nil}%
- \expandafter\aftergroup\csname SKV@%
- \SKV@ifx\resvd@a\@backslashchar{1}{2}of2\endcsname
- \endgroup
-}
-\SKV@def*\SKV@ensurescape#1{%
- \SKV@findescape{#1}{}%
- {\SKV@err{Backslash required in '\string#1'}%
- {I expected a backslash to be the leading\SKV@MB
- character in your argument '\string#1'.}}%
-}
-\SKV@def*\SKV@ensurenoscape#1{%
- \SKV@findescape{#1}%
- {\SKV@err{Backslash not allowed in '\string#1'}%
- {I didn't expect a backslash to be the leading\SKV@MB
- character in your argument '\string#1'.}}{}%
-}
-\SKV@pdef\SKV@ifnextchar#1#2#3{%
- \let\SKV@nxc#1\def\SKV@nxa{#2}\def\SKV@nxb{#3}%
- \futurelet\@temptoks\SKV@ifnextch@r
-}
-\SKV@def*\SKV@ifnextch@r{%
- \ifx\@temptoks\SKV@nxc\let\SKV@nxb\SKV@nxa\fi\SKV@nxb
-}
-\SKV@pdef\SKV@ifchar#1#2#3{%
- \SKV@ifnextchar#1{\begingroup
- \def\SKV@tempa#1{\endgroup#2}\SKV@tempa}{#3}%
-}
-\SKV@pdef*\SKV@ifstar{\SKV@ifchar{*}}
-\SKV@pdef*\SKV@ifplus{\SKV@ifchar{+}}
-\SKV@pdef*\SKV@ifask{\SKV@ifchar{?}}
-\SKV@pdef*\SKV@ifclam{\SKV@ifchar{!}}
-\SKV@pdef*\SKV@ifright{\SKV@ifchar{>}}
-\SKV@pdef*\SKV@ifleft{\SKV@ifchar{<}}
-\SKV@pdef*\SKV@if@brack#1#2{\SKV@ifnextchar[{#1}{#2}}
-\SKV@pdef*\SKV@if@paren#1#2{\SKV@ifnextchar({#1}{#2}}
-\SKV@pdef*\SKV@if@left#1#2{\SKV@ifnextchar<{#1}{#2}}
-\SKV@pdef*\SKV@testopt#1#2{\SKV@if@brack{#1}{#1[{#2}]}}
-\SKV@pdef*\SKV@testopta#1{\SKV@t@stopta{\SKV@t@st@pta{#1}}}
-\SKV@pdef*\SKV@t@stopta#1{\SKV@ifstar{\SKV@sttrue#1}{\SKV@stfalse#1}}
-\SKV@pdef*\SKV@t@st@pta#1{\SKV@ifplus{\SKV@pltrue#1}{\SKV@plfalse#1}}
-\SKV@pdef*\SKV@t@st@p@a#1{\SKV@ifclam{\SKV@cltrue#1}{\SKV@clfalse#1}}
-\SKV@pdef*\SKV@testoptb#1{\SKV@t@stopta{\SKV@t@st@pta{\SKV@t@st@p@a{#1}}}}
-\SKV@pdef*\SKV@t@stoptb#1{\SKV@t@stopta{\SKV@t@st@pta{#1}}}
-\SKV@pdef*\SKV@testoptc#1{\SKV@t@st@pta{\SKV@t@st@p@a{#1}}}
-\SKV@pdef*\SKV@testoptd#1{\SKV@t@stopta{\SKV@testopt#1{,}}}
-\SKV@pdef*\SKV@testopte#1{\SKV@testoptb{\SKV@testopt#1{,}}}
-\SKV@pdef*\SKV@t@stopte#1{\SKV@t@stoptb{\SKV@testopt#1{,}}}
-\SKV@pdef*\SKV@testoptf#1{\SKV@testoptc{\SKV@testopt#1{,}}}
-\SKV@pdef*\SKV@testoptg#1{\SKV@ifright{\SKV@rttrue#1}{\SKV@rtfalse#1}}
-\SKV@pdef*\SKV@t@stoptg#1{\SKV@ifleft{\SKV@lttrue#1}{\SKV@ltfalse#1}}
-\SKV@pdef*\SKV@testopth#1#2{\SKV@if@left{#1}{#1<{#2}>}}
-\SKV@pdef*\SKV@testoptp#1#2{\SKV@if@paren{#1}{#1({#2})}}
-\SKV@def*\SKV@Test@pt#1{\@nameuse{SKV@\SKV@ifempty{#1}{1}{2}of2}}
-\SKV@def*\SKV@IfBrack#1#2#3{\SKV@IfBr@ck#1&[&{#2}{#3{#1}}}
-\SKV@def*\SKV@IfBr@ck#1[#2&#3#{\SKV@Test@pt{#1#2}}
-\SKV@def*\SKV@TestOpt#1#2#3{\SKV@IfBr@ck#1&[&{#2#1}{#2[{#3}]{#1}}}
-\SKV@def*\SKV@IfStar#1#2#3{\SKV@IfSt@r#1&*&{#2}{#3{#1}}}
-\SKV@def*\SKV@IfSt@r#1*#2&#3#{\SKV@Test@pt{#1#2}}
-\SKV@def*\SKV@IfPlus#1#2#3{\SKV@IfPl@s#1&+&{#2}{#3{#1}}}
-\SKV@def*\SKV@IfPl@s#1+#2&#3#{\SKV@Test@pt{#1#2}}
-\SKV@def*\SKV@IfAsk#1#2#3{\SKV@IfA@k#1&?&{#2}{#3{#1}}}
-\SKV@def*\SKV@IfA@k#1?#2&#3#{\SKV@Test@pt{#1#2}}
-\SKV@def*\SKV@csalloc#1{\@nameuse{new#1\SKV@aftercs}}
-\SKV@pdef*\csnewif{\SKV@csalloc{if}}
-\SKV@pdef*\csnewtoks{\SKV@csalloc{toks}}
-\SKV@pdef*\csnewcount{\SKV@csalloc{count}}
-\SKV@pdef*\csnewdimen{\SKV@csalloc{dimen}}
-\SKV@pdef*\csnewbox{\SKV@csalloc{box}}
-\SKV@pdef*\csnewwrite{\SKV@csalloc{write}}
-\SKV@pdef*\csnewread{\SKV@csalloc{read}}
-\SKV@pdef*\NewWrites{\SKV@swtrue\SKV@testopt\SKV@NewWrites{}}
-\SKV@pdef*\DefWrites{\SKV@swfalse\SKV@testopt\SKV@NewWrites{}}
-\SKV@def*\SKV@NewWrites[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Write stream '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewwrite{#1\SKV@tempa}%
- }%
-}
-\SKV@pdef*\NewReads{\SKV@swtrue\SKV@testopt\SKV@NewReads{}}
-\SKV@pdef*\DefReads{\SKV@swfalse\SKV@testopt\SKV@NewReads{}}
-\SKV@def*\SKV@NewReads[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Read stream '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewread{#1\SKV@tempa}%
- }%
-}
-\SKV@pdef*\NewIfs{\SKV@swtrue\SKV@testopt\SKV@NewIfs{}}
-\SKV@pdef*\DefIfs{\SKV@swfalse\SKV@testopt\SKV@NewIfs{}}
-\SKV@def*\SKV@NewIfs[#1]#2{\SKV@testopt{\SKV@N@wIfs[#1]{#2}}{false}}
-\SKV@def*\SKV@N@wIfs[#1]#2[#3]{%
- \ifSKV@sw
- \SKV@getswstate\NewIfs{#3}%
- \else
- \SKV@getswstate\DefIfs{#3}%
- \fi
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \begingroup
- \SKV@oifstrequal{\SKV@tempa}{x}{\SKV@swnameerr{x}}%
- {\SKV@oifstrequal{\SKV@tempa}{on}{\SKV@swnameerr{on}}%
- {\SKV@oifstrequal{\SKV@tempa}{off}{\SKV@swnameerr{off}}%
- {\SKV@oifstrequal{\SKV@tempa}{tog}{\SKV@swnameerr{tog}}%
- {\SKV@oifstrequal{\SKV@tempa}{switch}{\SKV@swnameerr{switch}}%
- {}}}}}\endgroup
- \ifSKV@sw
- \SKV@csifdefinable{if#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{if#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Boolean '\@backslashchar
- if#1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \SKV@aftercs\SKV@N@wIf@{if#1\SKV@tempa}%
- \@nameuse{#1\SKV@tempa\SKV@swval}%
- }%
-}
-\SKV@def*\SKV@N@wIf@#1{%
- \@tempcnta\escapechar\escapechar\m@ne
- \let#1\iffalse
- \SKV@If#1\iftrue
- \SKV@If#1\iffalse
- \let\ifon\iftrue
- \let\ifoff\iffalse
- \SKV@If#1\ifon
- \SKV@If#1\ifoff
- \escapechar\@tempcnta
-}
-\def\SKV@If#1#2{%
- \SKV@aftercs\def{\expandafter\@gobbletwo\string#1%
- \expandafter\@gobbletwo\string#2}{\let#1#2}%
-}
-\SKV@pdef*\NewBooleans{\SKV@swtrue\SKV@testopt\SKV@NewBooleans{}}
-\SKV@pdef*\DefBooleans{\SKV@swfalse\SKV@testopt\SKV@NewBooleans{}}
-\SKV@def*\SKV@NewBooleans[#1]#2{%
- \SKV@testopt{\SKV@B@oleans[#1]{#2}}{false}}
-\SKV@def*\SKV@B@oleans[#1]#2[#3]{%
- \ifSKV@sw
- \SKV@getswstate\NewBooleans{#3}%
- \else
- \SKV@getswstate\DefBooleans{#3}%
- \fi
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \SKV@oifstrequal{\SKV@tempa}{tog}{%
- \SKV@err{'tog' not allowed as a boolean name}\@ehc
- }{%
- \SKV@oifstrequal{\SKV@tempa}{switch}{%
- \SKV@err{'switch' not allowed as a boolean name}\@ehc
- }{}%
- }%
- \SKV@ifstrnotequal{#1\SKV@tempa}{x}{}{%
- \SKV@err{'\string\ifx' is a TeX primitive}%
- {Why do you want to redefine '\string\ifx'? This is dangerous.}%
- }%
- \ifSKV@sw
- \SKV@csifdefinable{if#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{if#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Switch '\@backslashchar if#1\SKV@tempa'
- redefined\on@line}%
- }%
- \fi
- \csnewif{if#1\SKV@tempa}%
- \@nameuse{#1\SKV@tempa\SKV@swval}%
- }%
-}
-\SKV@pdef*\NewTogs{\SKV@swtrue\SKV@testopt\SKV@NewTogs{}}
-\SKV@pdef*\DefTogs{\SKV@swfalse\SKV@testopt\SKV@NewTogs{}}
-\SKV@def*\SKV@NewTogs[#1]#2{\SKV@testopt{\SKV@NewT@gs[#1]{#2}}{false}}
-\SKV@def*\SKV@NewT@gs[#1]#2[#3]{%
- \ifSKV@sw
- \SKV@getswstate\NewTogs{#3}%
- \else
- \SKV@getswstate\DefTogs{#3}%
- \fi
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \edef\SKV@tempa{#1\SKV@tempa}%
- \ifSKV@sw
- \SKV@expnext\newtog\SKV@tempa
- \else
- \SKV@expnext\deftog\SKV@tempa
- \fi
- \SKV@expargs{0}{\@nameuse{tog\SKV@swval}}\SKV@tempa\@nil
- }%
-}
-\SKV@pdef*\NewToks{\SKV@swtrue\SKV@testopt\SKV@NewToks{}}
-\SKV@pdef*\DefToks{\SKV@swfalse\SKV@testopt\SKV@NewToks{}}
-\SKV@def*\SKV@NewToks[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Token register '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewtoks{#1\SKV@tempa}%
- }%
-}
-\SKV@pdef*\NewCounts{\SKV@swtrue\SKV@testopt\SKV@NewCounts{}}
-\SKV@pdef*\DefCounts{\SKV@swfalse\SKV@testopt\SKV@NewCounts{}}
-\SKV@def*\SKV@NewCounts[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Counter register '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewcount{#1\SKV@tempa}%
- }%
-}
-\SKV@pdef*\NewDimens{\SKV@swtrue\SKV@testopt\SKV@NewDimens{}}
-\SKV@pdef*\DefDimens{\SKV@swfalse\SKV@testopt\SKV@NewDimens{}}
-\SKV@def*\SKV@NewDimens[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Dimension register '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewdimen{#1\SKV@tempa}%
- }%
-}
-\SKV@pdef*\NewBoxes{\SKV@swtrue\SKV@testopt\SKV@NewBoxes{}}
-\SKV@pdef*\DefBoxes{\SKV@swfalse\SKV@testopt\SKV@NewBoxes{}}
-\SKV@def*\SKV@NewBoxes[#1]#2{%
- \SKV@for[,]{#2}\SKV@tempa{%
- \SKV@expnext\SKV@ensurenoscape\SKV@tempa
- \ifSKV@sw
- \SKV@csifdefinable{#1\SKV@tempa}\relax
- \else
- \SKV@ifcsundef{#1\SKV@tempa}{}{%
- \SKV@vbmsg{warn}{Box register '\@backslashchar
- #1\SKV@tempa' redefined\on@line}%
- }%
- \fi
- \csnewbox{#1\SKV@tempa}%
- }%
-}
-\SKV@def\SKV@expnext#1#2{%
- \SKV@ifblank{#1}{%
- \SKV@badargerr{SKV@expnext}{first}%
- }{%
- \SKV@ifblank{#2}{%
- \SKV@badargerr{SKV@expnext}{second}%
- }{%
- \ifcat$\detokenize\expandafter{\SKV@cdr#1\@nil}$%
- \SKV@afterelsefi
- \expandafter#1\expandafter{#2}%
- \else
- \SKV@afterfi
- \SKV@badargerr{SKV@expnext}{first}%
- \fi
- }%
- }%
-}
-\SKV@pdef*\SKV@ifnewcmd{\SKV@savstate\SKV@t@stopte\SKV@ifn@wcmd}
-\SKV@def*\SKV@ifn@wcmd[#1]#2{%
- \ifSKV@st
- \ifSKV@pl
- \def\SKV@ndl{\SKV@for*[#1]#2}%
- \else
- \def\SKV@ndl{\SKV@tfor*#2}%
- \fi
- \else
- \ifSKV@pl
- \def\SKV@ndl{\SKV@for[#1]{#2}}%
- \else
- \def\SKV@ndl{\SKV@tfor{#2}}%
- \fi
- \fi
- \SKV@ndl\SKV@ndl{%
- \ifSKV@pl
- \SKV@despacectt\SKV@ndl
- \SKV@csifdefinable\SKV@ndl\relax
- \else
- \expandafter\SKV@ifdefinable\SKV@ndl\relax
- \fi
- }%
- \SKV@resstate
-}
-\let\SKV@no\z@
-\SKV@pdef*\SKV@aftergroup{%
- \SKV@ifstar{\SKV@aft@rgroup\@firstofone}%
- {\SKV@aft@rgroup\unexpanded}%
-}
-\SKV@def\SKV@aft@rgroup#1#2{%
- \edef\SKV@no{\the\numexpr\SKV@no+1}%
- \SKV@aftercs\xdef{SKV@aft@rgr@up\SKV@no}{%
- \SKV@csgundef{SKV@aft@rgr@up\SKV@no}%
- #1{#2}%
- }%
- \SKV@aftercs\aftergroup{SKV@aft@rgr@up\SKV@no}%
-}
-\SKV@pdef*\SKV@afterassignment{%
- \SKV@ifstar{\SKV@aft@rassignment\@firstofone}%
- {\SKV@aft@rassignment\unexpanded}%
-}
-\SKV@def\SKV@aft@rassignment#1#2{%
- \begingroup
- \edef\SKV@no{\the\numexpr\SKV@no+1}%
- \SKV@aftercs\xdef{SKV@aft@rassignm@nt\SKV@no}{%
- \SKV@csgundef{SKV@aft@rassignm@nt\SKV@no}%
- #1{#2}%
- }%
- \expandafter\endgroup\expandafter\afterassignment
- \csname SKV@aft@rassignm@nt\SKV@no\endcsname
-}
-\SKV@def*\SKV@sp@def#1#2{%
- \edef\@sp@def{\the\SKV@toks}%
- \SKV@toks\expandafter{%
- \romannumeral-`\q\SKV@sp@d@f\noexpand\noexpand#1& &}%
- \edef#2{\the\SKV@toks}%
- \SKV@toks\expandafter{\@sp@def}%
- \SKV@undef\@sp@def
-}
-\SKV@def*\SKV@sp@d@f#1 &{\SKV@sp@d@f@#1&}
-\SKV@def*\SKV@sp@d@f@#1&#2{\romannumeral-`\q#1}
-\SKV@def*\SKV@expox#1{\unexpanded\expandafter{#1}}
-\SKV@def*\SKV@csexpox#1{\SKV@aftercs\SKV@expox{#1}}
-\SKV@def*\SKV@exptx#1{\unexpanded\SKV@threexp{#1}}
-\SKV@def*\SKV@csexptx#1{\SKV@aftercs\SKV@exptx{#1}}
-\SKV@def\SKV@noexpcs#1{\unexpanded\expandafter{\csname#1\endcsname}}
-\SKV@pdef*\SKV@undef#1{\let#1\SKV@undefined}
-\SKV@pdef*\SKV@gundef{\global\SKV@undef}
-\SKV@pdef*\SKV@csundef#1{\SKV@aftercs\SKV@undef{#1}}
-\SKV@pdef*\SKV@csgundef{\global\SKV@csundef}
-\SKV@def*\SKV@undeflist{\SKV@savstate\SKV@t@st@p@a\SKV@und@flist}
-\SKV@def*\SKV@und@flist#1{%
- \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
- \XKV@for@n{#1}\SKV@resvd{%
- \SKV@expnext\SKV@ensurescape\SKV@resvd
- \gl@l@x\expandafter\SKV@undef\SKV@resvd
- }%
- \SKV@resstate
-}
-\SKV@pdef*\SKV@Undef{\SKV@savstate\SKV@testopte\SKV@Und@f}
-\SKV@def*\SKV@Und@f[#1]#2{%
- \ifSKV@st
- \ifSKV@pl
- \def\SKV@ndl{\SKV@for*[#1]#2}%
- \else
- \def\SKV@ndl{\SKV@tfor*#2}%
- \fi
- \else
- \ifSKV@pl
- \def\SKV@ndl{\SKV@for[#1]{#2}}%
- \else
- \def\SKV@ndl{\SKV@tfor{#2}}%
- \fi
- \fi
- \SKV@ndl\SKV@ndl{%
- \ifSKV@pl
- \SKV@despacectt\SKV@ndl
- \ifSKV@cl\expandafter\global\fi
- \SKV@threexp\let
- \expandafter\csname\SKV@ndl\endcsname\SKV@undefined
- \else
- \ifSKV@cl\expandafter\global\fi
- \expandafter\let\SKV@ndl\SKV@undefined
- \fi
- }%
- \SKV@resstate
-}
-\SKV@def*\SKV@ifdef#1{%
- \SKV@ifdefined{#1}%
- {\@nameuse{SKV@\SKV@ifx{#1}\relax{2}{1}of2}}\@secondoftwo
-}
-\SKV@def*\SKV@ifundef#1{\@nameuse{SKV@\SKV@ifdef{#1}{2}{1}of2}}
-\SKV@def*\SKV@ifcsdef#1{%
- \SKV@ifcsname{#1}%
- {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
- \relax{2}{1}of2}}\@secondoftwo
-}
-\SKV@def*\SKV@ifcsundef#1{\@nameuse{SKV@\SKV@ifcsdef{#1}{2}{1}of2}}
-\SKV@def*\SKV@ifonedef#1{%
- \def\SKV@resvda{#1}\SKV@swtrue
- \XKV@whilist\SKV@resvda\SKV@resvdb\ifSKV@sw\fi{%
- \SKV@oifdefined\SKV@resvdb\SKV@swfalse\SKV@swtrue
- }%
- \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
-}
-\SKV@def\DeclarePackageCommand#1#2{%
- \SKV@ensurescape{#2}%
- \SKV@ifdef#2{%
- \edef\resvd@a{\expandafter\@gobble\string#2}%
- \SKV@cslet{Saved\resvd@a}#2%
- \edef\resvd@a##1{\SKV@AtEndAfterPackageEnd%
- {##1Saved\resvd@a\noexpand\endcsname}}%
- \resvd@a{\expandafter\let\expandafter#2\csname}%
- \SKV@undef\resvd@a
- }{\SKV@AtEndAfterPackageEnd{\SKV@Undef!#2}}%
- #1#2%
-}
-\SKV@pdef*\SKV@providedef{\@star@or@long{\SKV@pr@videdef{}}}
-\SKV@pdef*\SKV@providerobustdef{\@star@or@long{\SKV@pr@videdef\protected}}
-\SKV@def\SKV@pr@videdef#1#2{%
- \SKV@ensurescape{#2}%
- \edef\SKV@prov@d{\expandafter\@gobble\string#2}%
- \SKV@aftercs\let{SKV@test@\SKV@prov@d}\SKV@undefined
- \SKV@ifdef#2{%
- \SKV@vbmsg{info}{Command '\string#2' already defined:\SKV@MB
- Not redefined\on@line}%
- \SKV@afterassignment{\SKV@gundef\SKV@pr@vid}%
- \def\SKV@pr@vid
- }{%
- \SKV@afterassignment{%
- \SKV@aftercs\edef{SKV@test@\SKV@prov@d}%
- {\expandafter\strip@prefix\meaning#2}%
- }%
- \l@ngrel@x#1\def#2%
- }%
-}
-\SKV@def\TestProvidedCommand#1{%
- \SKV@ensurescape{#1}%
- \begingroup
- \SKV@ifmacro#1{%
- \edef\SKV@resvda{\expandafter\@gobble\string#1}%
- \edef\SKV@resvdb{\expandafter\strip@prefix\meaning#1}%
- \expandafter\aftergroup\csname SKV@\expandafter
- \ifx\expandafter\SKV@resvdb
- \csname SKV@test@\SKV@resvda\endcsname
- 1\else2\fi of2\endcsname
- }{\aftergroup\@secondoftwo}%
- \endgroup
-}
-\SKV@pdef*\SKV@newdef{\SKV@def}
-\SKV@providerobustdef*\newdef{\SKV@def}
-\SKV@providerobustdef*\redef{\SKV@redef}
-\SKV@pdef*\SKV@robustdef{\SKV@pdef}
-\SKV@providerobustdef*\robustdef{\SKV@pdef}
-\SKV@providerobustdef*\robustredef{\SKV@predef}
-\SKV@providerobustdef*\providedef{\SKV@providedef}
-\SKV@providerobustdef*\providerobustdef{\SKV@providerobustdef}
-\SKV@providerobustdef*\aftercommission{\SKV@afterassignment}
-\SKV@providerobustdef*\aftercoterie{\SKV@aftergroup}
-\SKV@def*\SKV@ifmacro#1{%
- \begingroup
- \edef\SKV@tempa##1{\def##1####1\detokenize{macro}:####2&}%
- \SKV@tempa\SKV@tempa{\expandafter\aftergroup
- \csname SKV@\SKV@ifblank{##2}{2}{1}of2\endcsname}%
- \edef\SKV@tempb##1{##1\detokenize{macro}:&}%
- \SKV@tempb{\expandafter\SKV@tempa\meaning#1}%
- \endgroup
-}
-\SKV@def\SKV@csifmacro{\SKV@aftercs\SKV@ifmacro}
-\SKV@def\SKV@ifnotmacro#1{\SKV@ifmacro{#1}\@secondoftwo\@firstoftwo}
-\SKV@def*\SKV@simplecmdpatch{\begingroup\@makeother{\#}%
- \SKV@testopt\SKV@simpl@cmdpatch{########1}}
-\SKV@def*\SKV@simpl@cmdpatch[#1]#2#3#4{%
- \edef\SKV@resvda##1##2{%
- \def##1####1\detokenize{macro:}####2->####3&{%
- #1\def\string#2####2{##2####3&}%
- }%
- \def##2####1\detokenize{#3}####2&{####1\detokenize{#4}####2}%
- \edef##1{##1\meaning#2&}%
- }%
- \SKV@resvda\SKV@resvda\SKV@resvdb
- \everyeof{\noexpand}\endlinechar\m@ne\makeatletter
- \catcode`\#=6\relax
- \scantokens\expandafter{\SKV@resvda}%
- \global\let#2#2%
- \endgroup
-}
-\SKV@def*\SKV@ifrelax#1{%
- \SKV@ensurescape{#1}%
- \SKV@ifdefined{#1}%
- {\@nameuse{SKV@\SKV@ifx{#1}\relax{1}{2}of2}}\@secondoftwo
-}
-\SKV@def*\SKV@ifcsrelax#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsname{#1}%
- {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
- \relax{1}{2}of2}}\@secondoftwo
-}
-\SKV@def*\SKV@ifdefax#1{%
- \SKV@ensurescape{#1}%
- \SKV@ifdefined{#1}%
- {\@nameuse{SKV@\SKV@ifx{#1}\relax{2}{1}of3}}\@thirdofthree
-}
-\SKV@def*\SKV@ifcsdefax#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsname{#1}%
- {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname
- \relax{2}{1}of3}}\@thirdofthree
-}
-\SKV@def*\SKV@despacectt#1{%
- \SKV@ensurescape{#1}%
- \SKV@expnext\SKV@sp@def{#1}#1%
-}
-\SKV@def\SKV@detokdespace#1{%
- \edef#1{\detokenize\expandafter{#1}}%
- \SKV@despacectt#1%
+ \edef\skv@restorecodes{\do035,064,123,125,061,059,\do,}%
}
-\SKV@def\SKV@ifblank#1{\SKV@ifbl@nk#1&&\@secondoftwo\@firstoftwo:}
-\SKV@def\SKV@ifbl@nk#1#2&#3#4#5:{#4}
-\SKV@def\SKV@ifnotblank#1{\SKV@ifbl@nk#1&&\@firstoftwo\@secondoftwo:}
-\SKV@def\SKV@oifblank#1{\expandafter\SKV@ifblank\expandafter{#1}}
-\SKV@def\SKV@xifblank#1{\SKV@expargs{0}\SKV@ifblank{#1}\@nil}
-\SKV@def\SKV@ifstrequal#1#2{%
- \begingroup
- \edef\resvd@a{\detokenize{#1}}%
- \edef\resvd@b{\detokenize{#2}}%
- \SKV@despacectt\resvd@a\SKV@despacectt\resvd@b
- \expandafter\aftergroup
- \csname SKV@\SKV@ifx\resvd@a\resvd@b{1}{2}of2\endcsname
- \endgroup
-}
-\SKV@def\SKV@ifstrnotequal#1#2{%
- \SKV@ifstrequal{#1}{#2}\@secondoftwo\@firstoftwo}
-\SKV@def\SKV@oifstrequal#1#2{%
- \@expandtwoargs\SKV@ifstrequal{\SKV@expox{#1}}{\SKV@expox{#2}}}
-\SKV@def\SKV@xifstrequal#1#2{\@expandtwoargs\SKV@ifstrequal{#1}{#2}}
-\SKV@def\SKV@ifempty#1{\@nameuse{SKV@\ifcat$\detokenize{#1}$1\else2\fi of2}}
-\SKV@def\SKV@ifnotempty#1{\@nameuse{SKV@\SKV@ifempty{#1}{2}{1}of2}}
-\SKV@def\SKV@oifempty#1{\SKV@expnext\SKV@ifempty{#1}}
-\SKV@def\SKV@xifempty#1{\SKV@expargs{0}\SKV@ifempty{#1}\@nil}
-\SKV@def*\SKV@remparser{\SKV@testopt\SKV@remp@rser{,}}
-\SKV@def\SKV@remp@rser[#1]#2{%
- \begingroup
- \ifx#2\@empty\else
- \edef#2{#1\SKV@expox{#2}}%
- \def\SKV@tempa#1##1\@nil{%
- \gdef#2{##1}\futurelet\@temptoks\SKV@t@mp##1\@nil
- }%
- \def\SKV@t@mp##1\@nil{%
- \ifx\@temptoks\@sptoken
- \SKV@expnext\SKV@sp@def{#2}#2%
- \expandafter\SKV@tempa\expandafter#1#2\@nil
- \else
- \if#1\@temptoks\expandafter\SKV@tempa#2\@nil\fi
- \fi
+\skv@prova
+\catcode035 06 % #
+\catcode064 11 % @
+\catcode123 01 % {
+\catcode125 02 % }
+\catcode061 12 % =
+\catcode044 12 % ,
+\def\do#1=#2,{%
+ \ifx\do#1\else
+ \edef\skv@restorecodes{%
+ \skv@restorecodes
+ \catcode#1=\the\catcode#1\relax
}%
- \expandafter\SKV@tempa#2\@nil
+ \catcode#1=#2\relax
+ \expandafter\do
\fi
- \endgroup
-}
-\SKV@pdef*\SKV@appto{\SKV@savstate\SKV@testoptb{\SKV@hooktomac{>}}}
-\SKV@pdef*\SKV@prepto{\SKV@savstate\SKV@testoptb{\SKV@hooktomac{<}}}
-\SKV@def\SKV@hooktomac#1#2#3{%
- \ifSKV@st\let\SKV@iii\SKV@expox\else\let\SKV@iii\unexpanded\fi
- \ifSKV@pl
- \let\@ifundef\SKV@ifcsundef\let\SKV@iv\SKV@csexpox
- \def\SKV@i##1{\def\SKV@ii####1{\SKV@aftercs##1{####1}}}%
- \ifSKV@cl\SKV@i\xdef\else\SKV@i\edef\fi
- \else
- \let\@ifundef\SKV@ifundef\let\SKV@iv\SKV@expox
- \ifSKV@cl\def\SKV@ii##1{\xdef##1}\else
- \def\SKV@ii##1{\edef##1}\fi
- \fi
- \@ifundef{#2}{%
- \SKV@ii{#2}{\SKV@iii{#3}}%
- }{%
- \SKV@ifstrequal{#1}{>}%
- {\SKV@ii{#2}{\SKV@iv{#2}\SKV@iii{#3}}}%
- {\SKV@ii{#2}{\SKV@iii{#3}\SKV@iv{#2}}}%
- }%
- \SKV@resstate
- \SKV@undeflist!{\SKV@i,\SKV@ii,\SKV@iii,\SKV@iv}%
-}
-\SKV@pdef\apptomac#1#2{%
- \SKV@ifundef{#1}{\edef#1{\unexpanded{#2}}}%
- {\edef#1{\SKV@expox{#1}\unexpanded{#2}}}%
-}
-\SKV@pdef*\gapptomac{\global\apptomac}
-\SKV@pdef*\csapptomac{\SKV@aftercs\apptomac}
-\SKV@pdef*\csgapptomac{\global\csapptomac}
-\SKV@pdef\preptomac#1#2{%
- \SKV@ifundef{#1}{\edef#1{\unexpanded{#2}}}%
- {\edef#1{\unexpanded{#2}\SKV@expox{#1}}}%
-}
-\SKV@pdef*\gpreptomac{\global\preptomac}
-\SKV@pdef*\cspreptomac{\SKV@aftercs\preptomac}
-\SKV@pdef*\csgpreptomac{\global\cspreptomac}
-\SKV@pdef*\SKV@addtolist{\SKV@savstate\SKV@testoptc{%
- \SKV@t@stoptg{\SKV@testopt\SKV@addt@list{,}}}}
-\SKV@def*\SKV@addt@list[#1]{%
- \def\parser{#1}%
- \ifSKV@cl\let\glob@l@def\xdef\else\let\glob@l@def\edef\fi
- \ifSKV@pl
- \def\SKV@next##1{\SKV@aftercs\SKV@addt@l@st{##1}}%
- \else
- \let\SKV@next\SKV@addt@l@st
- \fi
- \SKV@next
-}
-\SKV@def\SKV@addt@l@st#1#2{%
- \SKV@ifundef{#1}{%
- \glob@l@def#1{\SKV@expox{#2}}%
- }{%
- \SKV@ifx#1\@empty{%
- \glob@l@def#1{\SKV@expox{#2}}%
- }{%
- \ifSKV@lt
- \glob@l@def#1{\SKV@expox{#2}\parser\SKV@expox{#1}}%
- \else
- \glob@l@def#1{\SKV@expox{#1}\parser\SKV@expox{#2}}%
- \fi
- }%
- }%
- \SKV@resstate
}
-\SKV@pdef*\SKV@relax#1{\let#1\relax}
-\SKV@pdef*\SKV@grelax{\global\SKV@relax}
-\SKV@pdef*\SKV@csrelax{\SKV@aftercs\SKV@relax}
-\SKV@pdef*\SKV@csgrelax{\global\SKV@csrelax}
-\@ifpackageloaded{atveryend}{%
- \@ifpackagecurrent{atveryend}{2010/03/24}{}{%
- \SKV@err{Your loaded version of atveryend package is
- not current}\@ehc}}{\RequirePackage{atveryend}[2010/03/24]}
-\SKV@pdef*\SKV@notprerr{%
- \SKV@err{You have issued a preamble command here}%
- {Move shown command to document preamble.}%
-}
-\SKV@pdef*\SKV@notenderr{%
- \SKV@err{You've called an \string\enddocument\space command\SKV@MB
- at the wrong place}{Move command to before \string\enddocument.}%
-}
-\SKV@pdef*\SKV@AtDocumentStart{\AtBeginDocument}
-\SKV@pdef*\SKV@BeforeDocumentStart{\SKV@appto!\SKV@beforedocstart}
-\def\SKV@beforedocstart{}
-\SKV@prepto\document{%
- \endgroup
- \let\SKV@BeforeDocumentStart\@firstofone
- \SKV@beforedocstart
- \let\SKV@BeforeDocumentStart\SKV@notprerr
- \SKV@gundef\SKV@beforedocstart
- \begingroup
-}
-\SKV@pdef*\SKV@AfterDocumentStart{\SKV@appto!\SKV@afterdocstart}
-\def\SKV@afterdocstart{}
-\SKV@appto\document{%
- \let\SKV@AfterDocumentStart\@firstofone
- \SKV@afterdocstart
- \let\SKV@AfterDocumentStart\SKV@notprerr
- \SKV@gundef\SKV@afterdocstart\ignorespaces
-}
-\SKV@BeforeDocumentStart{\let\SKV@AtDocumentStart\@firstofone}
-\SKV@pdef*\SKV@AtDocumentEnd{\AtEndDocument}
-\SKV@pdef*\SKV@BeforeLastPage{\SKV@appto!\SKV@beforelastpage}
-\def\SKV@beforelastpage{}
-\SKV@AtDocumentEnd{%
- \let\SKV@bef@relastpage\AtVeryEnd@BeforeClearDocumentHook
- \def\AtVeryEnd@BeforeClearDocumentHook{%
- \let\SKV@BeforeLastPage\@firstofone
- \SKV@beforelastpage\SKV@bef@relastpage
- \let\SKV@BeforeLastPage\SKV@notenderr
- \SKV@Undef!{\SKV@beforelastpage\SKV@bef@relastpage}%
- }%
-}
-\SKV@pdef*\SKV@AfterLastPage{\SKV@appto!\SKV@afterlastpage}
-\def\SKV@afterlastpage{}
-\SKV@AtDocumentEnd{%
- \let\SKV@afterl@stpage\AtVeryEnd@AfterLastShipoutHook
- \def\AtVeryEnd@AfterLastShipoutHook{%
- \let\SKV@AfterLastPage\@firstofone
- \SKV@afterlastpage\SKV@afterl@stpage
- \let\SKV@AfterLastPage\SKV@notenderr
- \SKV@Undef!{\SKV@afterlastpage\SKV@afterl@stpage}%
- }%
-}
-\SKV@pdef*\SKV@AfterDocumentEnd{\SKV@appto!\SKV@afterenddoc}
-\def\SKV@afterenddoc{}
-\SKV@AtDocumentEnd{%
- \let\SKV@aft@renddoc\AtVeryEnd@AtVeryEndDocumentHook
- \def\AtVeryEnd@AtVeryEndDocumentHook{%
- \let\SKV@AfterDocumentEnd\@firstofone
- \SKV@afterenddoc\SKV@aft@renddoc
- \let\SKV@AfterDocumentEnd\SKV@notenderr
- \SKV@Undef!{\SKV@afterenddoc\SKV@aft@renddoc}%
+\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,\do=,%
+
+\ProvidesPackage{skeyval}[2012/10/15 v1.1 Robust key-value parser (AM)]
+\NeedsTeXFormat{LaTeX2e}[2011/06/27]
+
+\input skeyval-core
+
+\skvrobustdef*\skvAfterEndPackage{%
+ \skvifcsdef{\@currname.\@currext-skv@endpkghook}{}{%
+ \@namedef{\@currname.\@currext-skv@endpkghook}{}%
}%
+ \expandafter\g@addto@macro
+ \csname\@currname.\@currext-skv@endpkghook\endcsname
}
-\SKV@pdef\SKV@AtPackageEnd{\AtEndOfPackage}
-\SKV@pdef*\SKV@BeforePackageEnd{%
- \SKV@prepto+{\@currname.\@currext-h@@k}%
-}
-\SKV@pdef*\SKV@AfterPackageEnd{%
- \SKV@appto+{\@currname.\@currext-skvh@@k}%
-}
-\let\SKV@AtClassEnd\SKV@AtPackageEnd
-\let\SKV@BeforeClassEnd\SKV@BeforePackageEnd
-\let\SKV@AfterClassEnd\SKV@AfterPackageEnd
-\SKV@prepto\@popfilename{%
- \SKV@csuse{\@currname.\@currext-skvh@@k}%
- \SKV@csgundef{\@currname.\@currext-skvh@@k}%
-}
-\SKV@pdef\@afterpackageloaded#1{%
- \SKV@AtDocumentStart{%
- \SKV@ifcsdef{ver@#1.\@pkgextension}{}{%
- \SKV@warn{Package '#1' was never loaded}%
+\skvrobustdef*\skvAfterPackage#1{%
+ \skvAfterBeginDocument{%
+ \skvifcsdef{ver@#1.\@pkgextension}{}{%
+ \skv@warn{Package '#1' was never loaded}%
}%
}
- \SKV@ifcsdef{ver@#1.\@pkgextension}{%
- \let\SKV@next\@firstofone
+ \skvifcsdef{ver@#1.\@pkgextension}{%
+ \@firstofone
}{%
- \def\SKV@next{\SKV@appto+{#1.\@pkgextension-skvh@@k}}%
+ \skvappendtomacro{#1.\@pkgextension-skv@endpkghook}%
}%
- \SKV@next
}
-\let\SKV@steno\z@
-\SKV@pdef*\SKV@for{\SKV@savstate\SKV@testoptd\SKV@f@r}
-\SKV@pdef*\SKV@f@r[#1]{%
- \let\SKV@steno\@ne
- \ifSKV@st
- \def\SKV@next{\SKV@for@b[#1]}%
- \else
- \def\SKV@next{\SKV@CommandGenParser{#1}\SKV@for@a}%
- \fi
- \SKV@next
-}
-\SKV@pdef*\SKV@CommandGenParser#1{%
- \def\parser{#1}%
- \protected\long\def\SKV@for@a##1##2##3{%
- \SKV@ifblank{##1}\SKV@fornoop\SKV@forloop
- ##2{##3}##1#1\@nil
+\xdef\@popfilename{%
+ \unexpanded{%
+ \csname\@currname.\@currext-skv@endpkghook\endcsname
+ \expandafter\let
+ \csname\@currname.\@currext-skv@endpkghook\endcsname\relax
}%
- \long\def\SKV@forloop##1##2##3#1##4\@nil{%
- \edef##1{\unexpanded{##3}}%
- \SKV@ifstrequal{##3}{\listbreak}{%
- \SKV@keylistrema##4\@nil#1%
- }{%
- \SKV@ifblank{##4}{%
- ##2\relax
- \ifnum\SKV@steno=\@ne\expandafter\SKV@resstate\fi
- \let\SKV@steno\z@
- }{%
- ##2\relax\SKV@forloop##1{##2}##4\@nil
- }%
- }%
- }%
- \long\def\SKV@fornoop##1\@nil{}%
-}
-\SKV@pdef*\SKV@for@b{\SKV@testopt\SKV@f@r@b{,}}
-\SKV@def\SKV@f@r@b[#1]#2{%
- \SKV@CommandGenParser{#1}\SKV@expnext\SKV@for@a{#2}%
-}
-\SKV@pdef*\SKV@tfor{\SKV@ifstar\SKV@tfor@b\SKV@tfor@a}
-\SKV@pdef*\SKV@tfor@a#1#2#3{%
- \SKV@ifblank{#1}{%
- \SKV@vbmsg{warn}{Empty list for '\string\SKV@tfor@a'\on@line}%
- }{%
- \SKV@ifblank{#3}{%
- \SKV@vbmsg{warn}%
- {Empty function for '\string\SKV@tfor@a'\on@line}%
- }{%
- \SKV@tforloop#1\@nil\@nil&#2{#3}%
- }%
- }%
-}
-\SKV@def\SKV@tforloop#1#2&#3#4{%
- \long\def#3{#1}%
- \SKV@ifstrequal{#1}{\listbreak}{%
- \let\SKV@next\SKV@tforrema
- }{%
- \SKV@ifstrequal{#1}{\@nil}{%
- \let\SKV@next\SKV@tfornoop
- }{%
- #4\relax\let\SKV@next\SKV@tforloop
- }%
- }%
- \SKV@next#2&#3{#4}%
-}
-\SKV@def\SKV@tfornoop#1&#2#3{}
-\SKV@pdef*\SKV@tforrema#1\@nil\@nil&#2#3{%
- \long\edef\SKV@remainder{\unexpanded{#1}}%
-}
-\SKV@pdef*\SKV@tfor@b#1#2#3{\SKV@expnext\SKV@tfor@a{#1}#2{#3}}
-\SKV@def*\SKV@preamblecmds{}
-\SKV@pdef*\SKV@onlypreamble{\SKV@savstate\SKV@t@st@pta\SKV@onlypre@mble}
-\SKV@pdef*\SKV@onlypre@mble#1{%
- \SKV@for[,]{#1}\SKV@resvd{%
- \SKV@despacectt\SKV@resvd
- \ifSKV@pl
- \SKV@expnext\SKV@ensurenoscape\SKV@resvd
- \edef\SKV@resvd##1##2{\SKV@appto!##1{##2\SKV@noexpcs{\SKV@resvd}}}%
- \else
- \SKV@expnext\SKV@ensurescape\SKV@resvd
- \edef\SKV@resvd##1##2{\SKV@appto!##1{##2\SKV@expox{\SKV@resvd}}}%
- \fi
- \SKV@resvd\SKV@preamblecmds\SKV@dopreamble
- }%
- \SKV@resstate
-}
-\SKV@AfterDocumentStart{%
- \gdef\SKV@dopreamble#1{%
- \gdef#1{\SKV@err{'\string#1' is a preamble command}%
- {Move command '\string#1' to document preamble.}}%
- }%
- \SKV@preamblecmds
- \global\let\SKV@dopreamble\@gobble
-}
-\SKV@pdef*\SKV@onlypackage{%
- \SKV@xifempty{\@currname\@currext}{%
- \SKV@err{Not in package environment}%
- {The command at top level of this message\SKV@MB
- is available only in package environment.}%
- }{}%
-}
-\def\SKV@aftergroupdef#1#2{%
- \expandafter\endgroup\expandafter\def\expandafter#1%
- \expandafter{#2}%
+ \unexpanded\expandafter{\@popfilename}%
}
-\SKV@def*\SKV@noexpparse#1{%
- \begingroup
- \def\SKV@resa{}%
- \edef\SKV@tempa{\detokenize\expandafter{#1}\@backslashchar&}%
- \edef\SKV@tempb##1{\def##1####1\@backslashchar####2&}%
- \SKV@tempb\SKV@tempb{%
- \SKV@ifempty{##2}{%
- \edef\SKV@resa{\SKV@expox\SKV@resa##1}%
- }{%
- \edef\SKV@resa{\SKV@expox\SKV@resa##1%
- \string\noexpand\@backslashchar}%
- \SKV@tempb##2&%
- }%
- }%
- \expandafter\SKV@tempb\SKV@tempa
- \expandafter\endgroup\expandafter\toks@\expandafter{\SKV@resa}%
- \edef#1{\the\toks@}%
-}
-\SKV@def*\SKV@CommandKeyParser#1{%
- \long\def\SKV@d@fine@keylist##1{%
- \global\let\ifSKV@st\ifSKV@st
- \endgroup
- \SKV@undeflist!{\skif,\skifx,\skifcase,\skor,\skelse,\skfi}%
- \ifSKV@st
- \edef\@keylist{\detokenize\expandafter{##1}}%
- \else
- \edef\@keylist{\detokenize{##1}}%
- \fi
- \SKV@scantoksa\@keylist
- \SKV@resstate
- \SKV@expnext\SKV@checksanitizec\@keylist\SKV@tempa
- \expandafter\SKV@readkeylist\SKV@tempa#1\@nil
- }%
- \long\def\SKV@readkeylist##1#1##2\@nil{%
- \SKV@ifblank{##1}{}%
- {%
- \SKV@ifstrequal{##1}{\listbreak}{%
- \SKV@keylistrema##2\@nil#1%
- }{%
- \SKV@define@multkeys##1\@nil
- \SKV@ifblank{##2}\relax{\SKV@readkeylist##2\@nil}%
- }%
- }%
- }%
-}
-\SKV@def*\SKV@checksanitizec#1#2{%
- \XKV@ch@cksanitize{#1}#2;%
- \ifin@\else\XKV@ch@cksanitize{#1}#2,\fi
- \ifin@\@selective@sanitize[0]{,;}#2\fi
-}
-\SKV@pdef\SKV@checkchoice#1#2#3#4{%
- \XKV@savstate\XKV@sttrue\XKV@pltrue
- \SKV@expargs{3}{\XKV@checkchoice[\val\nr]}{{#1}{#2}}{{#3}{#4}}\@nil
- \XKV@resstate
-}
-\SKV@simplecmdpatch\XKV@ch@ckch@ice{%
- \XKV@err{value `\the\XKV@toks' is not allowed}%
-}{%
- \SKV@err{Value '\the\XKV@toks' is not allowed}%
- {You have submitted an invalid value for a key.\SKV@MB
- You may proceed if you like but expect funny results.}%
-}
-\SKV@simplecmdpatch\XKV@@ch@ckchoice{%
- \XKV@err{value `\the\XKV@toks' is not allowed}%
-}{%
- \SKV@err{Value '\the\XKV@toks' is not allowed}%
- {You have submitted an invalid value for a key.\SKV@MB
- You may proceed if you like but expect funny results.}%
-}
-\SKV@pdef*\SKV@inputerr#1#2{%
- \SKV@err{Erroneous value '#1' for key '#2'}%
- {Please use the correct value for key '#2'\SKV@MB
- of families '\XKV@fams'.}%
-}
-\SKV@def*\SKV@despacelist{\SKV@savstate\SKV@testoptd\SKV@desp@celist}
-\SKV@def*\SKV@desp@celist[#1]#2{%
- \begingroup
- \let\SKV@resa\@empty
- \ifSKV@st
- \def\SKV@dsl{\SKV@for*[#1]#2}%
- \else
- \def\SKV@dsl{\SKV@for[#1]{#2}}%
- \fi
- \SKV@dsl\SKV@dsl{%
- \SKV@despacectt\SKV@dsl
- \SKV@appto*\SKV@resa{\expandafter#1\SKV@dsl}%
- }%
- \ifx\SKV@resa\@empty\else\SKV@remparser[#1]\SKV@resa\fi
- \ifSKV@st\global\let#2\SKV@resa\fi
- \endgroup
- \SKV@resstate
-}
-\SKV@def*\SKV@tdespacelt#1{%
- \SKV@tfor{#1}\SKV@dsl{\expandafter\SKV@despacectt\SKV@dsl}%
-}
-\SKV@pdef*\ReserveKeyPrefixNames{\SKV@ifstar\SKV@rkpn@m@s\SKV@rkpn@mes}
-\SKV@def*\SKV@rkpn@mes#1{\SKV@appto!\SKV@rkpnames{,#1}}
-\SKV@def*\SKV@rkpn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rkpnames{,#1}}}
-\SKV@pdef*\ReserveMacroPrefixNames{\SKV@ifstar\SKV@rmpn@m@s\SKV@rmpn@mes}
-\SKV@def*\SKV@rmpn@mes#1{\SKV@appto!\SKV@rmpnames{,#1}}
-\SKV@def*\SKV@rmpn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rmpnames{,#1}}}
-\SKV@pdef*\ReserveFamilyNames{\SKV@ifstar\SKV@rfn@m@s\SKV@rfn@mes}
-\SKV@def*\SKV@rfn@mes#1{\SKV@appto!\SKV@rfnames{,#1}}
-\SKV@def*\SKV@rfn@m@s#1{\SKV@AfterPackageEnd{\SKV@appto!\SKV@rfnames{,#1}}}
-\SKV@def*\SKV@rkpnames{XKV}
-\SKV@def*\SKV@rmpnames{XKV}
-\SKV@def*\SKV@rfnames{XKV}
-\ReserveKeyPrefixNames*{SKV}
-\ReserveMacroPrefixNames*{SKV}
-\ReserveFamilyNames*{skeyval}
-\SKV@def*\SKV@newlet{\SKV@savstate\SKV@t@stopta\SKV@n@wlet}
-\SKV@def*\SKV@n@wlet#1#2{%
- \SKV@ifdef#1{%
- \ifSKV@st
- \SKV@ifdef#2{%
- \let#1#2%
- \SKV@vbmsg{info}{Command '\string#1' redefined\on@line}%
- }{%
- \SKV@err{Command '\string#2' undefined}%
- {I can't let '\string#1' to '\string#2'.}%
- }%
- \else
- \SKV@err{Command '\string#1' already defined}%
- {I can't let '\string#1' to '\string#2'.}%
- \fi
- }{%
- \SKV@ifdef#2{\let#1#2}{%
- \SKV@err{Command '\string#2' undefined}%
- {I can't let '\string#1' to '\string#2'.}%
- }%
- }%
- \SKV@resstate
-}
-\AtEndOfPackage{\SKV@providedef*\NewLet{\SKV@newlet}}
-\SKV@pdef*\SKV@cslet{\SKV@savstate\SKV@t@stopta\SKV@csl@t}
-\SKV@def*\SKV@csl@t#1#2{%
- \ifSKV@st
- \def\SKV@next{\SKV@aftercs\let{#1}#2}%
- \else
- \def\SKV@next{%
- \SKV@ifdef{#2}{%
- \SKV@aftercs\let{#1}#2%
- }{%
- \SKV@err{Command '\string#2' undefined}%
- {You may use the starred version of \string\SKV@cslet.}%
- }%
- }%
- \fi
- \SKV@resstate\SKV@next
-}
-\SKV@pdef*\SKV@letcs{\SKV@savstate\SKV@t@stopta\SKV@l@tcs}
-\SKV@def*\SKV@l@tcs#1#2{%
- \ifSKV@st
- \def\SKV@next{%
- \begingroup\expandafter\endgroup
- \expandafter\let\expandafter#1\csname#2\endcsname
- }%
- \else
- \def\SKV@next{%
- \SKV@ifcsdef{#2}{%
- \expandafter\let\expandafter#1\csname#2\endcsname
- }{%
- \SKV@err{Command '\@backslashchar#2' undefined}%
- {You may use the starred version of \string\SKV@letcs.}%
+\skvrobustdef*\skv@getdocumentclass{%
+ \skv@swafalse
+ \ifx\@filelist\@undefined\else
+ \ifx\@filelist\relax\else
+ \ifx\@filelist\@gobble\else\skv@swatrue\fi
+ \fi\fi
+ \ifskv@swa
+ \skvcommaparse*\@filelist\skv@tempa{%
+ \filename@parse\skv@tempa
+ \ifx\filename@ext\@clsextension
+ \skvifcsundef{opt@\filename@area\filename@base.\filename@ext}{}{%
+ \edef\skv@documentclass{%
+ \filename@area\filename@base.\filename@ext
+ }%
+ }%
+ \fi
+ \ifx\skv@documentclass\@undefined\else\skvbreakloop\fi
+ }%
+ \fi
+}
+\skv@getdocumentclass
+% Filter class options to remove those with '=':
+\skvrobustdef*\skv@filterclassoptions{%
+ \skv@swafalse
+ \ifx\@classoptionslist\@undefined\else
+ \ifx\@classoptionslist\relax\else\skv@swatrue\fi
+ \fi
+ \ifskv@swa
+ \let\skv@filterclassoptions\relax
+ \skvkvnormalize\@classoptionslist
+ \let\skv@origclassoptlist\@classoptionslist
+ \let\skv@classoptionslist\@classoptionslist
+ \let\@classoptionslist\@empty
+ \skvcommaloop*\skv@origclassoptlist\skv@tempa{%
+ \skvxifin{=}{\skvexpandonce\skv@tempa}{}{%
+ \skvaddtolist*\@classoptionslist\skv@tempa
}%
}%
- \fi
- \SKV@resstate\SKV@next
-}
-\SKV@pdef*\SKV@csletcs{\SKV@savstate\SKV@t@stopta\SKV@csl@tcs}
-\SKV@def*\SKV@csl@tcs#1#2{%
- \ifSKV@st
- \def\SKV@next{%
- \begingroup\expandafter\endgroup
- \expandafter\let\csname#1\SKV@aftercs\endcsname{#2}%
- }%
- \else
- \def\SKV@next{%
- \SKV@ifcsdef{#2}{%
- \SKV@aftercs\let{#1\SKV@aftercs}{#2}%
- }{%
- \SKV@err{Command '\@backslashchar#2' undefined}%
- {You may use the starred version of \string\SKV@csletcs.}%
+ \def\@fileswith@ptions##1[##2]##3{%
+ \edef\skv@tempa{\unexpanded{##3}}%
+ \skvcsvnormalize\skv@tempa
+ % The following packages need access to the original
+ % \@classoptionslist.
+ \skvcommaloop{xkeyval,kvoptions,keyval2e,ltxkeys}\skv@prova{%
+ \skvxifin{,\skv@prova,}{,\skv@tempa,}{%
+ \let\@classoptionslist\skv@origclassoptlist
+ \skvbreakloop
+ }{}%
}%
+ \skvifnextchar[{\@fileswith@pti@ns##1[##2]##3}%
+ {\@fileswith@pti@ns##1[##2]##3[]}%
}%
\fi
- \SKV@resstate\SKV@next
-}
-\SKV@pdef*\SKV@numdef{\SKV@savstate\SKV@testoptc{\SKV@expr{num}}}
-\SKV@pdef*\SKV@dimdef{\SKV@savstate\SKV@testoptc{\SKV@expr{dim}}}
-\SKV@def*\SKV@expr#1{%
- \ifSKV@cl\let\gl@l@x\global\else\let\gl@l@x\relax\fi
- \ifSKV@pl
- \def\SKV@next##1{%
- \edef\resvd@a####1{####1{#1}\SKV@csexpox{##1}}%
- \resvd@a\SKV@ex@r
- }%
- \else
- \def\SKV@next{\SKV@ex@r{#1}}%
- \fi
- \SKV@resstate\SKV@next
-}
-\SKV@def*\SKV@ex@r#1#2#3{%
- \SKV@ensurescape@ne{#2}{#3}%
- \SKV@ifstrequal{#1}{num}%
- {\def\resvd@a{count}}{\def\resvd@a{dimen}}%
- \SKV@ifundef{#2}{%
- \@nameuse{new\resvd@a}#2%
- \gl@l@x#2=\@nameuse{#1expr}#3\relax
- }{%
- \gl@l@x#2=\@nameuse{#1expr}#3\relax
- }%
-}
-\SKV@def*\SKV@ensurescape@ne#1#2{%
- \SKV@ensurescape{#1}%
- \SKV@ifnotempty{#2}{}%
- {\SKV@err{Argument '\string#2' is empty}%
- {Empty argument '\string#2' is invalid.\SKV@MB
- I expected a nonempty argument here.}%
- }%
-}
-\SKV@def*\SKV@badkeylistparser{%
- \SKV@err{Key list parser '\SKV@keyparser' not allowed}%
- {Use semicolon (preferable) or colon as parser.}%
-}
-\define@boolkey+[KV]{skeyval}[SKV@]{xchoicelist}[true]{}{%
- \SKV@inputerr{#1}{xchoicelist}%
-}
-\define@cmdkey[KV]{skeyval}[SKV@]{genparser}[,]{%
- \@onelevel@sanitize\SKV@genparser
- \SKV@despacectt\SKV@genparser
- \SKV@expargs{0}\SKV@CommandGenParser\SKV@genparser\@nil
-}
-\define@cmdkey[KV]{skeyval}[SKV@]{keyparser}[;]{%
- \@onelevel@sanitize\SKV@keyparser
- \SKV@xifblank\SKV@keyparser\SKV@badkeylistparser\relax
- \SKV@despacectt\SKV@keyparser
- \begingroup
- \def\SKV@tempa{,}\SKV@detokdespace\SKV@tempa
- \SKV@ifx\SKV@keyparser\SKV@tempa
- {\aftergroup\SKV@badkeylistparser}{}%
- \endgroup
- \SKV@expargs{0}\SKV@CommandKeyParser\SKV@keyparser\@nil
}
-\SKV@def*\SKV@keyprefix@err{%
- \SKV@err{Key prefix '\SKV@keyprefix' is not allowed}%
- {Use another prefix name instead of '\SKV@keyprefix'.}%
-}
-\define@cmdkey[KV]{skeyval}[SKV@]{keyprefix}[KV]{%
- \SKV@xifblank\SKV@keyprefix\SKV@keyprefix@err\relax
- \SKV@despacectt\SKV@keyprefix
- \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rkpnames}}%
- \SKV@tempa\@nil
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@ifx\SKV@keyprefix\SKV@tempa\SKV@keyprefix@err\relax
- }%
-}
-\SKV@def*\SKV@keyfamily@err{%
- \SKV@err{Key family '\SKV@keyfamily' is not allowed}%
- {Use another family name instead of '\SKV@keyfamily'.}%
-}
-\define@cmdkey[KV]{skeyval}[SKV@]{keyfamily}[fam]{%
- \SKV@xifblank\SKV@keyfamily\SKV@keyfamily@err\relax
- \SKV@despacectt\SKV@keyfamily
- \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rfnames}}%
- \SKV@tempa\@nil
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@ifx\SKV@keyfamily\SKV@tempa\SKV@keyfamily@err\relax
+\skvifundef\skv@documentclass{%
+ \let\skv@documentclass\@empty
+ \let\skv@classoptionslist\@empty
+ \edef\@popfilename{%
+ \skvexpandonce\@popfilename\skv@filterclassoptions
}%
-}
-\SKV@def*\SKV@macroprefix@err{%
- \SKV@err{Macro prefix '\SKV@macroprefix' is not allowed}%
- {Use another macro prefix name instead of '\SKV@macroprefix'.}%
-}
-\define@cmdkey[KV]{skeyval}[SKV@]{macroprefix}[mp@]{%
- \SKV@xifblank\SKV@macroprefix\SKV@macroprefix@err\relax
- \SKV@despacectt\SKV@macroprefix
- \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rmpnames}}%
- \SKV@tempa\@nil
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@ifx\SKV@macroprefix\SKV@tempa\SKV@macroprefix@err\relax
- }%
-}
-\SKV@BeforePackageEnd{\deftog{draft}\deftog{final}}
-\define@boolkey+[KV]{skeyval}[SKV@]{draft}[true]{%
- \ifSKV@draft
- \setkeys[KV]{skeyval}{final=false}%
- \SKV@AtPackageEnd{\ifSKV@draft\togon{draft}\else
- \togoff{draft}\fi}%
- \fi
}{%
- \SKV@inputerr{#1}{draft}%
+ \skv@filterclassoptions
}
-\define@boolkey+[KV]{skeyval}[SKV@]{final}[true]{%
- \ifSKV@final
- \setkeys[KV]{skeyval}{draft=false}%
- \SKV@AtPackageEnd{\ifSKV@final\togon{final}\else
- \togoff{final}\fi}%
- \fi
-}{%
- \SKV@inputerr{#1}{final}%
-}
-\DeclareOptionX*{\SKV@warn{Unknown option '\CurrentOption' ignored}}
-\ExecuteOptionsX[KV]<skeyval>{genparser,keyparser,keyprefix,
- keyfamily,macroprefix,final}
-\ProcessOptionsX*[KV]<skeyval>\relax
-\SKV@pdef*\skvoptions#1{\setkeys[KV]{skeyval}{#1}}
-\SKV@pdef*\SKV@ifdraft{\@nameuse{SKV@\ifSKV@draft1\else2\fi of2}}
-\SKV@pdef*\SKV@iffinal{\@nameuse{SKV@\ifSKV@final1\else2\fi of2}}
-\SKV@pdef*\SKV@ifnotdraft{\@nameuse{SKV@\SKV@ifdraft2\else1\fi of2}}
-\SKV@pdef*\SKV@ifnotfinal{\@nameuse{SKV@\SKV@iffinal2\else1\fi of2}}
-\def\SKV@useinfo#1{Not using '\@backslashchar#1' of 'skyeval' package}
-\SKV@pdef*\SKV@in@#1#2{%
- \def\in@@##1#1##2##3\in@@{\ifx\in@##2\in@false\else\in@true\fi}%
- \in@@#2\@mil#1\in@\in@@
-}
-\SKV@pdef*\SKV@in@n#1#2{%
- \SKV@in@{#1}{#2}%
- \@nameuse{SKV@\ifin@1\else2\fi of2}%
-}
-\SKV@pdef*\SKV@in@o#1#2{%
- \@expandtwoargs\SKV@in@{\SKV@expox{#1}}{\SKV@expox{#2}}%
- \@nameuse{SKV@\ifin@1\else2\fi of2}%
-}
-\SKV@pdef*\SKV@in@x#1#2{%
- \@expandtwoargs\SKV@in@{#1}{#2}%
- \@nameuse{SKV@\ifin@1\else2\fi of2}%
-}
-\SKV@pdef*\in@tog#1#2{%
- \SKV@in@{#1}{#2}%
- \ifin@\togon{in@}\else\togoff{in@}\fi
+
+\skvrobustdef*\skvBeforeBeginDocument{%
+ \skvgappendtomacro\skv@beforebegindoc
}
-\AtEndOfPackage{\deftog{in@}}
-\SKV@pdef*\in@tok#1#2{%
- \begingroup
- \SKV@expnext\SKV@sp@def{\detokenize{#1}}\SKV@tempa
- \SKV@expnext\SKV@sp@def{\detokenize{#2}}\SKV@tempb
- \@expandtwoargs\SKV@in@\SKV@tempa\SKV@tempb
- \global\let\ifin@\ifin@
+\skvnewdef*\skv@beforebegindoc{}
+\skvprependtomacro\document{%
\endgroup
+ \let\skvBeforeBeginDocument\@firstofone
+ \skv@beforebegindoc
+ \gdef\skvBeforeBeginDocument{\skv@notprerr\skvBeforeBeginDocument}%
+ \global\let\skv@beforebegindoc\relax
+ \begingroup
}
-\AtBeginDocument{%
- \SKV@ifundef\ifdraft
- {\SKV@pdef*\ifdraft{\SKV@ifdraft}}%
- {\SKV@vbmsg{info}{\SKV@useinfo{ifdraft}}}%
-}
-\SKV@ifundef\ifnotdraft
- {\SKV@pdef*\ifnotdraft{\SKV@ifnotdraft}}%
- {\SKV@vbmsg{info}{\SKV@useinfo{ifnotdraft}}}
-\SKV@ifundef\iffinal
- {\SKV@pdef*\iffinal{\SKV@iffinal}}%
- {\SKV@vbmsg{info}{\SKV@useinfo{iffinal}}}
-\SKV@ifundef\ifnotfinal
- {\SKV@pdef*\ifnotfinal{\SKV@ifnotfinal}}%
- {\SKV@vbmsg{info}{\SKV@useinfo{ifnotfinal}}}
-\SKV@def\SKV@star@or@long#1{%
- \SKV@ifstar
- {\let\l@ngrel@x\relax\def\@star@or@none{*}#1}%
- {\let\l@ngrel@x\long\def\@star@or@none{}#1}%
+\skvrobustdef*\skvAfterBeginDocument{%
+ \skvgappendtomacro\skv@afterbegindoc
}
-\SKV@pdef\requirecmd{\SKV@star@or@long\SKV@require@cmd}
-\SKV@def\SKV@require@cmd#1{%
- \SKV@ensurescape{#1}%
- \SKV@ifdefined{#1}%
- {\CheckCommand\@star@or@none}{\newcommand\@star@or@none}{#1}%
+\skvnewdef*\skv@afterbegindoc{}
+\skvgappendtomacro\document{%
+ \let\skvAfterBeginDocument\@firstofone
+ \skv@afterbegindoc
+ \gdef\skvAfterBeginDocument{\skv@notprerr\skvAfterBeginDocument}%
+ \global\let\skv@afterbegindoc\relax
+ \ignorespaces
}
-\SKV@redef\@check@eq#1#2{%
- \SKV@ifx{#1}{#2}{}{%
- \SKV@vbmsg{warn}{%
- Previous definition of '\string#1'\SKV@MB
- doesn't match your new definition.\SKV@MB
- * I haven't redefined '\string#1' *}%
- }%
+\skvrobustdef*\skv@notprerr#1{%
+ \@latex@error{Command \detokenize{#1} should be used only
+ in preamble}\@ehd
}
-\SKV@def*\SKV@getswstate#1#2{%
- \SKV@checkchoice{#2}{true,on,false,off}{%
- \ifcase\nr\relax
- \def\SKV@swval{true}%
- \or
- \def\SKV@swval{true}%
- \or
- \def\SKV@swval{false}%
- \or
- \def\SKV@swval{false}%
- \fi
- }{%
- \SKV@swvalerr{#1}{#2}%
- }%
-}
-\SKV@pdef*\newswitch{\SKV@swtrue\SKV@testopt\SKV@newswitch{}}
-\SKV@pdef*\defswitch{\SKV@swfalse\SKV@testopt\SKV@newswitch{}}
-\SKV@def*\SKV@newswitch[#1]#2{\SKV@testopt{\SKV@n@wswitch[#1]{#2}}{false}}
-\SKV@def*\SKV@n@wswitch[#1]#2[#3]{%
- \SKV@in@n{,}{#2}{%
- \SKV@err{%
- Command \ifSKV@sw'\string\newswitch'\else'\string\defswitch'\fi\space
- doesn't accept list
- }{%
- Please submit only one switch to \ifSKV@sw'\string\newswitch'\else
- '\string\defswitch'\fi\SKV@MB at a time. You may consider using
- \ifSKV@sw'\string\NewSwitches'\else'\string\DefSwitches'\fi\SKV@MB
- if you really want to define a set of switches.
+\skvnewdef*\skv@everypagehook{}
+\skvrobustdef*\skvAtBeginEveryPage{\skvgappendtomacro\skv@everypagehook}
+\skvAfterBeginDocument{%
+ \let\skv@savedoutputpage\@outputpage
+ \def\@outputpage{%
+ \let\skv@savedbegindvi\@begindvi
+ \def\@begindvi{%
+ \skv@everypagehook
+ \skv@savedbegindvi
}%
- }{}%
- \SKV@ensurenoscape{#2}%
- \SKV@ifstrnotequal{#1#2}{x}{}{%
- \SKV@err{'\string\ifx' is a TeX primitive}%
- {You can't redefine '\string\ifx'! This is dangerous.}%
- }%
- \ifSKV@sw
- \SKV@getswstate\newswitch{#3}%
- \SKV@csifdefinable{if#1#2}\relax
- \else
- \SKV@getswstate\defswitch{#3}%
- \SKV@ifcsundef{if#1#2}{}{%
- \SKV@vbmsg{warn}{Switch '\@backslashchar if#1#2' redefined\on@line}%
- }%
- \fi
- \csnewif{if#1#2}%
- \@nameuse{#1#2\SKV@swval}%
-}
-\SKV@newlet\NewSwitches\NewBooleans
-\SKV@newlet\DefSwitches\DefBooleans
-\SKV@def*\setswitch#1#2{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsundef{if#1}{%
- \SKV@noswerr{#1}%
- }{%
- \SKV@getswstate\setswitch{#2}%
- \csname#1\SKV@swval\endcsname
+ \skv@savedoutputpage
+ \let\@begindvi\skv@savedbegindvi
}%
}
-\SKV@def*\switchon#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}}{\@nameuse{#1true}}%
-}
-\SKV@newlet\switchtrue\switchon
-\SKV@def*\switchoff#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}}{\@nameuse{#1false}}%
-}
-\SKV@newlet\switchfalse\switchoff
-\SKV@def*\ifswitchon#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}\@gobbletwo}%
- {\@nameuse{SKV@\@nameuse{if#1}1\else2\fi of2}}%
-}
-\SKV@newlet\ifswitchtrue\ifswitchon
-\SKV@def*\ifswitchoff#1{%
- \SKV@ensurenoscape{#1}%
- \SKV@ifcsundef{if#1}{\SKV@noswerr{#1}\@gobbletwo}%
- {\@nameuse{SKV@\@nameuse{if#1}2\else1\fi of2}}%
-}
-\SKV@newlet\ifswitchfalse\ifswitchoff
-\SKV@pdef*\SKV@noswerr#1{%
- \SKV@err{Switch '\string#1' is undefined}%
- {You need to first define the switch '\string#1'.}%
-}
-\SKV@pdef*\SKV@swnameerr#1{%
- \SKV@err{'\string\if#1' not allowed as a boolean}%
- {Invalid boolean name '\string#1'.}%
-}
-\SKV@def*\SKV@swvalerr#1#2{%
- \SKV@err{\string#1\space error: invalid boolean value '#2'}%
- {Valid boolean values are 'true', 'on', 'false', and 'off'.}%
-}
-\SKV@pdef*\SKV@undeftog@err#1{%
- \SKV@err{Toggle '#1' undefined}%
- {You need to first define '#1' before use.}%
-}
-\SKV@pdef*\newtog{\SKV@swtrue\SKV@testopt\SKV@newtog{}}
-\SKV@pdef*\deftog{\SKV@swfalse\SKV@testopt\SKV@newtog{}}
-\SKV@def*\SKV@newtog[#1]#2{\SKV@testopt{\SKV@n@wtog[#1]{#2}}{false}}
-\SKV@def*\SKV@n@wtog[#1]#2[#3]{%
- \SKV@in@n{,}{#2}{%
- \SKV@err{%
- Command \ifSKV@sw'\string\newtog'\else'\string\deftog'\fi\space
- doesn't accept list
- }{%
- Please submit only one tog to \ifSKV@sw'\string\newtog'\else
- '\string\deftog'\fi\space at a time.\SKV@MB You can use
- \ifSKV@sw'\string\NewTogs'\else'\string\DefTogs'\fi\space
- to define a set of togs.
- }%
- }{}%
- \SKV@ensurenoscape{#2}%
- \ifSKV@sw
- \SKV@getswstate\newtog{#3}%
- \SKV@ifcsdef{SKV@toggle@#1#2}{%
- \SKV@err{Toggle '#1#2' already defined}%
- {Please provide a new toggle or use '\string\deftog'.}%
- }{}%
- \else
- \SKV@getswstate\deftog{#3}%
- \SKV@ifcsundef{SKV@toggle@#1#2}{}{%
- \SKV@vbmsg{warn}{Toggle '#1#2' redefined\on@line}%
- }%
- \fi
- \SKV@csletcs{SKV@toggle@#1#2}{SKV@t@ggle\SKV@swval}
-}
-\SKV@pdef*\providetog#1{%
- \SKV@ifcsdef{SKV@toggle@#1}{%
- \SKV@vbmsg{info}%
- {Toggle '#1' already defined.\SKV@MB Not redefined\on@line}%
- }{\SKV@cslet{SKV@toggle@#1}\@secondoftwo}%
-}
-\SKV@pdef*\requiretog#1{\SKV@aftercs\requirecmd{SKV@toggle@#1}[2]{##2}}
-\SKV@def*\settog#1#2{%
- \SKV@ifcsdef{SKV@toggle@#1}{%
- \SKV@ifcsdef{SKV@t@ggle#2}{%
- \SKV@csletcs{SKV@toggle@#1}{SKV@t@ggle#2}%
+
+\skvnewdef*\skv@preamblecmdhook{}
+\skvrobustdef*\skvonlypreamble#1{%
+ \skvcommaparse{#1}\skv@tempa{%
+ \skvxifin{\detokenize\expandafter{\expandafter\do\skv@tempa}}%
+ {\skvoxdetok\skv@preamblecmdhook}{%
+ \skv@warn{Command '\skvexpandonce\skv@tempa' multiply
+ \MessageBreak submitted to \string\skvonlypreamble: ignored}%
}{%
- \SKV@err{Inadmissible value '#2' for toggle '#1'}%
- {Valid values for toggles are 'true', 'or', 'false', and 'off'.}%
+ \xdef\skv@preamblecmdhook{%
+ \skvexpandonce\skv@preamblecmdhook
+ \unexpanded\expandafter{\expandafter\do\skv@tempa}%
+ }%
}%
- }{\SKV@undeftog@err{#1}}%
-}
-\SKV@def*\togon#1{%
- \SKV@ifcsdef{SKV@toggle@#1}{%
- \SKV@cslet{SKV@toggle@#1}\SKV@t@ggleon
- }{\SKV@undeftog@err{#1}}%
-}
-\SKV@def*\togoff#1{%
- \SKV@ifcsdef{SKV@toggle@#1}{%
- \SKV@cslet{SKV@toggle@#1}\SKV@t@ggleoff
- }{\SKV@undeftog@err{#1}}%
-}
-\SKV@newlet\togtrue\togon
-\SKV@newlet\togfalse\togoff
-\SKV@newlet\SKV@t@ggleon\@firstoftwo
-\SKV@newlet\SKV@t@ggleoff\@secondoftwo
-\SKV@newlet\SKV@t@ggletrue\@firstoftwo
-\SKV@newlet\SKV@t@gglefalse\@secondoftwo
-\SKV@def*\iftogon#1{%
- \SKV@ifcsdef{SKV@toggle@#1}{\@nameuse{SKV@toggle@#1}}%
- {\SKV@undeftog@err{#1}}%
-}
-\SKV@def*\iftogoff#1{%
- \SKV@ifcsdef{SKV@toggle@#1}{%
- \@nameuse{SKV@toggle@#1}\@secondoftwo\@firstoftwo}%
- {\SKV@undeftog@err{#1}\@gobbletwo}%
-}
-\SKV@newlet\iftogtrue\iftogon
-\SKV@newlet\iftogfalse\iftogoff
-\deftog{pdf}
-\SKV@ifundef\pdfoutput{}{%
- \ifnum\pdfoutput<\@ne
- \SKV@pdef*\SKV@ifpdf{\@secondoftwo}%
- \else
- \togon{pdf}%
- \SKV@pdef*\SKV@ifpdf{\@firstoftwo}%
- \fi
- \SKV@pdef*\SKV@ifnotpdf{\SKV@ifpdf\@secondoftwo\@firstoftwo}%
-}
-\SKV@ifundef\ifnotpdf
- {\let\ifnotpdf\SKV@ifnotpdf}%
- {\SKV@vbmsg{info}{\SKV@useinfo{ifnotpdf}}}
-\SKV@AtDocumentStart{%
- \SKV@ifundef\ifpdf
- {\SKV@pdef*\ifpdf{\SKV@ifpdf}}%
- {\SKV@vbmsg{info}{\SKV@useinfo{ifpdf}}}%
-}
-\SKV@pdef*\SKV@definedkey@err#1{%
- \SKV@ifcsundef{\XKV@header#1}{}{%
- \SKV@err{Key '#1' already defined in family '\XKV@tfam'\SKV@MB
- with prefix '\SKV@pref'}{Use another key name instead of '#1'.}%
- }%
-}
-\SKV@pdef*\define@togkey{\SKV@skfalse
- \XKV@t@stopta{\XKV@testoptd\SKV@define@togkey{}}}
-\SKV@def*\SKV@define@togkey#1#2[#3]{%
- \SKV@findkeypointers{#2}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@Undef+{\XKV@header\SKV@resa,SKV@toggle@#1\SKV@resa}%
}%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \ifXKV@pl
- \def\SKV@next{\SKV@aftercs\SKV@d@f@ne@togkey}%
- \else
- \def\SKV@next{\SKV@aftercs\SKV@d@fine@togkey}%
- \fi
- \begingroup
- \edef\SKV@tempa{\endgroup
- {\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
- \aftergroup\SKV@next\SKV@tempa
-}
-\SKV@def*\SKV@d@fine@togkey#1#2#3#4#5{%
- \SKV@d@f@ne@t@gkey#1{#2}{#3}{#4}%
- {{\SKV@expargs{0}{\SKV@getswstate\SKV@d@fine@togkey}\XKV@resa\@nil
- \settog{#3}{\SKV@swval}#5}}%
}
-\SKV@def*\SKV@d@f@ne@togkey#1#2#3#4#5#6{%
- \SKV@d@f@ne@t@gkey#1{#2}{#3}{#4}%
- {{\SKV@expargs{0}{\SKV@getswstate\SKV@d@f@ne@togkey}\XKV@resa\@nil
- \settog{#3}{\SKV@swval}#5}{#6}}%
-}
-\SKV@def*\SKV@d@f@ne@t@gkey#1#2#3#4#5{%
- \deftog{#3}%
- \ifXKV@st\XKV@define@default{#2}{#4}\fi
- \edef#1##1{%
- \def#1####1{##1\unexpanded{\XKV@sttrue\XKV@checkchoice[\XKV@resa]}%
- {####1}{true,false,on,off}\unexpanded{#5}%
+\AtEndOfPackage{%
+ \skvAfterBeginDocument{%
+ \def\do#1{%
+ \skvifdef#1{%
+ \gdef#1{\@latexerr{'\string#1' is a preamble command}\@ehd}%
+ }{%
+ \@@warning{Undefined command '\unexpanded{#1}'
+ appeared in \string\skvonlypreamble}%
+ }%
}%
- }%
- \ifXKV@pl#1\XKV@pltrue\else#1\XKV@plfalse\fi
-}
-\SKV@pdef*\define@togkeys{\SKV@skfalse
- \XKV@plfalse\XKV@testoptd\SKV@define@togkeys{}}
-\SKV@def*\SKV@define@togkeys#1#2[#3]{%
- \SKV@despacelist{#2}%
- \SKV@for*[,]\SKV@resa\SKV@tempa{%
- \SKV@expargs{3}%
- \SKV@d@fine@togkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
- }%
-}
-\SKV@def*\SKV@d@fine@togkeys#1#2#3{%
- \SKV@findkeypointers{#1}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@Undef+{\XKV@header\SKV@resa,SKV@toggle@#2\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \edef\SKV@tempa##1##2##3{%
- ##1\@nameuse{\XKV@header\SKV@resa}%
- {\SKV@resa}{#2\SKV@resa}{#3}{{##2{#2\SKV@resa}{##3}}}%
- }%
- \SKV@tempa\SKV@d@f@ne@t@gkey\settog\XKV@resa
-}
-\SKV@pdef*\newordkey{\SKV@skfalse\XKV@testoptb\SKV@newordkey}
-\SKV@def*\SKV@newordkey#1{%
- \SKV@findkeypointers{#1}%
- \SKV@expnext\SKV@definedkey@err\SKV@resa
- \begingroup
- \edef\SKV@tempa{\endgroup
- \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}%
- {\noexpand\SKV@d@fine@key{\SKV@resa}}%
- }%
- \SKV@tempa
-}
-\SKV@pdef*\newcmdkey{\SKV@skfalse\XKV@testoptd\SKV@newcmdkey{cmd}}
-\SKV@def*\SKV@newcmdkey#1#2[#3]#4{%
- \SKV@reservmp{#1}\SKV@rmpnames
- \SKV@findkeypointers{#2}%
- \SKV@expnext\SKV@definedkey@err\SKV@resa
- \ifXKV@st
- \SKV@afterfi
- \SKV@expnext\XKV@define@default\SKV@resa{#3}%
- \fi
- \begingroup
- \edef\SKV@tempa{\def\SKV@noexpcs{\XKV@header\SKV@resa}####1}%
- \edef\SKV@tempb{\def\SKV@noexpcs{#1\SKV@resa}\unexpanded{{##1}#4}}%
- \expandafter\expandafter\expandafter\endgroup
- \expandafter\SKV@tempa\expandafter{\SKV@tempb}%
-}
-\SKV@pdef*\newcmdkeys{\SKV@skfalse\XKV@testoptd\SKV@newcmdkeys{cmd}}
-\SKV@def*\SKV@newcmdkeys#1#2[#3]{%
- \SKV@despacelist{#2}%
- \SKV@for*[,]\SKV@resa\SKV@tempa{%
- \edef\SKV@tempa{\noexpand\SKV@newcmdkey{#1}{\SKV@tempa}}%
- \SKV@tempa[#3]{}%
- }%
-}
-\SKV@pdef*\newchoicekey{\SKV@skfalse
- \XKV@testopta{\XKV@testoptb\SKV@newchoicekey}}
-\SKV@def*\SKV@newchoicekey#1{%
- \SKV@findkeypointers{#1}%
- \SKV@expnext\SKV@definedkey@err\SKV@resa
- \begingroup
- \edef\SKV@tempa##1{\endgroup\SKV@testopt{##1{\SKV@resa}}{}}%
- \SKV@tempa\XKV@d@fine@choicekey
-}
-\let\newmenukey\newchoicekey
-\SKV@pdef*\newboolkey{\SKV@skfalse
- \XKV@t@stopta{\XKV@testoptd\SKV@newboolkey{}}}
-\SKV@def*\SKV@newboolkey#1#2[#3]{%
- \SKV@findkeypointers{#2}%
- \SKV@expnext\SKV@definedkey@err\SKV@resa
- \ifXKV@pl
- \def\SKV@next{\SKV@aftercs\XKV@d@f@ne@boolkey}%
- \else
- \def\SKV@next{\SKV@aftercs\XKV@d@fine@boolkey}%
- \fi
- \edef\SKV@tempa{{\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
- \expandafter\SKV@next\SKV@tempa
-}
-\SKV@pdef*\newboolkeys{\SKV@skfalse
- \XKV@plfalse\XKV@testoptd\SKV@newboolkeys{}}
-\SKV@def*\SKV@newboolkeys#1#2[#3]{%
- \SKV@despacelist{#2}%
- \SKV@for*[,]\SKV@resa\SKV@tempa{%
- \SKV@definedkey@err\SKV@tempa
- \SKV@expargs{3}%
- \XKV@d@fine@boolkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
+ \skv@preamblecmdhook
+ \let\skv@preamblecmdhook\relax
+ \let\do\relax
}%
}
-\SKV@pdef*\newtogkey{\SKV@skfalse
- \XKV@t@stopta{\XKV@testoptd\SKV@newtogkey{}}}
-\SKV@def*\SKV@newtogkey#1#2[#3]{%
- \SKV@findkeypointers{#2}%
- \SKV@expnext\SKV@definedkey@err\SKV@resa
- \ifXKV@pl
- \def\SKV@next{\SKV@aftercs\SKV@d@f@ne@togkey}%
- \else
- \def\SKV@next{\SKV@aftercs\SKV@d@fine@togkey}%
- \fi
- \begingroup
- \edef\SKV@tempa{\endgroup
- {\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
- \aftergroup\SKV@next\SKV@tempa
-}
-\SKV@pdef*\newtogkeys{\SKV@skfalse
- \XKV@plfalse\XKV@testoptd\SKV@newtogkeys{}}
-\SKV@def*\SKV@newtogkeys#1#2[#3]{%
- \SKV@despacelist{#2}%
- \SKV@for*[,]\SKV@resa\SKV@tempa{%
- \SKV@definedkey@err\SKV@tempa
- \SKV@expargs{3}\SKV@d@fine@togkeys{{\SKV@tempa}}{{#1}{#3}}\@nil
- }%
-}
-\SKV@pdef*\define@biboolkeys{\SKV@compopta\define@boolkey\SKV@biboolkeys}
-\SKV@pdef*\newbiboolkeys{\SKV@compopta\newboolkey\SKV@biboolkeys}
-\SKV@pdef*\define@uniboolkeys{\SKV@compopta\define@boolkey\SKV@uniboolkeys}
-\SKV@pdef*\newuniboolkeys{\SKV@compopta\newboolkey\SKV@uniboolkeys}
-\SKV@pdef*\define@biuniboolkeys{%
- \SKV@savstate
- \SKV@t@stoptb{\SKV@compopta\define@boolkey\SKV@biuniboolkeys}%
-}
-\SKV@pdef*\newbiuniboolkeys{%
- \SKV@savstate
- \SKV@t@stoptb{\SKV@compopta\newboolkey\SKV@biuniboolkeys}%
-}
-\SKV@pdef*\define@bitogkeys{\SKV@compopta\define@togkey\SKV@bitogkeys}
-\SKV@pdef*\newbitogkeys{\SKV@compopta\newtogkey\SKV@bitogkeys}
-\SKV@pdef*\define@unitogkeys{\SKV@compopta\define@togkey\SKV@unitogkeys}
-\SKV@pdef*\newunitogkeys{\SKV@compopta\newtogkey\SKV@unitogkeys}
-\SKV@pdef*\define@biunitogkeys{%
- \SKV@savstate
- \SKV@t@stoptb{\SKV@compopta\define@togkey\SKV@biunitogkeys}%
+
+%%+++++++++++++++++ Utilities for handling options ++++++++++++++++%%
+
+% \skvunknownoptionhandler[<prefixes>]<<families>>{<handler>}
+%
+\skvrobustdef*\skvunknownoptionhandler{%
+ \skv@testopt\skv@unknownoptionhandler{KV}%
}
-\SKV@pdef*\newbiunitogkeys{%
- \SKV@savstate
- \SKV@t@stoptb{\SKV@compopta\newtogkey\SKV@biunitogkeys}%
+\skvrobustdef*\skv@unknownoptionhandler[#1]{%
+ \skvifnextchar<{\skv@unkn@wnoptionhandler{#1}}%
+ {\skv@unkn@wnoptionhandler{#1}<\@currname.\@currext>}%
}
-\SKV@def*\SKV@compopta#1#2{%
- \let\SKV@c@mpkey#1\let\SKV@co@pkey#2%
- \SKV@testopt{\SKV@compoptb}{KV}%
+\skvrobustdef*\skv@unkn@wnoptionhandler#1<#2>{%
+ \skv@unknownkeyhandler[#1]{#2}%
}
-\SKV@def*\SKV@compoptb[#1]#2{\SKV@testopt{\SKV@compoptc[#1]{#2}}{mp@}}
-\SKV@def*\SKV@compoptc[#1]#2[#3]#4{%
- \SKV@testopt{\SKV@co@pkey[#1]{#2}[#3]{#4}}{true}}
-\SKV@def*\SKV@biboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \ifswitchon{#3#4}{\switchoff{#3#6}}{\switchon{#3#6}#8\relax}%
- }%
- \@namedef{#1@#2@#6@func}{%
- #8\relax
- \ifswitchon{#3#6}{\switchoff{#3#4}}{\switchon{#3#4}#7\relax}%
- }%
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
-}
-\SKV@def*\SKV@uniboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \ifswitchon{#3#4}{\switchon{#3#6}#8\relax}{\switchoff{#3#6}}%
- }%
- \@namedef{#1@#2@#6@func}{%
- #8\relax
- \ifswitchon{#3#6}{\switchon{#3#4}#7\relax}{\switchoff{#3#4}}%
- }%
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
-}
-\SKV@def*\SKV@biuniboolkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \SKV@aftercs\def{#1@#2@#6@func}{#8\relax}%
- \ifswitchon{SKV@st}{%
- \ifswitchon{SKV@pl}{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\ifswitchon{#3#4}{}{\switchoff{#3#6}}%
- }%
- }{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \ifswitchon{#3#4}{}{\switchon{#3#6}\@nameuse{#1@#2@#6@func}}%
- }%
- }%
+
+
+\skvrobustdef*\skv@testopte#1{\skv@testopta{\skv@t@stopte{#1}}}
+\skvrobustdef*\skv@t@stopte#1{\skv@testopt{\skv@t@st@pte{#1}}{KV}}
+\skvrobustdef*\skv@t@st@pte#1[#2]{%
+ % Only one prefix is allowed:
+ \skvxifin{,}{\detokenize{#2}}{%
+ \skv@err{Only one prefix is allowed, but you gave '#2'}\@ehd
}{%
- \ifswitchon{SKV@pl}{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\ifswitchon{#3#4}{\switchoff{#3#6}}{}%
- }%
- }{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \ifswitchon{#3#4}{\switchon{#3#6}\@nameuse{#1@#2@#6@func}}{}%
- }%
- }%
- }%
- \SKV@resstate
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
-}
-\SKV@def*\SKV@bitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \iftogon{#3#4}{\togoff{#3#6}}{\togon{#3#6}#8\relax}%
- }%
- \@namedef{#1@#2@#6@func}{%
- #8\relax
- \iftogon{#3#6}{\togoff{#3#4}}{\togon{#3#4}#7\relax}%
- }%
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
-}
-\SKV@def*\SKV@unitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax
- \iftogon{#3#4}{\togon{#3#6}#8\relax}{\togoff{#3#6}}%
- }%
- \@namedef{#1@#2@#6@func}{%
- #8\relax
- \iftogon{#3#6}{\togon{#3#4}#7\relax}{\togoff{#3#4}}%
+ \skv@makeprefix{#2}%
+ \skvifnextchar<{\skv@@t@st@pte{#1}}%
+ {\skv@@t@st@pte{#1}<\@currname.\@currext>}%
}%
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
}
-\SKV@def*\SKV@biunitogkeys[#1]#2[#3]#4[#5]#6#7#8{%
- \@namedef{#1@#2@#6@func}{#8}%
- \ifswitchon{SKV@st}{%
- \ifswitchon{SKV@pl}{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\iftogoff{#3#4}{\togoff{#3#6}}{}%
- }%
- }{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\iftogoff{#3#4}{\togon{#3#6}#8\relax}{}%
- }%
- }%
+\skvrobustdef*\skv@@t@st@pte#1<#2>{%
+ \edef\skv@fams{#2}%
+ \skvxifin{,}{\detokenize{#2}}{%
+ \skvcsvnormalize\skv@fams
}{%
- \ifswitchon{SKV@pl}{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\iftogon{#3#4}{\togoff{#3#6}}{}%
- }%
- }{%
- \@namedef{#1@#2@#4@func}{%
- #7\relax\iftogon{#3#4}{\togon{#3#6}#8\relax}{}%
- }%
- }%
+ \skvdespacecontent\skv@fams
}%
- \SKV@resstate
- \SKV@compk@y{#1}{#2}{#3}{#4}{#5}{#6}%
+ \skv@testopt{#1}{}%
}
-\SKV@def*\SKV@compk@y#1#2#3#4#5#6{%
- \SKV@c@mpkey+[#1]{#2}[#3]{#4}[#5]{\@nameuse{#1@#2@#4@func}}%
- {\SKV@inputerr{##1}{#4}}%
- \SKV@c@mpkey+[#1]{#2}[#3]{#6}[#5]{\@nameuse{#1@#2@#6@func}}%
- {\SKV@inputerr{##1}{#6}}%
-}
-\SKV@pdef*\SKV@keylistrema#1\@nil#2{%
- \long\edef\SKV@remainder{\unexpanded{#1}}%
- \SKV@oifblank{\SKV@remainder}{}{%
- \def\SKV@tempa##1#2\@nil{\def\SKV@remainder{##1}}%
- \expandafter\SKV@tempa\SKV@remainder\@nil
- }%
-}
-\SKV@pdef*\define@keylist{%
- \SKV@define@keylist\define@key\define@cmdkey
- \define@boolkey\define@togkey\define@choicekey
-}
-\SKV@pdef*\newkeylist{%
- \SKV@define@keylist\newordkey\newcmdkey
- \newboolkey\newtogkey\newchoicekey
-}
-\newcommand*\SKV@define@keylist[5]{%
- \let\SKV@def@ordkey#1%
- \let\SKV@def@cmdkey#2%
- \let\SKV@def@boolkey#3%
- \let\SKV@def@togkey#4%
- \let\SKV@def@choicekey#5%
- \SKV@savstate
- \begingroup
- \@makeother{\#}%
- \SKV@t@stopta\SKV@d@fine@keylist
+
+\skvrobustdef*\skveveryunknownoption{\skvdeclareoption*}
+% \skvdeclareoption[<pref>]<<fam>>{<key>}[<defa>]{<callback>}
+% \skvdeclareoption*{<message>}
+\skvrobustdef*\skvdeclareoption{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \let\skvdefkey\skvordkey
+ \skvifstar\skv@dox\skv@dox@a
+}
+% \skvdeclarevoidoption[<pref>]<<fam>>{<key>}[<defa>]{<callback>}
+\skvrobustdef*\skvdeclarevoidoption{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \let\skvdefkey\skvvoidkey
+ \skv@dox@a
+}
+% \skvdeclarebooloption[<pref>]<<fam>>[<mp>]{<key>}[<defa>]{<callback>}
+\skvrobustdef*\skvdeclarebooloption{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \let\skvdefkey\skvboolkey
+ \skv@dox@a
+}
+% \skvdeclarecmdoption[<pref>]<<fam>>[<mp>]{<key>}[<defa>]{<callback>}
+\skvrobustdef*\skvdeclarecmdoption{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \let\skvdefkey\skvcmdkey
+ \skv@dox@a
}
-\SKV@def*\choicekeyvalues{%
- \SKV@t@stopta{\SKV@testopt\SKV@choic@keyvalues\SKV@keyprefix}}
-\SKV@def*\SKV@choic@keyvalues[#1]{%
- \SKV@testopt{\SKV@choic@keyv@lues[#1]}\SKV@keyfamily}
-\SKV@def*\SKV@choic@keyv@lues[#1][#2]#3#4{%
- \ifSKV@st
- \SKV@csedef{#1@#2@#3@altlist}{#4}%
- \else
- \SKV@ifcsundef{#1@#2@#3@altlist}{%
- \SKV@csedef{#1@#2@#3@altlist}{#4}%
- }{%
- \SKV@err
- {Problem with \string\choicekeyvalues\space for key '#3'}%
- {You have attempted to set two \string\choicekeyvalues\SKV@MB
- for choice key '#3' in the same family '#2'\SKV@MB
- with the same prefix '#1'. You can only do\SKV@MB
- that if you use the starred variant of \string\choicekeyvalues.}%
+
+% Our default action for unknown options is tied to \@currname & \@currext:
+\skvrobustdef\skv@dox#1{%
+ \skvcsedef{skv@dox@\@currname @\@currext}{%
+ \unexpanded{%
+ \begingroup
+ \ifx\skvcurrentvalue\skv@novaluetoks
+ \def\skvcurrentvalue{no value}%
+ \fi
+ \@onelevel@sanitize\CurrentOption
+ \@onelevel@sanitize\skvcurrentvalue
+ #1%
+ \endgroup
}%
- \fi
-}
-\SKV@newlet\CKVS\choicekeyvalues
-\SKV@def*\SKV@detok@z@p#1{%
- \edef#1{\detokenize\expandafter{#1}\space}%
- \edef#1{\expandafter\zap@space#1\@empty}%
-}
-\SKV@def*\SKV@detok@zsp#1{%
- \SKV@ensurescape{#1}%
- \begingroup
- \SKV@for*[,]#1\SKV@tempa{%
- \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}\space}%
- \edef\SKV@tempa{\expandafter\zap@space\SKV@tempa\@empty}%
- \SKV@csxdef*{SKV@zsp@\expandafter\@gobble\SKV@tempa}%
- {\SKV@expox{\SKV@tempa}}%
}%
- \endgroup
}
-\SKV@def*\SKV@detok@dsp#1{%
- \SKV@ensurescape{#1}%
- \begingroup
- \SKV@for*[,]#1\SKV@tempa{%
- \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}}%
- \SKV@despacectt\SKV@tempa
- \SKV@csxdef*{SKV@dsp@\expandafter\@gobble\SKV@tempa}%
- {\SKV@expox{\SKV@tempa}}%
- }%
- \endgroup
+\skvrobustdef*\skv@dox@a{\skv@testopt\skv@dox@b{KV}}
+\skvrobustdef*\skv@dox@b[#1]{%
+ \skvifnextchar<%
+ {\skv@dox@c{#1}}%
+ {\skv@dox@c{#1}<\@currname.\@currext>}%
}
-\SKV@def*\SKV@exceplist{%
- \par,\if,\ifcase,\or,\else,\skif,\iftog,\ifswitch}
-\SKV@detok@dsp\SKV@exceplist
-\SKV@def*\SKV@noiferr#1#2{%
- \SKV@err{You can't use '\@backslashchar #1' in\SKV@MB
- key macro within keylist}%
- {Use '\@backslashchar #2' instead of '\@backslashchar #1'.}%
+\skvrobustdef*\skv@dox@c#1<#2>{\skvdefkey[#1]{#2}}
+
+% \skvexecuteoptions+[<pref>]<fams>[<na>]{<kvlist>}
+% This has no star (*) variant; any star suffix is quietly ignored.
+\skvrobustdef*\skvexecuteoptions{%
+ \skv@testopte{\skv@stfalse\skv@setkeys@a}%
}
-\SKV@pdef*\uservalue{\uservalue}
-\SKV@pdef*\guservalue{\guservalue}
-\SKV@pdef*\savevalue{\savevalue}
-\SKV@pdef*\gsavevalue{\gsavevalue}
-\SKV@def\SKV@define@multkeys#1,#2,#3,#4\@nil{%
- \let\SKV@altlisterr\z@
- \SKV@sp@def{#1}\SKV@tempa
- \SKV@checkchoice{\SKV@tempa}{ord,cmd,bool,tog,choice,menu}{%
- \ifnum\nr=5%
- \let\SKV@keytype\nr
- \else
- \edef\SKV@keytype{\the\numexpr\nr+1}%
- \fi
+
+% \skvprocessoptions*+[<pref>]{<fams>}[<na>]
+%
+% 1. If not using LaTeX, then no processing of options.
+% 2. The plus (+) variant of \skvprocessoptions will process the options
+% in all the listed families. But the star form of \skvprocessoptions
+% doesn't seem to make sense here, since - unlike in LaTeX2e - a star
+% suffix here would mean 'save unknown keys'. It is meaningless to seek
+% to save unknown keys when processing options. Any star (*) suffix on
+% \skvprocessoptions is, therefore, quietly ignored.
+% 3. Class options are always processed first, but class options ocurring
+% also local/package options are dropped from the list of options
+% to be processed.
+\skvrobustdef*\skvprocessoptions{\skv@testopte\skv@pox}
+\skvrobustdef*\skv@pox[#1]{%
+ \skv@inpoxtrue
+ \let\@fileswith@pti@ns\@badrequireerror
+ \begingroup
+ \let\skv@classoptsfound\@empty
+ \let\skv@exitpoxkeys\@empty
+ \edef\skv@testclass{\@currname.\@currext}%
+ \skvifx\skv@testclass\skv@documentclass{%
+ \let\@unusedoptionlist\skv@classoptionslist
}{%
- \SKV@checkchoice{\SKV@tempa}{1,2,3,4,5}{%
- \edef\SKV@keytype{\the\numexpr\nr+1}%
- }{%
- \SKV@err{Unknown key type/identifier '\string#1'}%
- {Valid key types are 'ord', 'cmd', 'bool', 'tog',
- 'choice', 'menu',\SKV@MB and '1', '2', '3', '4', '5'}%
- }%
- }%
- \SKV@ifnotempty{#2}{}{%
- \SKV@err{No key name specified for key type '\string#1'}%
- {\string\define@keylist: key name required for all keys}%
- }%
- \begingroup
- \SKV@ifblank{#4}{}{%
- \edef\SKV@tempb{\detokenize{#4}\space}%
- \edef\SKV@tempb{\expandafter\zap@space\SKV@tempb\@empty}%
- \@expandtwoargs\SKV@in@\SKV@dsp@if\SKV@tempb
- \ifin@
- \@expandtwoargs\SKV@in@\SKV@dsp@iftog\SKV@tempb
- \ifin@\else
- \@expandtwoargs\SKV@in@\SKV@dsp@ifswitch\SKV@tempb
- \ifin@\else\SKV@noiferr{if}{skif}\fi
- \fi
+ \skv@swafalse
+ \ifx\skv@classoptionslist\@empty\else
+ \ifskv@st\skv@swatrue\fi
\fi
- \@expandtwoargs\SKV@in@\SKV@dsp@par\SKV@tempb
- \ifin@\SKV@afterfi\SKV@noiferr{par}{endgraf}\fi
- \@expandtwoargs\SKV@in@\SKV@dsp@ifcase\SKV@tempb
- \ifin@\SKV@afterfi\SKV@noiferr{ifcase}{skifcase}\fi
- \@expandtwoargs\SKV@in@\SKV@dsp@or\SKV@tempb
- \ifin@\SKV@afterfi\SKV@noiferr{or}{skor}\fi
- \@expandtwoargs\SKV@in@\SKV@dsp@else\SKV@tempb
- \ifin@\SKV@afterfi\SKV@noiferr{else}{skelse}\fi
- }%
- \protected@edef\SKV@tempa{\endgroup
- \ifcase\SKV@keytype\relax
- \or
- \noexpand\SKV@def@ordkey[\SKV@keyprefix]{\SKV@keyfamily}%
- {#2}[#3]{\unexpanded{#4}}%
- \or
- \noexpand\SKV@def@cmdkey[\SKV@keyprefix]{\SKV@keyfamily}%
- [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}%
- \or
- \noexpand\SKV@def@boolkey+[\SKV@keyprefix]{\SKV@keyfamily}%
- [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}{%
- \unexpanded{\SKV@inputerr{##1}{#2}}%
- }%
- \or
- \noexpand\SKV@def@togkey+[\SKV@keyprefix]{\SKV@keyfamily}%
- [\SKV@macroprefix]{#2}[#3]{\unexpanded{#4}}{%
- \unexpanded{\SKV@inputerr{##1}{#2}}%
+ \skvifnotbool{skv@swa}{}{%
+ \skvcommaloop*\skv@classoptionslist\CurrentOption{%
+ \expandafter\expandafter\expandafter
+ \skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey
+ \skvexpanded{%
+ % Test if key is defined in one of the families. The search will
+ % stop as soon as the key is found in any of the families.
+ \skvifkeyundef[\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}%
+ }{}{%
+ \edef\skv@classoptsfound{%
+ \skvexpandonce\skv@classoptsfound
+ \ifx\skv@classoptsfound\@empty\else,\fi
+ \skvexpandonce\CurrentOption
+ }%
+ \expandafter\skv@useoption\expandafter{\CurrentOption}%
}%
- \or
- \SKV@ifcsdef{\SKV@keyprefix @\SKV@keyfamily @#2@altlist}{}%
- {\let\SKV@altlisterr\@ne}%
- \noexpand\SKV@def@choicekey*+[\SKV@keyprefix]{\SKV@keyfamily}{#2}%
- [\unexpanded{\val\nr}]{%
- \SKV@csuse{\SKV@keyprefix @\SKV@keyfamily @#2@altlist}%
- }[#3]{\unexpanded{#4}}{\unexpanded{\SKV@inputerr{##1}{#2}}}%
- \fi
- }%
- \SKV@tempa
- \ifnum\SKV@altlisterr=\@ne
- \SKV@afterfi
- \SKV@err{%
- Choice key '#2' can't be defined.\SKV@MB
- Alternate key values list for '#2' is empty
- }{%
- You need to first define admissible\SKV@MB
- key values through '\string\choicekeyvalues'\SKV@MB
- for choice key '#2'.
}%
- \fi
-}
-\SKV@def*\SKV@resvfampf#1#2{%
- \begingroup
- \SKV@expnext\XKV@checksanitizeb#2\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \XKV@knftrue
- \XKV@whilist\SKV@tempa\SKV@tempa\ifXKV@knf\fi{%
- \SKV@aftercs\ifx{XKV@#1}\SKV@tempa\XKV@knffalse\fi
- }%
- \unless\ifXKV@knf
- \SKV@afterfi
- \SKV@err{Key #1 '\SKV@tempa' is reserved}%
- {You have used a reserved key #1: '\SKV@tempa'.\SKV@MB
- Use another #1 name instead of '\SKV@tempa'.}%
- \fi
- \endgroup
-}
-\SKV@redef*\XKV@makepf#1{%
- \SKV@sp@def{#1}\XKV@prefix
- \unless\ifSKV@sk
- \SKV@resvfampf{prefix}\SKV@rkpnames
- \fi
- \edef\SKV@pref{\ifx\XKV@prefix\@empty\else\XKV@prefix\fi}%
- \edef\XKV@prefix{\ifx\XKV@prefix\@empty\else\XKV@prefix @\fi}%
-}
-\SKV@redef*\XKV@makehd#1{%
- \SKV@expargs{3}\SKV@sp@def{{#1}}\XKV@header\@nil
- \unless\ifSKV@sk
- \SKV@resvfampf{family}\SKV@rfnames
- \fi
- \edef\XKV@header{%
- \XKV@prefix\ifx\XKV@header\@empty\else\XKV@header @\fi}%
-}
-\SKV@def*\SKV@resolvekey#1#2\@nil#3{%
- \def\SKV@resolve##1#2##2##3\@nil##4{%
- \edef##4{\unexpanded{##2}}%
- \ifx##4\@nnil
- \edef##4{\unexpanded{##1}}%
- \expandafter\@secondoftwo
- \else
- \expandafter\@firstoftwo
- \fi
- }%
- \SKV@resolve#1#2{\@nil}\@nil#3%
-}
-\SKV@def*\SKV@addtouserval{%
- \SKV@addtolist+{SKV@\XKV@header uservalue}\SKV@resa}
-\SKV@def*\SKV@gaddtouserval{%
- \SKV@addtolist+!{SKV@\XKV@header uservalue}\SKV@resa}
-\SKV@def*\SKV@addtosave{\SKV@addtolist+{XKV@\XKV@header save}\SKV@resa}
-\SKV@def*\SKV@gaddtosave{\begingroup
- \edef\SKV@tempa{\endgroup
- \SKV@addtolist+!{XKV@\XKV@header save}{\global{\SKV@resa}}}%
- \SKV@tempa
-}
-\SKV@def*\SKV@findkeypointers#1{%
- \SKV@resolvekey{#1}\uservalue\savevalue\@nil\SKV@resa
- {\SKV@addtouserval\SKV@addtosave}%
- {\SKV@resolvekey{#1}\guservalue\savevalue\@nil\SKV@resa
- {\SKV@gaddtouserval\SKV@addtosave}%
- {\SKV@resolvekey{#1}\savevalue\uservalue\@nil\SKV@resa
- {\SKV@addtouserval\SKV@addtosave}%
- {\SKV@resolvekey{#1}\gsavevalue\uservalue\@nil\SKV@resa
- {\SKV@addtouserval\SKV@gaddtosave}%
- {\SKV@resolvekey{#1}\guservalue\gsavevalue\@nil\SKV@resa
- {\SKV@gaddtouserval\SKV@gaddtosave}%
- {\SKV@resolvekey{#1}\gsavevalue\guservalue\@nil\SKV@resa
- {\SKV@gaddtouserval\SKV@gaddtosave}%
- {\SKV@resolvekey{#1}\uservalue\@nil\SKV@resa
- {\SKV@addtouserval}%
- {\SKV@resolvekey{#1}\guservalue\@nil\SKV@resa
- {\SKV@gaddtouserval}%
- {\SKV@resolvekey{#1}\savevalue\@nil\SKV@resa
- {\SKV@addtosave}%
- {\SKV@resolvekey{#1}\gsavevalue\@nil\SKV@resa
- {\SKV@gaddtosave}%
- {}}}}}}}}}}%
-}
-\SKV@predef*\define@key{\SKV@skfalse\XKV@testoptb\XKV@define@key}
-\def\XKV@define@key#1{%
- \SKV@findkeypointers{#1}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@csundef{\XKV@header\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \begingroup
- \edef\SKV@tempa{\endgroup
- \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}%
- {\noexpand\SKV@d@fine@key{\SKV@resa}}%
- }%
- \SKV@tempa
-}
-\def\XKV@d@fine@key#1[#2]#3{%
- \XKV@define@default{#1}{#2}%
- \@namedef{\XKV@header#1}##1{#3}%
-}
-\def\SKV@d@fine@key#1#2{\@namedef{\XKV@header#1}##1{#2}}
-\SKV@def*\SKV@reservmp#1#2{%
- \begingroup
- \SKV@sp@def{#1}\SKV@tempb
- \SKV@expnext\XKV@checksanitizeb#2\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \XKV@knftrue
- \XKV@whilist\SKV@tempa\SKV@tempa\ifXKV@knf\fi{%
- \ifx\SKV@tempb\SKV@tempa\XKV@knffalse\fi
- }%
- \unless\ifXKV@knf
- \SKV@afterfi
- \SKV@err{Macro prefix '\SKV@tempa' is reserved}%
- {You have used a reserved macro prefix: '\SKV@tempa'.\SKV@MB
- Use another macro prefix name instead of '\SKV@tempa'.}%
- \fi
- \endgroup
-}
-\SKV@predef*\define@cmdkey{%
- \SKV@skfalse\XKV@testoptd\XKV@define@cmdkey{cmd}}
-\SKV@predef*\define@cmdkeys{%
- \SKV@skfalse\XKV@testoptd\XKV@define@cmdkeys{cmd}}
-\def\XKV@define@cmdkey#1#2[#3]#4{%
- \SKV@reservmp{#1}\SKV@rmpnames
- \SKV@findkeypointers{#2}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@Undef+{\XKV@header\SKV@resa,#1\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \ifXKV@st
- \SKV@afterfi
- \SKV@expnext\XKV@define@default\SKV@resa{#3}%
- \fi
- \begingroup
- \def\SKV@tempa{%
- \expandafter\def\csname\XKV@header\SKV@resa\endcsname####1}%
- \SKV@threexp\endgroup\expandafter\SKV@tempa\expandafter%
- {\expandafter\def\csname#1\SKV@resa\endcsname{##1}#4}%
-}
-\SKV@predef*\define@choicekey{\SKV@skfalse
- \XKV@testopta{\XKV@testoptb\XKV@define@choicekey}}
-\SKV@newlet\define@menukey\define@choicekey
-\def\XKV@define@choicekey#1{%
- \SKV@findkeypointers{#1}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@csundef{\XKV@header\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \begingroup
- \edef\SKV@tempa{\endgroup
- \SKV@testopt{\noexpand\XKV@d@fine@choicekey{\SKV@resa}}{}%
- }%
- \SKV@tempa
-}
-\SKV@predef*\define@boolkey{\SKV@skfalse
- \XKV@t@stopta{\XKV@testoptd\XKV@define@boolkey{}}}
-\SKV@predef*\define@boolkeys{\SKV@skfalse
- \XKV@plfalse\XKV@testoptd\XKV@define@boolkeys{}}
-\def\XKV@define@boolkey#1#2[#3]{%
- \SKV@findkeypointers{#2}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}%
- \SKV@Undef+{\XKV@header\SKV@resa,#1\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \ifXKV@pl
- \def\SKV@next{\SKV@aftercs\XKV@d@f@ne@boolkey}%
- \else
- \def\SKV@next{\SKV@aftercs\XKV@d@fine@boolkey}%
- \fi
- \edef\SKV@tempa{{\XKV@header\SKV@resa}{\SKV@resa}{#1\SKV@resa}{#3}}%
- \expandafter\SKV@next\SKV@tempa
-}
-\def\XKV@d@fine@boolkey#1#2#3#4#5{%
- \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}%
- {{\SKV@expargs{0}{\SKV@getswstate\XKV@d@fine@boolkey}\XKV@resa\@nil
- \csname#3\SKV@swval\endcsname#5}}%
-}
-\def\XKV@d@f@ne@boolkey#1#2#3#4#5#6{%
- \XKV@d@f@ne@b@olkey#1{#2}{#3}{#4}%
- {{\SKV@expargs{0}{\SKV@getswstate\XKV@d@f@ne@boolkey}\XKV@resa\@nil
- \csname#3\SKV@swval\endcsname#5}{#6}}%
-}
-\def\XKV@d@f@ne@b@olkey#1#2#3#4#5{%
- \csnewif{if#3}%
- \ifXKV@st\XKV@define@default{#2}{#4}\fi
- \edef#1##1{%
- \def#1####1{##1\unexpanded{\XKV@sttrue\XKV@checkchoice[\XKV@resa]}%
- {####1}{true,false,on,off}\unexpanded{#5}%
+ \ifx\skv@classoptsfound\@empty\else\skvafterfi
+ \skvexpbracenext\skv@getkeynames\skv@classoptsfound\skv@tempd
+ \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ \fi
}%
}%
- \ifXKV@pl#1\XKV@pltrue\else#1\XKV@plfalse\fi
-}
-\def\XKV@d@fine@boolkeys#1#2#3{%
- \SKV@findkeypointers{#1}%
- \SKV@ifcsundef{\XKV@header\SKV@resa}{}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@resa' in family '\XKV@tfam' with\SKV@MB
- prefix '\SKV@pref' redefined\on@line}
- \SKV@Undef+{\XKV@header\SKV@resa,#2\SKV@resa}%
- }%
- \SKV@expnext\SKV@reservkey@err\SKV@resa
- \SKV@expnext\SKV@suspkey@err\SKV@resa
- \edef\SKV@tempa##1##2##3{%
- ##1\@nameuse{\XKV@header\SKV@resa}{\SKV@resa}%
- {#2\SKV@resa}{#3}{{##2{#2\SKV@resa##3}}}%
- }%
- \SKV@tempa\XKV@d@f@ne@b@olkey\@nameuse\XKV@resa
-}
-\SKV@pdef*\reserve@keys{\@testopt\SKV@reserve@keys{KV}}
-\SKV@def*\SKV@reserve@keys[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@res@rve@keys\SKV@tempa{#2}{#3}%
- }%
-}
-\SKV@def*\SKV@res@rve@keys#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@for@b\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam
- \SKV@res@rve@k@ys{#3}%
- }%
-}
-\SKV@def*\SKV@res@rve@k@ys#1{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@ifcsdef{\XKV@header\SKV@tempa}{%
- \SKV@err{%
- Key '\SKV@tempa' with prefix '\SKV@pref' in family
- \SKV@MB '\XKV@tfam' is already defined
- }{%
- Key '\SKV@tempa' in family '\XKV@tfam' can't be reserved.
- \SKV@MB You may wish to remove it before reserving it.
- \SKV@MB In that case, you can use '\string\remove@keys'.
- }%
- }{%
- \SKV@csedef*{\XKV@header\SKV@tempa}{%
- \SKV@err{%
- Key '\SKV@tempa' with prefix '\SKV@pref' in family
- '\XKV@tfam'\SKV@MB was reserved\on@line
- }{%
- Unreserve '\SKV@tempa' before use.
+ \skvletcs\skv@pkgorclsopts{opt@\@currname.\@currext}%
+ \skvifx\skv@pkgorclsopts\@empty{}{%
+ \skvifx\skv@pkgorclsopts\relax{}{%
+ \skvexpbracenext\skv@getkeynames\skv@pkgorclsopts\skv@tempd
+ \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ }%
+ }%
+ % Package options have higher priority than class options. Hence
+ % filter class options \skv@classoptsfound that are also present
+ % as package options \skv@pkgorclsopts:
+ \ifcase0\ifx\skv@classoptsfound\@empty0\else
+ \ifx\skv@pkgorclsopts\@empty0\else
+ \ifx\skv@pkgorclsopts\relax0\else1\fi\fi\fi\relax
+ \else\skvafterfi
+ \skvifx\skv@testclass\skv@documentclass{}{%
+ \skvcommaloop*\skv@classoptsfound\CurrentOption{%
+ \expandafter\expandafter\expandafter
+ \skv@g@tkeyname\CurrentOption=\skv@nil\skv@tempa
+ \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempd,}{}{%
+ \edef\skv@pkgorclsopts{%
+ \skvexpandonce\skv@pkgorclsopts,\skvexpandonce\CurrentOption
+ }%
}%
}%
- \SKV@csdef*{\XKV@header\SKV@tempa @reser}{}%
}%
- }%
-}
-\SKV@def*\SKV@reservkey@err#1{%
- \SKV@ifcsdef{\XKV@header#1@reser}\SKV@err\@gobbletwo
- {Key '#1' with prefix '\SKV@pref'\SKV@MB
- is reserved in family '\XKV@tfam'}{Unreserve '#1' before use.}%
-}
-\SKV@def*\ifkeyreserved{\@testopt\SKV@ifkeyreserved{KV}}
-\SKV@def*\SKV@ifkeyreserved[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@swtrue
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@ifkey@reserved\SKV@tempa{#2}{#3}%
- }%
- \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
-}
-\SKV@def*\SKV@ifkey@reserved#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@sp@def{#3}\XKV@tkey
- \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
- \XKV@makehd\XKV@tfam
- \SKV@ifcsdef{\XKV@header\XKV@tkey @reser}\SKV@swfalse\relax
- }%
-}
-\SKV@def*\ifkeysuspended{\@testopt\SKV@ifkeysuspended{KV}}
-\SKV@def*\SKV@ifkeysuspended[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@swtrue
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@ifkey@suspended\SKV@tempa{#2}{#3}%
- }%
- \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
-}
-\SKV@def*\SKV@ifkey@suspended#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@sp@def{#3}\XKV@tkey
- \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
- \XKV@makehd\XKV@tfam
- \SKV@ifcsdef{\XKV@header\XKV@tkey @susp}\SKV@swfalse\relax
- }%
-}
-\SKV@def*\ifkeydefined{\@testopt\SKV@ifkeydefined{KV}}
-\SKV@def*\SKV@ifkeydefined[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@swtrue
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@ifk@ydefined\SKV@tempa{#2}{#3}%
- }%
- \@nameuse{SKV@\ifSKV@sw2\else1\fi of2}%
-}
-\SKV@def*\SKV@ifk@ydefined#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@sp@def{#3}\XKV@tkey
- \XKV@whilist\XKV@fams\XKV@tfam\ifSKV@sw\fi{%
- \XKV@makehd\XKV@tfam
- \SKV@ifcsdef{\XKV@header\XKV@tkey}\SKV@swfalse\relax
- }%
-}
-\SKV@def*\SKV@disabledkey@err{%
- \SKV@err{%
- Key '\SKV@disabledkey' with prefix '\SKV@pref' in family
- \SKV@MB '\XKV@tfam' was disabled\on@line
- }{%
- You can't set or reset '\SKV@disabledkey' at this\SKV@MB
- late stage. Perhaps you're required to set it \SKV@MB
- earlier, within a package or in the document's preamble.
- }%
-}
-\def\disable@keys{%
- \SKV@ifstar{\@testopt\XKV@disable@keys{KV}}%
- {\@testopt\SKV@disable@keys{KV}}%
-}
-\SKV@def*\SKV@disable@keys[#1]#2#3{%
- \SKV@locfalse
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@dis@ble@keys\SKV@tempa{#2}{#3}%
- }%
-}
-\SKV@def*\SKV@dis@ble@keys#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@for@b\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam
- \SKV@dis@ble@k@ys{#3}%
- }%
-}
-\SKV@def*\SKV@dis@ble@k@ys#1{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
- \ifSKV@verbose\SKV@disabledkey@warn\fi
- }{%
- \SKV@dis@ble@k@y@\SKV@tempa
- }%
- }%
-}
-\def\SKV@disabledkey@warn{%
- \SKV@warn{Key '\SKV@tempa' with prefix '\SKV@pref'
- \SKV@MB is undefined in family '\XKV@tfam':
- \SKV@MB can't be \ifSKV@loc localized
- \else disabled\fi\on@line
- }%
-}
-\def\SKV@disabledkey@info{%
- \SKV@info{Key '\SKV@disabledkey' with prefix '\SKV@pref'
- in family '\XKV@tfam'\SKV@MB was \ifSKV@loc localized
- \else disabled\fi\on@line
- }%
-}
-\SKV@def*\SKV@dis@ble@k@y@#1{%
- \edef\SKV@disabledkey{#1}%
- \SKV@ifcsundef{\XKV@header#1@default}{%
- \edef#1{\noexpand\XKV@define@key{#1}}%
- }{%
- \edef#1{\noexpand\XKV@define@key{#1}[]}%
- }%
- \SKV@expargs{0}#1\SKV@disabledkey@err\@nil
- \ifSKV@verbose\SKV@disabledkey@info\fi
-}
-\SKV@pdef*\localize@keys{%
- \SKV@onlypackage\SKV@savstate
- \SKV@t@stopta{\@testopt\SKV@localize@keys{KV}}%
-}
-\SKV@def*\SKV@localize@keys[#1]#2#3{%
- \SKV@loctrue
- \ifSKV@st
- \expandafter\SKV@BeforeDocumentStart
- \else
- \expandafter\SKV@AfterPackageEnd
\fi
- {%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@dis@ble@keys\SKV@tempa{#2}{#3}%
- }%
- }%
- \SKV@resstate
-}
-\SKV@def*\SKV@suspkey@err#1{%
- \SKV@ifcsdef{\XKV@header#1@susp}\SKV@err\@gobbletwo
- {Key '#1' was suspended from family '\XKV@tfam'}%
- {You can use \string\restore@key\space to restore '#1'.}%
-}
-\SKV@def*\SKV@suspkey@e@r{%
- \SKV@err{Key '\SKV@suspkey' in family '\XKV@tfam' was\SKV@MB
- suspended\on@line}{You can use \string\restore@key\space
- to restore '\SKV@suspkey'.}%
-}
-\SKV@pdef*\suspend@keys{\@testopt\SKV@suspend@keys{KV}}
-\SKV@def*\SKV@suspend@keys[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@s@spend@keys\SKV@tempa{#2}{#3}%
- }%
-}
-\SKV@def*\SKV@s@spend@keys#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@for@b\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam
- \SKV@s@sp@nd@keys{#3}%
- }%
-}
-\SKV@def*\SKV@s@sp@nd@keys#1{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
- \SKV@vbmsg{warn}{%
- Key '\SKV@tempa' with prefix '\SKV@pref'
- \SKV@MB is undefined in family '\XKV@tfam':
- \SKV@MB can't be suspended\on@line}%
- }{%
- \SKV@s@sp@nd@k@ys\SKV@tempa
- }%
- }%
-}
-\SKV@def*\SKV@s@sp@nd@k@ys#1{%
- \SKV@ifcsdef{\XKV@header#1@susp}{%
- \SKV@err{%
- Key '#1' with prefix '\SKV@pref'
- was suspended from family '\XKV@tfam'
- }{%
- You can use \string\restore@key\space to restore '#1'.
- }%
- }{%
- \edef\SKV@suspkey{#1}%
- \global\SKV@csletcs{\XKV@header#1@susp}{\XKV@header#1}%
- \SKV@csedef*{\XKV@header#1}{\SKV@suspkey@e@r}%
- \SKV@vbmsg{info}{Key '\SKV@suspkey' with prefix '\SKV@pref' in
- \SKV@MB family '\XKV@tfam' was suspended\on@line}%
- }%
-}
-\SKV@pdef*\restore@keys{\@testopt\SKV@restore@keys{KV}}
-\SKV@def*\SKV@restore@keys[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@r@store@keys\SKV@tempa{#2}{#3}%
- }%
-}
-\SKV@def*\SKV@r@store@keys#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@for@b\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam
- \SKV@r@st@re@keys{#3}%
- }%
-}
-\SKV@def*\SKV@r@st@re@keys#1{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
- \SKV@vbmsg{warn}{Key '\SKV@tempa' with prefix '\SKV@pref'
- \SKV@MB is undefined in family '\XKV@tfam':
- \SKV@MB can't be restored\on@line}%
- }{%
- \SKV@r@st@re@k@ys\SKV@tempa
- }%
- }%
-}
-\SKV@def*\SKV@r@st@re@k@ys#1{%
- \SKV@ifcsundef{\XKV@header#1@susp}{%
- \SKV@err{Key '#1' wasn't suspended from family
- \SKV@MB '\XKV@tfam': can't be restored\on@line}%
- {I can't restore unsuspended key '#1'}%
- }{%
- \edef\SKV@restoredkey{#1}%
- \SKV@csletcs{\XKV@header#1}{\XKV@header#1@susp}%
- \SKV@csundef{\XKV@header#1@susp}%
- \SKV@vbmsg{info}{Key '\SKV@restoredkey' with prefix
- '\SKV@pref' in family \SKV@MB '\XKV@tfam' restored\on@line}%
- }%
-}
-\SKV@pdef*\remove@keys{\@testopt\SKV@remove@keys{KV}}
-\SKV@def*\SKV@remove@keys[#1]#2#3{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for*[,]\SKV@tempa\SKV@tempa{%
- \SKV@expnext\SKV@r@move@keys\SKV@tempa{#2}{#3}%
- }%
-}
-\SKV@def*\SKV@r@move@keys#1#2#3{%
- \XKV@makepf{#1}%
- \XKV@checksanitizeb{#2}\XKV@fams
- \SKV@despacelist*\XKV@fams
- \SKV@for@b\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam
- \SKV@r@m@ve@keys{#3}%
- }%
-}
-\SKV@def*\SKV@r@m@ve@keys#1{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@despacelist*\SKV@tempa
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@ifcsundef{\XKV@header\SKV@tempa @susp}{}{%
- \SKV@err{Key '\SKV@tempa' with prefix '\SKV@pref'
- \SKV@MB was suspended from family '\XKV@tfam':
- \SKV@MB I can't remove/unreserve it\on@line.
- \SKV@MB You need to first restore key '\SKV@tempa'
- \SKV@MB before you can remove/unreserve it}%
- {First restore key '\SKV@tempa' before removing it.}%
- }%
- \SKV@ifcsundef{\XKV@header\SKV@tempa}{%
- \SKV@vbmsg{warn}{Key '\SKV@tempa' with prefix '\SKV@pref'
- \SKV@MB is undefined in family '\XKV@tfam':
- \SKV@MB I can't remove or unreserve it\on@line}%
- }{%
- \SKV@r@m@ve@k@ys\SKV@tempa
- }%
- }%
-}
-\SKV@def*\SKV@r@m@ve@k@ys#1{%
- \begingroup
- \edef\SKV@tempa{\XKV@header#1,\XKV@header#1@default,
- \XKV@header#1@func,\XKV@header#1@altlist,
- \XKV@header#1@reser
- }%
- \SKV@for@b\SKV@tempa\SKV@tempa{%
- \SKV@despacectt\SKV@tempa
- \SKV@csgundef{\SKV@tempa}%
- }%
- \endgroup
- \SKV@vbmsg{info}{Key '#1' with prefix '\SKV@pref' in family\SKV@MB
- '\XKV@tfam' was removed\on@line}%
-}
-\SKV@newlet\unreserve@keys\remove@keys
-\SKV@def*\uservaluekeys{\XKV@testoptb\SKV@uservaluekeys}
-\SKV@def*\SKV@uservaluekeys#1{%
- \SKV@ifcsundef{SKV@\XKV@header uservalue}{%
- \XKV@checksanitizeb{#1}\SKV@tempa
- \SKV@csxdef*{SKV@\XKV@header uservalue}{\SKV@expox{\SKV@tempa}}%
- }{%
- \SKV@aftercs\XKV@merge{SKV@\XKV@header uservalue}{#1}\XKV@getsg
- }%
-}
-\SKV@def*\SKV@undefinedkeys#1#2#3{%
- \edef\SKV@resvd##1{\SKV@addtolist![;]##1{(#1:#2:#3)}}%
- \SKV@resvd\SKV@und@finedkeys
-}
-\SKV@predef*\ExecuteOptionsX{%
- \SKV@sktrue\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys}
-\SKV@predef*\setkeys{\SKV@sktrue\XKV@testopta{\XKV@testoptc\XKV@setkeys}}
-\SKV@newlet\skvsetkeys\setkeys
-\SKV@pdef*\UseSkeyvalSetkeys{%
- \SKV@ifx\setkeys\skvsetkeys\relax{\let\setkeys\skvsetkeys}%
-}
-\SKV@redef*\XKV@setkeys[#1]#2{%
- \def\skif##1{%
- \SKV@ensurenoscape{##1}%
- \SKV@ifcsdef{if##1}{}{%
- \SKV@err{Undefined boolean '##1'}%
- {'\string\skif' error: boolean '##1' undefined.}%
- }%
- \csname if##1\endcsname
- }%
- \let\skifx\ifx
- \let\skifcase\ifcase
- \let\skor\or
- \let\skelse\else
- \let\skfi\fi
- \let\SKV@und@finedkeys\@empty
- \XKV@checksanitizea{#2}\XKV@resb
- \SKV@normalizea\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
- \XKV@usepresetkeys{#1}{preseth}%
- \SKV@expnext\XKV@s@tkeys\XKV@resb{#1}%
- \XKV@usepresetkeys{#1}{presett}%
- \let\CurrentOption\@empty
- \SKV@skfalse
- \SKV@ifx\SKV@und@finedkeys\@empty{}{%
- \def\SKV@tempa{stop}%
- \SKV@warn{\string\setkeys\space error: Unknown keys:\SKV@MB
- \SKV@expox\SKV@und@finedkeys}%
- \typein[\answer]{%
- ^^JThe following keys are undefined and couldn't be set:
- ^^J\SKV@expox\SKV@und@finedkeys
- ^^JEnter 'stop' or 'go' and <return> to continue.}%
- \ifx\answer\SKV@tempa\stop\fi
+ \skvexpanded{\endgroup
+ \skv@exitpoxkeys
+ % There may be preset keys even when \skv@pkgorclsopts is empty:
+ \skvsetkeys\ifskv@pl+\fi[\skvcurrentprefix]{\skv@fams}[#1]%
+ {\skvexpandonce\skv@pkgorclsopts}%
}%
+ \skvcslet{skv@dox@\@currname @\@currext}\relax
+ \skvinitializermkeys*\skvcurrentprefix\skv@fams
+ \skv@inpoxfalse
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+ \csname skv@\@currname @\@currext @afterprocess@hook\endcsname
+ \skvcslet{skv@\@currname @\@currext @afterprocess@hook}\relax
}
-\SKV@redef*\XKV@s@tk@ys#1=#2=#3\@nil{%
- \XKV@g@tkeyname#1=\@nil\XKV@tkey
- \SKV@expnext\SKV@sp@def\XKV@tkey\XKV@tkey
- \SKV@ifx\XKV@tkey\@empty{%
- \SKV@ifempty{#2}{}{%
- \SKV@err{No key specified for value '#2'}%
- {You have supplied a value '#2' without key name.\SKV@MB
- This is certainly an error on your part.\SKV@MB
- I can't process this value without key name.\SKV@MB
- Please enter 'X' and <return>. Correct the error and rerun.}
- }%
- }{%
- \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}%
- \unless\ifin@
- \XKV@knftrue
- \SKV@sp@def{#2}\XKV@tempa
- \ifXKV@preset
- \XKV@s@tk@ys@{#3}%
- \else
- \ifXKV@pl
- \XKV@for@eo\XKV@fams\XKV@tfam{%
- \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}%
- }%
- \else
- \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{%
- \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}%
- }%
- \fi
- \fi
- \ifXKV@knf
- \ifXKV@inpox
- \SKV@ifx\XKV@doxs\relax{%
- \unless\ifx\@currext\@clsextension
- \let\CurrentOption\XKV@tkey\@unknownoptionerror
- \fi
- }{%
- \XKV@doxs
- }%
- \else
- \ifXKV@st
- \XKV@addtolist@o\XKV@rm\CurrentOption
- \else
- \SKV@undefinedkeys\SKV@pref\XKV@fams\XKV@tkey
- \fi
- \fi
- \else
- \ifXKV@inpox\ifx\XKV@testclass\XKV@documentclass
- \SKV@expnext\XKV@useoption\CurrentOption
- \fi\fi
- \fi
- \fi
- }%
+
+% \skvrestrictedprocessoptions*+[<pref>]{<fams>}[<na>]
+% 1. This will not process class options, but only options
+% issued to the package.
+\skvrobustdef*\skvrestrictedprocessoptions{\skv@testopte\skv@restrictedpox}
+\skvrobustdef*\skv@restrictedpox[#1]{%
+ \skv@inpoxtrue
+ \let\@fileswith@pti@ns\@badrequireerror
+ \begingroup
+ \let\skv@exitpoxkeys\@empty
+ \let\skv@pkgorclsopts\@empty
+ \skvletcs\skv@pkgorclsopts{opt@\@currname.\@currext}%
+ \ifcase0\ifx\skv@pkgorclsopts\@empty0\else
+ \ifx\skv@pkgorclsopts\relax0\else1\fi\fi\relax
+ \else\skvafterfi
+ \skvexpbracenext\skv@getkeynames\skv@pkgorclsopts\skv@tempd
+ \skvexpbracenext\skv@getpoxkeys\skv@tempd
+ \fi
+ \skvexpanded{\endgroup
+ \skv@exitpoxkeys
+ \skvsetkeys\ifskv@pl+\fi[\skvcurrentprefix]{\skv@fams}[#1]%
+ {\skvexpandonce\skv@pkgorclsopts}%
+ }%
+ \skvcslet{skv@dox@\@currname @\@currext}\relax
+ \skvinitializermkeys*\skvcurrentprefix\skv@fams
+ \skv@inpoxfalse
+ \let\@fileswith@pti@ns\@@fileswith@pti@ns
+ \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+ \csname skv@\@currname @\@currext @afterprocess@hook\endcsname
+ \skvcslet{skv@\@currname @\@currext @afterprocess@hook}\relax
}
-\SKV@redef*\XKV@s@tk@ys@#1{%
- \SKV@ifcsundef{\XKV@header\XKV@tkey}{%
- \SKV@vbmsg{warn}{No key macro for key '\XKV@tkey'\SKV@MB
- in families '\XKV@fams'}%
- }{%
- \XKV@knffalse
- \SKV@ifcsundef{SKV@\XKV@header uservalue}{}{%
- \SKV@aftercs\SKV@testuservaluekey
- {SKV@\XKV@header uservalue}\XKV@tkey
- \ifSKV@uv
- \SKV@ifnotblank{#1}{}{%
- \SKV@err{You're required to supply a value\SKV@MB
- for key '\XKV@tkey' in families '\XKV@fams'}%
- {Please supply a value for key '\XKV@tkey'\SKV@MB
- of families '\XKV@fams' and rerun.\SKV@MB
- The originator of this key meant it to\SKV@MB
- require a user value.}%
+
+% Get pox keys (ie, keys processed as options) from package or
+% class options:
+\skvrobustdef*\skv@getpoxkeys#1{%
+ \skvcommaloop{#1}\skvcurrentkey{%
+ \skvexpanded{%
+ \skvifkeynotinfamilies
+ [\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}%
+ }{}{%
+ % \skv@header is formed in the search for the key:
+ \skvletcs\skv@prova{\skv@header.@poxkeys}%
+ \skvifdef\skv@prova{%
+ \skvxifin{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@prova,}{}{%
+ \skvcsedef{\skv@header.@poxkeys}{\skv@prova,\skvcurrentkey}%
}%
- \fi
- }%
- \SKV@ifcsundef{XKV@\XKV@header save}{}{%
- \SKV@aftercs\XKV@testsavekey{XKV@\XKV@header save}\XKV@tkey
- }%
- \ifXKV@rkv
- \ifXKV@sg\expandafter\global\fi
- \SKV@aftercs\let{XKV@\XKV@header\XKV@tkey @value}\XKV@tempa
- \fi
- \SKV@expnext\XKV@replacepointers\XKV@tempa
- \SKV@ifblank{#1}{%
- \SKV@ifcsundef{\XKV@header\XKV@tkey @default}{%
- \SKV@err{'\XKV@tkey' in family '\XKV@tfam' with\SKV@MB
- prefix '\XKV@pref' has no default value and\SKV@MB
- you haven't supplied a value for it either}%
- {Supply a value for key '\XKV@tkey' and rerun.}%
}{%
- \SKV@xaftercs\XKV@default{\XKV@header\XKV@tkey @default}\@nil
+ \skvcsedef{\skv@header.@poxkeys}{\skvcurrentkey}%
+ }%
+ \skvxifin{\skvoxdetok\skv@header}{\skvoxdetok\skv@exitpoxkeys}{}{%
+ \edef\skv@exitpoxkeys{%
+ \skvexpandonce\skv@exitpoxkeys
+ \noexpand\skvcsexit{\skv@header.@poxkeys}%
+ }%
}%
- }{%
- \XKV@savstate
- \csname\XKV@header\XKV@tkey\expandafter
- \endcsname\expandafter{\XKV@tempa}\relax
- \XKV@resstate
- }%
- }%
-}
-\SKV@def*\SKV@testuservaluekey#1#2{%
- \SKV@swtrue\SKV@uvfalse
- \XKV@whilist#1\SKV@tempa\ifSKV@sw\fi{%
- \ifx#2\SKV@tempa\SKV@uvtrue\SKV@swfalse\fi
- }%
-}
-\SKV@def*\SKV@remspaceletter#1#2{%
- \begingroup
- \SKV@toks\expandafter{#2 #1}%
- \def\SKV@tempa##1 #1##2\@nil{%
- \SKV@ifblank{##2}{%
- \SKV@toks{##1}%
- }{%
- \SKV@toks{##1#1##2}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
- }%
- }%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
- \xdef#2{\the\SKV@toks}%
- \endgroup
-}
-\SKV@def*\SKV@remletterspace#1#2{%
- \begingroup
- \SKV@toks\expandafter{#2#1 }%
- \def\SKV@tempa##1#1 ##2\@nil{%
- \SKV@ifblank{##2}{%
- \SKV@toks{##1}%
- }{%
- \SKV@toks{##1#1##2}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
}%
}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
- \xdef#2{\the\SKV@toks}%
- \endgroup
}
-\SKV@def*\SKV@remletterletter#1#2{%
- \begingroup
- \SKV@toks\expandafter{#2#1#1}%
- \def\SKV@tempa##1#1#1##2\@nil{%
- \SKV@toks{##1#1##2}%
- \SKV@ifblank{##2}{}{%
- \expandafter\SKV@tempa\the\SKV@toks\@nil}%
+
+% +++++++++ Utilities for handling options via \directkeys +++++++++%
+
+\skvrobustdef*\dirkeys@declareoptions@a{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \skv@dox
+}
+\skvrobustdef*\dirkeys@declareoptions@b#1{%
+ \let\@fileswith@pti@ns\@badrequireerror
+ \skv@inopttrue
+ \begingroup
+ \edef\skv@tempb{\unexpanded{#1}}%
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvdefinekeys\ifskv@handlerswa*\fi[##1]{##2}%
+ [\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+ \skv@inoptfalse
+}
+\skvrobustdef*\dirkeys@executeoptions#1{%
+ \skv@inopttrue
+ \begingroup
+ \edef\skv@tempb{\unexpanded{#1}}%
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvsetkeys\ifskv@handlerswa+\fi
+ [##1]{##2}[\skvcsuse{##1/##2/.@ignoredkeys}]%
+ {\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+ \skv@inoptfalse
+}
+\skvrobustdef*\dirkeys@executeoptions@b#1{%
+ \skv@inopttrue
+ \begingroup
+ \def\skv@tempa{}\def\skv@tempb{}\def\skv@tempc{}%
+ \def\do##1##2{%
+ \skvxifin{,##1,}{,\skv@tempa,}{}{%
+ \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}%
+ }%
+ \skvxifin{,##2,}{,\skv@tempb,}{}{%
+ \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}%
+ }%
+ \edef\skv@tempc{%
+ \skv@tempc\ifx\skv@tempc\@empty\else,\fi
+ \skvcsuse{##1/##2/.@ignoredkeys}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \@tempcnta\skvz@
+ \let\skv@tempd\skv@tempa
+ \skvcommaloop*\skv@tempa\skv@prova{%
+ \advance\@tempcnta\@ne
+ \ifnum\@tempcnta>\@ne
+ \skv@err{You can't submit more than one prefix here}\@ehd
+ \skvbreakloop
+ \fi
}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
- \def\SKV@tempa##1#1#1\@nil{\gdef#2{##1}}%
- \expandafter\SKV@tempa\the\SKV@toks#1\@nil
- \endgroup
+ \skvexpanded{\endgroup
+ \skvsetkeys\ifskv@handlerswa+\fi[\skv@tempd]{\skv@tempb}[\skv@tempc]%
+ }{#1}%
+ \skv@inoptfalse
}
-\SKV@def*\SKV@remcommaequal#1#2{%
+\skvrobustdef*\dirkeys@processoptions{%
+ \skv@inopttrue
\begingroup
- \SKV@toks\expandafter{#2#1}%
- \def\SKV@tempa##1#1##2\@nil{%
- \SKV@ifblank{##2}{%
- \SKV@toks{##1}%
- }{%
- \SKV@toks{##1=##2}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
+ \def\skv@tempa{}%
+ \def\do##1##2{%
+ \edef\skv@tempa{%
+ \skvexpandonce\skv@tempa
+ \skvprocessoptions\ifskv@handlerswa*\fi\ifskv@handlerswb+\fi
+ [##1]<##2>[\skvcsuse{##1/##2/.@ignoredkeys}]%
}%
}%
- \expandafter\SKV@tempa\the\SKV@toks\@nil
- \xdef#2{\the\SKV@toks}%
- \endgroup
-}
-\SKV@def*\SKV@normalizea#1{%
- \@expandtwoargs\SKV@in@{ ,}{\SKV@expox{#1}}%
- \ifin@\SKV@remspaceletter{,}#1\fi
- \@expandtwoargs\SKV@in@{, }{\SKV@expox{#1}}%
- \ifin@\SKV@remletterspace{,}#1\fi
- \@expandtwoargs\SKV@in@{,,}{\SKV@expox{#1}}%
- \ifin@\SKV@remletterletter{,}#1\fi
- \@expandtwoargs\SKV@in@{ =}{\SKV@expox{#1}}%
- \ifin@\SKV@remspaceletter{=}#1\fi
- \@expandtwoargs\SKV@in@{= }{\SKV@expox{#1}}%
- \ifin@\SKV@remletterspace{=}#1\fi
- \@expandtwoargs\SKV@in@{==}{\SKV@expox{#1}}%
- \ifin@\SKV@remletterletter{=}#1\fi
- \@expandtwoargs\SKV@in@{,=}{\SKV@expox{#1}}%
- \ifin@\SKV@remcommaequal{,=}#1\fi
- \@expandtwoargs\SKV@in@{=,}{\SKV@expox{#1}}%
- \ifin@\SKV@remcommaequal{=,}#1\fi
+ \dirkeys@getcurrentroots\do
+ \expandafter\endgroup\skv@tempa
+ \skv@inoptfalse
}
-\SKV@def*\SKV@gobblescape{%
- \ifnum\escapechar>255\else
- \ifnum\escapechar<0\else
- \expandafter\expandafter
- \csname @gobble\ifnum\escapechar=32 space\fi
- \SKV@threexp\endcsname
- \fi\fi
- \string%
-}
-\SKV@def*\SKV@save#1{%
- \SKV@ensurescape{#1}%
- \edef\SKV@tempa{saved\SKV@gobblescape#1}%
- \SKV@ifcsdef\SKV@tempa{%
- \SKV@err{%
- \string#1\space already saved. You've to restore\SKV@MB
- it or undefine '\SKV@csexpox{\SKV@tempa}' before\SKV@MB
- you can save \string#1\space again
- }\@ehc
- }{%
- \SKV@ifdef{#1}{%
- \SKV@cslet\SKV@tempa{#1}%
- }{%
- \SKV@err{Undefined '\string#1' can't be saved\on@line}%
- {You can't restore undefined commands.\SKV@MB
- So why save undefined '\string#1' here?}%
- }%
+
+\skvrobustdef*\dirkeys@processoptions@b{%
+ \skv@inopttrue
+ \begingroup
+ \def\skv@tempa{}\def\skv@tempb{}\def\skv@tempc{}%
+ \def\do##1##2{%
+ \skvxifin{,##1,}{,\skv@tempa,}{}{%
+ \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}%
+ }%
+ \skvxifin{,##2,}{,\skv@tempb,}{}{%
+ \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}%
+ }%
+ \edef\skv@tempc{%
+ \skv@tempc\ifx\skv@tempc\@empty\else,\fi
+ \skvcsuse{##1/##2/.@ignoredkeys}%
+ }%
+ }%
+ \dirkeys@getcurrentroots\do
+ \@tempcnta\skvz@
+ \let\skv@tempd\skv@tempa
+ \skvcommaloop*\skv@tempa\skv@prova{%
+ \advance\@tempcnta\@ne
+ \ifnum\@tempcnta>\@ne
+ \skv@err{You can't submit more than one prefix here}\@ehd
+ \skvbreakloop
+ \fi
}%
-}
-\SKV@def*\SKV@restore#1{%
- \SKV@ensurescape{#1}%
- \edef\SKV@tempa{saved\SKV@gobblescape#1}%
- \SKV@ifcsdef\SKV@tempa{%
- \def\SKV@next{\SKV@letcs#1\SKV@tempa\SKV@csundef\SKV@tempa}%
- }{%
- \SKV@err{%
- '\@nameuse\SKV@tempa' is undefined:\SKV@MB
- '\string#1' can't be restored\on@line
- }{%
- '\string#1' can't be restored\on@line.\SKV@MB
- Note that each call to \string\SKV@restore\space
- undefines\SKV@MB the saved command.
- }%
+ \skvexpanded{\endgroup
+ \skvprocessoptions\ifskv@handlerswa+\fi
+ [\skv@tempd]<\skv@tempb>[\skv@tempc]%
}%
- \SKV@next
+ \skv@inoptfalse
}
-\SKV@providedef*\input@path{}
-\SKV@pdef*\InputFileOnce{%
- \def\SKV@inputfile##1##2{%
- \InputIfFileExists{##2}{%
- \SKV@cslet{##2@read}\@empty
- \let\SKV@inp@tfile\relax
- }{%
- \typein[\answer]{^^J! File '\string##2' does not exist.^^J
- Enter filename or 'no' and <return> to continue.}%
- \SKV@oifstrequal{\answer}{no}{%
- \let\SKV@inp@tfile\relax
- }{%
- \def\SKV@inp@tfile{%
- \SKV@expargs{0}{\SKV@InputFileOnce[##1]}\answer\@nil
- }}}}%
- \let\SKV@no\z@
- \SKV@save\input@path
- \SKV@t@stopta{\SKV@testopt\SKV@InputFileOnce{.}}%
+
+% ++++++++ Keys for the handler <.mega process options> +++++++++ %
+\directkeys*{%
+ .prefix=SKV,
+ .family=megapox,
+ .holder prefix=dirkeys@pox@,
+ .initialize keys after define=true,
+ .new keys={
+ .ord/.ignore options//
+ \def\dirkeys@pox@igkeys{#1}
+ \skvstripouterbraces{2}\dirkeys@pox@igkeys
+ ,
+ .ord/.options prefix/KV/
+ \skvxifin{,}{\detokenize{#1}}{
+ \skv@err{Only one prefix is allowed in processing options}\@ehd
+ }{
+ \def\dirkeys@pox@pref{#1}
+ \skvstripouterbraces{2}\dirkeys@pox@pref
+ }
+ ,
+ .ord/.options families/\@currname.\@currext/
+ \edef\dirkeys@pox@fams{#1}
+ \skvstripouterbraces{2}\dirkeys@pox@fams
+ ,
+ .ord/.copy class options/true/
+ \edef\dirkeys@pox@copyclass{\skvifstrcmp{#1}{true}{00}{01}}
+ ,
+ },
+ .styles={
+ .prefix/.options prefix=#1,
+ .options family/.options families=#1,
+ .family/.options families=#1,
+ .families/.options families=#1,
+ .include class options/.copy class options=#1,
+ },
+}
+%\skvshowcs{SKV/megapox/.options family.@cbk}
+%\skvshowcs{SKV/megapox/.pref.@cbk}
+
+\skvrobustdef*\dirkeys@megaprocessoptions#1{%
+ \skvpushfunctions\dirkeys@megaprocessoptions{%
+ \do\dirkeys@pox@pref\do\dirkeys@pox@fams
+ \do\dirkeys@pox@igkeys\do\dirkeys@pox@copyclass
+ }\skv@gendepth
+ \skv@inopttrue
+ \skvsetkeys[SKV]{megapox}{#1}%
+ \skvexpanded{%
+ \skvprocessoptions\if\dirkeys@pox@copyclass*\fi+%
+ [\dirkeys@pox@pref]<\dirkeys@pox@fams>[\dirkeys@pox@igkeys]%
+ }%
+ \skv@inoptfalse
+ \skvpopfunctions\dirkeys@megaprocessoptions\skv@gendepth
}
-\SKV@def*\SKV@InputFileOnce[#1]#2{%
- \SKV@appto!\input@path{{#1/}}%
- \ifSKV@st
- \SKV@afterelsefi
- \SKV@inputfile{#1}{#2}%
- \else
- \SKV@afterfi
- \SKV@ifcsdef{#2@read}{%
- \SKV@vbmsg{warn}{File '#2' already read:\SKV@MB
- File '#2' can't be read again}%
- }{%
- \SKV@inputfile{#1}{#2}%
+
+% +++++++++++++ Handlers for processing options ++++++++++++++ %
+
+\directkeys*{%
+ .new handlers={
+ .action for unknown options=\dirkeys@declareoptions@a{#1},
+ .declare options={
+ \skv@handlerswafalse\dirkeys@declareoptions@b{#1}
+ },
+ .new options={
+ \skv@handlerswatrue\dirkeys@declareoptions@b{#1}
+ },
+ % Handler <.execute options> has no star variant, since we don't
+ % want to ignore unknown options from within package or class.
+ .execute options={
+ \skv@handlerswafalse\dirkeys@executeoptions{#1}
+ },
+ .execute options+={
+ \skv@handlerswatrue\dirkeys@executeoptions@b{#1}
+ },
+ % 1. All <.process options> handlers will filter out ignored paths
+ % and keys.
+ % 2. <.process options*> will copy class options.
+ % 3. <.process options+> will set options in all the active families
+ % in which the options exist.
+ % 4. <.process options*+> will copy class options and set options in
+ % all the active families in which the options are found.
+ .process options={
+ \skv@handlerswafalse\skv@handlerswbfalse\dirkeys@processoptions
+ },
+ .process options*={
+ \skv@handlerswatrue\skv@handlerswbfalse\dirkeys@processoptions
+ },
+ .process options+={
+ \skv@handlerswafalse\skv@handlerswbtrue\dirkeys@processoptions@b
+ },
+ .process options*+={
+ \skv@handlerswatrue\skv@handlerswbtrue\dirkeys@processoptions@b
+ },
+ % The handler <.mega process options> will:
+ % 1. Search all families in its key <families>.
+ % 2. Not perform filtering of ignored paths and keys; in fact, will not
+ % use active paths and keys.
+ % 3. The handler '.mega process options' has the keys <ignore options>,
+ % <options prefix>, <options families>, and <copy class options>.
+ % These keys have aliases.
+ % See an example later in this file.
+ .mega process options={
+ \dirkeys@megaprocessoptions{#1}
+ },
+ .mega process options*={
+ \dirkeys@megaprocessoptions{#1,copy class options}
+ },
+ },
+ .handler let={
+ .action for unknown option=.action for unknown options,
+ .every unknown option=.action for unknown options,
+ .define options=.declare options,
+ .processoptions=.process options, .processoptions*=.process options*,
+ .copy class options and process options in all active families=
+ .process options*+,
+ .copy class options and process options in all families=
+ .process options*+,
+ .copy class options and process options=.process options*,
+ .executeoptions=.execute options,
+ },
+}
+%\skvshowcs{dirkeys@handler@.every unknown option}
+
+% Loading a package while in options section is illegal. The command
+% \skvafterprocessoptions can be used to defer the loading of packages
+% till after the options section:
+\skvrobustdef*\skvafterprocessoptions{%
+ \expandafter\skvgappendtomacro
+ \csname skv@\@currname @\@currext @afterprocess@hook\endcsname
+}
+\skvnewlet\skvAfterProcessOptions\skvafterprocessoptions
+\skvnewlet\skvifpackageloaded\@ifpackageloaded
+
+\def\skv@visiteduseoptions{01}
+
+\skvrobustdef*\skv@useoption#1{%
+ \if\skv@visiteduseoptions\else\skvafterfi
+ \skvcsvnormalize\@unusedoptionlist
+ \def\skv@visiteduseoptions{00}%
+ \fi
+ \begingroup
+ \def\do##1=##2=##3\useoption@nil{%
+ \edef\CurrentOption{\skvtrimspace{##1}}%
+ \def\skv@tempa{}%
+ \def\do####1=####2=####3\useoption@nil{%
+ \edef\reserved@a{\skvtrimspace{####1}}%
+ }%
+ \skvcommaloop*\@unusedoptionlist\skv@prova{%
+ \expandafter\do\skv@prova==\useoption@nil
+ \ifx\reserved@a\CurrentOption\else
+ \edef\skv@tempa{%
+ \skv@tempa\ifx\skv@tempa\@empty\else,\fi\skv@prova
+ }%
+ \fi
}%
- \fi
- \SKV@inp@tfile
- \ifnum\SKV@no=\z@\SKV@restore\input@path\fi
- \let\SKV@no\@ne
-}
-\SKV@pdef*\SKV@notloadederr#1{%
- \SKV@ifcsdef{ver@#1.\@pkgextension}{}{%
- \SKV@err{Package '#1' wasn't loaded}%
- {Document has begun and package '#1' wasn't loaded.\SKV@MB
- You wanted package '#1' loaded.}%
- }%
-}
-\SKV@def*\SKV@notloaded{}
-\SKV@pdef*\@ensurepackageloaded#1{%
- \SKV@for[,]{#1}\SKV@resvd{%
- \edef\SKV@resvd##1##2{\SKV@appto!##1{##2{\SKV@resvd}}}%
- \SKV@resvd\SKV@notloaded\SKV@doloaded
+ \let\@unusedoptionlist\skv@tempa
}%
+ \@onelevel@sanitize\@unusedoptionlist
+ \expandafter\do\detokenize{#1}==\useoption@nil
+ \skvaftergroupdef\@unusedoptionlist\endgroup
}
-\SKV@AtDocumentStart{%
- \let\SKV@doloaded\SKV@notloadederr
- \SKV@notloaded
- \global\let\SKV@doloaded\@gobble
-}
-\SKV@onlypreamble{%
- \SKV@preamblecmds,\SKV@onlypreamble,\@afterpackageloaded,
- \@ifpackagecurrent,\@ifpackagenotcurrent,\@ifloadedandcurrent,
- \@ensurepackageloaded,\SKV@AtPackageEnd,\SKV@AtClassEnd,
- \SKV@BeforePackageEnd,\SKV@BeforeClassEnd,\SKV@AfterPackageEnd,
- \SKV@AfterClassEnd,\SKV@BeforeLastPage,\SKV@AfterLastPage,
- \SKV@AfterDocumentEnd,\UseSkeyvalSetkeys
+
+\skvonlypreamble{%
+ \skvdeclareoption,\skvexecuteoptions,\skvprocessoptions,\skv@useoption
}
-\endinput
+%+++++++++++++++++ This package's options section ++++++++++++++++++%
+
+\skvrobustdef*\setupskeyval{\skvsetkeys[SKV]{skeyval}}
+\skv@inoptionsectrue
-%%% End of file skeyval.sty %%%
+%\skvshowcs{dirkeys@handler@.every unknown option}
+\directkeys*{%
+ .prefix=SKV,
+ .family=skeyval,
+ .holder prefix=skv@,
+ .every unknown option={
+ \@onelevel@sanitize\CurrentOption
+ \PackageWarning{skeyval}{Unknown option '\CurrentOption'}%
+ },
+ .new options={
+ .bool/tracingkeys/true,
+ .ords/{keyparser,key parser}/{,}/
+ \def\skv@keyparser{#1}%
+ \skvstripouterbraces{2}\skv@keyparser,
+ .bool/compatibility/true/
+ \ifskv@compatibility
+ \skvAfterProcessOptions{%
+ \skvifpackageloaded{skeyval-bc}{}{%
+ \RequirePackage{skeyval-bc}%
+ }
+ }%
+ \fi
+ ,
+ },
+ .execute options={
+ tracingkeys,keyparser
+ },
+ .mega process options={
+ .options prefix=SKV,
+ .options families={skeyval,definekeys},
+ .ignore options={},
+ .copy class options,
+ },
+}
+%\skvshowcs{SKV/skeyval/keyparser.@cbk}
+
+\skv@inoptionsecfalse
+
+\skv@restorecodes
+\endinput
diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds
index 909b5aff4c3..669384f7f60 100755
--- a/Master/tlpkg/libexec/ctan2tds
+++ b/Master/tlpkg/libexec/ctan2tds
@@ -874,6 +874,7 @@ chomp ($Build = `cd $Master/../Build/source && pwd`);
'sikumuna', "die 'skipping, lyx template'",
'simpsons', "die 'skipping, noinfo license'",
'skak', "&MAKEflatten",
+ 'skeyval', "&MAKEpkuthss",
'slashbox', "die 'skipping, noinfo license, c.1993'",
'slidenotes', "die 'skipping, nonfree'",
'smallcap', "die 'skipping, questionable license, 1996'",