%D \module
%D   [       file=mult-aux,
%D        version=2010.08.2,
%D          title=\CONTEXT\ Multilingual Macros,
%D       subtitle=Helpers,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D A generalization of \MKIV-like inheritance. Just something to play with
%D (interface might change). The code here evolved in an email exchange between me
%D and Wolgang Schuster.

%D We use constant definitions here because we don't need to expand the keywords
%D which saves a little on the stack (read: memory access). The gain in performance
%D is normally not noticeable unless one has plenty of parameter checking, which
%D can happen in some scenarios. Even then the gain is only there when one has
%D thousands of runs on e.g. virtual platforms.

\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}

\registerctxluafile{mult-aux}{}

\unprotect

\permanent\cdef\??empty{\tocharacter25}

\permanent\letcsname\tocharacter25\endcsname\empty % hex 19

% \edef\s!parent{\tocharacter29} % inlining  is ugly, a tiny bit faster, but neglectable on a run

%D \starttyping
%D \unprotect
%D     \def\????aa{@@@@aa}
%D
%D     \installparameterhandler   \????aa {whatever}
%D     \installsetuphandler       \????aa {whatever}
%D     \installdefinehandler      \????aa {whatever} \????aa % #3 == defaultroot
%D     \installfontandcolorhandler\????aa {whatever}
%D
%D   % \installcommandhandler     \????aa {whatever} \????aa
%D \protect
%D
%D % \whateverparameter \c!test
%D % \whateverparameterhash \c!test
%D % \namedwhateverparameter \mycurrentwhatever \c!test
%D % \usewhateverstyleandcolor \c!style \c!color
%D % \everydefinewhatever (sets \currentwhatever)
%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
%D % \everysetupwhatever (sets \currentwhatever)
%D
%D \starttext
%D     \definewhatever[first] \definewhatever[second][first]
%D                                           test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D     \setupwhatever        [method=unset]  test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D     \setupwhatever[first] [method=first]  test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D                                           test: \def\currentwhatever{second} \whateverparameter{method} \par
%D     \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par
%D \stoptext
%D \stoptyping

% problem: every* could clash
%
% There can be less {} in the following definitions if we assume \??aa and \c!somecs
%
% watch the push/pop and predefinition of current .. this is needed for nested
% definitions and overloaded defines using the predefined one

% todo: add (relaxed) postsetup and postdefine hooks, just after the everys

%D Start of experimental code: especially tables can have many assignments and
%D although most time is spent in the typesetting anyway, we can squeeze out a
%D little bit. Of course having 500 rows of 50 columns each with some setting does
%D not happen that often. One should keep in mind that in the average document
%D having some 500 assignments is no exception but there we're talking of
%D neglectable runtime for them. Of course in the definitions below there is no real
%D gain, only in the generated \setup* commands. Another situation with many
%D assignments is \XML\ where we can pass attributes and normally don't do testing
%D of them making sense.
%
% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s

