% \iffalse
%% File: l3prop.dtx Copyright (C) 1990-2006 LaTeX3 project
%%
%% It 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
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/cgi-bin/cvsweb.cgi/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<package>\RequirePackage{l3names}
%<*dtx>
%\fi
\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{%
  \def\fileversion{#2}%
  \def\filedate{#3/#4/#5}%
  \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]%
}
%\iffalse
%</dtx>
%\fi
\GetIdInfo$Id: l3prop.dtx 581 2006-12-12 12:28:27Z morten $
          {L3 Experimental Property Lists}
%
% \iffalse
%<*driver>
\documentclass{l3doc}

\begin{document}
\DocInput{l3prop.dtx}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3prop} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Property Lists}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
%
%
% \section{Property lists}
%
%  \LaTeX3 implements a data structure which allows to store information
% associated with individual tokens.
%
% \subsection{Functions}
%
% \begin{function}{%
%                  \prop_new:N |
%                  \prop_new:c |
% }
% \begin{syntax}
%    "\prop_new:N" <plist>
% \end{syntax}
% Defines <plist> to be a variable of type p-list.
% \end{function}
%
% \begin{function}{%
%                  \prop_clear:N |
%                  \prop_gclear:N |
% }
% \begin{syntax}
%   "\prop_clear:N"  <plist>
% \end{syntax}
% These functions locally or globally clear <plist>.
% \end{function}
%
% \begin{function}{%
%                  \prop_put:NNn |
%                  \prop_put:ccn |
%                  \prop_gput:NNn |
%                  \prop_gput:NNo |
%                  \prop_gput:NOo |
%                  \prop_gput:Ncn |
%                  \prop_gput:OOo |
%                  \prop_gput:NOx |
%                  \prop_gput:cNn |
%                  \prop_gput:ccn |
%                  \prop_gput:cco |
%                  \prop_gput:ccx |
% }
% \begin{syntax}
%   "\prop_put:NNn" <plist> <key> "{"<token list>"}"
% \end{syntax}
% Locally or globally associates <token list> with <key> in the p-list
% <plist>. If <key> has already a meaning within <plist> this value is
% overwritten.
% \end{function}
%
% \begin{function}{%
%                  \prop_gput_if_new:NNn |
% }
% \begin{syntax}
%   "\prop_gput_if_new:NNn" <plist> <key> "{"<token list>"}"
% \end{syntax}
%  Globally associates <token list> with <key> in the p-list
% <plist> but only if <key> has so far no meaning within <plist>.
% overwritten.
% \end{function}
%
% \begin{function}{%
%                  \prop_get:NNN |
%                  \prop_get:cNN |
%                  \prop_gget:NNN |
%                  \prop_gget:NcN |
%                  \prop_gget:cNN |
% }
% \begin{syntax}
%    "\prop_get:NNN" <plist> <key> <tlp>
% \end{syntax}
% If <info> is the information associated with <key> in the p-list
% <plist> then the token list pointer <tlp> gets <info> assigned.
% Otherwise its value is the special quark "\q_no_value".
%^^A See section \ref{sec:quarks} to test this.
% The assignment is done either locally or globally.
% \end{function}
%
% \begin{function}{%
%                  \prop_set_eq:NN |
%                  \prop_set_eq:cc |
%                  \prop_gset_eq:NN |
%                  \prop_gset_eq:cc
% }
% \begin{syntax}
%    "\prop_set_eq:NN" <plist 1> <plist 2>
% \end{syntax}
% A fast assignment of <plist>s.
% \end{function}
%
% \begin{function}{%
%                  \prop_get_gdel:NNN |
% }
% \begin{syntax}
%    "\prop_get_gdel:NNN" <plist> <key> <tlp>
% \end{syntax}
% Like "\prop_get:NNN" but additionally removes <key> (and its <info>)
% from <plist>.
% \end{function}
%
% \begin{function}{%
%                  \prop_del:NN |
%                  \prop_gdel:NN |
% }
% \begin{syntax}
%    "\prop_del:NN" <plist> <key>
% \end{syntax}
% Locally or globally deletes <key> and its <info> from <plist> if
% found. Otherwise does nothing.
% \end{function}
%
%
% \begin{function}{\prop_map_function:NN |
%                  \prop_map_function:cN |
%                  \prop_map_function:cc |
% }
% \begin{syntax}
%   "\prop_map_function:NN" <plist> <function>
% \end{syntax}
% Maps <function> which should be a function with two arguments (<key>
% and <info>) over every <key> <info> pair of <plist>. Expandable.
% \end{function}
%
% \begin{function}{\prop_map_inline:Nn |
%                  \prop_map_inline:cn
% }
% \begin{syntax}
%   "\prop_map_inline:Nn" <plist> "{" <inline function> "}"
% \end{syntax}
% Just like "\prop_map_function:NN" but with the function of two arguments
% supplied as inline code. Within <inline function> refer to the
% arguments via "##1" (<key>) and "##2" (<info>). Fast but not
% expandable.
% \end{function}
%
%
%  \begin{function}{%
%                   \prop_map_break:w |
%  }
%  \begin{syntax}
%     "\prop_map_break:w"
%  \end{syntax}
%  For breaking out of a loop. To be used inside "TF" type functions.
%  \end{function}
%
%
%
% \subsection{Predicates and conditionals}
%
% \begin{function}{\prop_if_empty:NTF}
% \begin{syntax}
%   "\prop_if_empty:NTF" <plist> "{"<true code>"}{"<false code>"}"
% \end{syntax}
% Set of conditionals that test whether or not a particular <plist>
% is empty.
% \end{function}
%
% \begin{function}{\prop_if_eq:NNF |
%                  \prop_if_eq:ccF
%                  }
% \begin{syntax}
%   "\prop_if_eq:NNF" <plist1> <plist2> "{"<false code>"}"
% \end{syntax}
% Execute <false code> if <plist1> doesn't hold the same token list as
% <plist2>.
% \end{function}
%
%
% \begin{function}{%
%                  \prop_if_in:NNTF |
%                  \prop_if_in:NOTF |
%                  \prop_if_in:ccTF |
% }
% \begin{syntax}
%   "\prop_if_in:NNTF" <plist><key>"{"<true code>"}{"<false code>"}"
% \end{syntax}
% Tests if <key> is used in <plist> and then either executes <true code>
% or <false code>.
% \end{function}
%
% \subsection{Internal functions}
%
% \begin{function}{%
%                  \prop_put_aux:w |
%                  \prop_put_if_new_aux:w |
% }
% Internal functions implementing the put operations.
% \end{function}
%
% \begin{function}{%
%                  \prop_get_aux:w |
%                  \prop_get_del_aux:w |
%                  \prop_del_aux:w |
% }
% Internal functions implementing the get and delete operations.
% \end{function}
%
% \begin{function}{%
%                  \prop_if_in_aux:w |
% }
% Internal function implementing the key test operation.
% \end{function}
%
% \begin{function}{%
%                  \prop_map_function_aux:NNn |
%                  \prop_map_inline_aux:Nn |
% }
% Internal functions implementing the map operations.
% \end{function}
%
% \begin{function}{%
%                  \l_prop_inline_level_num |
% }
% Fake integer used in internal name for function used inside
% "\prop_map_inline:NN".
% \end{function}
%
% \begin{function}{\prop_split_aux:NNn}
% \begin{syntax}
%   "\prop_split_aux:NNn" <plist> <key> <cmd>
% \end{syntax}
% Internal function that invokes <cmd> with 3 arguments: 1st is the
% beginning of <plist> before <key>, 2nd is the value associated with
% <key>, 3rd is the rest of <plist> after <key>.  If there is no key
% <key> in <plist>, then the 2 arg is "\q_no_value " and the 3rd arg is
% empty; otherwise the 3rd argument has the two extra tokens <prop>
% "\q_no_value" at the end.
%
% This function is used to implement various get operations.
% \end{function}
%
% \StopEventually{}
%
% \subsection {The Implementation}
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<package>\RequirePackage{l3toks}\par
%<*initex|package>
%    \end{macrocode}
%
% A property list is a token register whose contents is
% of the form `\zz{tok$\sb1$}\zv{val$\sb1$} \ldots{}
% \zz{tok$\sb{}n$}\zv{val$\sb{}n$}'. The properties have to be single
% token, the values might be arbitrary token lists they get surrounded
% by braces.
%
% To get values from property-lists, token lists should be passed to
% the appropriate functions.
%
% \begin{macro}{\prop_new:N}
% \begin{macro}{\prop_new:c}
%    Property lists are implemented as token lists.
%    \begin{macrocode}
\def_new:Npn \prop_new:N #1{\toks_new:N #1}
\def_new:Npn \prop_new:c {\exp_args:Nc \prop_new:N}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_clear:N}
% \begin{macro}{\prop_clear:c}
% \begin{macro}{\prop_gclear:N}
% \begin{macro}{\prop_gclear:c}
%    The same goes for clearing a property list, either
%    locally or globally.
%    \begin{macrocode}
\let_new:NN \prop_clear:N \toks_clear:N
\def_new:Npn \prop_clear:c {\exp_args:Nc\prop_clear:N}
\let_new:NN \prop_gclear:N \toks_gclear:N
\def_new:Npn \prop_gclear:c {\exp_args:Nc\prop_gclear:N}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_use:N}
%    The same goes for clearing a property list, either
%    locally or globally.
%    \begin{macrocode}
\let_new:NN \prop_use:N \toks_use:N
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prop_split_aux:NNn}
%   |\prop_split_aux:NNn|\zz{plist}\zz{prop}\zz{cmd} invokes \zz{cmd}
%   with 3 arguments: 1st is the beginning of \zz{plist} before
%   \zz{prop}, 2nd is the value associated with \zz{prop}, 3rd is the
%   rest of \zz{plist} after \zz{prop}.  If there is no property
%   \zz{prop} in \zz{plist}, then the 2nd argument will be |\q_no_value|
%   and the 3rd argument is empty; otherwise the 3rd argument has the two
%   extra tokens \zz{prop} |\q_no_value| at the end.
%    \begin{macrocode}
\def_long_new:Npn \prop_split_aux:NNn #1#2#3{
  \def:Npn \tmp:w ##1#2##2##3\q_stop {#3{##1}{##2}{##3}}
  \exp_after:NN\tmp:w \prop_use:N#1#2\q_no_value \q_stop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prop_get:NNN}
% \begin{macro}{\prop_get:cNN}
% \begin{macro}{\prop_get_aux:w}
%    |\prop_get:NNN |\zz{plist}\zz{prop}\zz{tlp} defines
%    \zz{tlp} to be the value associated with \zz{prop} in \zz{plist},
%    |\q_no_value| if not found.
%    \begin{macrocode}
\def_long_new:NNn \prop_get:NNN 2{
  \prop_split_aux:NNn #1#2\prop_get_aux:w}
\def_long_new:NNn \prop_get_aux:w 4{\toks_set:Nn#4{#2}}
\def_new:Npn \prop_get:cNN { \exp_args:Nc \prop_get:NNN }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_gget:NNN}
% \begin{macro}{\prop_gget:NcN}
% \begin{macro}{\prop_gget:cNN}
% \begin{macro}{\prop_gget_aux:w}
%    The global version of the previous function.
%    \begin{macrocode}
\def_long_new:NNn \prop_gget:NNN 2{
  \prop_split_aux:NNn #1#2\prop_gget_aux:w}
\def_new:Npn \prop_gget:NcN {\exp_args:NNc \prop_gget:NNN}
\def_new:Npn \prop_gget:cNN {\exp_args:Nc \prop_gget:NNN}
\def_long_new:NNn \prop_gget_aux:w 4{\toks_gset:Nn#4{#2}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_get_gdel:NNN}
% \begin{macro}{\prop_get_del_aux:w}
%    |\prop_get_gdel:NNN| is the same as |\prop_get:NNN| but the
%    \m{property_key} and its value are afterwards globally removed
%    from \m{property_list}. One probably also needs the local
%    variants or only the local one, or\ldots\ We decide this later.
%    \begin{macrocode}
\def_long_new:NNn \prop_get_gdel:NNN 3{
  \prop_split_aux:NNn #1#2{\prop_get_del_aux:w #3{\toks_gset:Nn #1}#2}}
\def_long_new:NNn \prop_get_del_aux:w 6{
  \quark_if_no_value:nF{#5} {
    \def:Npn \tmp:w ##1#3\q_no_value {#2{#4##1}}
    \tmp:w #6}
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_put:NNn}
% \begin{macro}{\prop_put:ccn}
% \begin{macro}{\prop_gput:NNn}
% \begin{macro}{\prop_gput:NNo}
% \begin{macro}{\prop_gput:NNx}
% \begin{macro}{\prop_gput:NOx}
% \begin{macro}{\prop_gput:NOo}
% \begin{macro}{\prop_gput:Ncn}
% \begin{macro}{\prop_gput:OOo}
% \begin{macro}{\prop_gput:cNn}
% \begin{macro}{\prop_gput:ccn}
% \begin{macro}{\prop_gput:cco}
% \begin{macro}{\prop_gput:ccx}
% \begin{macro}{\prop_put_aux:w}
%    |\prop_put:NNn |\zz{plist}\zz{prop}\zv{val} adds/changes the
%    value associated with \zz{prop} in \zz{plist} to \zv{val}.
%    \begin{macrocode}
\def_long_new:NNn \prop_put:NNn 2{
  \prop_split_aux:NNn #1#2{
    \toks_clear:N #1
    \prop_put_aux:w {\toks_put_right:Nn #1}#2}
}
\def_new:Npn \prop_put:ccn {\exp_args:Ncc \prop_put:NNn }
\def_long_new:NNn \prop_gput:NNn 2{
  \prop_split_aux:NNn #1#2{
    \toks_gclear:N #1
    \prop_put_aux:w {\toks_gput_right:Nn #1}#2}
}
\def_new:Npn \prop_gput:NNo {\exp_args:NNNo \prop_gput:NNn}
\def_new:Npn \prop_gput:NNx {\exp_args:Nnnx \prop_gput:NNn}
\def_new:Npn \prop_gput:NOx {\exp_args:Nnox \prop_gput:NNn}
\def_new:Npn \prop_gput:NOo {\exp_args:NNOo \prop_gput:NNn}
\def_new:Npn \prop_gput:Ncn {\exp_args:NNc  \prop_gput:NNn }
\def_new:Npn \prop_gput:OOo {\exp_args:NOOo \prop_gput:NNn}
\def_new:Npn \prop_gput:cNn {\exp_args:Nc \prop_gput:NNn}
\def_new:Npn \prop_gput:ccn {\exp_args:Ncc \prop_gput:NNn}
\def_new:Npn \prop_gput:cco {\exp_args:Ncco \prop_gput:NNn}
\def_new:Npn \prop_gput:ccx {\exp_args:Nccx \prop_gput:NNn}
\def_long_new:NNn \prop_put_aux:w 6{
  #1{#2{#6}#3}
  \quark_if_no_value:nF {#4}
  {
    \def:Npn \tmp:w ##1#2\q_no_value {#1{##1}}
    \tmp:w #5
  }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_del:NN}
% \begin{macro}{\prop_gdel:NN}
% \begin{macro}{\prop_del_aux:w}
%    |\prop_del:NN |\zz{plist}\zz{prop} deletes the entry for
%    \zz{prop} in \zz{plist}, if any.
%    \begin{macrocode}
\def_long_new:NNn \prop_del:NN 2{
  \prop_split_aux:NNn #1#2{\prop_del_aux:w {\toks_set:Nn #1}#2}}
\def_long_new:NNn \prop_gdel:NN 2{
  \prop_split_aux:NNn #1#2{\prop_del_aux:w {\toks_gset:Nn #1}#2}}
\def_long_new:NNn \prop_del_aux:w 5{\quark_if_no_value:nF {#4}
%    \end{macrocode}
%    I see no reason for updating the property list if we don't find
%    any entry.
%    \begin{macrocode}
%  {#1{#3}}
   {\def:Npn \tmp:w ##1#2\q_no_value {#1{#3##1}}\tmp:w #5}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\prop_if_in:NNTF}
% \begin{macro}{\prop_if_in:NOTF}
% \begin{macro}{\prop_if_in:ccTF}
% \begin{macro}{\prop_if_in_aux:w}
%    |\prop_if_in:NNTF| \m{property_list} \m{property_key}
%    \m{true_case} \m{false_case} will check whether or not
%    \m{property_key} is on the \m{property_list} and then select
%    either the true or false case.
%    \begin{macrocode}
\def_new:NNn \prop_if_in:NNTF 2{
  \prop_split_aux:NNn #1#2\prop_if_in_aux:w}
\def_new:Npn \prop_if_in:NOTF {\exp_args:Nno \prop_if_in:NNTF}
\def_new:Npn \prop_if_in:ccTF {\exp_args:Ncc \prop_if_in:NNTF}
\def_new:NNn \prop_if_in_aux:w 3{\quark_if_no_value:nFT {#2}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_gput_if_new:NNn}
%    |\prop_gput_if_new:NNn| \m{property_list} \m{property_key}
%    \m{property_value} is equivalent to
%    \begin{tabbing}
%       xxxxx\=xxxxx\= \kill
%       |\prop_if_in:NNTF |\m{property}\m{property_key} \\
%       \> |{}%| \\
%       \> |{\prop_gput:NNn| \\
%       \>\> \m{property_list} \\
%       \>\> \m{property_key} \\
%       \>\> \m{property_value}|}|
%     \end{tabbing}
%    Here we go (listening to Porgy \& Bess in a recording with Ella
%    F. and Louis A. which makes writing macros sometimes difficult; I
%    find myself humming instead of working):
%    \begin{macrocode}
\def_long_new:NNn \prop_gput_if_new:NNn 2{
  \prop_split_aux:NNn #1#2{\prop_put_if_new_aux:w #1#2}}
\def_long_new:NNn \prop_put_if_new_aux:w 6{
  \quark_if_no_value:nT {#4}{#1{#2{#6}#3}}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\prop_set_eq:NN}
% \begin{macro}{\prop_set_eq:Nc}
% \begin{macro}{\prop_set_eq:cN}
% \begin{macro}{\prop_set_eq:cc}
% \begin{macro}{\prop_gset_eq:NN}
% \begin{macro}{\prop_gset_eq:Nc}
% \begin{macro}{\prop_gset_eq:cN}
% \begin{macro}{\prop_gset_eq:cc}
%    This makes two \m{plist}s have the same contents.
%    \begin{macrocode}
\let_new:NN \prop_set_eq:NN  \toks_set_eq:NN
\let_new:NN \prop_set_eq:Nc \toks_set_eq:Nc
\let_new:NN \prop_set_eq:cN  \toks_set_eq:cN
\let_new:NN \prop_set_eq:cc \toks_set_eq:cc
\let_new:NN \prop_gset_eq:NN  \toks_gset_eq:NN
\let_new:NN \prop_gset_eq:Nc \toks_gset_eq:Nc
\let_new:NN \prop_gset_eq:cN  \toks_gset_eq:cN
\let_new:NN \prop_gset_eq:cc \toks_gset_eq:cc
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_if_empty_p:N}
% \begin{macro}{\prop_if_empty_p:c}
% \begin{macro}{\prop_if_empty:NTF}
% \begin{macro}{\prop_if_empty:NT}
% \begin{macro}{\prop_if_empty:NF}
% \begin{macro}{\prop_if_empty:cTF}
% \begin{macro}{\prop_if_empty:cT}
% \begin{macro}{\prop_if_empty:cF}
%    This conditional takes a \m{plist} as its argument and evaluates
%    either the true or the false case, depending on whether or not
%    \m{plist} contains any properties.
%    \begin{macrocode}
\let_new:NN \prop_if_empty_p:N \toks_if_empty_p:N
\let_new:NN \prop_if_empty_p:c \toks_if_empty_p:c
\let_new:NN \prop_if_empty:NTF \toks_if_empty:NTF
\let_new:NN \prop_if_empty:NT  \toks_if_empty:NT
\let_new:NN \prop_if_empty:NF  \toks_if_empty:NF
\let_new:NN \prop_if_empty:cTF \toks_if_empty:cTF
\let_new:NN \prop_if_empty:cT  \toks_if_empty:cTF
\let_new:NN \prop_if_empty:cF  \toks_if_empty:cF
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\prop_if_eq:NNTF}
% \begin{macro}{\prop_if_eq:NNT}
% \begin{macro}{\prop_if_eq:NNF}
% \begin{macro}{\prop_if_eq:NcTF}
% \begin{macro}{\prop_if_eq:NcT}
% \begin{macro}{\prop_if_eq:NcF}
% \begin{macro}{\prop_if_eq:cNTF}
% \begin{macro}{\prop_if_eq:cNT}
% \begin{macro}{\prop_if_eq:cNF}
% \begin{macro}{\prop_if_eq:ccTF}
% \begin{macro}{\prop_if_eq:ccT}
% \begin{macro}{\prop_if_eq:ccF}
%    This function test whether the property lists that are in its first
%    two arguments are equal; if they are not |#3| is executed.
%    \begin{macrocode}
\def_new:NNn \prop_if_eq:NNTF 2 {
  \tlist_if_eq:xxTF{\prop_use:N #1}{\prop_use:N #2}
}
\def_new:NNn \prop_if_eq:NNT 2 {
  \tlist_if_eq:xxT{\prop_use:N #1}{\prop_use:N #2}
}
\def_new:NNn \prop_if_eq:NNF 2 {
  \tlist_if_eq:xxF{\prop_use:N #1}{\prop_use:N #2}
}
\def_new:Npn \prop_if_eq:NcTF {\exp_args:NNc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:NcT {\exp_args:NNc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:NcF {\exp_args:NNc \prop_if_eq:NNF}
\def_new:Npn \prop_if_eq:cNTF {\exp_args:Nc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:cNT {\exp_args:Nc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:cNF {\exp_args:Nc \prop_if_eq:NNF}
\def_new:Npn \prop_if_eq:ccTF {\exp_args:Ncc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:ccT {\exp_args:Ncc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:ccF {\exp_args:Ncc \prop_if_eq:NNF}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_map_function:NN}
% \begin{macro}{\prop_map_function:cN}
% \begin{macro}{\prop_map_function:cc}
% \begin{macro}{\prop_map_function_aux:NNn}
%    Maps a function on every entry in the property list.  The
%    function must take 2 arguments: a key and a value.
%    \begin{macrocode}
\def_new:Npn \prop_map_function:NN #1#2{
    \exp_after:NN \prop_map_function_aux:NNn
    \exp_after:NN #2 \prop_use:N #1 \q_nil \q_no_value \q_stop
}
\def_new:Npn \prop_map_function_aux:NNn #1#2#3{
  \if_meaning:NN \q_nil #1
    \exp_after:NN \prop_map_break:w
  \fi:
  #1#2{#3}
  \prop_map_function_aux:NNn #1
}
\def_new:Npn \prop_map_function:cN {\exp_args:Nc \prop_map_function:NN }
\def_new:Npn \prop_map_function:cc {\exp_args:Ncc \prop_map_function:NN}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\prop_map_inline:Nn}
%  \begin{macro}{\prop_map_inline:cn}
%  \begin{macro}{\prop_map_inline_aux:Nn}
%  \begin{macro}{\l_prop_inline_level_num}
%  The inline functions are straight forward. It takes longer
%  to test if the list is empty than to run it on an empty list so
%  we don't waste time doing that.
%    \begin{macrocode}
\num_new:N \l_prop_inline_level_num
\def_new:Npn \prop_map_inline:Nn #1#2 {
  \num_incr:N \l_prop_inline_level_num
  \def_long:cpn {prop_map_inline_ \num_use:N \l_prop_inline_level_num :n} 
    ##1##2{#2}
  \exp_args:NcE \prop_map_function:N
    {prop_map_inline_ \num_use:N \l_prop_inline_level_num :n} 
    \prop_use:N #1 
  \q_nil \q_no_value \q_stop
  \num_decr:N \l_prop_inline_level_num
}
\def_new:Npn \prop_map_inline:cN { \exp_args:Nc \prop_map_inline:NN }

%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\prop_map_break:w}
%  The break statement.
%    \begin{macrocode}
\let_new:NN \prop_map_break:w \use_none_delimit_by_q_stop:w
%    \end{macrocode}
%  \end{macro}
%
%    Show token usage:
%    \begin{macrocode}
%</initex|package>
%<*showmemory>
%\showMemUsage
%</showmemory>
%    \end{macrocode}
%
%
%
%    \begin{macrocode}
%<*unused>
\file_input_stop:
%    \end{macrocode}
%
%
% \section {Properties}
%
%
% This is the version that uses individual pointers to hold the values.
% maybe we need both?
% It is currently disabled because it does not work with the
% implementation of the mark mechanism.
%
% A property list is a control sequence whose top_level expansion is
% of the form `\zz{tok$\sb1$}\zv{val$\sb1$} \ldots{}
% \zz{tok$\sb{}n$}\zv{val$\sb{}n$}'. The properties have to be single token,
% the values might be arbitrary token lists they get surrounded by
% braces.
%
% To get values from property_lists token_lists should be passed to
% the appropriate functions.
%
%
% \begin{macro}{\prop_split_aux:NNn}
%    |\prop_split_aux:NNn|\zz{plist}\zz{prop}\zz{cmd} invokes \zz{cmd}
%    with 3 arguments: 1st is the beginning of \zz{plist} before
%    \zz{prop}, 2nd is the value associated with \zz{prop}, 3rd is the
%    rest of \zz{plist} after \zz{prop}.  If there is no property
%    \zz{prop} in \zz{plist}, then the 2 arg is |\q_no_value | and
%    the 3rd arg is empty; otherwise the 3rd argument has the two
%    extra tokens \zz{prop} |\q_no_value| at the end.
%    \begin{macrocode}
\def_long:Npn \prop_split_aux:NNn #1#2#3{
  \def:Npn \tmp:w ##1#2##2##3\q_stop {#3{##1}##2{##3}}
  \exp_after:NN\tmp:w #1#2\q_no_value \q_stop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prop_get:NNN}
