% \iffalse meta-comment
%
% File: expkv-cs.dtx Copyright (C) 2020-2024 Jonathan P. Spratte
%
% This work  may be  distributed and/or  modified under  the conditions  of the
% LaTeX Project Public License (LPPL),  either version 1.3c  of this license or
% (at your option) any later version.  The latest version of this license is in
% the file:
%
%   http://www.latex-project.org/lppl.txt
%
% ------------------------------------------------------------------------------
%
%<*driver>^^A>>=
\def\expkvDocNoGenerate{}
\input expkv-bundle.ins
\generate{\file{expkv-cs.sty}{\from{expkv-cs.dtx}{pkg}}}
\generate{\file{expkv-cs.tex}{\from{expkv-cs.dtx}{tex}}}
\generate{\file{t-expkv-cs.tex}{\from{expkv-cs.dtx}{ctx}}}
\endbatchfile
%</driver>^^A=<<
% \fi
%
% \section{\expkvc}
%^^A the LaTeX package >>=
% \subsection{The \LaTeX\ Package}
% Just like for \expkv\ we provide a small \LaTeX\ package that sets up things
% such that we behave nicely on \LaTeX\ packages and files system. It'll
% |\input| the generic code which implements the functionality.
% \gobbledocstriptag
%<*pkg>
%    \begin{macrocode}
\RequirePackage{expkv-pop}
\def\ekvc@tmp
  {%
    \ProvidesFile{expkv-cs.tex}%
      [%
        \ekvcDate\space v\ekvcVersion\space
        define expandable key=val macros using expkv%
      ]%
  }
\input{expkv-cs.tex}
\ProvidesPackage{expkv-cs}%
  [%
    \ekvcDate\space v\ekvcVersion\space
    define expandable key=val macros using expkv%
  ]
%    \end{macrocode}
% \gobbledocstriptag
%</pkg>
%^^A=<<
%^^A the ConTeXt module >>=
% \subsection{The \ConTeXt\ module}
% \gobbledocstriptag
%<*ctx>
%    \begin{macrocode}
\writestatus{loading}{ConTeXt User Module / expkv-cs}
\usemodule[expkv-pop]
\unprotect
\input expkv-cs.tex
\writestatus{loading}
  {ConTeXt User Module / expkv-cs / Version \ekvcVersion\space loaded}
\protect\endinput
%    \end{macrocode}
% \gobbledocstriptag
%</ctx>
%^^A=<<
%^^A main file >>=
% \subsection{The Generic Code}
% The rest of this implementation will be the generic code.
% \gobbledocstriptag
%<*tex>
%
% Load \expkv\ if the package didn't already do so -- since \expkv\ has
% safeguards against being loaded twice this does no harm and the overhead
% isn't that big. Also we reuse some of the internals of \expkv\ to save us from
% retyping them.
%    \begin{macrocode}
\input expkv-pop
%    \end{macrocode}
%
% We make sure that \file{expkv-cs.tex} is only input once:
%    \begin{macrocode}
\expandafter\ifx\csname ekvcVersion\endcsname\relax
\else
  \expandafter\endinput
