% \iffalse
%% File: l3prop.dtx Copyright (C) 1990-1998 LaTeX3 project
%
%<*dtx>
          \ProvidesFile{l3prop.dtx}
%</dtx>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{l3prop}
%<driver> \ProvidesFile{l3prop.drv}
% \fi
%         \ProvidesFile{l3prop.dtx}
          [1998/05/04 v1.0e L3 Experimental Property Lists]
%
% \iffalse
%<*driver>
\documentclass{l3doc}

\begin{document}
\DocInput{l3prop.dtx}
\end{document}
%</driver>
% \fi
%
%
% \GetFileInfo{l3prop.dtx}
% \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:O |
% }
% \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_gput:NNn |
%                  \prop_gput:NNo |
%                  \prop_gput:NOo |
%                  \prop_gput:OOo |
%                  \prop_gput:NOx |
%                  \prop_gput:ccn |
%                  \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_gget:NNN |
% }
% \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
% }
% \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:NN |
%                  \prop_map:cN
% }
% \begin{syntax}
%   "\prop_map: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>.
% \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: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>).
% 
% Not implemented so far!
% \end{function}
% 
% \subsection{Predicates and conditionals}
% 
% \begin{function}{\prop_empty:NTF}
% \begin{syntax}
%   "\prop_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_in:NNTF |
%                  \prop_if_in:NOTF |
% }
% \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_aux:w |
% }
% Internal function implementing the map operation.
% \end{function}
% 
% \begin{function}{%
%                  \prop_map_funct:Nn |
% }
% Internal name for the function that is mapped over p-list during
% execution of "\prop_map: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}
% 
% 
% \section {Implementation}
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<package>\RequirePackage{l3seq}\par
%<*package>
%    \end{macrocode}
%    
% 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_new:N}
% \begin{macro}{\prop_new:O}
% \begin{macro}{\prop_new:c}
%    Property lists are a special case of sequences, so allocating
%    them is the same as allocating sequences.
%    \begin{macrocode}
\let_new:NN \prop_new:N \seq_new:N
\let_new:NN \prop_new:O \seq_new:O
\let_new:NN \prop_new:c \seq_new:c
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_clear:N}
% \begin{macro}{\prop_gclear:N}
%    The same goes for clearing a property list, either
%    locally or globally.
%    \begin{macrocode}
\let_new:NN \prop_clear:N \seq_clear:N
\let_new:NN \prop_gclear:N \seq_gclear:N
%    \end{macrocode}
% \end{macro}
% \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 #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
%    \zz{tlp} to be the value associated with \zz{prop} in \zz{plist},
%    |\q_no_value| if not found.
%    \begin{macrocode}
\def_long_new:Npn \prop_get:NNN #1#2{\prop_split_aux:NNn
                                    #1#2\prop_get_aux:w}
\def_long_new:Npn \prop_get_aux:w #1#2#3#4{\tlp_set:Nn#4{#2}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_gget:NNN}
% \begin{macro}{\prop_gget_aux:w}
%    The global version of the previous function.
%    \begin{macrocode}
\def_long_new:Npn \prop_gget:NNN #1#2{\prop_split_aux:NNn
                                    #1#2\prop_gget_aux:w}
\def_long_new:Npn \prop_gget_aux:w #1#2#3#4{\tlp_gset:Nn#4{#2}}
%    \end{macrocode}
% \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:Npn \prop_get_gdel:NNN #1#2#3{\prop_split_aux:NNn
            #1#2{\prop_get_del_aux:w #3{\tlp_gset:Nn #1}#2}}
\def_long_new:Npn \prop_get_del_aux:w #1#2#3#4#5#6{
  \tlp_set:Nn #1{#5}
  \quark_if_no_value:NF#1
    {\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_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_new:Npn \prop_put:NNn #1#2{\prop_split_aux:NNn
                                #1#2{\prop_put_aux:w {\tlp_set:Nn #1}#2}}
\def_long_new:Npn \prop_gput:NNn #1#2{\prop_split_aux:NNn
                                #1#2{\prop_put_aux:w {\tlp_gset:Nn #1}#2}}
\def_new:Npn \prop_gput:NNo {\exp_args:NNNo \prop_gput:NNn}
\def_new:Npn \prop_gput:NOx {\exp_args:Nnox \prop_gput:NNn}
\def_new:Npn \prop_gput:NNx {\exp_args:Nnnx \prop_gput:NNn}
\def_new:Npn \prop_gput:NOo {\exp_args:NNOo \prop_gput:NNn}
\def_new:Npn \prop_gput:OOo {\exp_args:NOOo \prop_gput:NNn}
\def_new:Npn \prop_gput:ccn {\exp_args:Ncc \prop_gput:NNn}
\def_new:Npn \prop_gput:ccx {\exp_args:Nccx \prop_gput:NNn}
\def_long_new:Npn \prop_put_aux:w #1#2#3#4#5#6{
  \quark_if_no_value:nTF {#4}
    {#1{#2{#6}#3}}
    {\def:Npn \tmp:w ##1#2\q_no_value {#1{#3#2{#6}##1}}
     \tmp:w #5}}
%    \end{macrocode}
% \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:Npn \prop_del:NN #1#2{\prop_split_aux:NNn
                                #1#2{\prop_del_aux:w {\tlp_set:Nn #1}#2}}
\def_long_new:Npn \prop_gdel:NN #1#2{\prop_split_aux:NNn
                                #1#2{\prop_del_aux:w {\tlp_gset:Nn #1}#2}}
\def_long_new:Npn \prop_del_aux:w #1#2#3#4#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_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:Npn \prop_if_in:NNTF #1#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_aux:w #1#2#3{\quark_if_no_value:nTF {#2}}
%    \end{macrocode}
% \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:Npn \prop_gput_if_new:NNn #1#2{\prop_split_aux:NNn #1#2
        {\prop_put_if_new_aux:w #1#2}}
\def_long_new:Npn \prop_put_if_new_aux:w #1#2#3#4#5#6{
  \quark_if_no_value:nT {#4}{#1{#2{#6}#3}}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\prop_set_eq:NN}
%    This makes two \m{plist}s have the same contents.
%    \begin{macrocode}
\let_new:NN\prop_set_eq:NN\tlp_set_eq:NN
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prop_empty:NTF}
%    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_empty:NTF \tlp_empty:NTF
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\prop_map:NN}
% \begin{macro}{\prop_map:cN}
% \begin{macro}{\prop_map_funct:Nn}
%    Maps a function on every entry in the property list.  The
%    function must take 2 arguments: a key and a value.
%    \begin{macrocode}
\let_new:NN \prop_map_funct:Nn \use_none:nn
\def_new:Npn \prop_map:NN #1#2{
  \let:NN \prop_map_funct:Nn #2
  \exp_after:NN\prop_map_aux:w #1\q_stop \q_stop}
\def_new:Npn \prop_map_aux:w #1#2{
  \if_meaning:NN#1\q_stop \else:
    \prop_map_funct:Nn #1{#2}
    \exp_after:NN\prop_map_aux:w
  \fi:}
\def_new:Npn \prop_map:cN { \exp_args:Nc \prop_map:NN }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%  \begin{macro}{\prop_map_inline:Nn}
%  \begin{macro}{\prop_map_inline:cn}
%    To be supplied.
%    \begin{macrocode}
\let_new:NN \prop_map_inline:Nn \ERROR
\let_new:NN \prop_map_inline:cn \ERROR
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%    Show token usage:
%    \begin{macrocode}
%</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}
%

