% \iffalse meta-comment
%
% File: expkv-def.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-def.sty}{\from{expkv-def.dtx}{pkg}}}
\generate{\file{expkv-def.tex}{\from{expkv-def.dtx}{tex}}}
\generate{\file{t-expkv-def.tex}{\from{expkv-def.dtx}{ctx}}}
\endbatchfile
%</driver>^^A=<<
% \fi
%
% \section{\expkvd}
%^^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\ekvd@tmp
  {%
    \ProvidesFile{expkv-def.tex}%
      [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]%
  }
\input{expkv-def.tex}
\ProvidesPackage{expkv-def}%
  [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]
%    \end{macrocode}
% \gobbledocstriptag
%</pkg>
%^^A=<<
%^^A the ConTeXt module >>=
% \subsection{The \ConTeXt\ module}
% \gobbledocstriptag
%<*ctx>
%    \begin{macrocode}
\writestatus{loading}{ConTeXt User Module / expkv-def}
\usemodule[expkv-pop]
\unprotect
\input expkv-def.tex
\writestatus{loading}
  {ConTeXt User Module / expkv-def / Version \ekvdVersion\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. Additionally load \expkvp, which aids in defining the type
% system (and \expkvp\ will actually do the \expkv\ loading).
%    \begin{macrocode}
\input expkv-pop
%    \end{macrocode}
%
% We make sure that \file{expkv-def.tex} is only input once:
%    \begin{macrocode}
\expandafter\ifx\csname ekvdVersion\endcsname\relax
\else
  \expandafter\endinput
\fi
%    \end{macrocode}
%
% \begin{macro}{\ekvdVersion,\ekvdDate}
% We're on our first input, so lets store the version and date in a macro.
%    \begin{macrocode}
\def\ekvdVersion{1.1}
\def\ekvdDate{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 |\ekvd@tmp| to use
% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
%    \begin{macrocode}
\csname ekvd@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 ekvd@tmp\endcsname=\catcode`\@
\catcode`\@=11
%    \end{macrocode}
% |\ekvd@tmp| will be reused later to handle expansion during the key
% defining. But we don't need it to ever store information long-term after
% \expkvd\ was initialized.
%
% \begin{macro}[internal]{\ekvd@ifprimitive}
%    \begin{macrocode}
\protected\long\def\ekvd@ifprimitive#1%
  {%
    \begingroup
      \edef\ekvd@tmpa{\string #1}%
      \edef\ekvd@tmpb{\meaning#1}%
      \expandafter
    \endgroup
    \ifx\ekvd@tmpa\ekvd@tmpb
      \ekv@fi@firstoftwo
    \fi
    \@secondoftwo
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {\ekvd@long,\ekvd@prot,\ekvd@clear@prefixes,\ekvd@ifalso}
% \expkvd\ will use |\ekvd@long|, |\ekvd@prot|, and |\ekvd@ifalso| to store
% whether a key should be defined as |\long| or |\protected| or adds an action
% to an existing key, and we have to clear them for every new key. By default
% |long| and |protected| will just be empty, |ifalso| will be
% |\@secondoftwo|, and |ifnew| will just use its third argument.
%    \begin{macrocode}
\protected\def\ekvd@clear@prefixes
  {%
    \let\ekvd@long\ekv@empty
    \let\ekvd@prot\ekv@empty
    \let\ekvd@ifalso\@secondoftwo
    \let\ekvd@do@new\@gobbletwo
  }
\ekvd@clear@prefixes
%    \end{macrocode}
% \end{macro}
%
% We define the parser for our front-facing macro and its \prefix{}es here:
%    \begin{macrocode}
\ekvpNewParser{ekvd@definekeys}
\ekvpDefNoValuePrefix{ekvd@definekeys}
  {\let\ekvd@ifnoarg\@firstoftwo}
  {\let\ekvd@ifnoarg\@secondoftwo}
\ekvpDefPrefixLet{ekvd@definekeys}{long}     \ekvd@long\long     \ekv@empty
\ekvpDefPrefixLet{ekvd@definekeys}{protected}\ekvd@prot\protected\ekv@empty
\ekvpDefPrefixLet{ekvd@definekeys}{protect}  \ekvd@prot\protected\ekv@empty
\ekvpDefPrefixLet{ekvd@definekeys}{also}\ekvd@ifalso\@firstoftwo\@secondoftwo
\ekvpDefPrefixLet{ekvd@definekeys}{new}\ekvd@do@new\ekvd@assert@new\@gobbletwo
%    \end{macrocode}
% We ease the process of error throwing a bit for now by using our own macro
% instead of relying on \expkvp's argument forwarding.
%    \begin{macrocode}
\ekvpDefAutoPrefix{ekvd@definekeys}{\edef\ekvd@cur{\detokenize{#3}}}{}
%    \end{macrocode}
%
% \begin{macro}{\ekvdefinekeys}
%   This is the one front-facing macro which provides the interface to define
%   keys. It stores the \set\ for which the keys should be defined in
%   |\ekvd@set| and calls a parser defined with \expkvp.
%    \begin{macrocode}
\protected\edef\ekvdefinekeys#1%
  {%
    \ekv@unexpanded{\def\ekvd@set}{#1}%
    \ekv@unexpanded{\ekvpParse@unsafe@auto\ekvp@@p@ekvd@definekeys}%
    \ekv@unexpanded\expandafter{\csname\ekvp@@p@ekvd@definekeys{ppa}\endcsname}%
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Key Types}
%
% \begin{macro}[internal]{\ekvd@def@type,\ekvd@def@type@fwd}
%   To reduce some typing the following is a shortcut to |\ekvpDefType|. The
%   |@fwd| variant will forward the key name and value and remove the
%   unprocessed key. The other variant automatically sets up a helper macro,
%   unfortunately this is necessary due to the design decision of \expkvp\ to
%   not |\detokenize| the key names while \expkvd\ used to do this very early.
%    \begin{macrocode}
\protected\def\ekvd@def@type#1#2%
  {%
    \ekv@exparg{\ekvpDefType{ekvd@definekeys}{#1}}
      {%
        \expandafter\expandafter\csname ekvd@th@#1\endcsname
          \detokenize{##1}\ekv@stop{##2}{##3}%
      }%
    \long\expandafter\def\csname ekvd@th@#1\endcsname##1\ekv@stop##2##3{#2}%
  }
\protected\long\def\ekvd@def@type@fwd#1#2%
  {\ekvpDefType{ekvd@definekeys}{#1}{\ekv@exparg{#2}{\detokenize{##1}}{##3}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{set}
% \begin{macro}[internal]{\ekvd@type@set}
%    \begin{macrocode}
\ekvd@def@type{set}
  {\ekvd@ifnoarg{\ekvd@type@set{#1}{#1}}{\ekvd@type@set{#1}{#3}}}
\protected\def\ekvd@type@set#1#2%
  {%
    \ekvd@assert@not@long
    \ekvd@assert@not@protected
    \ekvd@do@new{NoVal}{#1}%
    \ekv@ifempty{#2}%
      {\ekvd@err@missing@definition}%
      {%
        \ekvd@ifalso
          {%
            \ekv@expargtwice{\ekvd@add@noval{#1}}%
              {\ekvchangeset{#2}}%
              \ekvd@assert@not@protected@also
          }%
          {\ekv@expargtwice{\ekvdefNoVal\ekvd@set{#1}}{\ekvchangeset{#2}}}%
      }%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{noval,enoval}
% \begin{macro}[internal]{\ekvd@type@noval}
% Another pretty simple type, |noval| just needs to assert that there is a
% definition and that |long| wasn't specified.
% There are types where the difference in the variants is so small, that we
% define a common handler for them, those common handlers are named with
% |@type@|. |noval| and |enoval| are so similar that we can use such a |@type@|
% macro, even if we could've done |noval| in a slightly faster way without it.
%    \begin{macrocode}
\ekvd@def@type@fwd{noval}{\ekvd@type@noval\def}
\ekvd@def@type@fwd{enoval}{\ekvd@type@noval\edef}
\protected\long\def\ekvd@type@noval#1#2#3%
  {%
    \ekvd@do@new{NoVal}{#2}%
    \ekvd@assert@arg
    \ekvd@assert@not@long
    \ekvd@prot#1\ekvd@tmp{#3}%
    \ekvd@ifalso
      {\ekv@exparg{\ekvd@add@noval{#2}}\ekvd@tmp{}}%
      {\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{code,ecode}
% \begin{macro}[internal]{\ekvd@type@code}
% |code| is simple as well, |ecode| has to use |\edef| on a temporary macro,
% since \expkv\ doesn't provide an |\ekvedef|.
%    \begin{macrocode}
\ekvd@def@type@fwd{code}{\ekvd@type@code\def}
\ekvd@def@type@fwd{ecode}{\ekvd@type@code\edef}
\protected\long\def\ekvd@type@code#1#2#3%
  {%
    \ekvd@do@new{}{#2}%
    \ekvd@assert@arg
    \ekvd@prot\ekvd@long#1\ekvd@tmp##1{#3}%
    \ekvd@ifalso
      {\ekv@exparg{\ekvd@add@val{#2}}{\ekvd@tmp{##1}}{}}%
      {\ekvlet\ekvd@set{#2}\ekvd@tmp}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{default,qdefault,odefault,fdefault,edefault}
% \begin{macro}[internal]
%   {
%     \ekvd@type@default,\ekvd@t@default,\ekvd@t@qdefault,\ekvd@t@odefault,
%     \ekvd@t@fdefault
%   }
% |\ekvd@type@default| asserts there was an argument, also the key for which one
% wants to set a default has to be already defined (this is not so important for
% |default|, but |qdefault| requires it). If everything is good, |\edef| a
% temporary macro that expands |\ekvd@set| and the |\csname| for the key.
% The different expansion variants are implemented via |\ekv@unexpanded| and
% some |\expandafter|s.
%    \begin{macrocode}
\ekvd@def@type@fwd{default}{\ekvd@type@default{\ekv@unexpanded\expandafter}{}}
\ekvd@def@type@fwd{odefault}
  {\ekvd@type@default{\ekv@unexpanded\expandafter\expandafter\expandafter}{}}
\ekvpLet{ekvd@definekeys}{type}{qdefault}{odefault}
\ekvd@def@type@fwd{fdefault}
  {\ekvd@type@default{\ekv@unexpanded\expandafter}{\romannumeral`\^^@}}
\protected\long\def\ekvd@type@default#1#2#3#4%
  {%
    \ekvd@assert@arg
    \ekvd@do@new{NoVal}{#3}%
    \ekvd@assert@not@long
    \ekvifdefined\ekvd@set{#3}%
      {%
        \ekvd@prot\edef\ekvd@tmp
          {#1{#2\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}}%
        \ekvd@ifalso
          {\ekv@exparg{\ekvd@add@noval{#3}}\ekvd@tmp{}}%
          {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}%
      }%
      {\ekvd@err@undefined@key{#3}}%
  }
\ekvd@def@type{edefault}
  {%
    \ekvd@assert@arg
    \ekvd@do@new{NoVal}{#1}%
    \ekvd@assert@not@long
    \ekvifdefined\ekvd@set{#1}%
      {%
        \ekvd@prot\edef\ekvd@tmp
          {%
            \ekv@unexpanded\ekv@expanded
              {{\csname\ekv@name\ekvd@set{#1}\endcsname{#3}}}%
          }%
        \ekvd@ifalso
          {\ekv@exparg{\ekvd@add@noval{#1}}\ekvd@tmp{}}%
          {\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}%
      }%
      {\ekvd@err@undefined@key{#1}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{initial,oinitial,finitial,einitial}
% \begin{macro}[internal]{\ekvd@type@initial}
%    \begin{macrocode}
\ekvd@def@type@fwd{initial}{\ekvd@type@initial\@firstofone}
\ekvd@def@type@fwd{oinitial}{\ekvd@type@initial\ekv@exparg}
\ekvd@def@type@fwd{einitial}{\ekvd@type@initial\ekv@expandedarg}
\ekvd@def@type@fwd{finitial}{\ekvd@type@initial\ekv@fexparg}
\long\def\ekvd@type@initial#1#2#3%
  {%
    \ekvd@assert@not@new
    \ekvd@assert@not@also
    \ekvd@assert@not@long
    \ekvd@assert@not@protected
    \ekvd@ifnoarg
      {%
        \ekvifdefinedNoVal\ekvd@set{#2}%
          {\csname\ekv@name\ekvd@set{#2}N\endcsname}%
          {\ekvd@err@undefined@noval{#2}}%
      }%
      {%
        \ekvifdefined\ekvd@set{#2}%
          {#1{\csname\ekv@name\ekvd@set{#2}\endcsname}{#3}}%
          {\ekvd@err@undefined@key{#2}}%
      }%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{bool,gbool,boolTF,gboolTF,invbool,ginvbool,invboolTF,ginvboolTF}
% \begin{macro}[internal]{\ekvd@type@bool}
% The boolean types are a quicker version of a |choice| that accept |true| and
% |false|, and set up the |NoVal| action to be identical to \texttt{\key=true}.
% The |true| and |false| actions are always just |\let|ting the macro in |#7| to
% some other macro (\emph{e.g.}, \cs[no-index]{iftrue}).
%    \begin{macrocode}
\ekvd@def@type@fwd{bool}{\ekvd@type@bool{}\iftrue\iffalse}
\ekvd@def@type@fwd{gbool}{\ekvd@type@bool\global\iftrue\iffalse}
\ekvd@def@type@fwd{boolTF}{\ekvd@type@bool{}\@firstoftwo\@secondoftwo}
\ekvd@def@type@fwd{gboolTF}{\ekvd@type@bool\global\@firstoftwo\@secondoftwo}
\ekvd@def@type@fwd{invbool}{\ekvd@type@bool{}\iffalse\iftrue}
\ekvd@def@type@fwd{ginvbool}{\ekvd@type@bool\global\iffalse\iftrue}
\ekvd@def@type@fwd{invboolTF}{\ekvd@type@bool{}\@secondoftwo\@firstoftwo}
\ekvd@def@type@fwd{ginvboolTF}{\ekvd@type@bool\global\@secondoftwo\@firstoftwo}
\protected\def\ekvd@type@bool#1#2#3#4#5%
  {%
    \ekvd@do@new{}{#4}%
    \ekvd@do@new{NoVal}{#4}%
    \ekvd@assert@filledarg{#5}%
    \ekvd@newlet#5#3%
    \ekvd@type@choice{#4}%
    \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2}%
    \protected\expandafter\def
      \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname
      {#1\let#5#2}%
    \protected\expandafter\def
      \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname
      {#1\let#5#3}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{boolpair,gboolpair,boolpairTF,gboolpairTF}
% \begin{macro}[internal]{\ekvd@type@boolpair}
% The boolean pair types are essentially the same as the boolean types, but set
% two macros instead of one.
%    \begin{macrocode}
\ekvd@def@type{boolpair}
  {\ekvd@assert@twoargs{#3}\ekvd@type@boolpair{}\iftrue\iffalse{#1}#3}
\ekvd@def@type{gboolpair}
  {\ekvd@assert@twoargs{#3}\ekvd@type@boolpair\global\iftrue\iffalse{#1}#3}
\ekvd@def@type{boolpairTF}
  {\ekvd@assert@twoargs{#3}\ekvd@type@boolpair{}\@firstoftwo\@secondoftwo{#1}#3}
\ekvd@def@type{gboolpairTF}
  {%
    \ekvd@assert@twoargs{#3}%
    \ekvd@type@boolpair\global\@firstoftwo\@secondoftwo{#1}#3%
  }
\protected\def\ekvd@type@boolpair#1#2#3#4#5#6%
  {%
    \ekvd@do@new{}{#4}%
    \ekvd@do@new{NoVal}{#4}%
    \ekvd@newlet#5#3%
    \ekvd@newlet#6#2%
    \ekvd@type@choice{#4}%
    \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2#1\let#6#3}%
    \protected\expandafter\def
      \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname
      {#1\let#5#2#1\let#6#3}%
    \protected\expandafter\def
      \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname
      {#1\let#5#3#1\let#6#2}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{data,gdata,dataT,gdataT}
% \begin{macro}[internal]{\ekvd@type@data}
%    \begin{macrocode}
\ekvd@def@type@fwd{data}
  {\ekvd@type@data\@secondoftwo\edef{####2}{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{edata}
  {%
    \ekvd@type@data\@secondoftwo\edef
      {####2}{\ekv@unexpanded\ekv@expanded{{##1}}}%
  }
\ekvd@def@type@fwd{gdata}
  {\ekvd@type@data\@secondoftwo\xdef{####2}{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{xdata}
  {%
    \ekvd@type@data\@secondoftwo\xdef
      {####2}{\ekv@unexpanded\ekv@expanded{{##1}}}%
  }
\ekvd@def@type@fwd{dataT}{\ekvd@type@data\@gobble\edef{}{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{edataT}
  {\ekvd@type@data\@gobble\edef{}{\ekv@unexpanded\ekv@expanded{{##1}}}}
\ekvd@def@type@fwd{gdataT}{\ekvd@type@data\@gobble\xdef{}{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{xdataT}
  {\ekvd@type@data\@gobble\xdef{}{\ekv@unexpanded\ekv@expanded{{##1}}}}
\protected\def\ekvd@type@data#1#2#3#4#5#6%
  {%
    \ekvd@do@new{}{#5}%
    \ekvd@assert@filledarg{#6}%
    \ekvd@newlet#6#1%
    \ekvd@ifalso
      {%
        \let\ekvd@prot\protected
        \ekvd@add@val{#5}{\long#2#6####1#3{####1{#4}}}{}%
      }%
      {%
        \protected\ekvd@long\ekvdef\ekvd@set{#5}%
          {\long#2#6####1#3{####1{#4}}}%
      }%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{box,gbox}
% \begin{macro}[internal]{\ekvd@type@box}
% Set up our boxes. Though we're a generic package we want to be colour safe, so
% we put an additional grouping level inside the box contents, for the case that
% someone uses \pkg{color}. |\ekvd@newreg| is a small wrapper which tests
% whether the first argument is defined and if not does
% |\csname new#2\endcsname#1|.
%    \begin{macrocode}
\ekvd@def@type@fwd{box}{\ekvd@type@box{}}
\ekvd@def@type@fwd{gbox}{\ekvd@type@box\global}
\protected\def\ekvd@type@box#1#2#3%
  {%
    \ekvd@do@new{}{#2}%
    \ekvd@assert@filledarg{#3}%
    \ekvd@newreg#3{box}%
    \ekvd@ifalso
      {%
        \let\ekvd@prot\protected
        \ekvd@add@val{#2}{#1\setbox#3=\hbox{\begingroup##1\endgroup}}{}%
      }%
      {%
        \protected\ekvd@long\ekvdef\ekvd@set{#2}%
          {#1\setbox#3=\hbox{\begingroup##1\endgroup}}%
      }%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{toks,gtoks}
% \begin{macro}[internal]{\ekvd@type@toks}
% Similar to |box|, but set the |toks|.
%    \begin{macrocode}
\ekvd@def@type@fwd{toks}{\ekvd@type@toks{}}
\ekvd@def@type@fwd{gtoks}{\ekvd@type@toks\global}
\protected\def\ekvd@type@toks#1#2#3%
  {%
    \ekvd@do@new{}{#2}%
    \ekvd@assert@filledarg{#3}%
    \ekvd@newreg#3{toks}%
    \ekvd@ifalso
      {%
        \let\ekvd@prot\protected
        \ekvd@add@val{#2}{#1#3={##1}}{}%
      }%
      {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3={##1}}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@type@preapptoks,\ekvd@t@apptoks,\ekvd@t@gapptoks}
% Just like |toks|, but expand the current contents of the |toks| register to
% append the new contents.
%    \begin{macrocode}
\ekvd@ifprimitive\toksapp
  {%
    \ekvd@def@type@fwd{apptoks}{\ekvd@type@preapptoks\toksapp}
    \ekvd@def@type@fwd{gapptoks}{\ekvd@type@preapptoks\gtoksapp}
    \ekvd@def@type@fwd{pretoks}{\ekvd@type@preapptoks\tokspre}
    \ekvd@def@type@fwd{gpretoks}{\ekvd@type@preapptoks\gtokspre}
    \protected\def\ekvd@type@preapptoks#1#2#3%
      {%
        \ekvd@do@new{}{#2}%
        \ekvd@assert@filledarg{#3}%
        \ekvd@newreg#3{toks}%
        \ekvd@ifalso
          {%
            \let\ekvd@prot\protected
            \ekvd@add@val{#2}{#1#3{##1}}{}%
          }%
          {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3{##1}}}%
      }
  }
  {%
    \ekvd@def@type@fwd{apptoks}{\ekvd@type@apptoks{}}
    \ekvd@def@type@fwd{gapptoks}{\ekvd@type@apptoks\global}
    \protected\def\ekvd@type@apptoks#1#2#3%
      {%
        \ekvd@do@new{}{#2}%
        \ekvd@assert@filledarg{#3}%
        \ekvd@newreg#3{toks}%
        \ekvd@ifalso
          {%
            \let\ekvd@prot\protected
            \ekvd@add@val{#2}{#1#3=\expandafter{\the#3##1}}{}%
          }%
          {%
            \protected\ekvd@long\ekvdef\ekvd@set{#2}%
              {#1#3=\expandafter{\the#3##1}}%
          }%
      }
    \ekvd@def@type@fwd{pretoks}{\ekvd@type@pretoks{}}
    \ekvd@def@type@fwd{gpretoks}{\ekvd@type@pretoks\global}
    \newtoks\ekvd@toks
    \protected\def\ekvd@type@pretoks#1#2#3%
      {%
        \ekvd@do@new{}{#2}%
        \ekvd@assert@filledarg{#3}%
        \ekvd@newreg#3{toks}%
        \ekvd@ifalso
          {%
            \let\ekvd@prot\protected
            \ekvd@add@val{#2}%
              {#1#3=\ekv@expanded{{\ekv@unexpanded{##1}\the#3}}}%
              {}%
          }%
          {%
            \protected\ekvd@long\ekvdef\ekvd@set{#2}%
              {#1#3=\ekv@expanded{{\ekv@unexpanded{##1}\the#3}}}%
          }%
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {int,eint,gint,xint,dimen,edimen,gdimen,xdimen,skip,eskip,gskip,xskip}
% \begin{macro}[internal]{\ekvd@type@register}
% The |\ekvd@type@register| can handle all the types for which the assignment will
% just be \texttt{\meta{register}=\meta{value}}.
%    \begin{macrocode}
\ekvd@def@type@fwd {int}{\ekvd@type@register{count}{}{}}
\ekvd@def@type@fwd{eint}{\ekvd@type@register{count}{}\numexpr}
\ekvd@def@type@fwd{gint}{\ekvd@type@register{count}\global{}}
\ekvd@def@type@fwd{xint}{\ekvd@type@register{count}\global\numexpr}
\ekvd@def@type@fwd {dimen}{\ekvd@type@register{dimen}{}{}}
\ekvd@def@type@fwd{edimen}{\ekvd@type@register{dimen}{}\dimexpr}
\ekvd@def@type@fwd{gdimen}{\ekvd@type@register{dimen}\global{}}
\ekvd@def@type@fwd{xdimen}{\ekvd@type@register{dimen}\global\dimexpr}
\ekvd@def@type@fwd {skip}{\ekvd@type@register{skip}{}{}}
\ekvd@def@type@fwd{eskip}{\ekvd@type@register{skip}{}\glueexpr}
\ekvd@def@type@fwd{gskip}{\ekvd@type@register{skip}\global{}}
\ekvd@def@type@fwd{xskip}{\ekvd@type@register{skip}\global\glueexpr}
\protected\def\ekvd@type@register#1#2#3#4#5%
  {%
    \ekvd@do@new{}{#4}%
    \ekvd@assert@filledarg{#5}%
    \ekvd@newreg#5{#1}%
    \ekvd@ifalso
      {%
        \let\ekvd@prot\protected
        \ekvd@add@val{#4}{#2#5=#3##1\relax}{}%
      }%
      {\protected\ekvd@long\ekvdef\ekvd@set{#4}{#2#5=#3##1\relax}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{store,gstore,estore,xstore}
% \begin{macro}[internal]{\ekvd@type@store}
% The none-expanding |store| types use an |\edef| or |\xdef| and |\unexpanded|
% to be able to also store |#| easily.
%    \begin{macrocode}
\ekvd@def@type@fwd{store}{\ekvd@type@store\edef{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{gstore}{\ekvd@type@store\xdef{\ekv@unexpanded{##1}}}
\ekvd@def@type@fwd{estore}
  {\ekvd@type@store\edef{\ekv@unexpanded\ekv@expanded{{##1}}}}
\ekvd@def@type@fwd{xstore}
  {\ekvd@type@store\xdef{\ekv@unexpanded\ekv@expanded{{##1}}}}
\protected\def\ekvd@type@store#1#2#3#4%
  {%
    \ekvd@do@new{}{#3}%
    \ekvd@assert@filledarg{#4}%
    \ekvd@newlet#4\ekv@empty
    \ekvd@ifalso
      {%
        \let\ekvd@prot\protected
        \ekvd@add@val{#3}{#1#4{#2}}{}%
      }%
      {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#1#4{#2}}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{meta,nmeta}
% \begin{macro}[internal]{\ekvd@type@meta}
% |meta| sets up things such that another instance of |\ekvset| will be run on
% the argument, with the same \set.
%    \begin{macrocode}
\ekvd@def@type@fwd{meta}
  {\ekvd@type@meta{}{##1}\ekvd@add@val{{##1}}{}\ekv@exparg}
\ekvd@def@type@fwd{nmeta}
  {%
    \ekvd@assert@not@long
    \ekvd@type@meta
      {NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also\ekv@expargtwice
  }
\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7#8%
  {%
    \ekvd@do@new{#1}{#7}%
    \ekvd@assert@filledarg{#8}%
    #6{\ekvd@prot\ekvd@long\def\ekvd@tmp#2}{\ekvmorekv{#8}}%
    \ekvd@ifalso
      {\ekv@exparg{#3{#7}}{\ekvd@tmp#4}{#5}}%
      {\csname ekvlet#1\endcsname\ekvd@set{#7}\ekvd@tmp}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{smeta,snmeta}
% \begin{macro}[internal]
%   {\ekvd@type@smeta,\ekvd@type@smeta@}
% |smeta| is pretty similar to |meta|, but needs two arguments inside of \val,
% such that the first is the \set\ for which the sub-|\ekvset| and the second is
% the \kv\ list.
%    \begin{macrocode}
\ekvd@def@type@fwd{smeta}{\ekvd@type@smeta{}{##1}\ekvd@add@val{{##1}}{}}
\ekvd@def@type@fwd{snmeta}
  {%
    \ekvd@assert@not@long
    \ekvd@type@smeta{NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also
  }
\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7%
  {%
    \ekvd@do@new{#1}{#6}%
    \ekvd@assert@twoargs{#7}%
    \ekvd@type@smeta@#7{#2}%
    \ekvd@ifalso
      {\ekv@exparg{#3{#6}}{\ekvd@tmp#4}{#5}}%
      {\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}%
  }
\protected\long\def\ekvd@type@smeta@#1#2#3%
  {\ekvd@prot\ekvd@long\ekv@expargtwice{\def\ekvd@tmp#3}{\ekvset{#1}{#2}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{alias}
%   A few more or less standard tests and then copy over the definitions.
%    \begin{macrocode}
\ekvd@def@type{alias}
  {%
    \ekvd@assert@arg
    \ekvd@assert@not@protected
    \ekvd@assert@not@long
    \ekvd@assert@not@also
%    \end{macrocode}
%   In order to do nothing if |new| should be checked and the error condition
%   for either the |Val|- or |NoVal|-key is met we need to check for the defined
%   keys without actually copying here (the alternative would be using an
%   auxiliary variable which we would then need to check anyway).
%    \begin{macrocode}
    \ekvifdefined\ekvd@set{#3}{\ekvd@do@new{}{#1}}{}%
    \ekvifdefinedNoVal\ekvd@set{#3}{\ekvd@do@new{NoVal}{#1}}{}%
%    \end{macrocode}
%   Assert that at least one of |Val|- or |NoVal|-keys exist.
%    \begin{macrocode}
    \ekvpAssertTF
      {\ekvifdefined\ekvd@set{#3}\@firstoftwo{\ekvifdefinedNoVal\ekvd@set{#3}}}%
      {undefined key `#3'}%
%    \end{macrocode}
%   Copy the definitions.
%    \begin{macrocode}
    \ekvifdefined\ekvd@set{#3}{\ekvletkv\ekvd@set{#1}\ekvd@set{#3}}{}%
    \ekvifdefinedNoVal\ekvd@set{#3}{\ekvletkvNoVal\ekvd@set{#1}\ekvd@set{#3}}{}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{choice}
% \begin{macro}[internal]{\ekvd@type@choice,\ekvd@populate@choice}
%   The real key definition of a |choice| type is pretty simple, the heavy
%   lifting is done by a helper macro at run time. Though setting up the choices
%   needs a bit of work. First the key macro definition.
%    \begin{macrocode}
\protected\def\ekvd@type@choice#1%
  {%
    \ekvd@assert@not@long
    \ekv@expargtwice{\ekvd@prot\def\ekvd@tmp##1}%
      {%
        \expandafter\expandafter\expandafter
        \ekvd@h@choice
        \expandafter\expandafter\expandafter
          {\expandafter\ekvd@choice@name\expandafter{\ekvd@set}{#1}{##1}}%
      }%
    \ekvd@ifalso
      {%
        \ekvd@assert@val{#1}%
        \ekvd@if@not@already@choice{#1}%
          {%
            \ekv@exparg
              {%
                \expandafter\ekvd@add@aux
                  \csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}{#1}%
              }%
              {\ekvd@tmp{##1}}%
              {\ekvd@long\ekvdef}\ekvd@assert@not@long@also
          }%
      }%
      {\ekvlet\ekvd@set{#1}\ekvd@tmp}%
  }
%    \end{macrocode}
%   The set up of different choices is done through another parser, that one
%   needs relatively few types though.
%    \begin{macrocode}
\ekvpNewParser{ekvd@populate@choice}
\ekvpValueAlwaysRequired{ekvd@populate@choice}
\ekvpDefType{ekvd@populate@choice}{protect}
  {\ekvd@populate@choice\protected{#1}{#3}}
\ekvpDefType{ekvd@populate@choice}{unprotect}{\ekvd@populate@choice{}{#1}{#3}}
\ekvpDefNoType{ekvd@populate@choice}         {\ekvd@populate@choice{}{#1}{#3}}
\ekvpLet{ekvd@populate@choice}{type}{protected}{protect}
\ekvpLet{ekvd@populate@choice}{type}{unprotected}{unprotect}
%    \end{macrocode}
%   The choice definition is done by the following little helper:
%    \begin{macrocode}
\protected\long\def\ekvd@populate@choice#1#2#3%
  {%
    #1\expandafter\edef
        \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#2}\endcsname
      {\ekv@unexpanded{#3}}%
  }
%    \end{macrocode}
%   And we define the real type:
%    \begin{macrocode}
\ekvd@def@type{choice}
  {%
    \ekvd@do@new{}{#1}%
    \ekvd@assert@arg
    \ekvd@type@choice{#1}%
    \def\ekvd@set@choice{#1}%
    \ekvpParse@unsafe\ekvp@@p@ekvd@populate@choice{#3}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% 
% \begin{macro}{choice-store,choice-enum}
%   These two types define a special kind of |choice| key and are quite similar,
%   the only difference is what the different choices do (hence they use a
%   shared initialisation which differs in the chosen |populate| step).
%    \begin{macrocode}
\ekvd@def@type@fwd{choice-store}
  {\ekvd@type@choicespecial\ekvd@populate@choicestore}
\ekvd@def@type@fwd{choice-enum}
  {\ekvd@type@choicespecial\ekvd@populate@choiceenum}
%    \end{macrocode}
% \begin{macro}[internal]{\ekvd@type@choicespecial}
%   Initialise similar to a |choice| key. The difference is that we require two
%   arguments (which we assert), a macro to store things in, and a |csv|-list
%   containing the allowed values. |#1| is the |populate| macro according to the
%   type used.
%    \begin{macrocode}
\protected\long\def\ekvd@type@choicespecial#1#2#3%
  {%
    \ekvd@do@new{}{#2}%
    \ekvd@assert@twoargs{#3}%
    \ekvd@type@choice{#2}%
    \def\ekvd@set@choice{#2}%
    #1#3%
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}[internal]
%   {\ekvd@populate@choicestore,\ekvd@populate@choicestore@}
%   We initialise the storing macro if it doesn't yet exist, and then we loop
%   over the value list. The |\edef|s with |\unexpanded| are both necessary to
%   be able to store macro parameter tokens (the outer protects at define time,
%   the inner at use time).
%    \begin{macrocode}
\protected\long\def\ekvd@populate@choicestore#1%
  {%
    \ekvd@newlet#1\ekv@empty
    \ekvparse{\ekvd@populate@choicestore@k#1}{\ekvd@populate@choicestore@kv#1}%
  }
\protected\long\def\ekvd@populate@choicestore@kv#1#2#3%
  {%
    \protected\expandafter\edef
      \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#2}\endcsname
      {\ekv@unexpanded{\edef#1{\ekv@unexpanded{#3}}}}%
  }
\ekv@exparg{\protected\long\def\ekvd@populate@choicestore@k#1#2}%
  {\ekvd@populate@choicestore@kv{#1}{#2}{#2}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}[internal]
%   {\ekvd@populate@choiceenum,\ekvd@populate@choiceenum@}
%   This is similar to the population of a |choice-store| type, but instead of
%   storing the values in a macro this initialises a count and stores the
%   position of the value in the list inside that count (zero-indexed). The
%   space is necessary to terminate the number scanning, which is the reason we
%   use |\@firstofone| (so that the space after the macro name isn't gobbled by
%   \TeX).
%    \begin{macrocode}
\protected\long\def\ekvd@populate@choiceenum#1%
  {%
    \ekvd@newreg#1{count}%
    \def\ekvd@tmp{0}%
    \ekvcsvloop{\ekvd@populate@choiceenum@#1}%
  }
\protected\long\def\ekvd@populate@choiceenum@#1#2%
  {%
    \protected\expandafter\edef
      \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#2}\endcsname
      {#1=\@firstofone{\ekvd@tmp} }%
    \edef\ekvd@tmp{\the\numexpr\ekvd@tmp+1\relax}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{choice-aliases}
% \begin{macro}[internal]{\ekvd@t@choicealias}
%   Choice alias shall copy over separate choices to new names for the same key.
%   The code is pretty straight forward, we just make sure no disallowed
%   prefixes were used, the key exists, is already a choice key, and then we
%   loop through the list of aliases.
%    \begin{macrocode}
\ekvd@def@type{choice-aliases}
  {%
    \ekvd@assert@arg
    \ekvd@assert@not@protected
    \ekvd@assert@not@long
    \ekvd@assert@not@also
    \ekvd@assert@already@choice{#1}%
    \ekvparse\ekvd@err@missing@value{\ekvd@t@choicealias{#1}}{#3}%
  }
%    \end{macrocode}
%   The copying of the definitions is rather straight forward, check if choice
%   of that name exists, and if so copy it. The |new| prefix will apply for each
%   individual new choice, so we need to check this here.
%    \begin{macrocode}
\protected\long\def\ekvd@t@choicealias#1#2#3%
  {%
    \ifx\ekvd@do@new\ekvd@assert@new
      \ekv@fi@firstofone
    \fi
    \@gobble
      {%
        \ekv@ifdefined{\ekvd@choice@name\ekvd@set{#1}{#2}}%
          {\ekvd@err@not@new@choice{#2}\ekv@gobbleto@stop}%
          {}%
      }%
    \ekv@ifdefined{\ekvd@choice@name\ekvd@set{#1}{#3}}%
      {%
        \expandafter\let
          \csname\ekvd@choice@name\ekvd@set{#1}{#2}\expandafter\endcsname
          \csname\ekvd@choice@name\ekvd@set{#1}{#3}\endcsname
      }%
      {\ekvd@err@undefined@choice{#1}{#3}}%
    \@gobble\ekv@stop
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{unknown-choice}
%    \begin{macrocode}
\ekvd@def@type{unknown-choice}
  {%
    \ekvd@do@new@for@name{\ekvd@unknown@choice@name\ekvd@set{#1}}%
    \ekvd@assert@arg
    \ekvd@assert@not@long
    \ekvd@assert@not@also
    \ekvd@prot\expandafter
    \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#3}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{unknown}
% \begin{macro}[internal]{\ekvd@type@unknown@code,\ekvd@type@unknown@noval}
%   The |unknown| type has different subtypes which would be the key names for
%   other types. It is first checked whether that subtype is defined, if it
%   isn't throw an error, else use that subtype.
%    \begin{macrocode}
\ekvd@def@type{unknown}
  {%
    \ekv@ifdefined{ekvd@type@unknown@\detokenize{#1}}%
      {\csname ekvd@type@unknown@\detokenize{#1}\endcsname{#3}}%
      \ekvd@err@misused@unknown
  }
%    \end{macrocode}
%   The |unknown noval| type can use |\ekvdefunknownNoVal| directly (after
%   asserting some prefixes).
%    \begin{macrocode}
\protected\long\def\ekvd@type@unknown@noval#1%
  {%
    \ekvd@do@new@for@name{\ekv@name\ekvd@set{}uN}%
    \ekvd@assert@arg
    \ekvd@assert@not@also
    \ekvd@prot\ekvd@long\ekvdefunknownNoVal\ekvd@set{#1}%
  }
%    \end{macrocode}
%   The |unknown code| type uses some trickery during the definition in order to
%   swap out |#1| and |#2| in the user supplied definition. This is done via a
%   temporary macro that stores the definition but gets the parameter numbers
%   reversed while the real definition is done.
%    \begin{macrocode}
\protected\long\def\ekvd@type@unknown@code#1%
  {%
    \ekvd@do@new@for@name{\ekv@name\ekvd@set{}u}%
    \ekvd@assert@arg
    \ekvd@assert@not@also
    \begingroup
      \def\ekvd@tmp##1##2##3{#1}%
      \ekv@exparg
      {%
        \endgroup
        \ekvd@prot\ekvd@long\ekvdefunknown\ekvd@set
      }%
      {\ekvd@tmp{##2}{##1}{##3}}%
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@type@unknown@redirect,
%     \ekvd@type@unknown@redirect-code,
%     \ekvd@type@unknown@redirect-noval
%   }
%   The |unknown redirect| types also just forward to |\ekvredirectunknown|
%   after asserting some prefixes.
%    \begin{macrocode}
\protected\edef\ekvd@type@unknown@redirect#1%
  {%
    \expandafter\noexpand\csname ekvd@type@unknown@redirect-code\endcsname{#1}%
    \expandafter\noexpand\csname ekvd@type@unknown@redirect-noval\endcsname{#1}%
  }
\protected\expandafter\def\csname ekvd@type@unknown@redirect-code\endcsname#1%
  {%
    \ekvd@do@new@for@name{\ekv@name\ekvd@set{}u}%
    \ekvd@assert@arg
    \ekvd@assert@not@also
    \ekvd@assert@not@protected
    \expandafter\ekvredirectunknown\expandafter{\ekvd@set}{#1}%
  }
\protected\expandafter\def\csname ekvd@type@unknown@redirect-noval\endcsname#1%
  {%
    \ekvd@do@new@for@name{\ekv@name\ekvd@set{}uN}%
    \ekvd@assert@arg
    \ekvd@assert@not@also
    \ekvd@assert@not@protected
    \expandafter\ekvredirectunknownNoVal\expandafter{\ekvd@set}{#1}%
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Key Type Helpers}
% There are some keys that might need helpers during their execution (not during
% their definition, which are gathered as |@type@| macros). These helpers are
% named |@h@|.
%
% \begin{macro}[internal]{\ekvd@h@choice,\ekvd@h@choice@}
% The |choice| helper will just test whether the given choice was defined, if
% not throw an error expandably, else call the macro which stores the code for
% this choice.
%    \begin{macrocode}
\def\ekvd@h@choice#1%
  {%
    \expandafter\ekvd@h@choice@
      \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
      {#1}%
  }
\def\ekvd@h@choice@#1#2%
  {%
    \ifx#1\relax
      \ekvd@err@choice@invalid{#2}%
      \expandafter\@gobble
    \fi
    #1%
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Handling \texttt{also}}
%
% \begin{macro}[internal]
%   {\ekvd@add@val,\ekvd@add@noval,\ekvd@add@aux,\ekvd@add@aux@}
%    \begin{macrocode}
\protected\long\def\ekvd@add@val#1#2#3%
  {%
    \ekvd@assert@val{#1}%
    \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}%
      {#1}{#2}{\ekvd@long\ekvdef}{#3}%
  }
\protected\long\def\ekvd@add@noval#1#2#3%
  {%
    \ekvd@assert@noval{#1}%
    \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}N\endcsname{}%
      {#1}{#2}\ekvdefNoVal{#3}%
  }
\protected\long\def\ekvd@add@aux#1#2%
  {%
    \ekvd@extract@prefixes#1%
    \expandafter\ekvd@add@aux@\expandafter{#1#2}%
  }
%    \end{macrocode}
%   Once we're done with adding something to the definition of a key we need to
%   clear the prefixes. Maybe it would be better to only restore them if they
%   were changed by the |\ekvd@extract@prefixes| mechanism, but I think this is
%   fine with just resetting all (there should be no code dependent on any of
%   the prefix storing macros after this was run).
%    \begin{macrocode}
\protected\long\def\ekvd@add@aux@#1#2#3#4#5%
  {%
    #5%
    \ekvd@prot#4\ekvd@set{#2}{#1#3}%
    \ekvd@clear@prefixes
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@extract@prefixes,\ekvd@extract@prefixes@,
%     \ekvd@extract@prefixes@long,\ekvd@extract@prefixes@prot
%   }
% This macro checks which prefixes were used for the definition of a macro and
% sets |\ekvd@long| and |\ekvd@prot| accordingly.
%    \begin{macrocode}
\protected\def\ekvd@extract@prefixes#1%
  {%
    \expandafter\ekvd@extract@prefixes@\meaning#1\ekvd@stop
  }
%    \end{macrocode}
% In the following definition |#1| will get replaced by |macro:|, |#2| by
% |\long| and |#3| by |\protected| (in each, all tokens will have category
% other). This allows us to parse the |\meaning| of a macro for those strings.
%    \begin{macrocode}
\protected\def\ekvd@extract@prefixes@#1#2#3%
  {%
    \protected\def\ekvd@extract@prefixes@##1#1##2\ekvd@stop
      {%
        \ekvd@extract@prefixes@long
          ##1\ekvd@mark\@firstofone#2\ekvd@mark\@gobble\ekvd@stop
          {\let\ekvd@long\long}%
        \ekvd@extract@prefixes@prot
          ##1\ekvd@mark\@firstofone#3\ekvd@mark\@gobble\ekvd@stop
          {\let\ekvd@prot\protected}%
      }%
    \protected\def\ekvd@extract@prefixes@long##1#2##2\ekvd@mark##3##4\ekvd@stop
      {##3}%
    \protected\def\ekvd@extract@prefixes@prot##1#3##2\ekvd@mark##3##4\ekvd@stop
      {##3}%
  }
%    \end{macrocode}
% We use a temporary macro to expand the three arguments of
% |\ekvd@extract@prefixes@|, which will set up the real meaning of itself and
% the parsing for |\long| and |\protected|.
%    \begin{macrocode}
\begingroup
\edef\ekvd@tmp
  {%
    \endgroup
    \ekvd@extract@prefixes@
      {\detokenize{macro:}}%
      {\string\long}%
      {\string\protected}%
  }
\ekvd@tmp
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Tests}
%
% \begin{macro}[internal]{\ekvd@newlet,\ekvd@newreg}
% These macros test whether a control sequence is defined, if it isn't they
% define it, either via |\let| or via the correct \cs[no-index]{new\meta{reg}}.
%    \begin{macrocode}
\protected\def\ekvd@newlet#1#2%
  {%
    \ifdefined#1%
      \ifx#1\relax\ekv@fi@gobble\fi\@firstofone
      \ekv@fi@gobble
    \fi
    \@firstofone{\let#1#2}%
  }
\protected\def\ekvd@newreg#1#2%
  {%
    \ifdefined#1%
      \ifx#1\relax\ekv@fi@gobble\fi\@firstofone
      \ekv@fi@gobble
    \fi
    \@firstofone{\csname new#2\endcsname#1}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {\ekvd@assert@twoargs,\ekvd@ifnottwoargs,\ekvd@ifempty@gtwo}
% A test for exactly two tokens can be reduced for an empty-test after gobbling
% two tokens, in the case that there are fewer tokens than two in the argument,
% only macros will be gobbled that are needed for the true branch, which doesn't
% hurt, and if there are more this will not be empty.
%    \begin{macrocode}
\long\def\ekvd@assert@twoargs#1%
  {\ekvd@ifnottwoargs{#1}{\ekvd@err@missing@definition\ekvpGobbleT}{}}
\long\def\ekvd@ifnottwoargs#1%
  {%
    \ekvd@ifempty@gtwo#1\ekv@ifempty@B
      \ekv@ifempty@false\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
  }
\long\def\ekvd@ifempty@gtwo#1#2{\ekv@ifempty@\ekv@ifempty@A}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@assert@val,\ekvd@assert@val@,\ekvd@assert@noval,\ekvd@assert@noval@,
%     \ekvd@extract@args,\ekvd@extracted@args,\ekvd@one@arg@string
%   }
% Assert that a given key is defined as a value taking key or a |NoVal| key with
% the correct argument structure, respectively.
%    \begin{macrocode}
\protected\def\ekvd@assert@val#1%
  {%
    \ekvifdefined\ekvd@set{#1}%
      {\expandafter\ekvd@assert@val@\csname\ekv@name\ekvd@set{#1}\endcsname}%
      {%
        \ekvifdefinedNoVal\ekvd@set{#1}%
          \ekvd@err@add@val@on@noval
          {\ekvd@err@undefined@key{#1}}%
        \ekvpGobbleT
      }%
  }
\protected\def\ekvd@assert@val@#1%
  {%
    \expandafter\ekvd@extract@args\meaning#1\ekvd@stop
    \unless\ifx\ekvd@extracted@args\ekvd@one@arg@string
      \ekvd@err@unsupported@arg
      \expandafter\ekvpGobbleT
    \fi
  }%
\protected\def\ekvd@assert@noval#1%
  {%
    \ekvifdefinedNoVal\ekvd@set{#1}%
      {\expandafter\ekvd@assert@noval@\csname\ekv@name\ekvd@set{#1}N\endcsname}%
      {%
        \ekvifdefined\ekvd@set{#1}%
          \ekvd@err@add@noval@on@val
          {\ekvd@err@undefined@key{#1}}%
        \ekvpGobbleT
      }%
  }
\protected\def\ekvd@assert@noval@#1%
  {%
    \expandafter\ekvd@extract@args\meaning#1\ekvd@stop
    \unless\ifx\ekvd@extracted@args\ekv@empty
      \ekvd@err@unsupported@arg
      \expandafter\ekvpGobbleT
    \fi
  }
\protected\def\ekvd@extract@args#1%
  {%
    \protected\def\ekvd@extract@args##1#1##2->##3\ekvd@stop
      {\def\ekvd@extracted@args{##2}}%
  }
\expandafter\ekvd@extract@args\expandafter{\detokenize{macro:}}
\edef\ekvd@one@arg@string{\string#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@assert@arg,\ekvd@ifnoarg}
% The |\ekvd@ifnoarg| macro is initialised as |\@secondoftwo|. Each time a key
% without an argument is encountered it will be set to |\@firstoftwo| for the
% scope of that key's parsing.
%    \begin{macrocode}
\def\ekvd@assert@arg{\ekvd@ifnoarg{\ekvd@err@missing@definition\ekvpGobbleT}{}}
\let\ekvd@ifnoarg\@secondoftwo
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@assert@filledarg,\ekvd@ifnoarg@or@empty}
%    \begin{macrocode}
\long\def\ekvd@assert@filledarg#1%
  {\ekvd@ifnoarg@or@empty{#1}{\ekvd@err@missing@definition\ekvpGobbleT}{}}
\long\def\ekvd@ifnoarg@or@empty#1%
  {%
    \ekvd@ifnoarg
      \@firstoftwo
      {\ekv@ifempty{#1}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@assert@not@long,\ekvd@assert@not@protected,\ekvd@assert@not@also,
%     \ekvd@assert@not@long@also,\ekvd@assert@not@protected@also,
%     \ekvd@assert@new,\ekvd@assert@not@new
%   }
% Some key-types don't want to be |also|, |\long| or |\protected|, so we provide
% macros to test this and throw an error, this could be silently ignored but now
% users will learn to not use unnecessary stuff which slows the compilation
% down.
%    \begin{macrocode}
\def\ekvd@assert@not@long{\ifx\ekvd@long\long\ekvd@err@no@prefix{long}\fi}
\def\ekvd@assert@not@protected
  {\ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi}
\def\ekvd@assert@not@also{\ekvd@ifalso{\ekvd@err@no@prefix{also}}{}}
\def\ekvd@assert@not@long@also
  {\ifx\ekvd@long\long\ekvd@err@no@prefix@also{long}\fi}
\def\ekvd@assert@not@protected@also
  {\ifx\ekvd@prot\protected\ekvd@err@no@prefix@also{protected}\fi}
\def\ekvd@assert@new#1#2%
  {%
    \csname ekvifdefined#1\endcsname\ekvd@set{#2}%
      {\ekvd@err@not@new\ekvpGobbleT}%
      {}%
  }
\def\ekvd@assert@not@new
  {\ifx\ekvd@do@new\ekvd@assert@new\ekvd@err@no@prefix{new}\fi}
\def\ekvd@do@new@for@name#1%
  {%
    \ifx\ekvd@do@new\ekvd@assert@new
      \ekv@fi@firstofone
    \fi
    \@gobble{\ekv@ifdefined{#1}{\ekvd@err@not@new\ekvpGobbleT}{}}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@if@not@already@choice, \ekvd@if@not@already@choice@a,
%     \ekvd@if@not@already@choice@b
%   }
% It is bad to use |also| on a key that already contains a |choice|, as both
% choices would share the same valid values and thus lead to each callback being
% used twice. The following is a rudimentary test against this.
%    \begin{macrocode}
\protected\def\ekvd@if@not@already@choice#1%
  {%
    \ekvifdefined\ekvd@set{#1}%
      {%
        \expandafter
        \ekvd@if@not@already@choice@a
          \csname\ekv@name\ekvd@set{#1}\endcsname
          {}\ekvd@h@choice\ekvd@stop
      }%
      {\@firstofone}%
  }
\protected\def\ekvd@if@not@already@choice@a
  {%
    \expandafter\ekvd@if@not@already@choice@b
  }
\long\protected\def\ekvd@if@not@already@choice@b#1\ekvd@h@choice#2\ekvd@stop
  {%
    \ekv@ifempty{#2}\@firstofone\@gobble
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@assert@already@choice}
%   A small assertion that a key is defined as a choice key. With the test
%   |\ekvd@if@not@already@choice| this becomes pretty easy.
%    \begin{macrocode}
\long\def\ekvd@assert@already@choice#1%
  {\ekvd@if@not@already@choice{#1}{\ekvd@err@not@choice\ekvpGobbleT}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@ifspace,\ekvd@ifspace@}
% Yet another test which can be reduced to an if-empty, this time by gobbling
% everything up to the first space.
%    \begin{macrocode}
\long\def\ekvd@ifspace#1%
  {%
    \ekvd@ifspace@#1 \ekv@ifempty@B
      \ekv@ifempty@false\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
  }
\long\def\ekvd@ifspace@#1 % keep this space
  {%
    \ekv@ifempty@\ekv@ifempty@A
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Messages}
%
% Most messages of \expkvd\ are not expandable, since they only appear during
% key-definition, which is not expandable anyway.
%
% \begin{macro}[internal]
%   {
%     \ekvd@errm,\ekvd@err@missing@definition,
%     \ekvd@err@missing@type,
%     \ekvd@err@undefined@prefix,\ekvd@err@undefined@key,
%     \ekvd@err@undefined@noval,\ekvd@err@undefined@choice,
%     \ekvd@err@no@prefix,\ekvd@err@no@prefix@also,
%     \ekvd@err@add@val@on@noval,\ekvd@err@add@noval@on@val,
%     \ekvd@err@unsupported@arg,\ekvd@err@not@new,\ekvd@err@not@new@choice,
%     \ekvd@err@not@choice,\ekvd@err@missing@value
%   }
% The non-expandable error messages are boring, so here they are:
%    \begin{macrocode}
\protected\long\def\ekvd@errm#1{\errmessage{expkv-def Error: #1}}
\protected\def\ekvd@err@missing@definition
  {\ekvd@errm{Missing definition for key `\ekvd@cur'}}
\protected\def\ekvd@err@missing@type
  {\ekvd@errm{Missing type prefix for key `\ekvd@cur'}}
\protected\def\ekvd@err@undefined@prefix#1%
  {%
    \ekvd@errm
      {%
        Undefined prefix `\ekv@unexpanded{#1}' found while processing
        `\ekvd@cur'%
      }%
  }
\protected\def\ekvd@err@undefined@key#1%
  {%
    \ekvd@errm
      {Undefined key `\ekv@unexpanded{#1}' found while processing `\ekvd@cur'}%
  }
\protected\def\ekvd@err@undefined@noval#1%
  {%
    \ekvd@errm
      {%
        Undefined NoVal key `\ekv@unexpanded{#1}' found while processing
        `\ekvd@cur'%
      }%
  }
\protected\def\ekvd@err@no@prefix#1%
  {\ekvd@errm{prefix `#1' not accepted in `\ekvd@cur'}}
\protected\def\ekvd@err@no@prefix@also#1%
  {\ekvd@errm{`\ekvd@cur' not allowed with a `#1' key}}
\protected\def\ekvd@err@add@val@on@noval
  {\ekvd@errm{`\ekvd@cur' not allowed with a NoVal key}}
\protected\def\ekvd@err@add@noval@on@val
  {\ekvd@errm{`\ekvd@cur' not allowed with a value taking key}}
\protected\def\ekvd@err@unsupported@arg
  {%
    \ekvd@errm
      {%
        Existing key-macro has the unsupported argument string
        `\ekvd@extracted@args' for key `\ekvd@cur'%
      }%
  }
\protected\def\ekvd@err@not@new
  {\ekvd@errm{The key for `\ekvd@cur' is already defined}}
\protected\def\ekvd@err@not@new@choice#1%
  {\ekvd@errm{The choice `\detokenize{#1}' is already defined for `\ekvd@cur'}}
\protected\def\ekvd@err@misused@unknown
  {\ekvd@errm{Misuse of the unknown type found while processing `\ekvd@cur'}}
\protected\long\def\ekvd@err@not@choice
  {\ekvd@errm{The key for `\ekvd@cur' is not an existing choice key}}
\protected\long\def\ekvd@err@missing@value#1%
  {\ekvd@errm{Missing value for `#1' in `\ekvd@cur'}}
\protected\long\def\ekvd@err@undefined@choice#1#2%
  {%
    \ekvd@errm
      {Undefined choice `#2' for key `#1' found while processing `\ekvd@cur'}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]
%   {
%     \ekvd@err@choice@invalid,\ekvd@err@choice@invalid@,\ekvd@choice@name,
%     \ekvd@unknown@choice@name
%   }
% |\ekvd@err@choice@invalid| will have to use this mechanism to throw its
% message. Also we have to retrieve the name parts of the choice in an easy way,
% so we use parentheses of catcode 8 here, which should suffice in most cases to
% allow for a correct separation.
%    \begin{macrocode}
\def\ekvd@err@choice@invalid#1%
  {%
    \ekvd@err@choice@invalid@#1%
  }
\begingroup
\catcode40=8
\catcode41=8
\@firstofone{\endgroup
\def\ekvd@choice@name#1#2#3%
  {%
    ekvd#1(#2)\detokenize{#3}%
  }
\def\ekvd@unknown@choice@name#1#2%
  {%
    ekvd:u:#1(#2)%
  }
\def\ekvd@err@choice@invalid@ ekvd#1(#2)\detokenize#3%
  {%
    \ekv@ifdefined{\ekvd@unknown@choice@name{#1}{#2}}%
      {\csname\ekvd@unknown@choice@name{#1}{#2}\endcsname{#3}}%
      {\ekvd@err{invalid choice `#3' for `#2' in set `#1'}}%
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekvd@err}
% The expandable error messages use |\ekvd@err|, which is just like |\ekv@err|
% from \expkv. It uses a runaway argument to start the error message.
%    \begin{macrocode}
\ekv@exparg{\long\def\ekvd@err#1}{\ekverr{expkv-def}{#1}}
%    \end{macrocode}
% \end{macro}
%
% Now everything that's left is to reset the category code of |@|.
%    \begin{macrocode}
\catcode`\@=\ekvd@tmp
%    \end{macrocode}
%
% \gobbledocstriptag
%</tex>
%^^A=<<

.