\fi
%    \end{macrocode}
%
% \begin{macro}{\ekvcVersion,\ekvcDate}
% We're on our first input, so lets store the version and date in a macro.
%    \begin{macrocode}
\def\ekvcVersion{1.4}
\def\ekvcDate{2024-12-16}
%    \end{macrocode}
% \end{macro}
%
% If the \LaTeX\ format is loaded we want to be a good file and report back who
% we are, for this the package will have defined |\ekvc@tmp| to use
% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
%    \begin{macrocode}
\csname ekvc@tmp\endcsname
%    \end{macrocode}
%
% Store the category code of |@| to later be able to reset it and change it to
% 11 for now.
%    \begin{macrocode}
\expandafter\chardef\csname ekvc@tmp\endcsname=\catcode`\@
\catcode`\@=11
%    \end{macrocode}
% |\ekvc@tmp| will be reused later, but we don't need it to ever store
% information long-term after \expkvc\ was initialized.
%
% \begin{macro}[internal]{\ekvc@tripledots}
%   This macro just serves as a marker for a comparison to allow the syntax
%   for the unknown key handlers.
%    \begin{macrocode}
\edef\ekvc@tripledots{\detokenize{...}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@keycount}
%   We'll need to keep count how many keys must be defined for each macro in the
%   |split| variants.
%    \begin{macrocode}
\newcount\ekvc@keycount
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@long,\ekvc@any@long}
%   Some macros will have to be defined long. These two will be let to |\long|
%   when this should be the case.
%    \begin{macrocode}
\let\ekvc@long\ekv@empty
\let\ekvc@any@long\ekv@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@ifdefined}
%   We want to test whether a macro is already defined. This test checks for a
%   defined macro that isn't |\relax|.
%    \begin{macrocode}
\long\def\ekvc@ifdefined#1%
  {%
    \ifdefined#1%
      \ifx\relax#1%
        \ekv@fi@gobble
      \fi
      \@firstofone
      \ekv@fi@firstoftwo
    \fi
    \@secondoftwo
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@ekvset@pre@expander,
%     \ekvc@ekvset@pre@expander@a,
%     \ekvc@ekvset@pre@expander@b
%   }
%   This macro expands |\ekvset| twice so that the first two steps of expansion
%   don't have to be made every time the \expkvc\ macros are used. We have to do
%   a little magic trick to get the macro parameter |#1| for the macro
%   definition this is used in, even though we're calling |\unexpanded|. We do
%   that by splitting the expanded |\ekvset| at some marks and place |##1| in
%   between. At this spot we also add |\ekv@alignsafe| and |\ekv@endalignsafe|
%   to ensure that macros created with \expkvc\ are alignment safe.
%    \begin{macrocode}
\def\ekvc@ekvset@pre@expander#1%
  {%
    \expandafter\ekvc@ekvset@pre@expander@a\ekvset{#1}\ekvc@stop\ekvc@stop
  }
\def\ekvc@ekvset@pre@expander@a
  {%
    \expandafter\ekvc@ekvset@pre@expander@b
  }
\def\ekvc@ekvset@pre@expander@b#1\ekvc@stop#2\ekvc@stop
  {%
    \ekv@unexpanded\expandafter{\ekv@alignsafe}%
    \ekv@unexpanded{#1}##1\ekv@unexpanded{#2}%
    \ekv@unexpanded\expandafter{\ekv@endalignsafe}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcSplitAndUse}
%   The first user macro we want to set up can be reused for
%   \cs[no-index]{ekvcSplitAndForward} and \cs[no-index]{ekvcSplit}. We'll split
%   this one up so that the test whether the macro is already defined doesn't
%   run twice.
%    \begin{macrocode}
\protected\long\def\ekvcSplitAndUse#1#2%
  {%
    \let\ekvc@helpers@needed\@firstoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {\ekvcSplitAndUse@#1{}{#2}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvcSplitAndUse@}
%   The actual macro setting up things. We need to set some variables, forward
%   the key list to |\ekvc@SetupSplitKeys|, and afterwards define the front
%   facing macro to call |\ekvset| and put the initials and the argument sorting
%   macro behind it. The internals |\ekvc@any@long|, |\ekvc@initials| and
%   |\ekvc@keycount| will be set correctly by |\ekvc@SetupSplitKeys|.
%    \begin{macrocode}
\protected\long\def\ekvcSplitAndUse@#1#2#3%
  {%
    \edef\ekvc@set{\string#1}%
    \ekvc@SetupSplitKeys{#3}%
    \ekvc@helpers@needed
      {%
        \ekvc@any@long\edef#1##1%
          {%
            \expandafter\ekvc@ekvset@pre@expander\expandafter{\ekvc@set}%
            \ekv@unexpanded\expandafter
              {\csname ekvc@split@\the\ekvc@keycount\endcsname}%
            \ekv@unexpanded\expandafter{\ekvc@initials{}#2}%
          }%
      }%
      {%
        \ekvc@any@long\edef#1##1%
          {%
            \expandafter\ekvc@ekvset@pre@expander\expandafter{\ekvc@set}%
            \ekv@unexpanded{#2}%
            \ekv@unexpanded\expandafter{\ekvc@initials}%
          }%
      }%
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\ekvcSplitAndForward}
%   This just reuses |\ekvcSplitAndUse@| with a non-empty second argument,
%   resulting in that argument to be called after the splitting.
%    \begin{macrocode}
\protected\long\def\ekvcSplitAndForward#1#2#3%
  {%
    \let\ekvc@helpers@needed\@firstoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {\ekvcSplitAndUse@#1{{#2}}{#3}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcSplit}
%   The first half is just |\ekvcSplitAndForward| then we define the macro to
%   which the parsed key list is forwarded. There we need to allow for up to
%   nine arguments.
%    \begin{macrocode}
\protected\long\def\ekvcSplit#1#2#3%
  {%
    \let\ekvc@helpers@needed\@secondoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {%
        \expandafter
        \ekvcSplitAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
        \ifnum\ekvc@keycount<1
          \ekvc@any@long\expandafter\def\csname ekvc@\string#1\endcsname{#3}%
        \else
          \ifnum\ekvc@keycount>9
            \ekvc@err@toomany{#1}%
            \let#1\ekvc@undefined
          \else
            \ekvcSplit@build@argspec
            \ekvc@any@long\expandafter
            \def\csname ekvc@\string#1\expandafter\endcsname\ekvc@tmp{#3}%
          \fi
        \fi
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvcSplit@build@argspec,\ekvcSplit@build@argspec@}
%    \begin{macrocode}
\protected\def\ekvcSplit@build@argspec
  {%
    \begingroup
      \edef\ekvc@tmp
        {\endgroup\def\ekv@unexpanded{\ekvc@tmp}{\ekvcSplit@build@argspec@{1}}}%
    \ekvc@tmp
  }
\def\ekvcSplit@build@argspec@#1%
  {%
    \ifnum#1>\ekvc@keycount
      \ekv@fi@gobble
    \fi
    \@firstofone
      {%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@#1\endcsname####}#1%
        \expandafter\ekvcSplit@build@argspec@\expandafter{\the\numexpr#1+1}%
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@SetupSplitKeys, \ekvc@SetupSplitKeys@a, \ekvc@SetupSplitKeys@b,
%     \ekvc@SetupSplitKeys@unknown
%   }
%   These macros parse the list of keys and set up the key macros. First we need
%   to initialise some macros and start an \expkvp\ parser.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupSplitKeys
  {%
    \ekvc@keycount=\ekv@zero
    \let\ekvc@any@long\ekv@empty
    \let\ekvc@initials\ekv@empty
    \ekvpParse@unsafe\ekvp@@p@ekvc@setup@splitkeys
  }
%    \end{macrocode}
%   We're calling a parser here without the safety nets testing for parser
%   existence, so better define it now.
%    \begin{macrocode}
\ekvpNewParser{ekvc@setup@splitkeys}
\ekvpDefType{ekvc@setup@splitkeys}{short}
  {%
    \let\ekvc@long\ekv@empty
    \expandafter\ekvc@SetupSplitKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
\ekvpDefType{ekvc@setup@splitkeys}{long}
  {%
    \let\ekvc@long\long
    \let\ekvc@any@long\long
    \expandafter\ekvc@SetupSplitKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
\ekvpDefNoType{ekvc@setup@splitkeys}
  {%
    \let\ekvc@long\ekv@empty
    \expandafter\ekvc@SetupSplitKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
%    \end{macrocode}
%   If no value was provided this could either be an error, or the unknown key
%   forwarding. We have to check this (comparing against |...| inside
%   |\ekvc@tripledots|) and if this is the unknown key list type, set it up
%   accordingly (advancing the key count and setting up the unknown handlers of
%   \expkv). Else we simply throw an error and ignore the incident.
%    \begin{macrocode}
\ekvpDefNoValue{ekvc@setup@splitkeys}
  {%
    \begingroup
      \edef\ekvc@tmp{\detokenize{#1}}%
      \expandafter
    \endgroup
    \ifx\ekvc@tripledots\ekvc@tmp
      \advance\ekvc@keycount1
%    \end{macrocode}
%   The |\begingroup\expandafter\endgroup| ensures that the split mark isn't
%   actually defined (even if it just were with meaning |\relax|).
%    \begin{macrocode}
      \begingroup\expandafter\endgroup
      \expandafter\ekvc@SetupSplitKeys@unknown
        \csname ekvc@splitmark@\the\ekvc@keycount\endcsname
      \let\ekvc@any@long\long
    \else
      \ekvc@err@value@required{#1}%
    \fi
  }
%    \end{macrocode}
%
%   Now everything is parsed down to the point that we got the key name and its
%   value. We step the key counter and build the mark within a group to not
%   accidentally define the |\csname|.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupSplitKeys@a
  {%
    \advance\ekvc@keycount1
    \begingroup\expandafter\endgroup
    \expandafter\ekvc@SetupSplitKeys@b
      \csname ekvc@splitmark@\the\ekvc@keycount\endcsname
  }
\protected\long\def\ekvc@SetupSplitKeys@b#1#2\ekv@stop#3%
  {%
    \long\def\ekvc@tmp##1##2#1##3{##2#1{##1}}%
%    \end{macrocode}
%   The short variant needs a bit of special treatment. The key macro will be
%   short to throw the correct error, but since there might be long macros
%   somewhere the reordering of arguments needs to be long, so for short keys we
%   use a two step approach, first grabbing only the short argument, then
%   reordering.
%    \begin{macrocode}
    \ifx\ekvc@long\long
    \else
      \expandafter\let\csname ekvc@\ekvc@set(#2)\endcsname\ekvc@tmp
      \edef\ekvc@tmp##1%
        {%
          \ekv@unexpanded\expandafter{\csname ekvc@\ekvc@set(#2)\endcsname}%
          {##1}%
        }%
    \fi
    \ekvlet\ekvc@set{#2}\ekvc@tmp
    \edef\ekvc@initials{\ekv@unexpanded\expandafter{\ekvc@initials#1{#3}}}%
    \ekvc@helpers@needed
      {\expandafter\ekvc@setup@splitmacro\expandafter{\the\ekvc@keycount}}%
      {}%
  }
%    \end{macrocode}
%
%   Here we get everything readily set up, |#1| contains the mark for unknown
%   keys and they only have to do some reordering.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupSplitKeys@unknown#1%
  {%
    \long\def\ekvc@tmp##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
    \ekvletunknown\ekvc@set\ekvc@tmp
    \long\def\ekvc@tmp##1##2##3#1##4{##3#1{##4, {##2} }}%
    \ekvletunknownNoVal\ekvc@set\ekvc@tmp
    \edef\ekvc@initials{\ekv@unexpanded\expandafter{\ekvc@initials#1{}}}%
    \ekvc@helpers@needed
      {\expandafter\ekvc@setup@splitmacro\expandafter{\the\ekvc@keycount}}%
      {}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@defarggobbler}
%   This is needed to define a macro with 1-9 parameters programmatically.
%   \LaTeX's \cs[no-index]{newcommand} does something similar for example.
%    \begin{macrocode}
\protected\def\ekvc@defarggobbler#1{\def\ekvc@tmp##1#1##2##{##1#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@setup@splitmacro,
%     \ekvc@split@1, \ekvc@split@2, \ekvc@split@3,
%     \ekvc@split@4, \ekvc@split@5, \ekvc@split@6,
%     \ekvc@split@7
%   }
%   Since the first few split macros are different from the others we manually
%   set those up now. All the others will be defined as needed (always
%   globally).  The split macros just read up until the correct split mark, move
%   that argument into a list and reinsert the rest, calling the next split
%   macro afterwards.
%    \begin{macrocode}
\begingroup
\edef\ekvc@tmp
  {%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@1\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        ##2##3%
      {##3{##1}##2}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@2\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        ##3##4%
      {##4{##1}{##2}##3}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@3\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@3\endcsname}##3%
        ##4##5%
      {##5{##1}{##2}{##3}##4}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@4\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@3\endcsname}##3%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@4\endcsname}##4%
        ##5##6%
      {##6{##1}{##2}{##3}{##4}##5}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@5\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@3\endcsname}##3%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@4\endcsname}##4%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@5\endcsname}##5%
        ##6##7%
      {##7{##1}{##2}{##3}{##4}{##5}##6}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@6\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@3\endcsname}##3%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@4\endcsname}##4%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@5\endcsname}##5%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@6\endcsname}##6%
        ##7##8%
      {##8{##1}{##2}{##3}{##4}{##5}{##6}##7}%
    \long\gdef\ekv@unexpanded\expandafter{\csname ekvc@split@7\endcsname}%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@1\endcsname}##1%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@2\endcsname}##2%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@3\endcsname}##3%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@4\endcsname}##4%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@5\endcsname}##5%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@6\endcsname}##6%
        \ekv@unexpanded\expandafter{\csname ekvc@splitmark@7\endcsname}##7%
        ##8##9%
      {##9{##1}{##2}{##3}{##4}{##5}{##6}{##7}##8}%
  }
\ekvc@tmp
\endgroup
\protected\def\ekvc@setup@splitmacro#1%
  {%
    \ekv@ifdefined{ekvc@split@#1}{}%
      {%
        \begingroup
          \def\ekvc@tmp##1%
            {%
              \ekv@unexpanded\expandafter
                {\csname ekvc@splitmark@\the\numexpr#1-##1\relax\endcsname}%
            }%
          \edef\ekvc@tmp
            {%
              \long\gdef
                \ekv@unexpanded\expandafter{\csname ekvc@split@#1\endcsname}%
                  ####1%
                  \ekvc@tmp{6}####2%
                  \ekvc@tmp{5}####3%
                  \ekvc@tmp{4}####4%
                  \ekvc@tmp{3}####5%
                  \ekvc@tmp{2}####6%
                  \ekvc@tmp{1}####7%
                  \ekvc@tmp{0}####8%
                  ####9%
                {%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@split@\the\numexpr#1-7\relax\endcsname}%
                  ####1{{####2}{####3}{####4}{####5}{####6}{####7}{####8}####9}%
                }%
            }%
          \ekvc@tmp
        \endgroup
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcHashAndUse}
%   |\ekvcHashAndUse| works just like |\ekvcSplitAndUse|.
%    \begin{macrocode}
\protected\long\def\ekvcHashAndUse#1#2%
  {%
    \let\ekvc@helpers@needed\@firstoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {\ekvcHashAndUse@#1{}{#2}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvcHashAndUse@}
%   This is more or less the same as |\ekvcSplitAndUse@|. Instead of an empty
%   group we place a marker after the initials, we don't use the sorting macros
%   of |split|, but instead pack all the values in one argument.
%    \begin{macrocode}
\protected\long\def\ekvcHashAndUse@#1#2#3%
  {%
    \edef\ekvc@set{\string#1}%
    \ekvc@SetupHashKeys{#3}%
    \ekvc@helpers@needed
      {%
        \ekvc@any@long\edef#1##1%
          {%
            \expandafter\ekvc@ekvset@pre@expander\expandafter{\ekvc@set}%
            \ekv@unexpanded{\ekvc@hash@pack@argument}%
            \ekv@unexpanded\expandafter{\ekvc@initials\ekvc@stop#2}%
          }%
      }%
      {%
        \ekvc@any@long\edef#1##1%
          {%
            \expandafter\ekvc@ekvset@pre@expander\expandafter{\ekvc@set}%
            \ekv@unexpanded{#2}%
            \ekv@unexpanded\expandafter{\ekvc@initials\ekvc@stop}%
          }%
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcHashAndForward}
%   |\ekvcHashAndForward| works just like |\ekvcSplitAndForward|.
%    \begin{macrocode}
\protected\long\def\ekvcHashAndForward#1#2#3%
  {%
    \let\ekvc@helpers@needed\@firstoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {\ekvcHashAndUse@#1{{#2}}{#3}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcHash}
%   |\ekvcHash| does the same as |\ekvcSplit|, but has the advantage of not
%   needing to count arguments, so the definition of the internal macro is a bit
%   more straight forward.
%    \begin{macrocode}
\protected\long\def\ekvcHash#1#2#3%
  {%
    \let\ekvc@helpers@needed\@secondoftwo
    \ekvc@ifdefined#1%
      {\ekvc@err@already@defined#1}%
      {%
        \expandafter
        \ekvcHashAndUse@\expandafter#1\csname ekvc@\string#1\endcsname{#2}%
        \ekvc@any@long\expandafter\def\csname ekvc@\string#1\endcsname
            ##1\ekvc@stop
          {#3}%
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@hash@pack@argument}
%   All this macro does is pack the values into one argument and forward that to
%   the next macro.
%    \begin{macrocode}
\long\def\ekvc@hash@pack@argument#1\ekvc@stop#2{#2{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@SetupHashKeys,\ekvc@SetupHashKeys@a,\ekvc@SetupHashKeys@b,
%     \ekvc@SetupHashKeys@unknown
%   }
%   This should look awfully familiar as well, since it's just the same as for
%   the split keys with a few other names here and there.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupHashKeys
  {%
    \let\ekvc@any@long\ekv@empty
    \let\ekvc@initials\ekv@empty
    \ekvpParse@unsafe\ekvp@@p@ekvc@setup@hashkeys
  }
\ekvpNewParser{ekvc@setup@hashkeys}
\ekvpDefType{ekvc@setup@hashkeys}{short}
  {%
    \let\ekvc@long\ekv@empty
    \expandafter\ekvc@SetupHashKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
\ekvpDefType{ekvc@setup@hashkeys}{long}
  {%
    \let\ekvc@long\long
    \let\ekvc@any@long\long
    \expandafter\ekvc@SetupHashKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
\ekvpDefNoType{ekvc@setup@hashkeys}
  {%
    \let\ekvc@long\ekv@empty
    \expandafter\ekvc@SetupHashKeys@a\detokenize{#1}\ekv@stop{#3}%
  }
\ekvpDefNoValue{ekvc@setup@hashkeys}
  {%
    \begingroup
      \edef\ekvc@tmp{\detokenize{#1}}%
      \expandafter
    \endgroup
    \ifx\ekvc@tripledots\ekvc@tmp
      \ekvc@SetupHashKeys@unknown
      \let\ekvc@any@long\long
    \else
      \ekvc@err@value@required{#1}%
    \fi
  }
%    \end{macrocode}
%   Again we build the marker, this time instead of a numbered one a named
%   hashmark, inside a group to not actually define the macro used as a marker.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupHashKeys@a#1\ekv@stop
  {%
    \begingroup\expandafter\endgroup
    \expandafter\ekvc@SetupHashKeys@b\csname ekvc@hashmark@#1\endcsname{#1}%
  }
%    \end{macrocode}
%   Yes, even the defining macro looks awfully familiar. Instead of numbered we
%   have named marks. Still the key macros grab everything up to their
%   respective mark and reorder the arguments. The same quirk is applied for
%   short keys. And instead of the |\ekvc@setup@splitmacro| we use
%   |\ekvc@setup@hashmacro|.
%    \begin{macrocode}
\protected\long\def\ekvc@SetupHashKeys@b#1#2#3%
  {%
    \long\def\ekvc@tmp##1##2#1##3{##2#1{##1}}%
    \ifx\ekvc@long\long
    \else
      \expandafter\let\csname ekvc@\ekvc@set(#2)\endcsname\ekvc@tmp
      \edef\ekvc@tmp##1%
        {%
          \ekv@unexpanded\expandafter{\csname ekvc@\ekvc@set(#2)\endcsname}%
          {##1}%
        }%
    \fi
    \ekvlet\ekvc@set{#2}\ekvc@tmp
    \edef\ekvc@initials{\ekv@unexpanded\expandafter{\ekvc@initials#1{#3}}}%
    \ekvc@setup@hashmacro{#2}%
  }
%    \end{macrocode}
%   Another temporary definition, this time to get the hashmarks for the unknown
%   handler without defining them.
%    \begin{macrocode}
\def\ekvc@SetupHashKeys@unknown#1%
  {%
    \protected\def\ekvc@SetupHashKeys@unknown
      {%
        \ekvletunknown\ekvc@set\ekvc@hash@unknown@kv
        \ekvletunknownNoVal\ekvc@set\ekvc@hash@unknown@k
        \edef\ekvc@initials{\ekv@unexpanded\expandafter{\ekvc@initials#1{}}}%
        \ekvc@setup@hashmacro{...}%
      }%
    \long\def\ekvc@hash@unknown@kv##1##2##3##4#1##5{##4#1{##5, {##3} = {##1} }}%
    \long\def\ekvc@hash@unknown@k##1##2##3#1##4{##3#1{##4, {##2} }}%
  }
\begingroup\expandafter\endgroup
\expandafter\ekvc@SetupHashKeys@unknown
  \csname ekvc@hashmark@\ekvc@tripledots\endcsname
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@setup@hashmacro}
%   The safe hash macros will be executed inside of an |\unexpanded| expansion
%   context, so they have to insert braces for that once they are done.
%   Most of the tests which have to be executed will already be done, but we
%   have to play safe if the hash doesn't show up in the hash list. Therefore we
%   use some |\ekvc@mark|s and |\ekvc@stop| to throw errors if the hash isn't
%   found in the right place. The fast variants have an easier life and just
%   return the correct value.
%    \begin{macrocode}
\protected\def\ekvc@setup@hashmacro#1%
  {%
    \ekv@ifdefined{ekvc@fasthash@#1}{}%
      {%
        \begingroup
          \edef\ekvc@tmp
            {%
              \long\gdef
                \ekv@unexpanded\expandafter{\csname ekvc@fasthash@#1\endcsname}%
                  ####1%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@hashmark@#1\endcsname}%
                  ####2####3\ekv@unexpanded{\ekvc@stop}%
                {####2}%
              \long\gdef
                \ekv@unexpanded\expandafter{\csname ekvc@safehash@#1\endcsname}%
                  ####1%
                {%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@@safehash@#1\endcsname}%
                  ####1\ekv@unexpanded{\ekvc@mark}{}%
                  \ekv@unexpanded\expandafter
                    {%
                      \csname ekvc@hashmark@#1\endcsname{}%
                      \ekvc@mark{\ekvc@err@missing@hash{#1}}\ekvc@stop
                    }%
                }%
              \long\gdef
                \ekv@unexpanded\expandafter
                  {\csname ekvc@@safehash@#1\endcsname}%
                  ####1%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@hashmark@#1\endcsname}%
                  ####2####3\ekv@unexpanded{\ekvc@mark}####4####5%
                  \ekv@unexpanded{\ekvc@stop}%
                {%
                  ####4{####2}%
                }%
              \long\gdef\ekv@unexpanded\expandafter
                {\csname ekvc@fastsplithash@#1\endcsname}%
                  ####1%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@hashmark@#1\endcsname}%
                  ####2####3\ekv@unexpanded{\ekvc@stop}####4%
                {%
                  ####4{####2}%
                }%
              \long\gdef\ekv@unexpanded\expandafter
                {\csname ekvc@safesplithash@#1\endcsname}####1%
                {%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@@safesplithash@#1\endcsname}%
                  ####1\ekv@unexpanded{\ekvc@mark\ekvc@safe@after@hash}%
                  \ekv@unexpanded\expandafter
                    {%
                      \csname ekvc@hashmark@#1\endcsname{}%
                      \ekvc@mark
                      {\ekvc@err@missing@hash{#1}\ekvc@safe@after@hash}%
                      \ekvc@stop
                    }%
                }%
              \long\gdef\ekv@unexpanded\expandafter
                {\csname ekvc@@safesplithash@#1\endcsname}%
                  ####1%
                  \ekv@unexpanded\expandafter
                    {\csname ekvc@hashmark@#1\endcsname}%
                  ####2####3\ekv@unexpanded{\ekvc@mark}####4####5%
                  \ekv@unexpanded{\ekvc@stop}%
                {%
                  ####4{####2}%
                }%
            }%
          \ekvc@tmp
        \endgroup
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcValue}
% \begin{macro}[internal]{\ekvcValue@}
%   All this does is a few consistency checks on the first argument (not empty,
%   hash macro exists) and then call that hash-grabbing macro that will also
%   test whether the hash is inside of |#2| or not.
%    \begin{macrocode}
\long\def\ekvcValue#1%
  {%
    \ekv@unexpanded
    \expandafter\ekvcValue@\detokenize{#1}\ekvc@stop
  }
\def\ekvcValue@#1\ekvc@stop
  {%
    \ekv@ifdefined{ekvc@safehash@#1}%
      {\csname ekvc@safehash@#1\endcsname}%
      {\ekvc@err@unknown@hash{#1}\@firstoftwo{{}}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ekvcValueFast}
%   To be as fast as possible, this doesn't test for anything, assuming the user
%   knows best.
%    \begin{macrocode}
\long\def\ekvcValueFast#1#2%
  {\csname ekvc@fasthash@\detokenize{#1}\endcsname#2\ekvc@stop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcValueSplit}
% \begin{macro}[internal]{\ekvcValueSplit@,\ekvcValueSplit@recover}
%   This splits off a single value.
%    \begin{macrocode}
\long\def\ekvcValueSplit#1%
  {\expandafter\ekvcValueSplit@\detokenize{#1}\ekvc@stop}
\def\ekvcValueSplit@#1\ekvc@stop
  {%
    \ekv@ifdefined{ekvc@safesplithash@#1}%
      {\csname ekvc@safesplithash@#1\endcsname}%
      {\ekvc@err@unknown@hash{#1}\ekvcValueSplit@recover}%
  }
\long\def\ekvcValueSplit@recover#1#2{#2{}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@safe@after@hash}
%    \begin{macrocode}
\long\def\ekvc@safe@after@hash#1#2%
  {%
    #2{#1}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcValueSplitFast}
%   Again a fast approach which doesn't provide too many safety measurements.
%   This needs to build the hash function and expand it before passing the
%   results to the next control sequence. The first step only builds the control
%   sequence.
%    \begin{macrocode}
\long\def\ekvcValueSplitFast#1#2%
  {\csname ekvc@fastsplithash@\detokenize{#1}\endcsname#2\ekvc@stop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@safehash@,\ekvc@fasthash@,
%     \ekvc@safesplithash@,\ekvc@fastsplithash@
%   }
%   At least in the empty hash case we can provide a meaningful error message
%   without affecting performance by just defining the macro that would be build
%   in that case. There is of course a downside to this, the error will not be
%   thrown by |\ekvcValueFast| in three expansion steps. The safe hash variant
%   has to also stop the |\unexpanded| expansion.
%    \begin{macrocode}
\long\def\ekvc@safehash@#1{\ekvc@err@empty@hash{}}
\long\def\ekvc@fasthash@#1\ekvc@stop{\ekvc@err@empty@hash}
\long\def\ekvc@safesplithash@#1#2{\ekvc@err@empty@hash#2{}}
\long\def\ekvc@fastsplithash@#1\ekvc@stop#2{\ekvc@err@empty@hash#2{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcSecondaryKeys}
% \begin{macro}[internal]
%   {\ekvcSecondaryKeys@a,\ekvcSecondaryKeys@b,\ekvcSecondaryKeys@c}
%   Secondary keys use yet another \expkvp\ parser, keys will be set up further
%   down in their own subsection.
%    \begin{macrocode}
\ekvpNewParser{ekvc@setup@secondary}
\ekvpValueAlwaysRequired{ekvc@setup@secondary}
\protected\long\def\ekvcSecondaryKeys#1%
  {%
    \edef\ekvc@set{\string#1}%
    \let\ekvc@long\ekv@empty
    \ekvpParse@unsafe\ekvp@@p@ekvc@setup@secondary
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ekvcChange}
%   This can be used to change the defaults of an \expkvc\ defined macro. It
%   checks whether there is a set with the correct name and that the macro is
%   defined. If both is true the real work is done by |\ekvc@change|.
%    \begin{macrocode}
\protected\long\def\ekvcChange#1%
  {%
    \ekvifdefinedset{\string#1}%
      {%
        \ekvc@ifdefined#1%
          {\ekvc@change#1}%
          {\ekvc@err@no@key@macro#1\@gobble}%
      }%
      {\ekvc@err@no@key@macro#1\@gobble}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@change  ,\ekvc@change@a,\ekvc@change@b,
%     \ekvc@change@c,\ekvc@change@d,\ekvc@change@e
%   }
%   First we need to see whether the macro is currently |\long|. For this we get
%   the meaning and will parse it. |#1| is the macro name in which we want to
%   change the defaults.
%    \begin{macrocode}
\protected\def\ekvc@change#1%
  {\expandafter\ekvc@change@a\meaning#1\ekv@stop#1}
%    \end{macrocode}
%   A temporary definition to get the stringified |macro:|. |##1| will be the
%   list of prefixes, we don't care for the exact contents of |##2| and |##3|.
%    \begin{macrocode}
\def\ekvc@change@a#1%
  {%
    \protected\def\ekvc@change@a##1#1##2->##3\ekv@stop
      {%
        \ekvc@change@iflong{##1}%
          {\ekvc@change@b{}}%
          {\ekvc@change@b{\long}}%
      }%
  }
\expandafter\ekvc@change@a\expandafter{\detokenize{macro:}}
%    \end{macrocode}
%   Next we expand the macro once to get its contents (including the current
%   default values with their markers) and place |\ekvc@stop| instead of an
%   argument as a marker for the last step. |#1| is either |\long| or empty,
%   |#2| is the macro.
%    \begin{macrocode}
\protected\def\ekvc@change@b#1#2%
  {\expandafter\ekvc@change@c\expandafter{#2\ekvc@stop}{#1}#2}
%    \end{macrocode}
%   Here we place an unbalanced closing brace after the expansion of the macro.
%   Then we just parse the \kv-list with |\ekvset|, that will exchange the
%   values behind the markers. Once those are changed we give control to
%   |\ekvc@change@d|. The |\ekvset| step might horribly fail if the user defined
%   some keys that don't behave nice. |#1| is the expansion of the macro, |#2|
%   is either |\long| or empty, |#3| is the macro, and |#4| is the \kv-list
%   containing the new defaults.
%    \begin{macrocode}
\ekv@exparg{\protected\long\def\ekvc@change@c#1#2#3#4}%
  {%
    \expandafter\iffalse\expandafter{\expandafter{\expandafter\fi
      \ekvset{\string#3}{#4}%
      \ekvc@change@d{#2}{#3}%
      #1%
    }}%
  }
%    \end{macrocode}
%   The final step needs to put an unbalanced opening brace after |\edef|. Also
%   we have to protect everything from further expanding with the exception of
%   the redefined macro's argument, which is why we placed the |\ekvc@stop|
%   earlier. Then we need to also protect the rest of the contents from further
%   expanding using |\unexpanded| with another unbalanced opening brace.
%   |#1| will be either empty or |\long| and |#2| is the macro.
%    \begin{macrocode}
\protected\def\ekvc@change@d#1#2%
  {#1\edef#2##1{\expandafter\ekvc@change@e\iffalse}\fi}
\long\def\ekvc@change@e#1\ekvc@stop
  {\ekv@unexpanded{#1}##1\ekv@unexpanded\expandafter{\iffalse}\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@change@iflong,\ekvc@change@iflong@}
%   Checking whether a string contains the string representation of |\long| can
%   be done by gobbling everything up to the first |\long| and checking whether
%   the result is completely empty. We need a temporary macro to get the result
%   of |\string\long| inside the definitions.
%    \begin{macrocode}
\def\ekvc@change@iflong#1%
  {%
    \protected\def\ekvc@change@iflong##1%
      {\expandafter\ekv@ifempty\expandafter{\ekvc@change@iflong@##1#1}}%
    \def\ekvc@change@iflong@##1#1{}
  }
\expandafter\ekvc@change@iflong\expandafter{\string\long}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcPass}
%   This macro can be used to pass a value to a key of some macro (this way
%   more complicated key codes are possible that in the end pass processed
%   values on to some macro). The implemantation is pretty straight forward.
%    \begin{macrocode}
\long\def\ekvcPass#1#2%
  {%
    \ekvifdefined{\string#1}{#2}%
      {\csname\ekv@name{\string#1}{#2}\endcsname}%
      {\ekvc@err@unknown@key@or@macro{#1}{#2}\@gobble}%
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Secondary Key Types}
%
% There is a single prefix named |long| and set up pretty simple.
%    \begin{macrocode}
\ekvpDefPrefixLet{ekvc@setup@secondary}{long}\ekvc@long\long\ekv@empty
%    \end{macrocode}
%
% \begin{macro}[internal]
%   {
%     meta, nmeta,
%     \ekvc@type@meta, \ekvc@type@meta@
%   }
%   The |meta| and |nmeta| key types use |\ekvmorekv| to set other keys in
%   the same macro's \set. If the \kv\ list ist fixed (|nmeta|) we can expand
%   |\ekvmorekv| as far as possible (twice), else we expand it only once. This
%   makes a difference only if the \val\ of the |meta| key isn't forwarded in
%   braces and commas are active at the time of usage, in which case expanding
%   |\ekvmorekv| twice would result in wrong behaviour.
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{meta}
  {\ekvc@type@meta\ekv@exparg\ekvc@long{##1}\ekvlet{#1}{#3}}
\ekvpDefType{ekvc@setup@secondary}{nmeta}
  {\ekvc@assert@not@long\ekvc@type@meta\ekv@expargtwice{}{}\ekvletNoVal{#1}{#3}}
\protected\long\def\ekvc@type@meta#1#2#3#4#5#6%
  {%
    #1\ekvc@type@meta@{\ekvmorekv{#6}}{#2}{#3}%
    #4\ekvc@set{#5}\ekvc@tmp
  }
\protected\long\def\ekvc@type@meta@#1#2#3{#2\def\ekvc@tmp#3{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{alias}
%   |alias| just checks whether there is a key and/or |NoVal| key defined with
%   the target name and |\let| the key to those.
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{alias}
  {%
    \ekvc@assert@not@long
    \ekvc@assert@k@or@p@defined{#3}%
    \ekvifdefined\ekvc@set{#3}{\ekvletkv\ekvc@set{#1}\ekvc@set{#3}}{}%
    \ekvifdefinedNoVal\ekvc@set{#3}{\ekvletkvNoVal\ekvc@set{#1}\ekvc@set{#3}}{}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{default}
%   The |default| key can be used to set a \Nkey\ for an existing \Vkey. It
%   will just pass the \val\ to the key macro of that other key.
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{default}
  {%
    \ekvc@assert@defined{#1}%
    \ekvc@assert@not@long
    \edef\ekvc@tmp
      {%
        \ekv@unexpanded\expandafter
          {\csname\ekv@name\ekvc@set{#1}\endcsname{#3}}%
      }%
    \ekvletNoVal\ekvc@set{#1}\ekvc@tmp
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{enum,choice}
% \begin{macro}[internal]
%   {
%     \ekvc@type@enum,\ekvc@h@enum,\ekvc@h@enum@,\ekvc@enum@name,
%     \ekvc@type@choice,\ekvc@type@choice@k,\ekvc@type@choice@p
%   }
%   Enums don't need to apply special trickery to make the parts of the names
%   retrievable, so unlike in \expkvd\ we don't need catcode juggling.
%   The setup of an |enum| requires unpacking the value in two different
%   arguments so we need an auxiliary here. A |choice| is basically the same,
%   but a bit more flexible (it allows to specify a value to be forwarded
%   instead of just a positional number), hence we need a slightly different
%   second step.
%    \begin{macrocode}
\def\ekvc@enum@name#1#2#3{ekvc#1(#2)#3}
\ekvpDefType{ekvc@setup@secondary}{enum}
  {\ekvpAssertTwoValues{#3}\ekvc@type@enum{#1}#3}
\ekvpDefType{ekvc@setup@secondary}{choice}
  {\ekvpAssertTwoValues{#3}\ekvc@type@choice{#1}#3}
\protected\long\def\ekvc@type@enum@or@choice#1#2%
  {%
    \ekvc@assert@defined{#2}%
%    \end{macrocode}
%   At run time we need another helper and we need to expand the current
%   |\ekvc@set| now. The helper will check whether the given value is defined
%   and call the underlying macro (defined below).
%    \begin{macrocode}
    \ekvc@long\edef\ekvc@tmp##1%
      {%
        \ekv@unexpanded{\expandafter\ekvc@h@enum\detokenize}{##1}%
        \ekv@unexpanded{\ekvc@stop}%
        {\ekvc@set}{#1}%
      }%
    \ekvlet\ekvc@set{#1}\ekvc@tmp
  }
\protected\long\def\ekvc@type@enum#1#2%
  {%
    \ekvc@type@enum@or@choice{#1}{#2}%
%    \end{macrocode}
%   |\ekvc@type@enum@| will build a control sequence from each given value,
%   those will be set up in the |\ekvcsvloop|.
%    \begin{macrocode}
    \def\ekvc@tmp{0}%
    \expandafter\ekvcsvloop\expandafter
      {\expandafter\ekvc@type@enum@\csname\ekv@name\ekvc@set{#2}\endcsname{#1}}%
  }
%    \end{macrocode}
%   Here |#1| will be the key-macro of the underlying primary or secondary key,
%   |#2| is the |enum| key's name, and |#3| will be the choice. The rest is
%   pretty obvious.
%    \begin{macrocode}
\ekv@exparg{\protected\long\def\ekvc@type@enum@#1#2#3}%
  {%
    \expandafter\expandafter\expandafter\edef\expandafter
        \csname\ekvc@enum@name\ekvc@set{#2}{\detokenize{#3}}\endcsname
      {\ekv@unexpanded{#1}{\ekvc@tmp}}%
    \edef\ekvc@tmp{\the\numexpr\ekvc@tmp+1\relax}%
  }
%    \end{macrocode}
%   Similar code for the |choice| type.
%    \begin{macrocode}
\protected\long\def\ekvc@type@choice#1#2%
  {%
    \ekvc@type@enum@or@choice{#1}{#2}%
    \ekv@exparg
      {%
        \expandafter\ekvparse\expandafter
          {%
            \expandafter\ekvc@type@choice@k
              \csname\ekv@name\ekvc@set{#2}\endcsname{#1}%
          }%
      }%
      {%
        \expandafter\ekvc@type@choice@p
          \csname\ekv@name\ekvc@set{#2}\endcsname{#1}%
      }%
  }
\ekv@exparg{\protected\long\def\ekvc@type@choice@p#1#2#3#4}%
  {%
    \expandafter\expandafter\expandafter\edef\expandafter
        \csname\ekvc@enum@name\ekvc@set{#2}{\detokenize{#3}}\endcsname
      {\ekv@unexpanded{#1{#4}}}%
  }
\protected\long\def\ekvc@type@choice@k#1#2#3{\ekvc@type@choice@p#1{#2}{#3}{#3}}
%    \end{macrocode}
%   The use-time helper will check if the macro for the passed in choice exists,
%   if it doesn't throws an error, else calls that macro which will set the
%   correct value.
%    \begin{macrocode}
\ekv@if@lastnamedcs
  {%
    \ekv@exparg{\def\ekvc@h@enum#1\ekvc@stop#2#3}%
      {%
        \expandafter\ifcsname\ekvc@enum@name{#2}{#3}{#1}\endcsname
          \expandafter\ekvc@h@enum@\lastnamedcs
        \fi
        \ekvc@err@unknown@enum{#2}{#3}{#1}%
      }
    \def\ekvc@h@enum@#1\fi\ekvc@err@unknown@enum#2#3#4%
      {%
        \fi
        \ifx#1\relax
          \ekvc@err@unknown@enum{#2}{#3}{#4}%
          \expandafter\@gobble
        \fi
        #1%
      }
  }
  {%
    \def\ekvc@h@enum#1%
      {%
        \def\ekvc@h@enum##1\ekvc@stop##2##3%
          {%
            \expandafter\ekvc@h@enum@
              \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
              {##2}{##3}{##1}%
          }%
      }
    \expandafter\ekvc@h@enum\expandafter{\ekvc@enum@name{#2}{#3}{#1}}
    \def\ekvc@h@enum@#1#2#3#4%
      {%
        \ifx#1\relax
          \ekvc@err@unknown@enum{#2}{#3}{#4}%
          \expandafter\@gobble
        \fi
        #1%
      }
  }
%    \end{macrocode}
%   We don't need |\ekvc@enum@name| anymore, so let's undefine it.
%    \begin{macrocode}
\let\ekvc@enum@name\ekvc@undefined
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{aggregate,e-aggregate}
%   Aggregating isn't easy to define. We'll have to extract the correct mark for
%   the specified key, branch correctly for short and long keys, and use a small
%   hack to have the correct arguments on the user interface (|#1| as the
%   current contents, |#2| as the new value). This is split into a few steps
%   here.
%
%   First, assert that the user input is well-behaved.
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{aggregate}
  {%
    \let\ekvc@type@aggregate@ifexpanded\@secondoftwo
    \ekvc@type@aggregate{#1}{#3}%
  }
\ekvpDefType{ekvc@setup@secondary}{e-aggregate}
  {%
    \let\ekvc@type@aggregate@ifexpanded\@firstoftwo
    \ekvc@type@aggregate{#1}{#3}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {\ekvc@type@aggregate,\ekvc@type@aggregate@a,\ekvc@type@aggregate@b}
%   The next step stores the user defined processing in a temporary macro that's
%   used to do the parameter number swapping later. It also builds the names of
%   the key macro and the helper which would be used for processing a short key.
%    \begin{macrocode}
\protected\long\def\ekvc@type@aggregate#1#2%
  {%
    \ekvc@assert@not@long
    \ekvpAssertTwoValues{#2}%
    \ekvc@type@aggregate@a
      \ekvc@type@aggregate@long\ekvc@type@aggregate@short
      {#1}#2%
  }
\protected\long\def\ekvc@type@aggregate@a#1#2#3#4#5%
  {%
    \ekvc@assert@defined{#4}%
    \def\ekvc@type@aggregate@tmp##1##2{#5}%
    \begingroup\expandafter\endgroup
    \expandafter\ekvc@type@aggregate@b
      \csname\ekv@name\ekvc@set{#4}\expandafter\endcsname
      \csname ekvc@\ekvc@set(#4)\endcsname
      #1#2%
      {#3}%
  }
\protected\long\def\ekvc@type@aggregate@b#1#2#3#4%
  {%
    \ekvc@type@aggregate@check@long#1#2%
      {#3#1}%
      {#4#2}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@type@aggregate@check@long,
%     \ekvc@type@aggregate@check@long@a,\ekvc@type@aggregate@check@long@b
%   }
%   To check whether the primary key is long we see whether its |\meaning|
%   contains the helper which would only be there for short keys. For this we
%   have to get the stringified name of the internal (using |\detokenize|),
%   and afterwards get the |\meaning| of the macro. A temporary helper does the
%   real test by gobbling and forwarding the result to |\ekv@ifempty|.
%    \begin{macrocode}
\protected\long\def\ekvc@type@aggregate@check@long#1#2%
  {\expandafter\ekvc@type@aggregate@check@long@a\detokenize{#2}\ekv@stop#1}
\protected\long\def\ekvc@type@aggregate@check@long@a#1\ekv@stop#2%
  {%
    \def\ekvc@type@aggregate@check@long@@##1#1{}%
    \expandafter\ekvc@type@aggregate@check@long@b\meaning#2\ekv@stop{#1}%
  }
\protected\def\ekvc@type@aggregate@check@long@b#1\ekv@stop#2%
  {\expandafter\ekv@ifempty\expandafter{\ekvc@type@aggregate@check@long@@#1#2}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@type@aggregate@long,\ekvc@type@aggregate@long@}
%   The long variant just builds the split mark we extract, uses the hack to
%   swap argument order, and then does the definition via |\ekvlet| and a
%   temporary macro.
%    \begin{macrocode}
\protected\long\def\ekvc@type@aggregate@long#1%
  {%
    \begingroup\expandafter\endgroup\expandafter
    \ekvc@type@aggregate@long@
      \csname\ekvc@extract@mark#1\expandafter\endcsname
      \expandafter{\ekvc@type@aggregate@tmp{##3}{##1}}%
  }
\protected\long\def\ekvc@type@aggregate@long@#1#2#3%
  {%
    \ekvc@type@aggregate@ifexpanded
      {%
        \long\def\ekvc@type@aggregate@tmp##1##2#1##3%
          {\ekv@expanded{\ekv@unexpanded{##2#1}{#2}}}%
      }%
      {\long\def\ekvc@type@aggregate@tmp##1##2#1##3{##2#1{#2}}}%
    \ekvlet\ekvc@set{#3}\ekvc@type@aggregate@tmp
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {\ekvc@type@aggregate@short,\ekvc@type@aggregate@short@}
%   The short variant will have to build the marker and the name of the helper
%   function, and swap the user argument order. Hence here are a few more
%   |\expandafter|s involved. But afterwards we can do the definition of the key
%   and the helper macro directly.
%    \begin{macrocode}
\protected\long\def\ekvc@type@aggregate@short#1#2%
  {%
    \begingroup\expandafter\endgroup\expandafter
    \ekvc@type@aggregate@short@
      \csname\ekvc@extract@mark#1\expandafter\endcsname
      \csname ekvc@\ekvc@set(#2)\expandafter\endcsname
      \expandafter{\ekvc@type@aggregate@tmp{##3}{##1}}%
      {#2}%
  }
\protected\long\def\ekvc@type@aggregate@short@#1#2#3#4%
  {%
    \ekvdef\ekvc@set{#4}{#2{##1}}%
    \ekvc@type@aggregate@ifexpanded
      {\long\def#2##1##2#1##3{\ekv@expanded{\ekv@unexpanded{##2#1}{#3}}}}%
      {\long\def#2##1##2#1##3{##2#1{#3}}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{process}
%   The |process| type can reuse much of |aggregate|, just the last step of
%   definition differ.
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{process}
  {%
    \ekvpAssertTwoValues{#3}%
    \ifx\ekvc@long\long
      \ekv@fi@firstoftwo
    \fi
    \@secondoftwo
      {%
        \ekvc@type@aggregate@a
          \ekvc@type@process@long\ekvc@type@process@long
      }%
      {%
        \ekvc@type@aggregate@a
          \ekvc@type@process@short\ekvc@type@process@short
      }%
      {#1}#3%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@type@process@long,\ekvc@type@process@long@}
%   This defines a temporary macro to grab the current value (found after the
%   marker |#1|), executes the user code and puts everything back to where it
%   belongs. Then |\ekvlet| is used to assign that meaning to the key macro.
%    \begin{macrocode}
\protected\long\def\ekvc@type@process@long#1%
  {%
    \begingroup\expandafter\endgroup\expandafter
    \ekvc@type@process@long@
      \csname\ekvc@extract@mark#1\expandafter\endcsname
      \expandafter{\ekvc@type@aggregate@tmp{##3}{##1}}%
  }
\protected\long\def\ekvc@type@process@long@#1#2#3%
  {%
    \long\def\ekvc@type@aggregate@tmp##1##2#1##3{#2##2#1{##3}}%
    \ekvlet\ekvc@set{#3}\ekvc@type@aggregate@tmp
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@type@process@short,\ekvc@type@process@short@}
%   We define the key macro directly to just grab the argument once and forward
%   it to the auxiliary. That one does essentially the same as the long variant.
%    \begin{macrocode}
\protected\long\def\ekvc@type@process@short#1#2%
  {%
    \begingroup\expandafter\endgroup\expandafter
    \ekvc@type@process@short@
      \csname\ekvc@extract@mark#1\expandafter\endcsname
      \csname ekvc@\ekvc@set(#2)\expandafter\endcsname
      \expandafter{\ekvc@type@aggregate@tmp{##3}{##1}}%
      {#2}%
  }
\protected\long\def\ekvc@type@process@short@#1#2#3#4%
  {%
    \ekvdef\ekvc@set{#4}{#2{##1}}%
    \long\def#2##1##2#1##3{#3##2#1{##3}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{flag-bool}
%    \begin{macrocode}
\ekvpDefType{ekvc@setup@secondary}{flag-bool}
  {%
    \ekvc@assert@not@long
    \ekvpAssertOneValue{#3}%
    \ifdefined#3\else\ekvcFlagNew#3\fi
    \ekvdef\ekvc@set{#1}%
      {%
        \ekv@ifdefined{ekvc@flag@set@##1}%
          {%
            \csname ekvc@flag@set@##1\expandafter\endcsname
              \ekvcFlagHeight#3\ekv@stop#3%
          }%
          {\ekvc@err@invalid@bool{##1}}%
      }%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{flag-true,flag-false,flag-raise}
% \begin{macro}[internal]{\ekvc@type@flag}
%    \begin{macrocode}
\protected\def\ekvc@type@flag#1#2#3%
  {%
    \ekvc@assert@not@long
    \ekvpAssertOneValue{#3}%
    \ifdefined#3\else\ekvcFlagNew#3\fi
    \ekv@exparg{\ekvdefNoVal\ekvc@set{#2}}{#1#3}%
  }
\ekvpDefType{ekvc@setup@secondary}{flag-true}
  {\ekvc@type@flag\ekvcFlagSetTrue{#1}{#3}}
\ekvpDefType{ekvc@setup@secondary}{flag-false}
  {\ekvc@type@flag\ekvcFlagSetFalse{#1}{#3}}
\ekvpDefType{ekvc@setup@secondary}{flag-raise}
  {\ekvc@type@flag\ekvcFlagRaise{#1}{#3}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsubsection{Flags}
%
% The basic idea of flags is to store information by the fact that \TeX\
% expandably assigns the meaning |\relax| to undefined control sequences which
% were built with |\csname|. This mechanism is borrowed from \pkg{expl3}.
%
% \begin{macro}[internal]{\ekvc@flag@name,\ekvc@flag@namescheme}
%   Flags follow a simple naming scheme which we define here. |\ekvc@flag@name|
%   will store the name of an internal function that is used to build names of
%   the second naming scheme defined by |\ekvc@flag@namescheme|.
%    \begin{macrocode}
\def\ekvc@flag@name{ekvcf\string}
\def\ekvc@flag@namescheme#1#2{ekvch#2#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagHeight}
%   For semantic reasons we use |\number| with another name.
%    \begin{macrocode}
\let\ekvcFlagHeight\number
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagNew}
%   This macro defines a new flag. It stores the function build with the
%   |\ekvc@flag@name| naming scheme after the internal function
%   |\ekvc@flag@height| that'll determine the current flag height. It'll also
%   define the macro named via |\ekvc@flag@name| to build names according to
%   |\ekvc@flag@namescheme|.
%    \begin{macrocode}
\protected\def\ekvcFlagNew#1%
  {%
    \edef#1%
      {%
        \ekv@unexpanded{\ekvc@flag@height}%
          \ekv@unexpanded\expandafter{\csname\ekvc@flag@name#1\endcsname}%
      }%
    \ekv@expargtwice
      {\expandafter\def\csname\ekvc@flag@name#1\endcsname##1}%
      {\expandafter\ekvc@flag@namescheme\expandafter{\string#1}{##1}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@flag@height,\ekvc@flag@height@}
%   This macro gets the height of a flag by a simple loop. The first loop
%   iteration differs a bit from the following in that it doesn't have to get
%   the current iteration count. The space at the end of |\ekvc@flag@height|
%   ends the |\number| evaluation.
%    \begin{macrocode}
\def\ekvc@flag@height#1%
  {%
    \ifcsname#10\endcsname
      \ekvc@flag@height@1\ekv@stop#1%
    \fi
    \@firstofone{0} % leave this space
  }
\def\ekvc@flag@height@#1\ekv@stop#2\fi\@firstofone#3%
  {%
    \fi
    \ifcsname#2{#1}\endcsname
      \expandafter\ekvc@flag@height@\the\numexpr#1+1\relax\ekv@stop#2%
    \fi
    \@firstofone{#1}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagRaise}
%   Raising a flag simply means letting the |\ekvc@flag@namescheme| macro for
%   the current height to relax. The result of raising a flag is that its height
%   is bigger by $1$.
%    \begin{macrocode}
\ekv@exparg{\def\ekvcFlagRaise#1}%
  {%
    \expandafter\expandafter\expandafter\@gobble\expandafter
      \csname\ekvc@flag@namescheme{\string#1}{\ekvcFlagHeight#1}\endcsname
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagSetTrue,\ekvcFlagSetFalse}
% \begin{macro}[internal]{\ekvc@flag@set@true,\ekvc@flag@set@false}
%   A flag is considered true if its current height is odd, and as false if it
%   is even. Therefore |\ekvcFlagSetTrue| and |\ekvcFlagSetFalse| only need to
%   raise the flag if the opposing boolean value is the current one.
%    \begin{macrocode}
\def\ekvcFlagSetTrue#1%
  {\expandafter\ekvc@flag@set@true\ekvcFlagHeight#1\ekv@stop#1}
\def\ekvcFlagSetFalse#1%
  {\expandafter\ekvc@flag@set@false\ekvcFlagHeight#1\ekv@stop#1}
%    \end{macrocode}
%   We can expand |\ekvc@flag@namescheme| at definition time here, which is why
%   we're using a temporary definition to set up |\ekvc@flag@set@true| and
%   |\ekvc@flag@set@false|.
%    \begin{macrocode}
\def\ekvc@flag@set@true#1%
  {%
    \def\ekvc@flag@set@true##1\ekv@stop##2%
      {%
        \ifodd##1
          \ekv@fi@gobble
        \fi
        \@firstofone{\expandafter\@gobble\csname#1\endcsname}%
      }%
    \def\ekvc@flag@set@false##1\ekv@stop##2%
      {%
        \ifodd##1
          \ekv@fi@firstofone
        \fi
        \@gobble{\expandafter\@gobble\csname#1\endcsname}%
      }%
  }
\expandafter\ekvc@flag@set@true\expandafter
  {\ekvc@flag@namescheme{\string#2}{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ekvcFlagIf}
%   As already explained, truthiness is defined as a flag's height being odd, so
%   we just branch accordingly here.
%    \begin{macrocode}
\def\ekvcFlagIf#1%
  {%
    \ifodd#1%
      \ekv@fi@firstoftwo
    \fi
    \@secondoftwo
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagIfRaised}
%   This macro uses flags as a switch, if a flag's current height is bigger than
%   $0$ this test yields true.
%    \begin{macrocode}
\ekv@exparg{\def\ekvcFlagIfRaised#1}%
  {%
    \expandafter\ifcsname\ekvc@flag@namescheme{\string#1}0\endcsname
      \ekv@fi@firstoftwo
    \fi
    \@secondoftwo
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvcFlagReset,\ekvcFlagResetGlobal}
% \begin{macro}[internal]{\ekvc@flag@reset,\ekvc@flag@reset@}
%   Resetting works by locally letting all the defined internal macros named
%   after |\ekvc@flag@namescheme| to undefined.
%    \begin{macrocode}
\protected\def\ekvcFlagReset#1%
  {\expandafter\ekvc@flag@reset\csname\ekvc@flag@name#1\endcsname{}}
\protected\def\ekvcFlagResetGlobal#1%
  {\expandafter\ekvc@flag@reset\csname\ekvc@flag@name#1\endcsname\global}
\protected\def\ekvc@flag@reset#1#2%
  {%
    \ifcsname#10\endcsname
      #2\expandafter\let\csname#10\endcsname\ekvc@undefined
      \ekvc@flag@reset@1\ekv@stop#1{#2}%
    \fi
  }
\protected\def\ekvc@flag@reset@#1\ekv@stop#2#3\fi
  {%
    \fi
    \ifcsname#2{#1}\endcsname
      #3\expandafter\let\csname#2{#1}\endcsname\ekvc@undefined
      \expandafter\ekvc@flag@reset@\the\numexpr#1+1\relax\ekv@stop#2{#3}%
    \fi
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ekvcFlagGetHeight}
% \begin{macro}[internal]{\ekvc@flag@get@height@single}
%   These are just small helpers, first getting the height of the flag and then
%   passing it on to the user supplied code.
%    \begin{macrocode}
\def\ekvcFlagGetHeight#1%
  {\expandafter\ekvc@flag@get@height@single\ekvcFlagHeight#1\ekv@stop}
\long\def\ekvc@flag@get@height@single#1\ekv@stop#2{#2{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ekvcFlagGetHeights}
% \begin{macro}[internal]
%   {\ekvc@flag@get@heights,\ekvc@flag@get@heights@,\ekvc@flag@get@heights@done}
%   This works by a simple loop that stops at |\ekv@stop|. As long as that
%   marker isn't hit, get the next flags height and put it into a list after
%   |\ekv@stop|. |\ekvc@flag@get@heights@| uses the same marker name for the
%   end of the height, which shouldn't clash in any case. Once we're done we
%   remove the remainder of the current iteration and leave the user supplied
%   code in the input stream with all the flags' heights as a single argument.
%    \begin{macrocode}
\def\ekvcFlagGetHeights#1%
  {%
    \ekvc@flag@get@heights#1\ekv@stop{}%
  }
\def\ekvc@flag@get@heights#1%
  {%
    \ekv@gobbleto@stop#1\ekvc@flag@get@heights@done\ekv@stop
    \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight#1\ekv@stop
  }
\def\ekvc@flag@get@heights@#1\ekv@stop#2\ekv@stop#3%
  {\ekvc@flag@get@heights#2\ekv@stop{#3{#1}}}
\long\def\ekvc@flag@get@heights@done
    \ekv@stop
    \expandafter\ekvc@flag@get@heights@\ekvcFlagHeight\ekv@stop\ekv@stop#1#2%
  {#2{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsubsection{Helper Macros}
%
% \begin{macro}[internal]{\ekvc@extract@mark,\ekvc@extract@mark@}
%   This is used to extract the mark of a split or hash key from its definition.
%   This is kind of fragile, it assumes |#1| is always a macro used for hashing
%   or splitting. Also it assumes that the escape character is a backslash.
%    \begin{macrocode}
\def\ekvc@extract@mark#1{\expandafter\ekvc@extract@mark@\meaning#1\ekv@stop}
\begingroup
\lccode`;=`#
\lccode`/=`\\
\lowercase{\endgroup
\def\ekvc@extract@mark@#1:#2/#3 ;#4\ekv@stop{#3}%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Assertions}
%
% \begin{macro}[internal]{\ekvc@assert@not@long}
%   Some keys don't want to be |long| and we have to educate the user, so let's
%   throw an error if someone wanted these to be long.
%    \begin{macrocode}
\ekv@exparg{\def\ekvc@assert@not@long}%
  {\ekvpAssertIfNot{\ifx\ekvc@long\long}{`long' not accepted}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@assert@defined,\ekvc@assert@k@or@p@defined}
%   Since some keys interact with existing other keys we need to assert those
%   exist.
%    \begin{macrocode}
\long\def\ekvc@assert@defined#1%
  {\ekvpAssertTF{\ekvifdefined\ekvc@set{#1}}{undefined key `#1'}}
\long\def\ekvc@assert@k@or@p@defined#1%
  {%
    \ekvpAssertTF
      {\ekvifdefined\ekvc@set{#1}\@firstoftwo{\ekvifdefinedNoVal\ekvc@set{#1}}}%
      {undefined key `#1'}%
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Messages}
%
% \begin{macro}[internal]
%   {
%     \ekvc@errm,
%     \ekvc@err@toomany,\ekvc@err@value@required,
%     \ekvc@err@already@defined,\ekvc@err@no@key@macro,
%   }
%   Boring unexpandable error messages.
%    \begin{macrocode}
\protected\long\def\ekvc@errm#1{\errmessage{expkv-cs Error: #1}}
\protected\long\def\ekvc@err@toomany#1%
  {\ekvc@errm{Too many keys for macro `\string#1'}}
\protected\long\def\ekvc@err@value@required#1%
  {\ekvc@errm{Missing value for key `\ekv@unexpanded{#1}'}}
\protected\long\def\ekvc@err@already@defined#1%
  {\ekvc@errm{Macro `\string#1' already defined}}
\protected\long\def\ekvc@err@no@key@macro#1%
  {\ekvc@errm{\string#1 is no key=val macro}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvc@err}
%   We need a way to throw error messages expandably in some contexts.
%    \begin{macrocode}
\ekv@exparg{\long\def\ekvc@err#1}{\ekverr{expkv-cs}{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvc@err@unknown@hash,\ekvc@err@empty@hash,\ekvc@err@missing@hash,
%     \ekvc@err@invalid@bool,\ekvc@err@unknown@key@or@macro,
%     \ekvc@err@unknown@enum
%   }
%   And here are the expandable error messages.
%    \begin{macrocode}
\long\def\ekvc@err@unknown@hash#1{\ekvc@err{unknown hash `#1'}}
\long\def\ekvc@err@missing@hash#1{\ekvc@err{hash `#1' not found}}
\long\def\ekvc@err@empty@hash{\ekvc@err{empty hash}}
\def\ekvc@err@invalid@bool#1{\ekvc@err{invalid boolean value `#1'}}
\long\def\ekvc@err@unknown@key@or@macro#1#2%
  {\ekvc@err{unknown key `#2' for #1}}
\def\ekvc@err@unknown@enum#1#2#3%
  {\ekvc@err{unknown choice `#3' for `#2' in #1}}
%    \end{macrocode}
% \end{macro}
%
%
% Now everything that's left is to reset the category code of |@|.
%    \begin{macrocode}
\catcode`\@=\ekvc@tmp
%    \end{macrocode}
%
% \gobbledocstriptag
%</tex>
%^^A=<<