% \begin{macro}{\prop_get_aux:w}
%    |\prop_get:NNN |\zz{plist}\zz{prop}\zz{tlp} defines
%    command to be the value associated with \zz{prop} in \zz{plist},
%    |\q_no_value| if not found.
%    \begin{macrocode}
\def_long:Npn \prop_get:NNN #1#2{\prop_split_aux:NNn
                                    #1#2\prop_get_aux:w}
\def_long:Npn \prop_get_aux:w #1#2#3#4{\tlp_set_eq:NN#4#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\prop_put:NNn}
% \begin{macro}{\prop_put_aux:w}
% \begin{macro}{\prop_gput:NNn}
% \begin{macro}{\prop_gput:NNx}
% \begin{macro}{\prop_gput:NNo}
% \begin{macro}{\prop_gput:NOx}
% \begin{macro}{\prop_gput:NOo}
% \begin{macro}{\prop_gput:OOo}
% \begin{macro}{\prop_gput:ccx}
%    |\prop_put:NNn |\zz{plist}\zz{prop}\zv{val} adds/changes the
%    value associated with \zz{prop} in \zz{plist} to \zv{val}.
%    \begin{macrocode}
\def_long:Npn \prop_put:NNn #1#2{\prop_split_aux:NNn
                                #1#2{\prop_put_aux:w \tlp_set:Nn #1#2}}
