summaryrefslogtreecommitdiff
path: root/macros/generic/yax/yax.tex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/generic/yax/yax.tex
Initial commit
Diffstat (limited to 'macros/generic/yax/yax.tex')
-rw-r--r--macros/generic/yax/yax.tex707
1 files changed, 707 insertions, 0 deletions
diff --git a/macros/generic/yax/yax.tex b/macros/generic/yax/yax.tex
new file mode 100644
index 0000000000..3bf7429841
--- /dev/null
+++ b/macros/generic/yax/yax.tex
@@ -0,0 +1,707 @@
+% This is the YaX package.
+% Relevant information can be found in yax-doc.pdf
+%
+% Author: Paul Isambert.
+% E-mail: zappathustra AT free DOT fr
+% Comments and suggestions are welcome.
+% Date: January 2011.
+%
+\ifcsname yax@already_loaded\endcsname
+ \expandafter\endinput
+\fi
+
+\input texapi % Everything I need. It figures: I wrote it for this.
+
+\ifdefined\texapiversion
+ \ifdim\texapiversion pt<1.03pt
+ \senderror{YaX}{You need texapi with version at least 1.03. I quit}
+ \expandafter\expandafter\expandafter\endinput
+ \fi
+\else
+ % \texapiversion was introduced in v.1.02.
+ \senderror{YaX}{You need texapi with version at least 1.03. I quit}
+ \expandafter\endinput
+\fi
+
+\setcatcodes{@_=11}
+\def\yaxversion{1.03}
+\let\yax@already_loaded\relax
+\def\yax@error{\senderror{YaX}}
+
+%
+% Retrieval of parameter and attribute.
+%
+\def\yax@getparameter#1#2:{%
+ \passtrim{#2}{#1}%
+ }
+\def\yax@defparameter#1#2{%
+ \def\yax@parameter{#2}#1
+ }
+% #1 and #2 are thing_to_do and parameter.
+\def\yax@getattribute#1#2#3 {%
+ \ifemptystring{#3}{\yax@getattribute{#1}{#2}}
+ {#1{#2}{#3}}%
+ }
+% \yax@getall\foo
+% => \foo{<parameter>}{<attribute>}
+\def\yax@getall#1{%
+ \yax@getparameter{\yax@getattribute{#1}}%
+ }
+%
+\long\def\yax@get_topar#1#2\par{%
+ #1{#2}%
+ }
+%
+%
+%
+%
+%%%%%%%%%%%%%%% SETTING PARAMETERS %%%%%%%%%%%%%%%
+%
+% The crux of the biscuit.
+%
+% \setparameter <list of parameters> :
+% <prefix><attribute1> = <value1>
+% <prefix><attribute2> = <value2>
+% ...
+% <prefix><attributeN> = <valueN>
+% \par
+%
+% A generic loop for space-delimited lists.
+% The the texapi documentation for the information on the \newfor loop.
+%
+\newfornoempty\yax@space_loop{1}#2 {#1{#2}}%
+%
+\pdef\setparameter{%
+ \yax@getparameter\yax@setparameter_getattributes
+ }
+\long\def\yax@setparameter_getattributes#1#2\par{%
+ \yax@setparameter_getpairs{}{#2 }%
+ \expandafter\yax@space_loop\expandafter{\expandafter\yax@setparameter_assign\expandafter{\yax@setparameters_pairs}}{#1 }%
+ \yax@space_loop\yax@setparameter_execute{#1 }%
+ }
+\newfor\yax@setparameter_getpairs{1}#2={%
+ \pausefor{\skipspace{\passtrim{#2}{\yax@setparameter_checkprefix{\yax@setparameter_howgiven{#1}}}}}%
+ }[\def\yax@setparameters_pairs{#1}]
+
+\newstring{e:} \newstring{g:} \newstring{x:}
+\long\def\yax@setparameter_checkprefix#1#2{%
+ \ifprefix{e:}{#2}
+ {\removeprefixand{e:}{#2}\passtrim{#1\edefcs}}
+ {\ifprefix{g:}{#2}
+ {\removeprefixand{g:}{#2}\passtrim{#1\gdefcs}}
+ {\ifprefix{x:}{#2}
+ {\removeprefixand{x:}{#2}\passtrim{#1\xdefcs}}
+ {#1\defcs{#2}}}}%
+ }
+
+\long\def\yax@setparameter_howgiven#1#2#3{%
+ \ifnextnospace"
+ {\yax@setparameter_getquote{#1}{#2}{#3}}
+ % No need for a new nospace: it has been removed
+ {\ifcatnext\foo
+ {\yax@setparameter_getcommand{#1}{#2}{#3}}
+ {\yax@setparameter_getspace{#1}{#2}{#3}}}%
+ }
+
+\long\def\yax@setparameter_getquote#1#2#3"#4"{%
+ \skipspace{\resumefor\yax@setparameter_getpairs{#1{#2}{#3}{#4}}}% Better not to forget this!
+ }
+\long\def\yax@setparameter_getcommand#1#2#3#4{%
+ \skipspace{\resumefor\yax@setparameter_getpairs{#1{#2}{#3}{#4}}}%
+ }
+\long\def\yax@setparameter_getspace#1#2#3#4 {%
+ \skipspace{\resumefor\yax@setparameter_getpairs{#1{#2}{#3}{#4}}}%
+ }
+
+\long\def\yax@setparameter_assign#1#2{%
+ \yax@setparameter_assignloop{#2}{#1}%
+ }
+
+\newfor\yax@setparameter_assignloop{1}#2#3#4{%
+ \yax@space_loop{\yax@setparameter_do{#1}{#2}{#4}}{#3 }%
+ }
+
+\newif\ifyax@makedef
+% #1 = parameter; #2 = \<|e|g|x>defcs; #3 = value; #4 = attribute
+\long\def\yax@setparameter_do#1#2#3#4{%
+ \yax@makedeftrue
+ \iffcs{yax@#1@restricted}% Parameter restricted.
+ {\reverse\iffcs{yax@#1:#4@allowed}% Attribute not allowed.
+ {\yax@makedeffalse
+ \yax@error{Attribute `#4' is not allowed in parameter `#1'.
+ Authorized attributes are `\unexpandedcs{yax@#1@restricted}'}}}%
+ \ifcs{yax@#1:#4@restricted}% Attribute restricted in this parameter.
+ {\reverse\iffcs{yax@#1:#4:\detokenize{#3}@allowed}% Value not allowed.
+ {\yax@makedeffalse
+ \yax@error{Value `\detokenize{#4}' is not allowed in attribute `#1:#4'.
+ Authorized values are `\unexpandedcs{yax@#1:#4@restricted}'}}}%
+ {\iffcs{yax@attribute@#4@restricted}% Attribute restricted in all parameters.
+ {\reverse\iffcs{yax@attribute@#4:\detokenize{#3}@allowed}% Value not allowed.
+ {\yax@makedeffalse
+ \yax@error{Value `\detokenize{#3}' is not allowed in attribute `#4'.
+ Authorized values are `\unexpandedcs{yax@attribute@#4@restricted}'}}}}%
+ \ifyax@makedef
+ \reverse\iffcs{yax@#1@attributelist}{\gdefcs{yax@#1@attributelist}{}}%
+ \ifx#2\gdefcs
+ \passexpandedcs{\yax@parameterlist_add\global{#1}{#4}}{yax@#1@attributelist}%
+ \else\ifx#2\xdefcs
+ \passexpandedcs{\yax@parameterlist_add\global{#1}{#4}}{yax@#1@attributelist}%
+ \else
+ \passexpandedcs{\yax@parameterlist_add{}{#1}{#4}}{yax@#1@attributelist}%
+ \fi\fi
+ #2{yax@#1:#4}{#3}%
+ \fi
+ }
+
+\newfor\yax@parameterlist_add{3}#4{%
+ \iffstring{#3}{#4}{\breakfor{}}%
+ }[#1\eaddrightcs{yax@#2@attributelist}{{#3}}]
+
+\def\yax@setparameter_execute#1{%
+ \iffcs{yax@#1@active}{\usecs{yax@#1@def}}%
+ }
+%
+% \setparameterlist <list of parameters>[<default value>|*<cs>]<attribute>=<value>, ...
+%
+\def\setparameterlist#1{%
+ \ifnextnospace[
+ {\yax@setparameterlist_getdefault{#1}}
+ {\yax@setparameterlist_getdefault{#1}[]}%
+ }
+
+\def\yax@setparameterlist_getdefault#1[#2]#3{%
+ \yax@setparameterlist_loop{#1}{#2}{#3,}%
+ \yax@space_loop\yax@setparameter_execute{#1 }%
+ }
+
+\newstring{=}
+\newfornoempty\yax@setparameterlist_loop{2}#3,{%
+ \ifcontains={#3}
+ {\yax@setparameterlist_getargs{#1}#3\yax@endofentry}
+ {\ifemptystring{#2}
+ {\yax@setparameterlist_getargs{#1}#3=true\yax@endofentry}
+ {\passtrim{#3}{#2}}}%
+ }
+
+\long\def\yax@setparameterlist_getargs#1#2=#3\yax@endofentry{%
+ \yax@setparameter_checkprefix{\passtrim{#3}{\yax@setparameterlist_assign{#1}}}{#2}%
+ }
+
+\long\def\yax@setparameterlist_assign#1#2#3#4{%
+ \yax@space_loop{\yax@setparameterlist_do{#3}{#2}{#4}}{#1 }%
+ }
+
+\long\def\yax@setparameterlist_do#1#2#3#4{%
+ \yax@space_loop{\yax@setparameter_do{#4}{#1}{#2}}{#3 }%
+ }
+%
+% \setattribute <parameter> : <attribute> = <value>
+%
+\def\yax@removesign#1#2#3#4={#1{#2}{#3}}%
+\pdef\setattribute{%
+ \yax@getall{\yax@removesign{\yax@setattribute\defcs}}%
+ }
+\pdef\esetattribute{%
+ \yax@getall{\yax@removesign{\yax@setattribute\edefcs}}%
+ }
+\pdef\gsetattribute{%
+ \yax@getall{\yax@removesign{\yax@setattribute\gdefcs}}%
+ }
+\pdef\xsetattribute{%
+ \yax@getall{\yax@removesign{\yax@setattribute\xdefcs}}%
+ }
+\def\yax@setattribute#1#2#3{%
+ \skipspace{\yax@setattribute_getvalue{#1}{#2}{#3}}%
+ }
+\long\def\yax@setattribute_getvalue#1#2#3#4 {%
+ \yax@setparameter_do{#2}{#1}{#4}{#3}%
+ }
+%
+% \copyparameter <list of parameters> : <parameter>
+%
+\pdef\copyparameter{%
+ \yax@getall{\yax@copyparameter{}}%
+ }
+\pdef\gcopyparameter{%
+ \yax@getall{\yax@copyparameter\global}%
+ }
+\def\yax@copyparameter#1#2#3{%
+ \reverse\iffcs{yax@#3@attributelist}{#1\letcs{yax@#3@attributelist}\emptycs}%
+ \yax@space_loop{\yax@copyparameter_do{#1}{#3}}{#2 }%
+ }
+\def\yax@copyparameter_do#1#2#3{%
+ \iffcs{yax@#3@attributelist}{%
+ \passexpandedcs{\yax@parameterlist_copy{#1}{#3}{#2}}{yax@#3@attributelist}}%
+ }
+\newfor\yax@parameterlist_copy{3}#4{%
+ #1\letcstocs{yax@#3:#4}{yax@#2:#4}%
+ \passexpandedcs{\yax@parameterlist_add{#1}{#3}{#4}}{yax@#3@attributelist}%
+ }
+%
+%
+%
+% \deleteparameter <list of parameters>:
+%
+\pdef\deleteparameter{%
+ \yax@getparameter{\yax@deleteparameter{}}%
+ }
+\pdef\gdeleteparameter{%
+ \yax@getparameter{\yax@deleteparameter\global}%
+ }
+\def\yax@deleteparameter#1#2{%
+ \yax@space_loop{\yax@deleteparameter_do{#1}}{#2 }%
+ }
+\def\yax@deleteparameter_do#1#2{%
+ \iffcs{yax@#2@attributelist}{\passexpandedcs{\yax@parameterlist_delete{#1}{#2}}{yax@#2@attributelist}}%
+ }
+\newfor\yax@parameterlist_delete{2}#3{%
+ #1\letcs{yax@#2:#3}\yax@somethinghopefullyundefined
+ }[#1\letcs{yax@#2@attributelist}\yax@somethinghopefullyundefined]
+%
+%
+% \deleteattribute <parameter> : <attribute>
+%
+\def\deleteattribute{%
+ \yax@getall{\yax@deleteattribute{}}%
+ }
+\def\gdeleteattribute{%
+ \yax@getall{\yax@deleteattribute\global}%
+ }
+\def\yax@deleteattribute#1#2#3{%
+ \iffcs{yax@#2@attributelist}{%
+ #1\letcs{yax@#2:#3}\yax@undefined
+ \passexpandedcs{\yax@parameterlist_remove{#1\edefcs}{#2}{#3}{}}{yax@#2@attributelist}}%
+ }
+
+\newfor\yax@parameterlist_remove{4}#5{%
+ \reverse\iffstring{#3}{#5}{\passarguments{#1}{#2}{#3}{#4{#5}}}%
+ }[#1{yax@#2@attributelist}{#4}]
+%
+%
+%
+%
+% \restrictparameter <list of parameters> :
+% <attribute1>
+% <attribute2>
+% ...
+% <attributeN>
+% \par
+%
+\pdef\restrictparameter{%
+ \yax@getparameter\yax@restrictparameter_getrestrictions
+ }%
+\long\def\yax@restrictparameter_getrestrictions#1#2\par{%
+ \yax@space_loop{\yax@restrictparameter{#2 meta }}{#1 }% Meta is always allowed.
+ }
+\long\def\yax@restrictparameter#1#2{%
+ \def\yax@parameter{#2}%
+ \yax@space_loop\yax@restrictparameter_readrestrictions{#1}%
+ }
+\long\def\yax@restrictparameter_readrestrictions#1{%
+ \letcs{yax@\yax@parameter :#1@allowed}\relax
+ \ifcs{yax@\yax@parameter @restricted}
+ {\addrightcs{yax@\yax@parameter @restricted}{, #1}}
+ {\defcs{yax@\yax@parameter @restricted}{#1}}%
+ }
+%
+% \restrictattribute <parameter>:<attribute>
+% <value1>
+% <value2>
+% ...
+% <valueN>
+%\par
+%
+\pdef\restrictattribute{%
+ \yax@getall\yax@restrictattribute_getrestrictions
+ }
+\long\def\yax@restrictattribute_getrestrictions#1#2#3\par{%
+ \yax@space_loop{\yax@restrictattribute_readrestrictions{#1}{#2}}{#3 }%
+ }
+\long\def\yax@restrictattribute_readrestrictions#1#2#3{%
+ \letcs{yax@#1:#2:\detokenize{#3}@allowed}\relax
+ \ifcs{yax@#1:#2@restricted}
+ {\addrightcs{yax@#1:#2@restricted}{, #3}}
+ {\defcs{yax@#1:#2@restricted}{#3}}%
+ }
+%
+% \restrictallattributes <attribute>
+% <value1>
+% <value2>
+% ...
+% <valueN>
+%\par
+%
+\long\pdef\restrictallattributes#1 #2\par{%
+ \yax@space_loop{\yax@restrictallattributes_readrestrictions{#1}}{#2 }%
+ }
+\long\def\yax@restrictallattributes_readrestrictions#1#2{%
+ \letcs{yax@attribute@#1:\detokenize{#2}@allowed}\relax
+ \ifcs{yax@attribute@#1@restricted}
+ {\addrightcs{yax@attribute@#1@restricted}{, #2}}
+ {\defcs{yax@attribute@#1@restricted}{#2}}%
+ }
+%
+%
+%
+%
+% \defparameter<list of parameters>{<definition>}
+% \defactiveparameter<list of parameters>{<definition>}
+% \executeparameter <parameter> :
+%
+\newif\ifyax@activeparameter
+\def\defparameter#1#{%
+ \def\yax@parameter{#1 }%
+ \afterassignment\yax@defparameter_do
+ \def\yax@temp##1%
+ }%
+\def\yax@defparameter_do{%
+ \passexpanded{\yax@space_loop\yax@defparameter_def}\yax@parameter
+ \yax@activeparameterfalse
+ }
+
+\def\defactiveparameter{%
+ \yax@activeparametertrue\defparameter
+ }%
+\long\def\yax@defparameter_def#1{%
+ \edefcs{yax@#1@def}{\primunexpanded\expandafter{\yax@temp{#1}}}%
+ \ifyax@activeparameter
+ \letcs{yax@#1@active}\relax
+ \fi
+ }
+\def\executeparameter{%
+ \yax@getparameter\yax@executeparameter
+ }
+\def\yax@executeparameter#1{%
+ \iffcs{yax@#1@def}{\csname yax@#1@def\endcsname}%
+ }
+%
+%
+%
+%
+%%%%%%%%%%%%%%%%%% USING VALUES %%%%%%%%%%%%%%%%%%
+%
+% These are the loops used to check whether <parameter>:<attribute> exists,
+% and if not to search the meta-parameters. They are used of course in
+% \usevalue and associates.
+% I could use one loop only for all macros, but then I should have used more
+% internal code to pass arguments here and there.
+%
+% #1 = list of parameters already checked (used to spot loops in meta-search)
+% => becomes {#1{#3}} on each iteration.
+% #2 = command executed on yax@<parameter>:<attribute> if it exists.
+% => doesn't change from one iteration to the next.
+% #3 = <parameter>
+% => becomes \usecs{yax@<parameter>:<meta>} on each iteration, thus
+% returning a new <parameter> to be searched.
+% #4 = <attribute>
+% => doesn't change from one iteration to the next.
+% #5 = <or> if alone, <and> when #6 exists.
+% #6 = <or>.
+% => neither change.
+%
+% The loop does the following:
+% If <parameter>:<attribute> exists, then execute #2 on it followed by <and> if any.
+% Or, if <parameter> has a meta attribute, it calls
+% the \yax@ifattribute_checkmeta subloop with <or> and <parameter>
+% as passed arguments and <list of previous parameters> as the list argument.
+% This command compares each item in the list with <parameter>, and if they
+% have the same meta, it means we're in a meta-loop, we break and execute <or>.
+% If no match obtains, we rerun the original loop (with #3 turned to its meta).
+% Or, if <parameter> had no meta in the first place, we break and execute <or>.
+%
+\newwhile\yax@ifattribute_noarg4{#1{#3}}{#2}{\usecs{yax@#3:meta}}{#4}{%
+ \ifcs{yax@#3:#4}
+ {\breakwhile{#2{yax@#3:#4}}}
+ {\ifcs{yax@#3:meta}% <parameter> has no <attribute>.
+ {\yax@ifattribute_checkmeta{}{#3}{#1}}% It has a meta, though. We do some testing (see next macro).
+ {\breakwhile{}}}% No meta, we break the loop, gobble <true> and release <false>
+ }
+\newwhile\yax@ifattribute_or5{#1{#3}}{#2}{\usecs{yax@#3:meta}}{#4}{#5}{%
+ \ifcs{yax@#3:#4}
+ {\breakwhile{#2{yax@#3:#4}}}
+ {\ifcs{yax@#3:meta}
+ {\yax@ifattribute_checkmeta{#5}{#3}{#1}}
+ {\breakwhile{#5}}}%
+ }
+\newwhile\yax@ifattribute_and6{#1{#3}}{#2}{\usecs{yax@#3:meta}}{#4}{#5}{#6}{%
+ \ifcs{yax@#3:#4}
+ {\breakwhile{#2{yax@#3:#4}#5}}
+ {\ifcs{yax@#3:meta}
+ {\yax@ifattribute_checkmeta{#6}{#3}{#1}}
+ {\breakwhile{#6}}}%
+ }
+% The _if version pass <or> to the execution of the parameter,
+% since a test is supposed to happen.
+\newwhile\yax@ifattribute_if6{#1{#3}}{#2}{\usecs{yax@#3:meta}}{#4}{#5}{#6}{%
+ \ifcs{yax@#3:#4}
+ {\breakwhile{#2{yax@#3:#4}{#5}{#6}}}
+ {\ifcs{yax@#3:meta}
+ {\yax@ifattribute_checkmeta{#6}{#3}{#1}}
+ {\breakwhile{#6}}}%
+ }
+\newfor\yax@ifattribute_checkmeta{2}#3{%
+ \iffxcscs{yax@#2:meta}{yax@#3:meta}% Both parameters have the same meta. So we're in a meta-loop, and we break.
+ {\breakfor{\breakwhile{#1}}}%
+ }
+%
+% The nometa version are definitely simpler.
+%
+\long\def\yax@ifattributenometa_and#1#2#3#4#5{%
+ \ifcs{yax@#2:#3}{#1{yax@#2:#3}#4}{#5}%
+ }
+\long\def\yax@ifattributenometa_or#1#2#3#4{%
+ \ifcs{yax@#2:#3}{#1{yax@#2:#3}}{#4}%
+ }
+\def\yax@ifattributenometa_noarg#1#2#3{%
+ \iffcs{yax@#2:#3}{#1{yax@#2:#3}}%
+ }
+%
+%
+%
+%
+% \nometa
+%
+\def\nometa#1{%
+ \ifcs{yax@\commandtoname#1_nometa}
+ {\usecs{yax@\commandtoname#1_nometa}}
+ {\yax@error{You can't use \noexpand\nometa before \string#1}}%
+ }
+%
+%
+%
+% Defining \<com>, \<com>or and \<com>and at once,
+% with the \nometa-variant.
+%
+\def\yax@def_noarg#1#2{%
+ \def#1{\yax@getall{\yax@ifattribute_noarg{}{#2}}}%
+ \defcs{\commandtoname#1or}{\yax@getall{\yax@ifattribute_or{}{#2}}}%
+ \defcs{\commandtoname#1and}{\yax@getall{\yax@ifattribute_and{}{#2}}}%
+%
+ \defcs{yax@\commandtoname#1_nometa}{\yax@getall{\yax@ifattributenometa_noarg{#2}}}%
+ \defcs{yax@\commandtoname#1or_nometa}{\yax@getall{\yax@ifattributenometa_or{#2}}}%
+ \defcs{yax@\commandtoname#1and_nometa}{\yax@getall{\yax@ifattributenometa_and{#2}}}%
+ }
+\def\yax@def_onearg#1#2{%
+ \def#1##1{\yax@getall{\yax@ifattribute_noarg{}{#2{##1}}}}%
+ \defcs{\commandtoname#1or}##1{\yax@getall{\yax@ifattribute_or{}{#2{##1}}}}%
+ \defcs{\commandtoname#1and}##1{\yax@getall{\yax@ifattribute_and{}{#2{##1}}}}%
+%
+ \defcs{yax@\commandtoname#1_nometa}##1{\yax@getall{\yax@ifattributenometa_noarg{#2{##1}}}}%
+ \defcs{yax@\commandtoname#1or_nometa}##1{\yax@getall{\yax@ifattributenometa_or{#2{##1}}}}%
+ \defcs{yax@\commandtoname#1and_nometa}##1{\yax@getall{\yax@ifattributenometa_and{#2{##1}}}}%
+ }
+%
+%
+%
+%
+% \ifattribute
+%
+\def\ifattribute{%
+ \yax@getall{\yax@ifattribute_and{}\gobbleone}%
+ }%
+\def\yax@ifattribute_nometa{%
+ \yax@getall{\yax@ifattributenometa_and\gobbleone}%
+ }
+%
+%
+%
+%
+% \passvalue
+%
+\yax@def_onearg\passvalue\yax@passvalue
+\def\yax@passvalue#1#2{%
+ \passexpandedcs{#1}{#2}%
+ }
+\yax@def_onearg\passvaluenobraces\yax@passvalue_nobrace
+\def\yax@passvalue_nobrace#1#2{%
+ \passexpandedcs\swapargs{#2}{#1}%
+ }
+%
+%
+%
+%
+% \usevalue
+%
+\yax@def_noarg\usevalue\usecs
+%
+%
+%
+%
+% \settovalue (not expandable, obviously,
+% although it leaves nothing in the input but
+% the assignment.
+%
+\yax@def_onearg\settovalue\yax@settovalue
+\def\yax@settovalue#1#2{%
+ #1 \usecs{#2}\relax
+ }
+%
+%
+%
+%
+% \storevalue (like \settovalue, basically).
+%
+\yax@def_onearg\storevalue\yax@storevalue
+\def\yax@storevalue#1#2{%
+ \lettocs#1{#2}%
+ }%
+%
+%
+%
+%
+% \ifvalue
+%
+\def\ifvalue{%
+ \yax@getall{\yax@removesign\yax@ifvalue_getvalue}%
+ }%
+
+\def\yax@ifvalue_nometa{%
+ \yax@getall{\yax@removesign\yax@ifvaluenometa_getvalue}%
+ }%
+\long\def\yax@ifvalue_getvalue#1#2#3 {%
+ \ifemptystring{#3}
+ {\yax@ifvalue_getvalue{#1}{#2}}
+ {\yax@ifattribute_if{}{\passexpandedcs{\ifstring{#3}}}{#1}{#2}}%
+ }
+\def\yax@ifvaluenometa_getvalue#1#2#3 {%
+ \ifemptystring{#3}
+ {\yax@ifvaluenometa_getvalue{#1}{#2}}
+ {\ifcs{yax@#1:#2}{\passexpandedcs{\ifstring{#3}}{yax@#1:#2}}\secondoftwo}%
+ }
+%
+%
+%
+%
+% \ifcasevalue
+%
+\let\yax@ifcasevalue_passvalueor\passvalueor % just in case \passvalue is redefined by a \newsyntax.
+\let\yax@yax@ifcasevalue_passvalueor_nometa\yax@passvalueor_nometa
+\letcstocs{yax@yax@ifcasevalue_passvalueor_nometa}{yax@passvalueor_nometa}
+
+\def\ifcasevalue{%
+ \yax@getall\yax@ifcasevalue_getvalue
+ }
+\def\yax@ifcasevalue_nometa{%
+ \yax@getall{\expandafter\nometa\yax@ifcasevalue_getvalue}%
+ }
+\def\yax@ifcasevalue_getvalue#1#2{%
+ \yax@ifcasevalue_passvalueor\yax@ifcasevalue_scan#1:#2 \yax@ifcasevalue_novalue
+ }
+\newstring\val \newstring\elseval
+\long\def\yax@ifcasevalue_novalue#1\endval{%
+ \iffcontains{\elseval}{#1}{\splitstringat{\elseval}{#1}\yax@ifcasevalue_doelse}%
+ }
+\def\yax@ifcasevalue_doelse#1#2{\trim{#2}}
+\def\yax@ifcasevalue_scan#1#2\endval{%
+ \ifcontains{\elseval}{#2}
+ {\splitstringat{\elseval}{#2}\yax@ifcasevalue_dotest{#1}}
+ {\yax@ifcasevalue_dotest{#2}{}{#1}}%
+ }
+\def\yax@ifcasevalue_dotest#1#2#3{%
+ \yax@ifcasevalue_loop{#3}{#2}{{yax@dummy_value} #1\val}%
+ }
+\newfor\yax@ifcasevalue_loop{2}#3 #4\val{%
+ \iffstring{#1}{#3}{\passtrim{#4}\breakfor}%
+ }[\passtrim{#2}\unbrace]
+%
+%
+%
+%
+% \parameterloop<list of parameters>:<command>
+%
+\def\parameterloop{%
+ \yax@getparameter\yax@parameterloop
+ }
+\long\def\yax@parameterloop#1#2{%
+ \yax@space_loop{\yax@parameterloop_launch{#2}}{#1 }%
+ }
+\long\def\yax@parameterloop_launch#1#2{%
+ \iffcs{yax@#2@attributelist}
+ {\passexpandedcs{\yax@parameterloop_do{#1}{#2}}{yax@#2@attributelist}}%
+ }
+\newfor\yax@parameterloop_do{2}#3{%
+ \passvalue{#1{#2}{#3}}{#2}:{#3}
+ }
+%
+%
+%
+%
+% \newsyntax
+%
+\long\def\newsyntax#1#{%
+ \yax@newsyntax{#1}%
+ }
+\long\def\yax@newsyntax_noarg#1#2#3{%
+ \defcs{#1}#2{\yax@ifattribute_noarg{}{#3}{##1}{##2}}%
+ \defcs{#1or}#2{\yax@ifattribute_or{}{#3}{##1}{##2}}%
+ \defcs{#1and}#2{\yax@ifattribute_and{}{#3}{##1}{##2}}%
+%
+ \defcs{yax@#1_nometa}#2{\yax@ifattributenometa_noarg{#3}{##1}{##2}}%
+ \defcs{yax@#1or_nometa}#2{\yax@ifattributenometa_or{#3}{##1}{##2}}%
+ \defcs{yax@#1and_nometa}#2{\yax@ifattributenometa_and{#3}{##1}{##2}}%
+ }
+\long\def\yax@newsyntax_onearg#1#2#3{%
+ \defcs{#1}##1#2{\yax@ifattribute_noarg{}{#3{##1}}{##2}{##3}}%
+ \defcs{#1or}##1#2{\yax@ifattribute_or{}{#3{##1}}{##2}{##3}}%
+ \defcs{#1and}##1#2{\yax@ifattribute_and{}{#3{##1}}{##2}{##3}}%
+%
+ \defcs{yax@#1_nometa}##1#2{\yax@ifattributenometa_noarg{#3{##1}}{##2}{##3}}%
+ \defcs{yax@#1or_nometa}##1#2{\yax@ifattributenometa_or{#3{##1}}{##2}{##3}}%
+ \defcs{yax@#1and_nometa}##1#2{\yax@ifattributenometa_and{#3{##1}}{##2}{##3}}%
+ }
+\long\def\yax@newsyntax#1#2{%
+ \defcs{#2restrictattribute}#1{\yax@restrictattribute_getrestrictions{##1}{##2}}%
+ \defcs{#2deleteattribute}#1{\letcs{yax@##1:##2}\yax@undefined}%
+ \defcs{#2setattribute}#1{\yax@removesign{\skipspace{\yax@setattribute\defcs}}{##1}{##2}}%
+ \defcs{#2esetattribute}#1{\yax@removesign{\skipspace{\yax@setattribute\edefcs}}{##1}{##2}}%
+ \defcs{#2gsetattribute}#1{\yax@removesign{\skipspace{\yax@setattribute\gdefcs}}{##1}{##2}}%
+ \defcs{#2xsetattribute}#1{\yax@removesign{\skipspace{\yax@setattribute\xdefcs}}{##1}{##2}}%
+ \defcs{#2ifattribute}#1{\yax@ifattribute_and{}\gobbleone{##1}{##2}}%
+ \defcs{yax@#2ifattribute_nometa}#1{\yax@ifattributenometa_and\gobbleone{##1}{##2}}%
+ \yax@newsyntax_noarg{#2usevalue}{#1}\usecs
+ \def\yax@temp##1##2{#1}%
+ \passexpanded{\yax@newsyntax_onearg{#2passvalue}}{\yax@temp{##2}{##3}}\yax@passvalue
+ \passexpanded{\yax@newsyntax_onearg{#2passvaluenobraces}}{\yax@temp{##2}{##3}}\yax@passvalue_nobrace
+ \passexpanded{\yax@newsyntax_onearg{#2settovalue}}{\yax@temp{##2}{##3}}\yax@settovalue
+ \passexpanded{\yax@newsyntax_onearg{#2storevalue}}{\yax@temp{##2}{##3}}\yax@storevalue
+ \defcs{#2ifvalue}#1{\yax@removesign\yax@ifvalue_getvalue{##1}{##2}}%
+ \defcs{yax@#2ifvalue_nometa}#1{\yax@removesign\yax@ifvaluenometa_getvalue{##1}{##2}}%
+ \defcs{#2ifcasevalue}#1{\yax@ifcasevalue_getvalue{##1}{##2}}%
+ \defcs{yax@#2ifcasevalue_nometa}#1{\expandafter\nometa\yax@ifcasevalue_getvalue{##1}{##2}}%
+ }
+
+\def\yax@let#1#2#3{%
+ \letcstocs{#2#1}{#3#1}%
+ \letcstocs{yax@#2#1_nometa}{yax@#3#1_nometa}%
+ }
+\def\yax@let_all#1#2#3{%
+ \yax@let{#1}{#2}{#3}\yax@let{#1or}{#2}{#3}\yax@let{#1and}{#2}{#3}%
+ }
+\def\copysyntax#1#2{%
+ \letcstocs{#1restrictattribute}{#2restrictattribute}%
+ \letcstocs{#1deleteattribute}{#2deleteattribute}%
+ \letcstocs{#1setattribute}{#2setattribute}%
+ \letcstocs{#1esetattribute}{#2esetattribute}%
+ \letcstocs{#1gsetattribute}{#2gsetattribute}%
+ \letcstocs{#1xsetattribute}{#2xsetattribute}%
+ \yax@let{ifattribute}{#1}{#2}%
+ \yax@let_all{usevalue}{#1}{#2}\yax@let_all{passvalue}{#1}{#2}\yax@let_all{passvaluenobraces}{#1}{#2}%
+ \yax@let_all{settovalue}{#1}{#2}\yax@let_all{storevalue}{#1}{#2}%
+ \yax@let{ifvalue}{#1}{#2}%
+ \yax@let{ifcasevalue}{#1}{#2}%
+ }
+
+\def\letyaxcommand#1#2{%
+ \let#1#2% Base \let.
+ \ifcs{yax@\commandtoname#2and_nometa} % #2 is a YaX command with -and -or variants.
+ {\letcstocs{\commandtoname#1or}{\commandtoname#2or}%
+ \letcstocs{\commandtoname#1and}{\commandtoname#2and}%
+ \letcstocs{yax@\commandtoname#1_nometa}{yax@\commandtoname#2_nometa}%
+ \letcstocs{yax@\commandtoname#1or_nometa}{yax@\commandtoname#2or_nometa}%
+ \letcstocs{yax@\commandtoname#1and_nometa}{yax@\commandtoname#2and_nometa}}%
+ {\iffcs{yax@\commandtoname#2_nometa}% #2 is a YaX command without variants but with \nometa (i.e. the \if...).
+ {\letcstocs{yax@\commandtoname#1_nometa}{yax@\commandtoname#2_nometa}}}%
+ }
+
+\restorecatcodes
+\endinput