summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/gates
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-12-11 22:34:58 +0000
committerKarl Berry <karl@freefriends.org>2012-12-11 22:34:58 +0000
commit9c2e43824938d7b86a78035bc5318a5fb370d36b (patch)
treef53b6e011b952ee79c792ca8de584a902bd358c4 /Master/texmf-dist/tex/generic/gates
parent7fb7feb9e84e495b3140986af5f65206fe8e8379 (diff)
gates.tex in runtime
git-svn-id: svn://tug.org/texlive/trunk@28502 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/gates')
-rw-r--r--Master/texmf-dist/tex/generic/gates/gates.tex925
1 files changed, 925 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/gates/gates.tex b/Master/texmf-dist/tex/generic/gates/gates.tex
new file mode 100644
index 00000000000..c535686cddb
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/gates/gates.tex
@@ -0,0 +1,925 @@
+% This is the Gates package.
+% Relevant information can be found in gates-doc.pdf
+% (or gates-doc.txt in a text editor).
+%
+% Author: Paul Isambert.
+% E-mail: zappathustra AT free DOT fr
+% Comments and suggestions are welcome.
+% Date: May 2012.
+
+\csname Come on, Gates is already loaded\endcsname
+\expandafter\let\csname Come on, Gates is already loaded\endcsname\endinput
+\input texapi
+\setcatcodes{_@=11}
+
+\def\gates@error{\senderror{Gates}}%
+\def\gates@error_nogate#1{\gates@error{`#1' isn't a gate}}
+\def\gates@error_nogatelist#1{\gates@error{`#1' isn't a gate list}}
+\def\gates@error_nogatein#1#2{\gates@error{No gate `#1' in list `#2'}}
+
+\def\gates@family_update#1{%
+ \def\gates@family_current{#1}%
+ }
+\newstring{:}
+\def\gates@family_check{%
+ \gates@family_pass\unbrace
+ }
+\def\gates@family_pass#1#2{%
+ \passexpanded{\passtrim{#2}{\gates@family_passdo{#1}}}{\gates@family_current}%
+ }
+\def\gates@family_passdo#1#2#3{%
+ \passexpanded{\ifcontains{:}}{#2}
+ {#1{#2}}{#1{#3:#2}}%
+ }
+\def\gates@ifexists#1#2{%
+ \ifcs{gate \gates@family_check{#1}:#2}%
+ }
+
+
+\def\gates@gates#1#2{%
+ \ifstring{#2}[
+ {\gates@family_update{#1}%
+ \gates@gates_macro}
+ {\ifstring{#2}(
+ {\gates@family_update{#1}%
+ \gates@gates_list}
+ {\gates@gates_check{#1}}}#2%
+ }
+\def\gates@gates_macro[#1]{%
+ \passtrim{#1}\gates@action@def
+ }
+\def\gates@gates_list(#1){%
+ \passtrim{#1}\gates@action@list
+ }
+\def\gates@gates_check#1#2 {%
+ \ifelseif{%
+ {\ifcs{gates@action@#2}}
+ {\gates@family_update{#1}\usecs{gates@action@#2}}
+ {\ifcs{gates@action@#2_withfamily}}
+ {\usecs{gates@action@#2_withfamily}{#1}}
+ {\ifcs{gate \gates@family_passdo\unbrace{#2}{#1}:code}}
+ {\gates@family_update{#1}\gates@action@execute{#2}}
+ \iftrue
+ {\gates@error{Action `\gates@family_passdo\unbrace{#2}{#1}' doesn't exist and there is no gate with that name}}}%
+ }
+
+\def\gates{%
+ \gates@gates{gates}%
+ }
+
+\def\gates@action#1{%
+ \long\defcs{gates@action@#1}%
+ }
+\def\gates@action_withfamily#1{%
+ \long\defcs{gates@action@#1_withfamily}%
+ }
+
+\gates@action{new}#1#2{%
+ \def#1{%
+ \gates@gates{#2}%
+ }%
+ }
+
+\gates@action_withfamily{family}#1{#1}
+
+%%%
+%%% The gate stack.
+%%%
+\def\gates@stack{}
+\protected\def\gates@stack_push#1{%
+ \xdef\gates@current_gate{#1}%
+ \xdef\gates@stack{{#1}{\gates@stack}}%
+ }
+\protected\def\gates@stack_pop{%
+ \expandafter\gates@stack_popit\gates@stack\gates@end
+ }
+\def\gates@stack_popit#1#2\gates@end{%
+ \gdef\gates@stack{#2}%
+ \gates@stack_getcurrent#2{}\gates@end
+ }
+\def\gates@stack_getcurrent#1#2\gates@end{%
+ \gdef\gates@current_gate{#1}%
+ }
+
+%%%
+%%% Tracing and showing.
+%%%
+\def\gates@trace_value{0}
+\gates@action{trace}#1{%
+ \defcs{gates@trace_value:\gates@family_current}{#1}%
+ }
+\def\gates@trace_tab{}
+\def\gates@trace_white{}
+\def\gates@trace_addtab{%
+ \edef\gates@trace_tab{\gates@trace_tab. }%
+ \edef\gates@trace_white{\gates@trace_white\unbrace{ } }%
+ }
+\def\gates@trace_untab{%
+ \passexpanded{\removeprefixin{. }}\gates@trace_tab\gates@trace_tab
+ \passexpanded{\passexpanded\removeprefixin{\unbrace{ } }}\gates@trace_white\gates@trace_white
+ }
+\def\gates@trace_write#1#2{%
+ \iffcs{gates@trace_value:\gates@trace_getfamily#1\gates@terminator}
+ {\ifnum\usecs{gates@trace_value:\gates@trace_getfamily#1\gates@terminator}>0
+ \immediate\write16{\gates@trace_white #2}%
+ \fi}}
+\def\gates@trace_writetab#1#2{%
+ \iffcs{gates@trace_value:\gates@trace_getfamily#1\gates@terminator}
+ {\ifnum\usecs{gates@trace_value:\gates@trace_getfamily#1\gates@terminator}>0
+ \immediate\write16{\gates@trace_tab #2}%
+ \fi}}
+\def\gates@trace_getfamily#1:#2\gates@terminator{#1}
+
+\gates@action{show}#1{%
+ \immediate\write16{}%
+ \gates@family_pass\gates@show{#1}%
+ }
+\def\gates@show#1{%
+ \ifcs{gate #1:list}
+ {\gates@show_write{#1 is an l-gate}{}{#1}%
+ \passexpandedcs{\gates@show_loop{#1}{. }}{gate #1:list}}%
+ {\ifcs{gate #1:code}
+ {\gates@show_write{#1 is an m-gate}{}{#1}}{\gates@error_nogate{#1}}}%
+ }
+\newfor\gates@show_loop{2}#3,{%
+ \gates@show_write{#2#3}{#1_subgate_}{#3}%
+ \iffcs{gate #3:list}{\passexpandedcs{\gates@show_loop{#3}{#2. }}{gate #3:list}}%
+ }
+\def\gates@show_write#1#2#3{%
+ \immediate\write16{#1
+ \reverse\iffemptystring{#2}{(\ifcs{gate #3:list}lm-gate) }%
+ [\usecs{gate #3:args}]
+ (status: \ifcase\usecs{gate #2#3:status}
+ \or open\or ajar\or skip\or close\fi)%
+ \gates@show_condition{#2#3}{conditional}%
+ \gates@show_condition{#2#3}{loop}%
+ \gates@show_condition{#2#3}{loopuntil}%
+ }%
+ }
+
+\def\gates@show_condition#1#2{%
+ \iffcs{gate #1:#2}
+ { (#2: \expandafter\expandafter\expandafter\gates@show_conditionstrip
+ \expandafter\meaning\csname gate #1:#2\endcsname)}%
+ }
+\def\gates@show_conditionstrip#1->{}%
+
+
+%%%
+%%% Checking conditions in gate definition.
+%%%
+\long\def\gates@conditions_get#1{%
+ \ifnextnospace?
+ {\gates@conditions_getlaunch{#1}}
+ {#1{{}{}{}{}}}%
+ }
+\newstring{,}
+\long\def\gates@conditions_getlaunch#1?#2{%
+ \ifsuffix,{#2}
+ {\gates@conditions_getloop{#1}{}{}{}{}{#2}}
+ {\gates@conditions_getloop{#1}{}{}{}{}{#2,}}%
+ }
+\newfornoempty\gates@conditions_getloop{5}#6=#7,{%
+ \ifelseif{%
+ {\passtrim{#6}\ifstring{status}} {\passarguments{#1}{\trim{#7}}{#3}{#4}{#5}}
+ {\passtrim{#6}\ifstring{conditional}} {\passarguments{#1}{#2}{#7}{#4}{#5}}
+ {\passtrim{#6}\ifstring{loop}} {\passarguments{#1}{#2}{#3}{#7}{#5}}
+ {\passtrim{#6}\ifstring{loopuntil}} {\passarguments{#1}{#2}{#3}{#4}{#7}}
+ \iftrue {\gates@error{`#6' isn't a condition}}%
+ }
+ }[#1{{#2}{#3}{#4}{#5}}]
+\long\def\gates@conditions_make#1#2#3#4#5{%
+ \gates@list_checkmaster
+ {\gates@action@add{#1}{\gates@list_master}%
+ \reverse\iffemptystring{#2}{\usecs{gates@action@#2}{#1}{\gates@list_master}}%
+ \reverse\iffemptystring{#3}{\gates@action@conditional{#1}{\gates@list_master}{#3}}
+ \reverse\iffemptystring{#4}{\gates@action@loop{#1}{\gates@list_master}{#4}}
+ \reverse\iffemptystring{#5}{\gates@action@loopuntil{#1}{\gates@list_master}{#5}}}
+ {\straightenif{ifnum}{\gates@list_subcount>0 }
+ {\gates@error{Wrong level of embedding for gate `#1'}}%
+ {\reverse\iffemptystring{#2}{\usecs{gates@action@#2!}{#1}}%
+ \reverse\iffemptystring{#3}{\usecs{gates@action@conditional!}{#1}{#3}}
+ \reverse\iffemptystring{#4}{\usecs{gates@action@loop!}{#1}{#4}}%
+ \reverse\iffemptystring{#5}{\usecs{gates@action@loopuntil!}{#1}{#5}}}}%
+ }
+
+%%%
+%%% Defining list-gates.
+%%%
+\newcount\gates@list_subcount
+\def\gates@list_masterlist{}%
+\gates@action{list}#1{%
+ \ifnextnospace[
+ {\gates@family_pass\gates@list_checkarg{#1}}
+ {\gates@family_pass\gates@list_checkarg{#1}[0]}%
+ }
+
+\def\gates@list_checkarg#1[#2]{%
+ \ifcs{gates@execute_get_#2_args}
+ {\gates@conditions_get{\gates@list_create{#1}{#2}}}
+ {\gates@list_create{#1}{0}{{}{}{}{}}[#2]}%
+ }
+
+\long\def\gates@list_create#1#2#3{%
+ \straightenif{ifnum}{#2<10 }
+ {\xdefcs{gate #1:args}{#2}%
+ \gdefcs{gate #1:status}{\gates@state_open}%
+ \gdefcs{gate #1:conditional}##1##2##3##4##5##6##7##8##9{\iftrue}%
+ \gdefcs{gate #1:list}{}%
+ \long\xdefcs{gate #1:code}##1##2##3##4##5##6##7##8##9{%
+ \ifcase#2
+ \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{}{}{}{}{}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{}{}{}{}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{}{}{}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{}{}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{##5}{}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{##5}{##6}{}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}{}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{}}}{gate #1:list}%
+ \or \noexpand\passexpandedcs{\noexpand\gates@process{#1}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}}}{gate #1:list}%
+ \fi}%
+ \gates@conditions_make{#1}#3%
+ \eaddright\gates@list_masterlist{{#1}}%
+ \gates@list_checknext}
+ {\gates@error{Gates can't take more than 9 arguments}}%
+ }
+
+\def\gates@list_checknext{%
+ \gates@list_subcount=1
+ \skipspace{\futurelet\gates@list_nextchar\gates@list_checknextchar}%
+ }
+
+\def\gates@list_checknextchar{%
+ \expandafter\gates@list_checknextcharloop\expandafter{\gates@list_charlist}%
+ }
+
+\def\gates@list_charlist{.}
+\gates@action{subchar}#1{%
+ \ifexpression{%
+ \if\noexpand#1[%
+ | \if\noexpand#1(%
+ | \if\noexpand#1<%
+ | \if\noexpand#1?}
+ {\gates@error{You can't use `#1' as a continuation char}}
+ {\eaddright\gates@list_charlist{\string#1}}%
+ }
+
+\newfor\gates@list_checknextcharloop#1{%
+ \if\noexpand\gates@list_nextchar\noexpand#1%
+ \advance\gates@list_subcount1
+ \afterfi{\breakfor{\gobbleoneand{%
+ \skipspace{\futurelet\gates@list_nextchar\gates@list_checknextchar}}}}%
+ \fi
+ }[\gates@list_getsub]
+
+\def\gates@list_getsub{%
+ \ifnext[
+ {\gates@list_getsubdef}
+ {\ifnext(
+ {\gates@list_getsublist}
+ {\ifnext<
+ {\gates@list_getsubgate}
+ {\gates@list_subcount=0
+ \def\gates@list_masterlist{}}}}%
+ }
+
+\def\gates@list_getsublist(#1){%
+ \gates@action@list{#1}%
+ }
+
+\def\gates@list_getsubdef[#1]{%
+ \gates@def\gdefcs{#1}%
+ }
+
+\def\gates@list_getsubgate<#1>{%
+ \gates@conditions_get{\gates@list_dosubgate{#1}}%
+ }
+
+\def\gates@list_dosubgate#1#2{%
+ \gates@list_subgateloop#2{}{#1,}%
+ }
+
+\newfornoempty\gates@list_subgateloop{5}#6,{%
+ \gates@ifexists{#6}{code}
+ {\gates@family_pass\gates@conditions_make{#6}{#1}{#2}{#3}{#4}%
+ \passarguments{#1}{#2}{#3}{#4}{#6}}
+ {\gates@error_nogate{\gates@family_check{#6}}}%
+ }[\gates@ifexists{#5}{list}
+ {\eaddright\gates@list_masterlist{{\gates@family_check{#5}}}}{}%
+ \gates@list_checknext]
+
+\def\gates@list_checkmaster{%
+ \let\gates@list_master\gates@HopefullyThisRemainsUndefined
+ \passexpanded{\gates@list_getmaster{}{1}}\gates@list_masterlist
+ }
+
+\newfor\gates@list_getmaster{2}#3{%
+ \ifnum\gates@list_subcount=\numexpr#2\relax
+ \def\gates@list_master{#3}%
+ \afterfi{\breakfor{\def\gates@list_masterlist{#1{#3}}\firstoftwo}}%
+ \else
+ \afterfi{\passarguments{#1{#3}}{#2+1}}%
+ \fi
+ }[\def\gates@list_masterlist{#1}\secondoftwo]%
+
+
+%%%
+%%% Defining macro-gates.
+%%%
+\gates@action{def}{\gates@def\gdefcs}
+\gates@action{edef}{\gates@def\xdefcs}
+
+\def\gates@def#1#2{%
+ \ifnextnospace[
+ {\gates@family_pass{\gates@def_getargs{#1}}{#2}}
+ {\gates@family_pass{\gates@def_getargs{#1}}{#2}[0]}%
+ }
+
+\def\gates@def_getargs#1#2[#3]{%
+ \gates@conditions_get{\gates@def_prepare{#1}{#2}{#3}}%
+ }
+
+\long\def\gates@def_prepare#1#2#3#4#5{%
+ \ifelseif{% Can't use \ifcase, because #5 might contain an unbalanced conditional.
+ {\ifnum#3=0 } {\gates@def_do#1{#2}{#3}{}{}{#5}{#4}}
+ {\ifnum#3=1 } {\gates@def_do#1{#2}{#3}{##1}{{##1}}{#5}{#4}}
+ {\ifnum#3=2 } {\gates@def_do#1{#2}{#3}{##1##2}{{##1}{##2}}{#5}{#4}}
+ {\ifnum#3=3 } {\gates@def_do#1{#2}{#3}{##1##2##3}{{##1}{##2}{##3}}{#5}{#4}}
+ {\ifnum#3=4 } {\gates@def_do#1{#2}{#3}{##1##2##3##4}{{##1}{##2}{##3}{##4}}{#5}{#4}}
+ {\ifnum#3=5 } {\gates@def_do#1{#2}{#3}{##1##2##3##4##5}{{##1}{##2}{##3}{##4}{##5}}{#5}{#4}}
+ {\ifnum#3=6 } {\gates@def_do#1{#2}{#3}{##1##2##3##4##5##6}{{##1}{##2}{##3}{##4}{##5}{##6}}{#5}{#4}}
+ {\ifnum#3=7 } {\gates@def_do#1{#2}{#3}{##1##2##3##4##5##6##7}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}}{#5}{#4}}
+ {\ifnum#3=8 } {\gates@def_do#1{#2}{#3}{##1##2##3##4##5##6##7##8}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}}{#5}{#4}}
+ {\ifnum#3=9 } {\gates@def_do#1{#2}{#3}{##1##2##3##4##5##6##7##8##9}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}}{#5}{#4}}
+ {\iftrue} {\gates@error{Wrong number of arguments}}}%
+ }
+
+% #1: \gdef or \xdef
+% #2: gate's name
+% #3: number of arguments
+% #4: parameter text (e.g., ##1, ##1##2, etc.) for internal code
+% #5: replacement text (e.g., {##1}, {##1}{##2}, etc.) for internal code
+% #6: definition of internal code
+% #7: conditions
+\long\def\gates@def_do#1#2#3#4#5#6#7{%
+ \xdefcs{gate #2:args}{#3}%
+ \gdefcs{gate #2:status}{\gates@state_open}%
+ \gdefcs{gate #2:conditional}##1##2##3##4##5##6##7##8##9{\iftrue}%
+ \long#1{gate #2:code}##1##2##3##4##5##6##7##8##9{%
+ \iffcs{gates@trace_value:\gates@trace_getfamily#2\gates@terminator}
+ {\ifnum\usecs{gates@trace_value:\gates@trace_getfamily#2\gates@terminator}=2
+ \gates@trace_args{1}{#2}{#5}%
+ \fi}%
+ \usecs{gate #2:innercode}#5}%
+ \long#1{gate #2:innercode}#4{#6}%
+ \gates@conditions_make{#2}#7%
+ \reverse\iffemptycommand\gates@list_masterlist{\gates@list_checknext}%
+ }
+
+\newfor\gates@trace_args{2}#3{%
+ \gates@trace_write{#2}{\string##\the\numexpr#1<-\unexpanded{#3}}%
+ \passarguments{#1+1}{#2}%
+ }
+
+\gates@action_withfamily{type}#1#2{%
+ \ifcs{gate \gates@family_passdo\unbrace{#2}{#1}:code}
+ {\ifcs{gate \gates@family_passdo\unbrace{#2}{#1}:list}{2}{1}}
+ {0}%
+ }
+
+%%%
+%%% Copying gates.
+%%%
+\gates@action{copy}#1#2{%
+ \gates@family_pass{\gates@family_pass\gates@copy_do{#1}}{#2}%
+ }
+\def\gates@copy_do#1#2{%
+ \gates@ifexists{#2}{code}
+ {\global\letcstocs{gate #1:args}{gate #2:args}%
+ \gdefcs{gate #1:status}{\gates@state_open}% Better than to copy the gate's status.
+ \global\letcstocs{gate #1:conditional}{gate #2:conditional}%
+ \global\letcstocs{gate #1:loop}{gate #2:loop}%
+ \global\letcstocs{gate #1:loopuntil}{gate #2:loopuntil}%
+ \global\letcstocs{gate #1:code}{gate #2:code}
+ \gates@ifexists{#2}{list}
+ {\global\letcstocs{gate #1:list}{gate #2:list}%
+ \passexpandedcs{\gates@let_list{#1}{#2}}{gate #2:list}}
+ {\global\letcstocs{gate #1:internalcode}{gate #2:internalcode}}}%
+ {\gates@error_nogate{#2}}%
+ }
+
+\newfor\gates@let_list{2}#3,{%
+ \global\letcstocs{gate #1_subgate_#3:status}{gate #2_subgate_#3:status}%
+ \global\letcstocs{gate #1_subgate_#3:conditional}{gate #2_subgate_#3:conditional}%
+ \global\letcstocs{gate #1_subgate_#3:loop}{gate #2_subgate_#3:loop}%
+ \global\letcstocs{gate #1_subgate_#3:loopuntil}{gate #2_subgate_#3:loopuntil}%
+ }
+
+%%%
+%%% Executing gates.
+%%%
+\def\gates@ifinlist{%
+ \ifdefined\gates@current_gate
+ \ifcsname gate \gates@current_gate:list\endcsname
+ \expandafter\expandafter\expandafter\firstoftwo
+ \else
+ \expandafter\expandafter\expandafter\secondoftwo
+ \fi
+ \else
+ \expandafter\secondoftwo
+ \fi
+ }
+\gates@action{execute}#1{%
+ \gates@family_pass\gates@execute{#1}%
+ }
+\def\gates@execute#1{%
+ \gates@ifexists{#1}{code}
+ {\gates@ifinlist
+ {\usecs{gates@execute_get_9_args}{#1}}
+ {\usecs{gates@execute_get_\usecs{gate #1:args}_args}{#1}}}
+ {\gates@error_nogate{#1}}%
+ }
+\long\defcs{gates@execute_get_0_args}#1{%
+ \gates@execute_do{#1}{{}{}{}{}{}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_1_args}#1#2{%
+ \gates@execute_do{#1}{{#2}{}{}{}{}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_2_args}#1#2#3{%
+ \gates@execute_do{#1}{{#2}{#3}{}{}{}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_3_args}#1#2#3#4{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{}{}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_4_args}#1#2#3#4#5{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{#5}{}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_5_args}#1#2#3#4#5#6{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{#5}{#6}{}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_6_args}#1#2#3#4#5#6#7{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{#5}{#6}{#7}{}{}{}}%
+ }
+\long\defcs{gates@execute_get_7_args}#1#2#3#4#5#6#7#8{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{}{}}%
+ }
+\long\defcs{gates@execute_get_8_args}#1#2#3#4#5#6#7#8#9{%
+ \gates@execute_do{#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}{}}%
+ }
+\long\defcs{gates@execute_get_9_args}#1#2#3#4#5#6#7#8#9{%
+ \gates@execute_get_nine_arg{#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}%
+ }
+\long\def\gates@execute_get_nine_arg#1#2#3{%
+ \gates@execute_do{#1}{#2{#3}}%
+ }
+
+\long\def\gates@execute_do#1#2{%
+ \ifcase\usecs{gate #1:status}
+ \or % open
+ \gates@processtrue
+ \def\gates@trace_status{}%
+ \or % ajar
+ \gates@processtrue
+ \gdefcs{gate #1:status}{\gates@state_close}%
+ \def\gates@trace_status{ (ajar -> close)}%
+ \or % skip
+ \gates@processfalse
+ \gdefcs{gate #1:status}{\gates@state_open}%
+ \def\gates@trace_status{ (skip -> open)}%
+ \or % close
+ \gates@processfalse
+ \def\gates@trace_status{ (close)}%
+ \fi
+%
+ \iffemptycommand\gates@trace_tab{\gates@trace_write{#1}{}}%
+%
+ \edef\gates@process_tempconditional{\primunexpanded\expandafter\expandafter\expandafter{\csname gate #1:conditional\endcsname#2}}%
+ \ifexpression{\ifgates@process & \expandafter\ifexpression\expandafter{\gates@process_tempconditional}}
+ {\gates@trace_write{#1}{Executing \ifcs{gate #1:list}{l-}{m-}gate #1\gates@trace_status}%
+ \gates@stack_push{#1}%
+ \gates@execute_launchloop{#1}{#2}}
+ {\gates@trace_write{#1}{Ignoring \ifcs{gate #1:list}{l-}{m-}gate #1\gates@trace_status
+ \expandafter\reverse\expandafter\iffexpression{\gates@process_tempconditional}{ (False conditional)}}%
+ \gates@ifinlist{\gates@execute_backtolist{#2}}{}}%
+ }
+
+\long\def\gates@execute_launchloop#1#2{%
+ \iffcs{gate #1:list}\gates@trace_addtab
+ \ifcs{gate #1:loop}
+ {\gates@execute_loop{#1}{#2}}
+ {\usecs{gate #1:code}#2\gates@execute_stoploop{#1}{#2}}%
+ }
+\long\def\gates@execute_loop#1#2{%
+ \expandafter\expandafter\expandafter\ifexpression
+ \expandafter\expandafter\expandafter{\csname gate #1:loop\endcsname#2}
+ {\usecs{gate #1:code}#2\gates@execute_stoploop{#1}{#2}}%
+ {\gates@execute_end{#2}}%
+ }
+\long\def\gates@execute_loopuntil#1#2{%
+ \expandafter\expandafter\expandafter\ifexpression
+ \expandafter\expandafter\expandafter{\csname gate #1:loopuntil\endcsname#2}
+ {\gates@execute_end{#2}}%
+ {\usecs{gate #1:code}#2\gates@execute_stoploop{#1}{#2}}%
+ }
+\long\def\gates@execute_stoploop#1#2{%
+ \ifcs{gate #1:loop}
+ {\gates@execute_loop{#1}{#2}}
+ {\ifcs{gate #1:loopuntil}
+ {\gates@execute_loopuntil{#1}{#2}}
+ {\gates@execute_end{#2}}}%
+ }
+\long\def\gates@execute_end#1{%
+ \iffcs{gate \gates@current_gate:list}\gates@trace_untab
+ \gates@stack_pop
+ \iffcs{gate \gates@current_gate:list}
+ {\gates@execute_backtolist{#1}}%
+ }
+\long\def\gates@execute_backtolist#1#2#3{%
+ \gates@process_stoploop{#2}{#3}{#1}{#2}{#3}%
+ }
+
+\gates@action{return}{\usecs{gates@action@return\usecs{gate \gates@current_gate:args}}}
+\gates@action{return!}#1{%
+ \gates@process_returncount#1{gates@end}{gates@end}{gates@end}{gates@end}{gates@end}{gates@end}{gates@end}{gates@end}{gates@end}\gates@reallytheend#1%
+ }%
+\long\def\gates@process_returncount#1#2#3#4#5#6#7#8#9{%
+ \gates@process_returngobble{%
+ \ifelseif{%
+ {\ifstring{#1}{gates@end}} {\usecs{gates@action@return0}}
+ {\ifstring{#2}{gates@end}} {\usecs{gates@action@return1}}
+ {\ifstring{#3}{gates@end}} {\usecs{gates@action@return2}}
+ {\ifstring{#4}{gates@end}} {\usecs{gates@action@return3}}
+ {\ifstring{#5}{gates@end}} {\usecs{gates@action@return4}}
+ {\ifstring{#6}{gates@end}} {\usecs{gates@action@return5}}
+ {\ifstring{#7}{gates@end}} {\usecs{gates@action@return6}}
+ {\ifstring{#8}{gates@end}} {\usecs{gates@action@return7}}
+ {\ifstring{#9}{gates@end}} {\usecs{gates@action@return8}}
+ \ifrue {\usecs{gates@action@return9}}}
+ }%
+ }
+\gates@action{return0}{%
+ \gates@return_pass{\unbrace{}}%
+ }
+\gates@action{return1}#1{%
+ \gates@return_pass{\gobbleoneand{{#1}}}%
+ }
+\gates@action{return2}#1#2{%
+ \gates@return_pass{\gobbletwoand{{#1}{#2}}}%
+ }
+\gates@action{return3}#1#2#3{%
+ \gates@return_pass{\gobblethreeand{{#1}{#2}{#3}}}%
+ }
+\gates@action{return4}#1#2#3#4{%
+ \gates@return_pass{\gobblefourand{{#1}{#2}{#3}{#4}}}%
+ }
+\gates@action{return5}#1#2#3#4#5{%
+ \gates@return_pass{\gobblefiveand{{#1}{#2}{#3}{#4}{#5}}}%
+ }
+\gates@action{return6}#1#2#3#4#5#6{%
+ \gates@return_pass{\gobblesixand{{#1}{#2}{#3}{#4}{#5}{#6}}}%
+ }
+\gates@action{return7}#1#2#3#4#5#6#7{%
+ \gates@return_pass{\gobblesevenand{{#1}{#2}{#3}{#4}{#5}{#6}{#7}}}%
+ }
+\gates@action{return8}#1#2#3#4#5#6#7#8{%
+ \gates@return_pass{\gobbleeightand{{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}%
+ }
+\gates@action{return9}#1#2#3#4#5#6#7#8#9{%
+ \gates@return_passnine{{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}%
+ }
+\long\def\gates@return_pass#1#2\gates@execute_stoploop#3#4{%
+ \passexpanded{\gates@execute_stoploop{#3}}{#1#4}%
+ }
+\long\def\gates@return_passnine#1#2\gates@execute_stoploop#3#4{%
+ \gates@execute_stoploop{#3}{#1}%
+ }
+
+
+%%%
+%%% Processing l-gates.
+%%%
+\newife\ifgates@process
+\newfornoempty\gates@process{2}#3,{%
+ \ifcase\usecs{gate #1_subgate_#3:status}
+ \or % open
+ \gates@processtrue
+ \def\gates@trace_status{}%
+ \or % ajar
+ \gates@processtrue
+ \gdefcs{gate #1_subgate_#3:status}{\gates@state_close}%
+ \def\gates@trace_status{ (ajar -> close)}%
+ \or % skip
+ \gates@processfalse
+ \gdefcs{gate #1_subgate_#3:status}{\gates@state_open}%
+ \def\gates@trace_status{ (skip -> open)}%
+ \or % close
+ \gates@processfalse
+ \def\gates@trace_status{ (close)}%
+ \fi
+ \edef\gates@process_tempconditional{\primunexpanded\expandafter\expandafter\expandafter{\csname gate #1_subgate_#3:conditional\endcsname#2}}%
+ \ifexpression{\ifgates@process & \expandafter\ifexpression\expandafter{\gates@process_tempconditional}}
+ {\gates@trace_writetab{#1}{Calling subgate #3\gates@trace_status}%
+ \gates@process_launchloop{#1}{#3}{#2}{#1}{#3}}%
+ {\gates@trace_writetab{#1}{Ignoring subgate #3\gates@trace_status
+ \expandafter\ifexpression\expandafter{\gates@process_tempconditional}{}{ (False conditional)}}}%
+ }[\usecs{gates@action@return\usecs{gate #1:args}}#2]
+
+\def\gates@process_launchloop#1#2#3{%
+ \ifcs{gate #1_subgate_#2:loop}
+ {\gates@process_loop{#1}{#2}{#3}}
+ {\gates@action@execute{#2}#3}%
+ }
+\def\gates@process_loop#1#2#3{%
+ \expandafter\expandafter\expandafter\ifexpression
+ \expandafter\expandafter\expandafter{\csname gate #1_subgate_#2:loop\endcsname#3}
+ {\gates@action@execute{#2}#3}
+ {\gates@process_nextgate{#3}}%
+ }
+\def\gates@process_loopuntil#1#2#3{%
+ \expandafter\expandafter\expandafter\ifexpression
+ \expandafter\expandafter\expandafter{\csname gate #1_subgate_#2:loopuntil\endcsname#3}
+ {\gates@process_nextgate{#3}}%
+ {\gates@action@execute{#2}#3}
+ }
+\def\gates@process_stoploop#1#2#3{%
+ \ifcs{gate #1_subgate_#2:loop}
+ {\gates@process_loop{#1}{#2}{#3}}
+ {\ifcs{gate #1_subgate_#2:loopuntil}
+ {\gates@process_loopuntil{#1}{#2}{#3}}
+ {\gates@process_nextgate{#3}}}%
+ }
+\long\def\gates@process_nextgate#1#2{%
+ \passarguments{#2}{#1}%
+ }
+
+
+\gates@action{subgates}#1{%
+ \gates@family_pass{\def\gates@subgates_gate}{#1}%
+ \afterassignment\gates@subgates_create
+ \def\gates@subgates_macro##1%
+ }
+
+\def\gates@subgates_create{%
+ \ifcs{gate \gates@subgates_gate:list}
+ {\passexpandedcs{\gates@subgates_process{\gates@subgates_macro}}{gate \gates@subgates_gate:list}}
+ {\gates@error_nogatelist{\gates@subgates_gate}}%
+ }
+
+\newfor\gates@subgates_process{1}#2,{%
+ #1{#2}%
+ }
+
+%%%
+%%% Managing gate lists.
+%%%
+\gates@action{add}#1{%
+ \ifnextnospace[
+ {\gates@add{#1}}
+ {\gates@add{#1}[]}%
+ }
+
+\newstring{before } \newstring{after }
+\def\gates@add#1[#2]#3{%
+ \gates@family_pass{\gates@add_prepare{#1}{#2}}{#3}%
+ }
+\def\gates@add_prepare#1#2#3{%
+ \ifcs{gate #3:list}
+ {\let\gates@add_prefix\gates@somethingtotallyundefined
+ \let\gates@add_suffix\gates@somethingtotallyundefined
+%
+ \ifelseif{%
+ {\ifexpression{ \ifemptystring{#2} | \ifstring{#2}{last} | \ifstring{#2}{after last} }}
+ {\passexpandedcs\gates@add_setends{gate #3:list}{}}
+ {\ifexpression{ \ifstring{#2}{first} | \ifstring{#2}{before first} }}
+ {\passexpandedcs{\gates@add_setends{}}{gate #3:list}}
+ {\ifprefix{before }{#2}}
+ {\removeprefixand{before }{#2}{\passexpandedcs\gates@add_split{gate #3:list}{0}{#3}}}
+ {\ifprefix{after }{#2}}
+ {\removeprefixand{after }{#2}{\passexpandedcs\gates@add_split{gate #3:list}{1}{#3}}}
+ \iftrue
+ {\gates@error{Unknown position: `#2'}}}%
+%
+ \ifdefined\gates@add_prefix
+ \gates@add_do{#3}{#1,}%
+ \xdefcs{gate #3:list}{\gates@add_prefix\gates@add_suffix}%
+ \fi}%
+%
+ {\gates@error_nogatelist{#3}}%
+ }
+
+\def\gates@add_setends#1#2{%
+ \def\gates@add_prefix{#1}%
+ \def\gates@add_suffix{#2}%
+ }
+
+\def\gates@add_split#1#2#3#4{%
+ \ifelseif{%
+ {\ifstring{#4}{first}}% "before first" has been dealt with, so this is "after first".
+ {\splitstringat{,}{#1}\gates@add_setends
+ \addright\gates@add_prefix{,}}
+ {\ifstring{#4}{last}}% Same thing, the other way around: "before last". Harder.
+ {\let\gates@add_prefix\emptycs
+ \def\gates@add_suffix{#1}%
+ \dowhile{\expandafter\gates@add_iftwo\gates@add_suffix,,\gates@end}
+ {\passexpanded{\splitstringat{,}}{\gates@add_suffix}\gates@add_setends
+ \addright\gates@add_prefix{,}}}
+ \iftrue
+ {\gates@family_pass{\gates@add_splitat{#1}{#2}{#3}}{#4}}}%
+ }
+\def\gates@add_splitat#1#2#3#4{%
+ \ifelseif{%
+ {\ifprefix{#4,}{#1}}
+ {\ifcase#2
+ \gates@add_setends{}{#1}%
+ \or
+ \def\gates@add_prefix{#4,}%
+ \removeprefixin{#4,}{#1}\gates@add_suffix
+ \fi}
+ {\ifcontains{,#4,}{#1}}
+ {\splitstringat{,#4,}{#1}\gates@add_setends
+ \ifcase#2
+ \addright\gates@add_prefix{,}%
+ \addleft\gates@add_suffix{#4,}%
+ \or
+ \addright\gates@add_prefix{,#4,}
+ \fi}
+ \iftrue
+ {\gates@error_nogatein{#4}{#3}}}%
+ }
+
+\def\gates@add_iftwo#1,#2,#3\gates@end{%
+ \ifemptystring{#2}\secondoftwo\firstoftwo
+ }
+
+\newfornoempty\gates@add_do{1}#2,{%
+ \gates@ifexists{#2}{code}
+ {\eaddright\gates@add_prefix{\gates@family_check{#2},}%
+ \gdefcs{gate #1_subgate_\gates@family_check{#2}:status}{\gates@state_open}%
+ \gdefcs{gate #1_subgate_\gates@family_check{#2}:conditional}##1##2##3##4##5##6##7##8##9{\iftrue}}
+ {\gates@error_nogate{\gates@temp}}%
+ }
+
+\gates@action{remove}#1#2{%
+ \gates@family_pass{\gates@remove_launch{#1}}{#2}%
+ }
+\def\gates@remove_launch#1#2{%
+ \ifcs{gate #2:list}
+ {\gates@remove{#2}{#1,}}
+ {\gates@error_nogate{#2}}%
+ }
+\newfornoempty\gates@remove{1}#2,{%
+ \gates@family_pass{\gates@remove_do{#1}}{#2}%
+ }
+\def\gates@remove_do#1#2{%
+ \passexpandedcs\gates@remove_check{gate #1:list}{#2}
+ {\global\letcs{gate #1_subgate_#2:status}\gates@thisisabsolutelyundefined
+ \global\letcs{gate #1_subgate_#2:conditional}\gates@thisisabsolutelyundefined
+ \global\letcs{gate #1_subgate_#2:loop}\gates@thisisabsolutelyundefined
+ \global\letcs{gate #1_subgate_#2:loopuntil}\gates@thisisabsolutelyundefined
+ \passexpandedcs{\gates@remove_loop{}{#1}{#2}}{gate #1:list}}
+ {\gates@error_nogatein{#2}{#1}}%
+ }
+\def\gates@remove_check#1#2{%
+ \ifcontains{,#2,}{#1}% The first comma so it doesn't spot ...,xxx#2,...
+ {\firstoftwo}
+ {\ifprefix{#2,}{#1}\firstoftwo\secondoftwo}%
+ }
+\newfor\gates@remove_loop{3}#4,{%
+ \reverse\iffstring{#3}{#4}{\passarguments{#1#4,}{#2}{#3}}%
+ }[\gdefcs{gate #2:list}{#1}]
+
+%%%
+%%% opening, ajaring (it exists!), skipping and closing.
+%%%
+\chardef\gates@state_open = 1
+\chardef\gates@state_ajar = 2
+\chardef\gates@state_skip = 3
+\chardef\gates@state_close = 4
+
+\gates@action_withfamily{status}#1#2#3{%
+ \ifcs{gate \gates@family_passdo\unbrace{#3}{#1}_subgate_\gates@family_passdo\unbrace{#2}{#1}:status}
+ {\passcs\the{gate \gates@family_passdo\unbrace{#3}{#1}_subgate_\gates@family_passdo\unbrace{#2}{#1}:status}}
+ {0}%
+ }
+
+\gates@action_withfamily{status!}#1#2{%
+ \ifcs{gate \gates@family_passdo\unbrace{#2}{#1}:status}
+ {\passcs\the{gate \gates@family_passdo\unbrace{#2}{#1}:status}}
+ {0}%
+ }
+
+\long\def\gates@status_change#1#2{%
+ \gates@family_pass{\gates@status_changedo{#1}}{#2}%
+ }
+\def\gates@status_changedo#1#2#3#4{%
+ \ifcs{gate #2:list}
+ {\ifelseif{%
+ {\ifprefix{before }{#1}} {\passexpandedcs{\removeprefixand{before }{#1}{\gates@family_pass{\gates@switch_b{#3}{#2}}}{#4}}{gate #2:list}}%
+ {\ifprefix{after }{#1}} {\passexpandedcs{\removeprefixand{after }{#1}{\gates@family_pass{\gates@switch_a{#3}{#2}}}{#4}}{gate #2:list}}%
+ \iftrue {\gates@switch{#3}{#2}{#4}{#1,}}}}
+ {\gates@error_nogatelist{#2}}%
+ }
+
+\gates@action{open}#1#2{%
+ \gates@status_change{#1}{#2}{status}{\gates@state_open}%
+ }
+\gates@action{open!}#1{%
+ \gates@switch_x{status}{\gates@state_open}{#1,}%
+ }
+
+\gates@action{ajar}#1#2{%
+ \gates@status_change{#1}{#2}{status}{\gates@state_ajar}%
+ }
+\gates@action{ajar!}#1{%
+ \gates@switch_x{status}{\gates@state_ajar}{#1,}%
+ }
+
+\gates@action{skip}#1#2{%
+ \gates@status_change{#1}{#2}{status}{\gates@state_skip}%
+ }
+\gates@action{skip!}#1{%
+ \gates@switch_x{status}{\gates@state_skip}{#1,}%
+ }
+
+\gates@action{close}#1#2{%
+ \gates@status_change{#1}{#2}{status}{\gates@state_close}%
+ }
+\gates@action{close!}#1{%
+ \gates@switch_x{status}{\gates@state_close}{#1,}%
+ }
+
+\gates@action{conditional}#1#2#3{%
+ \gates@status_change{#1}{#2}{conditional}{#3}%
+ }
+\gates@action{conditional!}#1#2{%
+ \gates@switch_x{conditional}{#2}{#1,}%
+ }
+
+\gates@action{loop}#1#2#3{%
+ \gates@status_change{#1}{#2}{loop}{#3}%
+ }
+\gates@action{loop!}#1#2{%
+ \gates@switch_x{loop}{#2}{#1,}%
+ }
+
+\gates@action{noloop}#1#2{%
+ \gates@status_change{#1}{#2}{noloop}{}%
+ }
+\gates@action{noloop!}#1{%
+ \gates@switch_x{noloop}{}{#1,}%
+ }
+
+\gates@action{loopuntil}#1#2#3{%
+ \gates@status_change{#1}{#2}{loopuntil}{#3}%
+ }
+\gates@action{loopuntil!}#1#2{%
+ \gates@switch_x{loopuntil}{#2}{#1,}%
+ }
+
+\gates@action{noloopuntil}#1#2{%
+ \gates@status_change{#1}{#2}{noloopuntil}%
+ }
+\gates@action{noloopuntil!}#1{%
+ \gates@switch_x{noloopuntil}{}{#1,}%
+ }
+
+\newfornoempty\gates@switch{3}#4,{%
+ \gates@family_pass{\gates@switch_do{#1}{#2}{#3}}{#4}%
+ }
+\long\def\gates@switch_do#1#2#3#4{%
+ \ifcs{gate #2_subgate_#4:status}
+ {\gates@switch_evaluate{#2_subgate_#4}{#1}{#3}}
+ {\gates@error_nogatein{#4}{#2}}%
+ }
+\newfornoempty\gates@switch_b{4}#5,{%
+ \ifstring{#3}{#5}
+ {\breakfor{}}%
+ {\gates@switch_evaluate{#2_subgate_#5}{#1}{#4}}%
+ }
+\newfornoempty\gates@switch_a{4}#5,{%
+ \iffstring{#3}{#5}
+ {\retrieverest{\gates@switch{#1}{#2}{#4}}}%
+ }[\gates@error_nogatein{#3}{#2}]
+\newfornoempty\gates@switch_x{2}#3,{%
+ \ifcs{gate \gates@family_check{#3}:status}
+ {\gates@switch_evaluate{\gates@family_check{#3}}{#1}{#2}}
+ {\gates@error_nogate{\gates@family_check{#3}}}%
+ }
+\long\def\gates@switch_evaluate#1#2#3{%
+ \ifelseif{%
+ {\ifexpression{ \ifstring{#2}{conditional} | \ifstring{#2}{loop} | \ifstring{#2}{loopuntil} }}
+ {\gdefcs{gate #1:#2}##1##2##3##4##5##6##7##8##9{#3}}
+ {\ifstring{#2}{noloop}}
+ {\global\letcs{gate #1:loop}\gates@somethingtotallyundefined}
+ {\ifstring{#2}{noloopuntil}}
+ {\global\letcs{gate #1:loopuntil}\gates@somethingtotallyundefined}
+ \iftrue
+ {\gdefcs{gate #1:#2}{#3}}}
+ }
+
+\restorecatcodes
+\endinput
+% There was a time when writing this code I thought
+% I could keep it below 200 lines. Then 300. Then I stopped
+% counting. I'm cursed by loops.