\def_long:Npn \prop_gput:NNn #1#2{\prop_split_aux:NNn
                                #1#2{\prop_put_aux:w \tlp_gset:Nn #1#2}}
\def:Npn \prop_gput:NNo {\exp_args:Nnno \prop_gput:NNn}
\def:Npn \prop_gput:NOx {\exp_args:Nnox \prop_gput:NNn}
\def:Npn \prop_gput:NNx {\exp_args:Nnnx \prop_gput:NNn}
\def:Npn \prop_gput:NOo {\exp_args:NNOo \prop_gput:NNn}
\def:Npn \prop_gput:OOo {\exp_args:NOOo \prop_gput:NNn}
\def:Npn \prop_gput:ccn {\exp_args:Ncc \prop_gput:NNn}
\def:Npn \prop_gput:ccx {\exp_args:Nccx \prop_gput:NNn}
\def_long:Npn \prop_put_aux:w #1#2#3#4#5#6#7{
  \quark_if_no_value:nTF#5
    {
     \cs_ggen_sym:N\l_testa_tlp
     \exp_after:NN#1\exp_after:NN#2\exp_after:NN{\exp_after:NN#3\l_testa_tlp#4}
     \exp_after:NN\tlp_gset:Nn\l_testa_tlp
    }
    {#1#5}
  {#7}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
%    Show token usage:
%    \begin{macrocode}
%<*showmemory>
%\showMemUsage
%</showmemory>
%</unused>
%    \end{macrocode}
%
% \endinput
%
% $Log$
% Revision 1.15  2006/03/20 18:26:38  braams
% Updated the copyright notice (2006) and demoted all implementation
% sections to subsections and so on to clean up the toc for source3.tex
%
% Revision 1.14  2005/12/27 16:00:44  morten
% Update map functions and changed RCS information retrieval
%
% Revision 1.13  2005/03/22 23:26:14  morten
% Added more functions, removed dependency of l3seq
%
% Revision 1.12  2005/03/16 22:36:04  braams
% Added the tweaks necessary to be able to load with initex
%
% Revision 1.11  2005/03/11 21:40:35  braams
% Fixed the use of RCS information; added \StopEventually
%