% KEEP THIS:
%
% \lettonothing\m_mult_interfaces_namespace
%
% \def\mult_interfaces_get_parameters#1[#2%
%   {\if\noexpand#2]%
%      \expandafter\gobbleoneargument
%    \else
%      \def\m_mult_interfaces_namespace{#1}%
%      \expandafter\mult_interfaces_get_parameters_indeed
%    \fi#2}
%
% \def\mult_interfaces_get_parameters_indeed#1]% namespace already set
%   {\mult_interfaces_get_parameters_item#1,],^^^^0004}
%
% \def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
%   {\if,#1,% dirty trick for testing #1=empty
%      \expandafter\mult_interfaces_get_parameters_item
%    \orelse\if]#1%
%      \expandafter\gobbleoneargument
%    \else
%      \mult_interfaces_get_parameters_assign#1==\empty^^^^0004%
%    % \expandafter\mult_interfaces_get_parameters_item % saves skipping when at end
%    \fi#2}
%
% \def\mult_interfaces_get_parameters_error#1#2% #3%
%   {\mult_interfaces_get_parameters_error_indeed{#1}{#2}%
%    \gobbleoneargument}
%
% \def\mult_interfaces_get_parameters_error_indeed#1#2%
%   {\showassignerror{#2}{\the\inputlineno\space(#1)}}
%
% \def\mult_interfaces_get_parameters_assign#1=#2=#3#0^^^^0004%
%   {\ifx\empty#1\empty
%      \expandafter\mult_interfaces_get_parameters_error
%    \orelse\ifx#3\empty
%      \expandafter\mult_interfaces_get_parameters_error
%    \else
%      \expandafter\mult_interfaces_adef % assignment def
%    \fi
%    \m_mult_interfaces_namespace{#1}{#2}%
%    \doubleexpandafter\mult_interfaces_get_parameters_item}
%
% \startinterface english
%
%     % some 10% faster
%
%     \let\mult_interfaces_get_parameters_error\undefined
%
%     \def\mult_interfaces_get_parameters_error_one#0\csname#2#3\endcsname#0%
%       {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue}
%
%     \def\mult_interfaces_get_parameters_error_two#0\csname#2#3\endcsname#0%
%       {\mult_interfaces_get_parameters_error_indeed{#2}{#3}}
%
%     \def\mult_interfaces_get_parameters_assign#1=#2=#3#0^^^^0004%
%       {\ifx\empty#1\empty
%          \mult_interfaces_get_parameters_error_one
%        \orelse\ifx#3\empty
%          \mult_interfaces_get_parameters_error_two
%        \else
%          \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
%        \fi
%        \doubleexpandafter\mult_interfaces_get_parameters_item}
%
% \stopinterface
%
% \newif\ifassignment
%
% \def\mult_check_for_assignment_indeed#0=#2#0^^^^0004%
%   {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi}
%
% \def\mult_check_for_assignment_indeed_begin_#0=#2#0^^^^0004%
%   {\if#2^^^^0003}
%
% \def\mult_check_for_assignment#1%
%   {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004}
%
% % End of experimental code.

%D We keep the above as reference, but from now on experiment with the following
%D implementation. In principle this one is faster, but because normally we don't
%D have that many assignments it doesn't get noticed. For instance, the \LUAMETATEX\
%D manual does less than 6000 assignments and the payoff starts around a tenfold of
%D that. But \unknown\ it's less tracing, so that's another benefit.

%D Watch out: we accept that a \[k=v,,k=v] will generate a case where a key can become
%D a comma and trigger a warning but we intercept that elsewhere. The alternative is
%D to skip to the comma first which takes more time.

\lettonothing\m_mult_interfaces_namespace

% \def\mult_interfaces_get_parameters#1[%
%   {\def\m_mult_interfaces_namespace{#1}%
%    \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed}
%
% \def\mult_interfaces_get_parameters_indeed#1]%
%   {\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments}
%
% \def\mult_interfaces_get_parameters_item#*#1,%
%   {\ifarguments
%    \else
%      \mult_interfaces_get_parameters_item_okay#1,\ignorearguments
%      \expandafter\mult_interfaces_get_parameters_item
%    \fi}
%
% \def\mult_interfaces_get_parameters_item_okay#1=#2,%
%   {\ifarguments
%      % done
%    \or
%      \mult_interfaces_get_parameters_item_error
%    \else
%      \mult_interfaces_adef\m_mult_interfaces_namespace{#1}{#2}%
%    \fi}
%
% \def\mult_interfaces_get_parameters_item_error#-#-#-#1#2%
%   {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi}
%
% \startinterface english
%
%     \def\mult_interfaces_get_parameters_item_okay#1=#2,%
%       {\ifarguments
%          % done
%        \or
%          \mult_interfaces_get_parameters_item_error
%        \else
%          \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
%        \fi}
%
%     \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-%
%       {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi}
%
% \stopinterface

% cheap with no checking
%
% \def\mult_interfaces_get_parameters#1[#S#2]%
%   {\cdef\m_mult_interfaces_namespace{#1}%
%    \mult_interfaces_get_parameters_item_okay#2\ignorearguments\ignorearguments}
%
% \tolerant\def\mult_interfaces_get_parameters_item_okay#*#1=#S#2,#M,%
%   {\ifparameter#2\or
%      \ifcsname\k!prefix!#1\endcsname
%        \defcsname\m_mult_interfaces_namespace\lastnamedcs\endcsname{#2}%
%      \else
%        \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
%      \fi
%    \orelse\ifparameter#1\or
%      \ifcsname\k!prefix!#1\endcsname
%        \letcsname\m_mult_interfaces_namespace\lastnamedcs\endcsname\empty
%      \else
%        \letcsname\m_mult_interfaces_namespace#1\endcsname\empty
%      \fi
%    \else
%      \expandafter\gobbleoneargument
%    \fi
%    \mult_interfaces_get_parameters_item_okay}
%
% \startinterface english
%
%    \tolerant\def\mult_interfaces_get_parameters_item_okay#*#1=#S#2,#M,%
%      {\ifparameter#2\or
%         % k=v
%         \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
%       \orelse\ifparameter#1\or
%         % k=
%         \letcsname\m_mult_interfaces_namespace#1\endcsname\empty
%       \else
%         \expandafter\gobbleoneargument
%       \fi
%       \mult_interfaces_get_parameters_item_okay}
%
% \stopinterface

%D Still not nice

% \def\mult_interfaces_get_parameters#1[%
%   {\cdef\m_mult_interfaces_namespace{#1}%
%    \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed}
%
% \def\mult_interfaces_get_parameters_indeed#S#1]%
%   {\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments}

\def\mult_interfaces_get_parameters#1[#S#2]%
  {\cdef\m_mult_interfaces_namespace{#1}%
   \mult_interfaces_get_parameters_item#2\ignorearguments\ignorearguments}

% \def\mult_interfaces_get_parameters_item#*#S#1,%
%   {\ifarguments
%    \else
%      \mult_interfaces_get_parameters_item_okay#1,\ignorearguments
%      \expandafter\mult_interfaces_get_parameters_item
%    \fi}

\def\mult_interfaces_get_parameters_item#*#S#1,%
  {\ifarguments
     \expandafter\gobbleoneargument
   \else
     \mult_interfaces_get_parameters_item_okay#1,\ignorearguments
   \fi
   \mult_interfaces_get_parameters_item}

% \tolerant\def\mult_interfaces_get_parameters_item_okay#1=#S#2,%
%   {\ifarguments
%      % done
%    \or
%      \mult_interfaces_get_parameters_item_error
%    \else
%      \mult_interfaces_adef\m_mult_interfaces_namespace{#1}{#2}%
%    \fi}

% \tolerant\def\mult_interfaces_get_parameters_item_okay#1=#S#2,%
%   {\ifarguments
%      % done
%    \or
%      \mult_interfaces_get_parameters_item_error{#1}%
%    \orelse\ifcsname\k!prefix!#1\endcsname
%      \defcsname\m_mult_interfaces_namespace\lastnamedcs\endcsname{#2}%
%    \else
%      \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
%    \fi}

\tolerant\def\mult_interfaces_get_parameters_item_okay#1=#S#2,%
  {\ifarguments
     % done
   \or
     \mult_interfaces_get_parameters_item_error{#1}%
   \or
     \defcsname
       \m_mult_interfaces_namespace
       \ifcsname\k!prefix!#1\endcsname\lastnamedcs\else#1\fi
     \endcsname{#2}%
   \fi}

\def\mult_interfaces_get_parameters_item_error#1%
  {\if,#1\else\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#1}\fi}

\startinterface english

    \def\mult_interfaces_get_parameters_item_okay#1=#S#2,%
      {\ifarguments
         % done
       \or
         \mult_interfaces_get_parameters_item_error{#1}%
       % \mult_interfaces_get_parameters_item_error
       % \if,#1\else\mult_interfaces_get_parameters_item_error\fi
       \else
         \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
       \fi}

  % \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-%
  %   {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi}

  % \def\mult_interfaces_get_parameters_item_error#-\defcsname#-#1\endcsname#-%
  %   {\if,#1\else\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#1}\fi}

    \def\mult_interfaces_get_parameters_item_error#1%
      {\if,#1\else\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#1}\fi}

  % \def\mult_interfaces_get_parameters_item_error
  %    {\mult_interfaces_get_parameters_error_indeed
  %       {\m_mult_interfaces_namespace}
  %       {\expandparameter\plusthree}}

\stopinterface

% % No longer used:
%
% \def\mult_check_for_assignment_indeed#-=#1#-^^^^0004%
%   {\if#1^^^^0003\assignmentfalse\else\assignmenttrue\fi}
%
% \def\mult_check_for_assignment_indeed_begin_#-=#1#-^^^^0004%
%   {\if#1^^^^0003}
%
% \def\mult_check_for_assignment#1%
%   {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004}

%D Beware, zero arguments is an assignment!

\def\mult_aux_no_assignment_indeed#1=#2]{\ifcase\ifarguments\plusone\or\zerocount\else\plusone\fi}
\def\mult_aux_no_assignment#1]{\mult_aux_no_assignment_indeed#1\ignorearguments\relax}

%D This can give wrong results when we pass e.g. \type{\c!format}, so either we need
%D to use the \type {\k!} ones, but these are not defined in the english interface
%D so from now on we assume that the low level ones are used with the symbolic names
%D and that only the high level setup commands are used with language specific
%D interfaces.

% \startinterface english
    \protected\def\mult_interfaces_let #1#2{\letcsname#1#2\endcsname}
    \protected\def\mult_interfaces_lete#1#2{\letcsname#1#2\endcsname\empty}
    \protected\def\mult_interfaces_def #1#2{\defcsname#1#2\endcsname}
    \protected\def\mult_interfaces_edef#1#2{\edefcsname#1#2\endcsname}
    \protected\def\mult_interfaces_gdef#1#2{\gdefcsname#1#2\endcsname}
    \protected\def\mult_interfaces_xdef#1#2{\xdefcsname#1#2\endcsname}
% \stopinterface

%D Do, we only interface the assignment definition:

\protected\def\mult_interfaces_adef#1#2{\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
%protected\def\mult_interfaces_adef#1#2{\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\csnamestring\endcsname\else#2\fi\endcsname}

\startinterface english
    \protected\def\mult_interfaces_adef#1#2{\defcsname#1#2\endcsname}
\stopinterface

% the commented detokenized variant that backtracks ... needs testing usage first
%
% \let\whatever\relax
%
% \definetest[oeps][bagger=\whatever]
%
% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
%
% slower: \def#3##1{\csname\ifcsname#1#2:##1\endcsname\expandafter\csstring\lastnamedcs\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%

%D pre-expansion can be a bit faster but handly any effect on a normal run so let's
%D go for saving some memory.

%def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}

% \protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9%
%   {\frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
%    \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
%    \frozen\edef#5##1##2{\noexpand\ifrelax##1\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ?
%    \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
%   %\frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
%    \frozen\def#7##1{\expandafter\detokened\csname#1#2:##1\endcsname}% always root, no backtrack
%    \frozen\def#8##1{\begincsname#1#2:##1\endcsname}%
%    % TODO
%    \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}}

\protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9%
  {\frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname\csnamestring\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
   \frozen\def#4##1##2{\ifcsname##1:##2\endcsname\csnamestring\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
   \frozen\edef#5##1##2{\noexpand\ifrelax##1\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ?
   \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname\csnamestring\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
  %\frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
   \frozen\def#7##1{\expandafter\detokened\csname#1#2:##1\endcsname}% always root, no backtrack
   \frozen\def#8##1{\begincsname#1#2:##1\endcsname}%
   % TODO
   \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname\csnamestring\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}}

\permanent\protected\def\installparameterhandler#1#2%
  {\mutable\constant\letcsname current#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_parameter_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname do#2parameter\endcsname        % or: #2_parameter
        \expandafter\noexpand\csname do#2parentparameter\endcsname  % or: #2_parent_parameter
        \expandafter\noexpand\csname named#2parameter\endcsname
        \expandafter\noexpand\csname detokenized#2parameter\endcsname
        \expandafter\noexpand\csname direct#2parameter\endcsname
        \expandafter\noexpand\csname letfrom#2parameter\endcsname}} % strict#2parameter is gone

\protected\def\mult_interfaces_install_root_parameter_handler#1#2#3%
 %{\frozen\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
  {\frozen\def#2##1{\expandafter\detokened\csname#1:##1\endcsname}% always root
   \frozen\def#3##1{\begincsname#1:##1\endcsname}}

\permanent\protected\def\installrootparameterhandler#1#2%
  {\expanded
     {\mult_interfaces_install_root_parameter_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
        \expandafter\noexpand\csname root#2parameter\endcsname}}

\protected\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
  {\frozen\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
   \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
   \frozen\def#5##1##2{\ifrelax##1\else#4##1{##2}\fi}%
   \frozen\def#6{#1#2:}%
   \frozen\def#7##1{#1##1:}%
% won't work unless we also save the name of an undefined but called seldom (so no \else for now)
%  \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname\csnamestring\endcsname#1\fi}%
   \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname#1#2:\s!parent\endcsname#1\fi}%
   \frozen\protected\def#9##1{\edefcsname#1##1:\s!parent\endcsname{#1#2}}}

\permanent\protected\def\installparameterhashhandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \permanent\letcsname#2namespace\endcsname#1%
   \expanded
     {\mult_interfaces_install_parameter_hash_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameterhash\endcsname
        \expandafter\noexpand\csname do#2parameterhash\endcsname         % or : #2_parameter_hash
        \expandafter\noexpand\csname do#2parentparameterhash\endcsname   % or : #2_parent_parameter_hash
        \expandafter\noexpand\csname current#2hash\endcsname
        \expandafter\noexpand\csname named#2hash\endcsname
        \expandafter\noexpand\csname check#2parent\endcsname
        \expandafter\noexpand\csname chaintocurrent#2\endcsname}}

%D In \MKIV\ we can probably use the english variant for all other languages too.

% todo: inline the def/let

% \startinterface english
    \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
      {\frozen\protected\def#3##1{\defcsname#1#2:##1\endcsname}%        ##1 {##2} (braces are mandate)
       \frozen\protected\def#4##1{\edefcsname#1#2:##1\endcsname}%       ##1 {##2} (braces are mandate)
       \frozen\protected\def#5##1{\letcsname#1#2:##1\endcsname}%        ##1 ##2
       \frozen\protected\def#6##1{\letcsname#1#2:##1\endcsname\empty}}% ##1
% \stopinterface

\permanent\protected\def\installparametersethandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_parameter_set_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname set#2parameter\endcsname
        \expandafter\noexpand\csname setexpanded#2parameter\endcsname
        \expandafter\noexpand\csname let#2parameter\endcsname
        \expandafter\noexpand\csname reset#2parameter\endcsname}}

\mutable\let\dousecurrentstyleparameter   \relax
\mutable\let\dousecurrentcolorparameter   \relax
\mutable\let\dousecurrentlanguageparameter\relax

\mutable\lettonothing\currentstyleparameter
\mutable\lettonothing\currentcolorparameter
\mutable\lettonothing\currentlanguageparameter

%D We can extend the next one to also handle language but we migh tend up
%D with a dedicated one. There is no gain if we also want to pass the key:
%D chickens and eggs. At some poitn we might decide to have additional
%D language keys (\foregroundlanguage) btu so far no one asked for it. And
%D it only serves tagging.
%D
%D This actually might make sense because language could determine style:
%D
%D \use...languagestyleandcolor\c!language\c!style\c!color
%D
%D and then we can sacrifice the singluar ones.

\protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
  {\frozen\protected\def#2##1##2% style color
     {\cdef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
      \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi
      \cdef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
      \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}%
   \frozen\protected\def#3##1% style
     {\cdef\currentstyleparameter{#1{##1}}% this name is public
      \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}%
   \frozen\protected\def#4##1% color
     {\cdef\currentcolorparameter{#1{##1}}% this name is public
      \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}}

\permanent\protected\def\installstyleandcolorhandler#1#2%
  {\expanded
     {\mult_interfaces_install_style_and_color_handler
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
        \expandafter\noexpand\csname use#2styleparameter\endcsname
        \expandafter\noexpand\csname use#2colorparameter\endcsname}}

% \protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4#5%
%   {\frozen\protected\def#2##1##2% style color
%      {\cdef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
%       \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi
%       \cdef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
%       \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}%
%    \frozen\protected\def#3##1% style
%      {\cdef\currentstyleparameter{#1{##1}}% this name is public
%       \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}%
%    \frozen\protected\def#4##1% color
%      {\cdef\currentcolorparameter{#1{##1}}% this name is public
%       \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}%
%    \frozen\protected\def#5##1% (no argument)
%      {\cdef\currentlanguageparameter{#1{##1}}% this name is public
%       \ifempty\currentlanguageparameter\else\dousecurrentlanguageparameter\fi}}
%
% \permanent\protected\def\installstyleandcolorhandler#1#2%
%   {\expanded
%      {\mult_interfaces_install_style_and_color_handler
%         \expandafter\noexpand\csname #2parameter\endcsname
%         \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
%         \expandafter\noexpand\csname use#2styleparameter\endcsname
%         \expandafter\noexpand\csname use#2colorparameter\endcsname
%         \expandafter\noexpand\csname use#2language\endcsname}}

\def\mult_check_for_parent#1#2#3#4%
  {\ifcsname#1#4:\s!parent\endcsname\orelse\ifx#4\empty\else
     \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
     \cdefcsname#1#4:\s!parent\endcsname{#2}%
   \fi}

          \def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi}
\permanent\def\getparentchain       #1#2{\begincsname#1#2:\s!chain\endcsname}
\permanent\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname}

% we could have a \setcurrent... macro and then always make them a frozen
% but it might have a little impact on performance ... something to leave
% to when we're done with the transition (it's kind of massive)

\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8%
  {\newtoks#5%
   \newtoks#6%
   \frozen\tolerant\protected\def#2[##1]##*[##S##2]##*[##S##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
     {\let#8#4%
      % watch out: no \edef#4{##1} before the ifarguments because #1 can have macros
      \ifarguments
        \lettonothing#4%
        \expand#5% predefine
        \lettonothing#7%
        \letcsname#1#4:\s!chain\endcsname\empty
        \cdefcsname#1#4:\s!parent\endcsname{#3}%
      \or
        \cdef#4{##1}%
        \expand#5% predefine
        \lettonothing#7%
        \cdefcsname#1#4:\s!chain\endcsname{##1}%
        \cdefcsname#1#4:\s!parent\endcsname{#3}%
      \or
        \cdef#4{##1}%
        \expand#5% predefine
        \relax
        \ifhastok={##2}%
          \lettonothing#7%
          \cdefcsname#1#4:\s!chain\endcsname{##1}%
          \cdefcsname#1#4:\s!parent\endcsname{#3}%
          \mult_interfaces_get_parameters{#1#4:}[##2]%
        \else
          \cdef#7{##2}%
          \ifempty#7%
            \cdefcsname#1#4:\s!chain\endcsname{##1}%
            \cdefcsname#1#4:\s!parent\endcsname{#3}%
          \else
            \mult_check_for_parent{#1}{#3}#4#7%
            \cdefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
            \cdefcsname#1#4:\s!parent\endcsname{#1##2}%
          \fi
        \fi
      \or
        \cdef#4{##1}%
        \expand#5% predefine
        \cdef#7{##2}%
        \mult_check_for_parent{#1}{#3}#4#7%
        \cdefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
        \cdefcsname#1#4:\s!parent\endcsname{#1##2}%
        \mult_interfaces_get_parameters{#1#4:}[##3]%
      \fi
      \expand#6%
      \let#4#8}}

\permanent\protected\def\installdefinehandler#1#2#3%
  {\mutable\letcsname current#2\endcsname\empty
   \mutable\letcsname current#2parent\endcsname\empty
   \expanded
     {\mult_interfaces_install_define_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname define#2\endcsname
        {\noexpand#3}% root
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname everypreset#2\endcsname
        \expandafter\noexpand\csname everydefine#2\endcsname
        \expandafter\noexpand\csname current#2parent\endcsname
        \expandafter\noexpand\csname saved_defined_#2\endcsname}}

\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
  {\newtoks#4%
   \newtoks#7%
   \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
   \frozen\tolerant\protected\def#2[##S##1]##*[##S##2]% maybe helper
     {\let#6#3%
      \ifnum\lastarguments=\plustwo
        \def#8####1% we will have a simple one as well
          {\cdef#3{####1}%
           \mult_interfaces_get_parameters{#1#3:}[##2]%
           \expand#4}%
        \processcommalist[##1]#8%
      \else
        \lettonothing#3%
        \mult_interfaces_get_parameters{#1:}[##1]%
        \expand#4%
      \fi
      \let#3#6%
      \expand#7}}

\permanent\protected\def\installsetuphandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname everysetup#2root\endcsname
        \expandafter\noexpand\csname nested_setup_current#2\endcsname}}

\aliased\let\doingrootsetupnamed\plusone    % \setuplayout[name][key=value]
\aliased\let\doingrootsetuproot \plustwo    % \setuplayout      [key=value]
\aliased\let\doingrootsetnamed  \plusthree  % \setuplayout[name]
\aliased\let\doingrootsetroot   \plusfour   % \setuplayout

% \protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3%
%   {\frozen\protected\def#3{\mult_interfaces_get_parameters{#1#2:}}}

% \protected\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
%   {\newtoks#5%
%    \newconstant#2%
%    \newtoks#8%
%    \newtoks#9%
%    \frozen\tolerant\protected\def#4[##1]##*[##2]% maybe helper
%      {\ifarguments
%         % \setuplayout
%         \let#6#3%      % previous becomes current
%         \lettonothing#3%   % current becomes empty
%         #2\doingrootsetroot
%         \expand#5%
%         \expand#8% switchsetups
%       \or
%         \ifhastok={##1}%
%           % \setuplayout[key=value]
%           \let#7#3%
%           \let#6#3%
%           \lettonothing#3%
%           #2\doingrootsetuproot
%           \mult_interfaces_get_parameters{#1:}[##1]%
%           \expand#5%
%           \expand#8% switchsetups
%           \let#3#7%
%         \else
%           % \setuplayout[whatever]
%           \let#6#3%   % previous becomes current
%           \cdef#3{##1}% this will catch reset so one needs to test for it
%           \ifempty#3%
%             \let#7#6%
%             #2\doingrootsetuproot
%             \expand#5%
%             \expand#8% switchsetups
%             \let#3#7%
%           \else
%             #2\doingrootsetnamed
%             \expand#5%     % we can check for previous vs current
%             \expand#8% switchsetups
%           \fi
%         \fi
%       \or
%         % \setuplayout[whatever][key=value]
%         \let#7#3%
%         \let#6#3%
%         \cdef#3{##1}%
%         #2\doingrootsetupnamed
%         \mult_interfaces_get_parameters{#1#3:}[##2]%
%         \expand#5%
%         \ifx#3#6\expand#8\fi % only switchsetups if previous == current
%         \let#3#7%
%       \fi
%       #2\zerocount % mode is always zero at the end
%       \expand#9}}

% \permanent\protected\def\installswitchsetuphandler#1#2%
%   {\mutable\letcsname current#2\endcsname\empty
%    \mutable\letcsname previous#2\endcsname\empty
%    \expanded
%      {\mult_interfaces_install_switch_setup_handler_a
%         {\noexpand#1}% \??aa
%         \expandafter\noexpand\csname current#2\endcsname
%         \expandafter\noexpand\csname setupcurrent#2\endcsname
%       \mult_interfaces_install_switch_setup_handler_b
%         {\noexpand#1}% \??aa
%         \expandafter\noexpand\csname #2setupmode\endcsname
%         \expandafter\noexpand\csname current#2\endcsname
%         \expandafter\noexpand\csname setup#2\endcsname
%         \expandafter\noexpand\csname everysetup#2\endcsname
%         \expandafter\noexpand\csname previous#2\endcsname
%         \expandafter\noexpand\csname saved_setup_current#2\endcsname
%         \expandafter\noexpand\csname everyswitch#2\endcsname
%         \expandafter\noexpand\csname everysetup#2root\endcsname}}

\protected\def\mult_interfaces_install_switch_setup_handler#1#2#3#4#5#6#7#8#9#A%
  {\newtoks#5%
   \newconstant#2%
   \newtoks#8%
   \newtoks#9%
   \frozen\tolerant\protected\def#4[##S##1]##*[##S##2]% maybe helper
     {\ifarguments
        % \setuplayout
        \let#6#3%      % previous becomes current
        \lettonothing#3%   % current becomes empty
        #2\doingrootsetroot
        \expand#5%
        \expand#8% switchsetups
      \or
        \ifhastok={##1}%
          % \setuplayout[key=value]
          \let#7#3%
          \let#6#3%
          \lettonothing#3%
          #2\doingrootsetuproot
          \mult_interfaces_get_parameters{#1:}[##1]%
          \expand#5%
          \expand#8% switchsetups
          \let#3#7%
        \else
          % \setuplayout[whatever]
          \let#6#3%   % previous becomes current
          \cdef#3{##1}% this will catch reset so one needs to test for it
          \ifempty#3%
            \let#7#6%
            #2\doingrootsetuproot
            \expand#5%
            \expand#8% switchsetups
            \let#3#7%
          \else
            #2\doingrootsetnamed
            \expand#5%     % we can check for previous vs current
            \expand#8% switchsetups
          \fi
        \fi
      \or
        % \setuplayout[whatever][key=value]
        \let#7#3%
        \let#6#3%
        \cdef#3{##1}%
        #2\doingrootsetupnamed
        \mult_interfaces_get_parameters{#1#3:}[##2]%
        \expand#5%
        \ifx#3#6\expand#8\fi % only switchsetups if previous == current
        \let#3#7%
      \fi
      #2\zerocount % mode is always zero at the end
      \expand#9}%
    \frozen\protected\def#A{\mult_interfaces_get_parameters{#1#3:}}}

\permanent\protected\def\installswitchsetuphandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \mutable\letcsname previous#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_switch_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname #2setupmode\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname previous#2\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname everyswitch#2\endcsname
        \expandafter\noexpand\csname everysetup#2root\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname}}


\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
  {\newtoks#4%
   \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}%
   \frozen\tolerant\protected\def#2[##S##1]##*[##S##2]##*[##S##3]%
     {\let#7#3%
      \ifarguments
        \lettonothing#3%
        \expand#4%
      \or
        \lettonothing#3%
        \mult_interfaces_get_parameters{#1:}[##1]%
        \expand#4%
      \or
        \def#8####1%
          {\cdef#3{####1}%
           #6% checks parent and sets if needed
           \mult_interfaces_get_parameters{#1#3:}[##2]%
           \expand#4}%
        \processcommalist[##1]#8%
      \or
        \def#8####1%
          {\cdef#3{####1}%
           \cdefcsname#1#3:\s!parent\endcsname{#1##2}%
           \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
           \expand#4}%
        \processcommalist[##1]#8%
      \fi
      \let#3#7}}

\permanent\protected\def\installautosetuphandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_auto_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname
        \expandafter\noexpand\csname check#2parent\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname nested_setup_current#2\endcsname}}

\permanent\protected\def\installbasicparameterhandler#1#2%
  {\installparameterhandler    {#1}{#2}%
   \installparameterhashhandler{#1}{#2}%
   \installparametersethandler {#1}{#2}%
   \installrootparameterhandler{#1}{#2}}

\permanent\protected\def\installbasicautosetuphandler#1#2% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installautosetuphandler     {#1}{#2}}

\permanent\protected\def\installstylisticautosetuphandler#1#2% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installautosetuphandler     {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\permanent\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installsetuphandler         {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\permanent\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installswitchsetuphandler   {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\permanent\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installautosetuphandler     {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\permanent\protected\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
  {\installbasicparameterhandler{#1}{#2}%
   \installsetuphandler         {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

%D Many mechanisms have some kind of inheritance in place, and these are the
%D speed||critical ones. Therefore there is no reason to stick to \type {\@@xxkey}
%D for the sake of performance. For this reason we also provide a direct variant.
%D This permits a more consistent treatment of namespaces. A \type
%D {\whateverparameter} call is three times slower and a \type
%D {\directwhateverparameter} call two times but for some 100K expansions we only
%D loose some .1 second which is neglectable given the small amount of expansions in
%D real runs.

%D We don't need colons for such simple cases.

\protected\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
  {\frozen\def#3##1{\begincsname#1##1\endcsname}%
  %\frozen\def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
   \frozen\def#4##1{\expandafter\detokened\csname#1##1\endcsname}%
   \frozen\def#5##1{\begincsname#1##1\endcsname}}

\permanent\protected\def\installdirectparameterhandler#1#2%
  {\mutable\letcsname current#2\endcsname\empty
   \expanded
     {\mult_interfaces_install_direct_parameter_handler
        {\noexpand#1}%
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname detokenized#2parameter\endcsname
        \expandafter\noexpand\csname direct#2parameter\endcsname}}

\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4%
  {\newtoks#4%
   \frozen\tolerant\protected\def#2[##S##1]{\mult_interfaces_get_parameters#1[##1]\expand#4}%
   \frozen\protected\def#3{\mult_interfaces_get_parameters#1}}

\permanent\protected\def\installdirectsetuphandler#1#2%
  {\expanded
     {\mult_interfaces_install_direct_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
        \expandafter\noexpand\csname everysetup#2\endcsname}}

% \startinterface english
    \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
      {\frozen\protected\def#2##1{\defcsname#1##1\endcsname}%
       \frozen\protected\def#3##1{\edefcsname#1##1\endcsname}%
       \frozen\protected\def#4##1{\letcsname#1##1\endcsname}%
       \frozen\protected\def#5##1{\letcsname#1##1\endcsname\empty}}%
% \stopinterface

\permanent\protected\def\installdirectparametersethandler#1#2%
  {\expanded
     {\mult_interfaces_install_direct_parameter_set_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname set#2parameter\endcsname
        \expandafter\noexpand\csname setexpanded#2parameter\endcsname
        \expandafter\noexpand\csname let#2parameter\endcsname
        \expandafter\noexpand\csname reset#2parameter\endcsname}}

\aliased\let\installdirectstyleandcolorhandler\installstyleandcolorhandler

\permanent\protected\def\installdirectcommandhandler#1#2%
  {\installdirectparameterhandler    {#1}{#2}%
   \installdirectsetuphandler        {#1}{#2}%
   \installdirectparametersethandler {#1}{#2}%
   \installdirectstyleandcolorhandler{#1}{#2}}

\permanent\protected\def\installsetuponlycommandhandler#1#2%
  {\installdirectparameterhandler   {#1}{#2}%
   \installdirectsetuphandler       {#1}{#2}%
   \installdirectparametersethandler{#1}{#2}}

% Experiment:

% \installcorenamespace {one}
% \installcorenamespace {two}
%
% \installcommandhandler \??one {one} \??one
% \installcommandhandler \??two {two} \??two
%
% \defineone[test] \setupone[test][alpha=first]
% \definetwo[test] \setuptwo[test][beta=second]
%
% \protect
%
% \def\currentone{test}
% \def\currenttwo{test}
%
% \relateparameterhandlers {two} {test} {one} {test}
%
% yes:\oneparameter{alpha}\par
% nop:\oneparameter{beta}\par
% yes:\twoparameter{alpha}\par
% yes:\twoparameter{beta}\par

\permanent\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
  {% can this be a cdef ... is faster in tests
   \permanent\edefcsname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}

\permanent\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance}
  {\cdefcsname#1#2:\s!parent\endcsname{#3#4}}

%D Here is another experiment:

\protected\def\mult_interfaces_install_action_handler#1#2#3%
  {\frozen\tolerant\protected\defcsname#1\endcsname[##S##1]##*[##S##2]%
     {\begingroup
      \ifarguments
        \lettonothing#2%
      \or
       %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004%
      % \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments
      %   \cdef#2{##1}%
      % \else
      %   \lettonothing#2%
      %   #3[##1]%
      % \fi
        \ifhastok={##1}%
          \lettonothing#2%
          #3[##1]%
        \else
          \cdef#2{##1}%
        \fi
      \or
        \cdef#2{##1}%
        #3[##2]%
      \fi
      \directsetup{handler:action:#1}%
      \endgroup}}

\permanent\protected\def\installactionhandler#1%
  {\mutable\letcsname current#1\endcsname\empty
   \expanded
     {\mult_interfaces_install_action_handler
        {#1}%
        \expandafter\noexpand\csname current#1\endcsname
        \expandafter\noexpand\csname setupcurrent#1\endcsname}}

% First we had, in tune with the regular system variables:
%
% \starttyping
% \protected\def\installnamespace#1{\defcsname ????#1\endcsname{@@@@#1}}
% \stoptyping
%
% The following variant is nicer and in principle faster but that gets unnoticed
% unless lots of expansion happens. Also, we can use long tags but the internal
% expansion will be relatively small (and unlikely more than 4 characters). For
% instance, \??xx used to expand to @@xx but now becomes for instance 123::. This
% is one character more but in quite some cases we had : after such a tag in the
% old situation. In the new situation we create more namespaces and don't need that
% : any more, so we end up with on the average the same amount of tokens and
% definitely less when we consider cases like \??xx:\c!align: which now is just
% \??somealign and therefore has length 5 now (instead of 4+1+5+1=10).
%
% Eventualy we will have a verbose \blablanamespace and the difference between core
% and regular can go ... after all, \xxxparameter can already clash between the two
% prefix groups .. if users use this mechanism a lot they should use verbose names
% anyway (the old two character names were mostly an optimization as they also
% expanded to these characters).

% todo: register namespaces at lua end for logging and reverse resolve
% todo: move this to syst-ini so that we can use it real early

\newinteger\c_mult_interfaces_n_of_namespaces

\def\v_interfaces_prefix_template{\the\c_mult_interfaces_n_of_namespaces>}

\permanent\protected\def\installnamespace#1% for modules and users
  {\ifcsname ????#1\endcsname
     \writestatus\m!system{duplicate user namespace '#1'}\wait
   \else
     \global\advanceby\c_mult_interfaces_n_of_namespaces\plusone
     \global\permanent\cdefcsname ????#1\endcsname{\v_interfaces_prefix_template}%
   \fi}

\permanent\protected\def\installcorenamespace#1%
  {\ifcsname ??#1\endcsname
     \writestatus\m!system{duplicate core namespace '#1'}\wait
   \else
     \global\advanceby\c_mult_interfaces_n_of_namespaces\plusone
     \global\permanent\cdefcsname ??#1\endcsname{\v_interfaces_prefix_template}%
     \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
   \fi}

% \permanent\protected\def\installnamespace#1% for modules and users
%   {\ifcsname ????#1\endcsname
%      \writestatus\m!system{duplicate user namespace '#1'}\wait
%    \else
%      \global\advanceby\c_mult_interfaces_n_of_namespaces\plusone
%      \global\permanent\expandafter\stringdef\csname ????#1\endcsname\c_mult_interfaces_n_of_namespaces
%      \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
%    \fi}

% \permanent\protected\def\installcorenamespace#1%
%   {\ifcsname ??#1\endcsname
%      \writestatus\m!system{duplicate core namespace '#1'}\wait
%    \else
%      \global\advanceby\c_mult_interfaces_n_of_namespaces\plusone
%      \global\permanent\expandafter\stringdef\csname ??#1\endcsname\c_mult_interfaces_n_of_namespaces
%      \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
%    \fi}

\def\mult_interfaces_get_parameters_error_indeed#1#2%
  {\clf_showassignerror{#1}{#2}\inputlineno}

% We install two core namespaces here, as we want nice error messages. Maybe
% we will reserve the first 9.

\installcorenamespace{fontinstanceready}
\installcorenamespace{fontinstancebasic}
\installcorenamespace{fontinstanceclass}

%D The next one is handy for local assignments.

\installcorenamespace{dummy}

\letcsname\??dummy\endcsname\empty

\permanent          \def\dummyparameter           #1{\begincsname\??dummy#1\endcsname}
\permanent          \def\directdummyparameter     #1{\begincsname\??dummy#1\endcsname}
\permanent\protected\def\setdummyparameter        #1{\defcsname  \??dummy#1\endcsname}
\permanent\protected\def\setexpandeddummyparameter#1{\edefcsname \??dummy#1\endcsname}
\permanent\protected\def\letdummyparameter        #1{\letcsname  \??dummy#1\endcsname}
\permanent\protected\def\resetdummyparameter      #1{\letcsname  \??dummy#1\endcsname\empty}

\cdef\mult_interfaces_dummy{\??dummy} % not immutable

% \permanent\protected\def\getdummyparameters[#S#1%
%   {\if\noexpand#1]%
%      \expandafter\gobbleoneargument
%    \else
%      \let\m_mult_interfaces_namespace\mult_interfaces_dummy
%      \expandafter\mult_interfaces_get_parameters_indeed
%    \fi#1}

% \permanent\protected\def\getdummyparameters[#S#1]%
%   {\let\m_mult_interfaces_namespace\mult_interfaces_dummy
%    \mult_interfaces_get_parameters_item_okay#1\ignorearguments\ignorearguments}

\permanent\protected\def\getdummyparameters[#S#1]%
  {\let\m_mult_interfaces_namespace\mult_interfaces_dummy
   \mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments}

\let\usedummylanguageparameter\donothing

\mult_interfaces_install_style_and_color_handler
  \directdummyparameter
  \usedummystyleandcolor
  \usedummystyleparameter
  \usedummycolorparameter
  \usedummylanguageparameter

% Maybe a \definecorenamespace[name][directparameter,directsetup][parent] but we
% don't gain much. Actually we might just inline all definitions.

% \enabletrackers[interfaces.namespaces,context.flush]
%
% \definenamespace
%   [xy]
%   [type=module,
%    comment=test module,
%    version=1,
%    name=test,
%    style=yes,
%    command=yes,
%    setup=list,
%    set=yes,
%    parent=xy]
%
% \unprotect
% \getparameters
%   [\????xy]
%   [text=]
% \protect
%
% \definetest[one]
%
% \starttext
%
%   “\testparameter{text}”
%
%   \setuptest[text=foo]
%
%   “\testparameter{text}”
%
%   \setuptest[one][text=bar]
%
%   “\testparameter{text}”
%
% \stoptext
%
% This is a user (module) command:

\permanent\tolerant\protected\def\definenamespace[#1]#*[#2]% namespace settings
  {\clf_definenamespace{#1}{#2}}

\permanent\protected\def\listnamespaces
  {\clf_listnamespaces}

%D Helper:
%D
%D \starttyping
%D \showparentchain{@@am}{left}
%D \stoptyping

\permanent\protected\def\showparentchain#1#2%
  {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}

\def\mult_interfaces_show_parent_chain#1%
  {#1 => %
   \ifcsname#1:\s!parent\endcsname
      \expandafter\mult_interfaces_show_parent_chain\lastnamedcs
   \fi}

%D Another helper (needs to be applied):

\permanent\protected\def\doifelsecommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\aliased\let\doifcommandhandlerelse\doifelsecommandhandler

\permanent\protected\def\doifcommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\permanent\protected\def\doifnotcommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\permanent\def\ifcommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname}

% another set of (fast) helpers (grep for usage):

\permanent\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
  {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}

\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy
  {#1\endcsname#1\else#2\fi\endcsname}

\permanent\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
  {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}

\permanent\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
  {\csname#1\ifcsname#1\expanded{\noexpand\syst_helpers_expand_checked_value{#2}}}

\def\syst_helpers_expand_checked_value#1#2%
  {#1\endcsname#1\else#2\fi\endcsname}

%D Conventions:
%D
%D \starttyping
%D \newinteger     \c_class_whatever
%D \newconditional \c_class_whatever
%D \newconstant    \c_class_whatever
%D \newdimension   \d_class_whatever
%D \newgluespec    \s_class_whatever
%D \newmuskip      \s_class_whatever
%D \newbox         \b_class_whatever
%D \newtoks        \t_class_whatever
%D
%D \edef\p_class_whatever{\classparameter\c!whatever}
%D \edef\m_class_whatever{whatever}
%D \stoptyping

% experiment: in principle this is faster but not that noticeable as we don't do that
% many assignments and mechanism that do are also slow; the advantage is mostly nicer
% in tracing

\mutable\let\c_mult_set\relax

\protected\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7%
  {\newinteger#3%
   \lettonothing#6%
   \protected\def#2%
     {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname
      \ifrelax\c_mult_set
        \expandafter\newtoks\c_mult_set
        \letcsname#1_t_#6\endcsname\c_mult_set
      \fi}
   \frozen\protected\def#4##1%
     {\pushmacro#6%
      \advanceby#3\plusone
      \cdef#6{##1}%
      \unprotect}%
   \frozen\protected\def#5%
     {\protect
      \advanceby#3\minusone
      \popmacro#6}%
   \frozen\protected\def#7##1%
     {\cdef#6{##1}%
      #2%
      \the\c_mult_set\relax}}

\permanent\protected\def\installdefinitionset#1#2%
  {\expanded
     {\mult_interfaces_install_definition_set
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname set_#2_toks\endcsname
        \expandafter\noexpand\csname #2_nesting_depth\endcsname
        \expandafter\noexpand\csname push#2\endcsname
        \expandafter\noexpand\csname pop#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname use#2\endcsname}}

\protected\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc
  {\let#5#2%
   \frozen\protected\def#2%
     {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}%
   \tolerant\protected\def#6[##S##1]##*[##S##2]%
     {\ifarguments\or
        #3\toksapp\c_mult_set{#7[##1]}%
      \or
        #3\toksapp\c_mult_set{#8[##1][##2]}%
      \fi}}

\permanent\protected\def\installdefinitionsetmember#1#2#3#4%
  {\expanded
     {\mult_interfaces_install_definition_set_member
        {\noexpand#3}% \??aa
        \expandafter\noexpand\csname setup#4\endcsname
        \expandafter\noexpand\csname set_#2_toks\endcsname
        \expandafter\noexpand\csname #2_nesting_depth\endcsname
        \expandafter\noexpand\csname normal_setup_#4\endcsname
        \expandafter\noexpand\csname delayed_setup_#4\endcsname
        \expandafter\noexpand\csname setup#4_\s!single\endcsname
        \expandafter\noexpand\csname setup#4_\s!double\endcsname}}

%D Another experiment:

\protected\def\mult_interfaces_install_parent_injector#1#2#3#4%
  {\frozen\protected\def#4##1%
     {\ifempty#3%
        \cdefcsname#1#2:\s!parent\endcsname{#1##1}% was def
      \fi}}

\permanent\protected\def\installparentinjector#1#2%
  {\expanded{\mult_interfaces_install_parent_injector
     {\noexpand#1}%
     \expandafter\noexpand\csname current#2\endcsname
     \expandafter\noexpand\csname current#2parent\endcsname
     \expandafter\noexpand\csname inject#2parent\endcsname}}

%D Cheaper (assumes grouping at some point):

\permanent\protected\def\mult_interfaces_install_local_current_injector#1#2#3#4#5%
  {\lettonothing#4% \currentglobalXXX
   \protected\def#5##1%
     {\advanceby#2\plusone
      \cdef#3{##1:\the#2}% \currentXXX
      \cdef#4{##1}% \currentglobalXXX
      \cdefcsname#1#3:\s!parent\endcsname{#1##1}}}

\permanent\protected\def\installlocalcurrenthandler#1#2% \??XXX {XXX}
  {\expandafter\newinteger\csname#1:\s!counter\endcsname
   \expanded{\mult_interfaces_install_local_current_injector
     {\noexpand#1}%
     \expandafter\noexpand\csname #1:\s!counter\endcsname
     \expandafter\noexpand\csname current#2\endcsname
     \expandafter\noexpand\csname currentglobal#2\endcsname
     \expandafter\noexpand\csname setlocal#2current\endcsname}}

%  \unprotect
%
%  \installcorenamespace {test} \installcommandhandler \??test {test} \??test
%  \protected\def\TestMeA[#1]%
%    {\edef\currenttest{#1}
%     \edef\p_before{\testparameter\c!before}%
%     \ifempty\p_before \relax \else \relax \fi}
%  \protected\def\TestMeB[#1]%
%    {\edef\currenttest{#1}
%     \doifelsenothing{\testparameter\c!before}\relax\relax}
%  \protected\def\TestMeC[#1]%
%    {\edef\currenttest{#1}
%     \expandafter\expandafter\expandafter\ifempty\testparameter\c!before \relax \else \relax \fi}
%  \protected\def\TestMeD[#1]%
%    {\edef\currenttest{#1}
%     \doubleexpandafter\ifempty\testparameter\c!before \relax \else \relax \fi}
%
%  \protect
%
%  \starttext
%    \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed]
%    \testfeatureonce{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502
%    \testfeatureonce{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530
%    \testfeatureonce{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487
%    \testfeatureonce{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493
%  \stoptext

% There is no real demand for this ... even if this is two to three times as fast we
% only gain a few milliseconds:
%
% \starttyping
% \protected\def\foo#1{[foo:#1]}
%
% \installcommalistprocessor                        {foo} \foo
% \installcommalistprocessorcommand \processfoolist \foo
%
% \infofont
%
% \commalistprocessor{foo}[a,b,c,{x,y,z},d]\par
% \processfoolist[a, b, c, {x,y,z}, d]\par
% \processcommalist[{x,y,z}]\foo\blank
%
% \commalistprocessor{foo}[{x,y,z},a]\par
% \commalistprocessor{foo}[{x,y,z}]\par
% \processfoolist[{x,y,z},a]\par
% \processfoolist[{x,y,z}]\par
% \processcommalist[{x,y,z}]\foo\blank
%
% \protected\def\foo#1{}
%
% \testfeatureonce{400000}{\processfoolist         [fixed,middle,bar]}     \elapsedtime\quad
%%\testfeatureonce{400000}{\commalistprocessor{foo}[fixed,middle,bar]}     \elapsedtime\quad
% \testfeatureonce{400000}{\processcommalist       [fixed,middle,bar]\foo} \elapsedtime\quad
% \stoptyping
%
% For instance the luatex manual only has some 3000 calls. But I keep this around as one
% never knows when we might need it.

\installcorenamespace{commalistprocessor}
\installcorenamespace{commalistprocessoraction}

% \installcorenamespace{commalistprocessorwrap}
% \installcorenamespace{commalistprocessorfirst}
% \installcorenamespace{commalistprocessornext}
%
% \permanent\protected\def\installcommalistprocessor#1#2% 5 macro names overhead
%   {\protected\edefcsname\??commalistprocessor#1\endcsname[%
%      {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {}
%    \protected\edefcsname\??commalistprocessorwrap#1\endcsname##1]%
%      {\csname\??commalistprocessorfirst#1\endcsname##S##1,]}%
%    \protected\edefcsname\??commalistprocessorfirst#1\endcsname\relax
%      {\csname\??commalistprocessornext#1\endcsname}%
%    \protected\edefcsname\??commalistprocessornext#1\endcsname
%      {\noexpand\futureexpandis]%
%         \noexpand\gobbleoneargument
%         \csname\??commalistprocessoraction#1\endcsname}
%    \protected\edefcsname\??commalistprocessoraction#1\endcsname##1,%
%      {\noexpand#2{##1}%
%       \csname\??commalistprocessornext#1\endcsname}}

\permanent\protected\def\installcommalistprocessor#1#2% 2 macro names overhead
  {\tolerant\protected\edefcsname\??commalistprocessor#1\endcsname[##S##1]%
     {\csname\??commalistprocessoraction#1\endcsname##1\ignorearguments\ignorearguments}%
   \tolerant\protected\edefcsname\??commalistprocessoraction#1\endcsname##S##1,%
     {\noexpand\ifarguments\noexpand\or
        \noexpand#2{##1}%
        \noexpand\expandafter\csname\??commalistprocessoraction#1\endcsname
      \noexpand\fi}}

\permanent\protected\def\installcommalistprocessorcommand#1#2% \processor \action
  {\cdef\p_name{\csstring#2}%
   \installcommalistprocessor\p_name{#2}%
   \expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname}

\permanent\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname}

%D This is a special one, used in \METAPOST\ graphic support. It is english only because
%D we have no multilingual interface in \METAFUN.

% \startinterface english
%     \let\mult_interfaces_install_native_auto_setup_handler\mult_interfaces_install_auto_setup_handler
%     \aliased\let\installbasicnativeautosetuphandler\installbasicsetuphandler
% \stopinterface

\ifdefined\installnativebasicsetuphandler \else

              \let\mult_interfaces_adef_yes\mult_interfaces_adef
    \protected\def\mult_interfaces_adef_nop#1#2{\defcsname#1#2\endcsname}

    \protected\def\mult_interfaces_install_native_auto_setup_handler#1#2#3#4#5#6#7#8%
      {\newtoks#4%
       \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}%
       \frozen\tolerant\protected\def#2[##S##1]##*[##S##2]##*[##S##3]%
         {\let#7#3%
          \ifarguments
            \lettonothing#3%
            \expand#4%
          \or
            \lettonothing#3%
            \let\mult_interfaces_adef\mult_interfaces_adef_nop
            \mult_interfaces_get_parameters{#1:}[##1]%
            \let\mult_interfaces_adef\mult_interfaces_adef_yes
            \expand#4%
          \or
            \def#8####1%
              {\cdef#3{####1}%
               #6% checks parent and sets if needed
               \let\mult_interfaces_adef\mult_interfaces_adef_nop
               \mult_interfaces_get_parameters{#1#3:}[##2]%
               \let\mult_interfaces_adef\mult_interfaces_adef_yes
               \expand#4}%
            \processcommalist[##1]#8%
          \or
            \def#8####1%
              {\cdef#3{####1}%
               \cdefcsname#1#3:\s!parent\endcsname{#1##2}%
               \let\mult_interfaces_adef\mult_interfaces_adef_nop
               \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
               \let\mult_interfaces_adef\mult_interfaces_adef_yes
               \expand#4}%
            \processcommalist[##1]#8%
          \fi
          \let#3#7}}

    \permanent\protected\def\installnativeautosetuphandler#1#2%
      {\mutable\letcsname current#2\endcsname\empty
       \expanded
         {\mult_interfaces_install_native_auto_setup_handler
            {\noexpand#1}% \??aa
            \expandafter\noexpand\csname setup#2\endcsname
            \expandafter\noexpand\csname current#2\endcsname
            \expandafter\noexpand\csname everysetup#2\endcsname
            \expandafter\noexpand\csname setupcurrent#2\endcsname
            \expandafter\noexpand\csname check#2parent\endcsname
            \expandafter\noexpand\csname saved_setup_current#2\endcsname
            \expandafter\noexpand\csname nested_setup_current#2\endcsname}}

    \permanent\protected\def\installbasicnativeautosetuphandler#1#2%
      {\installbasicparameterhandler {#1}{#2}%
       \installnativeautosetuphandler{#1}{#2}}

\fi

\protect \endinput
