summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-10-17 22:50:05 +0000
committerKarl Berry <karl@freefriends.org>2012-10-17 22:50:05 +0000
commitdf2ce83ed9a6a3beca08c07cc656611e26d220d7 (patch)
tree086e2f15b6585eb8151e83f7852eb858db2f4b80 /Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
parent468e15f0c59bbedcccfaa606c1f72d3b6d3a8f9a (diff)
skeyval
git-svn-id: svn://tug.org/texlive/trunk@28005 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex')
-rw-r--r--Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex2583
1 files changed, 2583 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
new file mode 100644
index 00000000000..b02ed4f91ed
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/skeyval/skeyval-for.tex
@@ -0,0 +1,2583 @@
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+% This is file 'skeyval-for', version 1.1, October 2012. %
+% %
+% This package and accompanying files may be distributed and/or %
+% modified under the conditions of the LaTeX Project Public License, %
+% either version 1.3 of this license or any later version. The latest %
+% version of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% The LPPL maintenance status of this software is 'author-maintained'. %
+% %
+% This software is provided 'as it is', without warranty of any kind, %
+% either expressed or implied, including, but not limited to, the %
+% implied warranties of merchantability and fitness for a particular %
+% purpose. %
+% %
+% The following files constitute the skeyval bundle and must be %
+% distributed as a whole: %
+% %
+% readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, %
+% skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, %
+% skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, %
+% and skeyval-testpkg.sty. %
+% %
+% Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). %
+%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
+
+\csname skeyval-for-loaded\endcsname
+\expandafter\let\csname skeyval-for-loaded\endcsname\endinput
+
+\edef\skv@for@restorecatcodes{%
+ \catcode`\noexpand\@\the\catcode`\@\relax
+ \let\noexpand\skv@for@restorecatcodes\relax
+}
+\catcode`\@=11\relax
+
+\ifx\ProvidesFile\@undefined
+ \message{File 'skeyval-for.tex' 2012/10/15 v1.1
+ Loops for skeyval package (AM)}
+\else
+ \ProvidesFile{skeyval-for.tex}
+ [2012/10/15 v1.1 Loops for skeyval package (AM)]
+ \@addtofilelist{skeyval-for.tex}
+\fi
+
+\skvrobustdef*\skv@nostackerr{\skv@err{You've called empty stack}\@ehd}
+% \skvsavestate<base-fn>{<fn-list>}<counter>
+\skvrobustdef*\skvsavestate#1#2#3{%
+ \skvgadvanceno#3\@ne
+ \begingroup
+ \let\s\string\escapechar\m@ne
+ \def\skv@prova##1{\s##1@skv@\romannumeral#3}%
+ \def\do##1{\let\noexpand##1\skvnoexpandcs{\skv@prova{##1}}}%
+ \skvifcsdef{\s#1@skv@stack}{}{\skvcsdef{\s#1@skv@stack}{\nostack}}%
+ \skvcsxdef{\s#1@skv@stack}{#2{\skvexpandcsonce{\s#1@skv@stack}}}%
+ \def\do##1{\let\skvnoexpandcs{\skv@prova{##1}}\noexpand##1}%
+ \edef\reserved@a{\endgroup#2}\reserved@a
+}
+% \skvrestorestate<base-fn><counter>
+\skvrobustdef*\skvrestorestate#1#2{%
+ \begingroup
+ \let\nostack\skv@nostackerr
+ \edef\skv@elt{\skvnoexpandcs{\skvremovescape#1@skv@stack}}%
+ \expandafter\ifx\skv@elt\relax
+ \skv@err{Stack of '\noexpand#1' is undefined}\@ehd
+ \fi
+ \edef\skv@prova{\skvexpandtwice\skv@elt}%
+ \edef\skv@provb##1##{\endgroup##1\gdef\skvexpandonce\skv@elt}%
+ \expandafter\skv@provb\skv@prova
+ \skvgadvanceno#2\m@ne
+}
+
+\skvnewregisters\bool{\ifskvbreakloop\ifforeachlastitem
+ \ifskvprocessempty\ifskv@tempst\ifskv@foreach@swa
+ \ifskv@foreach@swb\ifskv@foreach@parenth
+}
+\skvnewnumbers[skv@]{csvdepth,dolistcnt}
+
+\skvrobustdef*\skv@usetempst#1#2{%
+ \edef#2{\skvifdefbool{skv@tempst}\skvexpandonce\unexpanded{#1}}%
+}
+%
+% \skvdolist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvdolist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+%
+% 1. This can be nested to any depth, with different parsers on each
+% level.
+% 2. This will not process an empty list; see \skvecommaloop.
+% 3. For comma lists, \skvcommaloop and \skvcommaparse are faster.
+% See later.
+% 4. For processing kv lists, use \skvkvparse.
+%
+\skvrobustdef*\skvdolist{\skv@testst\skv@dolist}
+\skvrobustdef*\skv@dolist#1#2#3#4{%
+ \skvgadvanceno\skv@dolistcnt\@ne
+ \skv@usetempst{#2}#3%
+ \def\skv@dolist@a{skv@dolist@\skvrom\skv@dolistcnt}%
+ \skvcsdef{\skv@dolist@a}##1##2##3#1{%
+ \skvifstrcmp{##3}{\skv@dolist@nil}{%
+ % To allow nesting of loop:
+ \skvbreakloopfalse
+ }{%
+ \edef##1{\unexpanded{##3}}%
+ ##2\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \skvcsdef{\skv@dolist@a}####1\skv@dolist@nil#1{\endgroup}%
+ \fi
+ \@nameuse{\skv@dolist@a}##1{##2}%
+ }%
+ }%
+ \skvifempty#3{}{%
+ \edef\reserved@a{\unexpanded{\@nameuse{\skv@dolist@a}#3{#4}}}%
+ \expandafter\reserved@a#3#1\skv@dolist@nil#1%
+ }%
+ \skvgadvanceno\skv@dolistcnt\m@ne
+}
+
+% First normalize the list before parsing.
+%
+% \skvparselist{<parser>}{<list>}<holdercmd>{<callback>}
+% \skvparselist*{<parser>}{<listcmd>}<holdercmd>{<callback>}
+%
+\skvrobustdef*\skvparselist{\skv@testst\skv@parselist}
+\skvrobustdef*\skv@parselist#1#2#3{%
+ \skv@usetempst{#2}#3%
+ \skvcsvnormalize[#1]#3%
+ \skv@tempsttrue
+ \skv@dolist{#1}#3#3%
+}
+
+\skvifdefinable\listbreaker{\let\listbreaker\relax}
+\skvifdefinable\listpauser{\let\listpauser\relax}
+\skvnewdef*\skv@listbreakertoks{\listbreaker}
+\skvnewdef*\skv@listpausertoks{\listpauser}
+
+\skvnewlet\skvprocessempty\skvprocessemptytrue
+\skvletmanytocmd{\skvbreakloop\interruptloop\skvbreakforeach
+ \interruptforeach}\skvbreaklooptrue
+
+% Reversing tokens:
+\skvnewdef*\skvreverse#1{\skv@reverse#1\skv@reverse@stop}
+\skvnewdef*\skv@reverse#1#2\skv@reverse@stop{%
+ \if\relax\detokenize{#2}\relax\skv@reverse@stop\fi
+ \skv@reverse#2\skv@reverse@stop\skvreversedo{#1}%
+}
+\skvnewdef*\skv@reverse@stop#1\skv@reverse@stop{\fi}
+\let\skvreversedo\@iden
+
+\skvrobustdef*\skv@removetrailingparser#1#2{%
+ \skvxifin{\detokenize{#1}\relax}{\skvoxdetok#2\relax}{%
+ \def\skv@prova##1#1\skv@trim@nil{\unexpanded{##1}}%
+ \edef#2{\expandafter\skv@prova#2\skv@trim@nil}%
+ }{}%
+}
+
+% \skvrecurse<body>\while<\if...>\fi
+%
+% On entry, the condition is checked before the body is executed.
+%
+% \@tempcnta\z@
+% \skvrecurse{
+% \advance\@tempcnta\@ne
+% \@tempcntb\z@
+% \skvrecurse
+% \advance\@tempcntb\@ne
+% \typeout{Doing \the\@tempcnta,\the\@tempcntb}
+% \while
+% \ifnum\@tempcntb<3
+% \fi
+% }
+% \while
+% \ifnum\@tempcnta<4
+% \fi
+%
+\skvrobustdef\skvrecurse#1\while#2\fi{%
+ \@expandtwoargs\skv@dobody{\skvtrimspace{#2}}{\skvtrimspace{#1}}%
+}
+\skvrobustdef\skv@dobody#1#2{%
+ #1\relax\expandafter\@iden\else\expandafter\@gobble\fi
+ {#2\relax\skv@dobody{#1}{#2}}%
+}
+
+% A version of LaTeX's \@tfor that can parse undoubled parameter
+% characters.
+%
+% \skvtfor<holder.cmd>{<list>}\do{<callback>}
+% \skvtfor*<holder.cmd>{<listcmd>}\do{<callback>}
+%
+% Example:
+%
+% \skvnewregister\count\nr
+% \skvtfor\x:=a \ifx {\def\x#1{#1}} \fi\do{%
+% \nr\z@
+% \skvtfor\y:=12345\do{%
+% \typeout{Doing: \detokenize\expandafter{\x}--\y}%
+% \advance\nr\@ne
+% \ifnum\nr>\tw@\skvbreakloop\fi
+% }
+% }
+%
+\skvnewdef*\skv@tfor@nil{\skv@tfor@nil}
+\skvrobustdef*\skvtfor{\skv@testst\skv@tfor}
+\skvrobustdef*\skv@tfor#1:={\skv@tf@r#1 }
+\skvrobustdef\skv@tf@r#1#2\do#3{%
+ \edef#1{\skvtrimspace{#2}}%
+ \edef#1{\skvifbool{skv@tempst}\skvexpandtwice\skvexpandonce{#1}}%
+ \skvifempty#1{}{%
+ \skvbreakloopfalse
+ \expandafter\skv@tforloop#1\skv@tfor@nil\skv@tfor#1{#3}%
+ }%
+}
+\skvrobustdef\skv@tforloop#1#2\skv@tfor#3#4{%
+ \edef#3{\unexpanded{#1}}%
+ \skvifx#3\skv@tfor@nil{%
+ \skvbreakloopfalse
+ }{%
+ #4\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \def\skv@tforloop##1\skv@tfor@nil\skv@tfor##2##3{%
+ \endgroup
+ \edef\skvremainder{\unexpanded{##1}}%
+ }%
+ \fi
+ \skv@tforloop#2\skv@tfor#3{#4}%
+ }%
+}
+
+% Non-expandable comma loops
+%
+% 1. These follow from \skvdolist and \skvparselist, but they are
+% specialized for comma lists and they are faster.
+% 2. They can be nested.
+% 3. \skvecommaloop needs \skv@c@mmaloop.
+%
+% \skvcommaloop{<list>}<holder-cmd>{<callback>}
+% \skvcommaloop*{<listcmd>}<holder-cmd>{<callback>}
+%
+\skvrobustdef*\skvcommaloop{\skv@testst\skv@commaloop}
+\skvrobustdef\skv@commaloop#1#2#3{%
+ \skv@usetempst{#1}#2%
+ % Don't put \skvcsvnormalize#2 here. Use \skvcommaparse instead.
+ % Some callers of \skvcommaloop already have their lists normalized.
+ \skvifx#2\@empty{}{%
+ \skvexpandnext{\skv@c@mmaloop#2{#3}}#2,\skv@commaloop@nil,%
+ }%
+}
+\skvrobustdef\skv@c@mmaloop#1#2#3,{%
+ \skvifstrcmp{#3}{\skv@commaloop@nil}{%
+ \skvbreakloopfalse
+ }{%
+ \edef#1{\unexpanded{#3}}%
+ #2\relax
+ \ifskvbreakloop
+ \skvbreakloopfalse
+ \begingroup
+ \long\def\skv@c@mmaloop##1\skv@commaloop@nil,{\endgroup}%
+ \fi
+ \skv@c@mmaloop#1{#2}%
+ }%
+}
+%
+% \skvecommaloop{<list>}<cmd>{<callback>}
+% \skvecommaloop*{<listcmd>}<cmd>{<callback>}
+%
+% \skvecommaloop is as \skvcommaloop but will execute <callback>
+% once when <list> is empty. This is needed for processing empty
+% families.
+%
+\skvrobustdef\skvecommaloop{\skv@testst\skv@ecommaloop}
+\skvrobustdef\skv@ecommaloop#1#2#3{%
+ \edef#2{\unexpanded{\skv@c@mmaloop#2{#3}}}%
+ \ifskv@tempst\expandafter\expandafter\fi#2#1,\skv@commaloop@nil,%
+}
+%
+% \skvcommaparse{<list>}<cmd>{<callback>}
+% \skvcommaparse*{<listcmd>}<cmd>{<callback>}
+%
+% \skvcommaparse is as \skvcommaloop but will first normalize <list>
+% using \skvcsvnormalize.
+%
+\skvrobustdef*\skvcommaparse{\skv@testst\skv@commaparse}
+\skvrobustdef\skv@commaparse#1#2#3{%
+ \skv@usetempst{#1}#2%
+ \skvcsvnormalize#2%
+ \skvcommaloop*#2#2{#3}%
+}
+%
+% \skvkvparse{<list>}<cmd>{<callback>}
+% \skvkvparse*{<listcmd>}<cmd>{<callback>}
+%
+% \skvkvparse is as \skvcommaloop but will first normalize <list> using
+% \skvkvnormalize.
+%
+\skvrobustdef*\skvkvparse{\skv@testst\skv@kvparse}
+\skvnewlet\skvparsekeyvals\skvkvparse
+\skvrobustdef\skv@kvparse#1#2#3{%
+ \skv@usetempst{#1}#2%
+ \skvkvnormalize#2%
+ \skvcommaloop*#2#2{#3}%
+}
+%
+
+% \skv@foreach@normalize[<parser>]<listcmd>
+\skvrobustdef*\skv@foreach@normalize{\skv@testopt\skv@foreach@norm@lize,}
+\skvrobustdef*\skv@foreach@norm@lize[#1]#2{%
+ \skvxifntype{\detokenize{#1}}\skvcsvnormalize\skvmacnormalize[#1]#2%
+}
+
+% \newforeach[<options>] <holders> {<list>} {<callback>}
+% \newforeach*[<options>] <holders> {<listcmd>} {<callback>}
+% \newforeach[<options>] <holders> in {<list>} do {<callback>}
+% \newforeach*[<options>] <holders> in {<listcmd>} do {<callback>}
+% \newforeach[<options>] <holders> in {<list>} <callback> ;
+% \newforeach*[<options>] <holders> in {<listcmd>} <callback> ;
+%
+% 1. <callback> is the code that will be executed for each element
+% of the list. It will refer to the holder macros <holders>.
+%
+% 3. Elements of the form (a,b) and [a,b] are grabbed together.
+%
+% 4. Use \interruptforeach to break out of the loop prematurely.
+%
+% 5. \newforeach can be nested.
+
+% \skv@foreach@sisterdepth must be different from \foreachdepth,
+% to avoid confusing two different stacks.
+\skvnewnumbers{foreachdepth,skv@foreach@sisterdepth,skv@foreach@nra,%
+ skv@warnsubparser}
+\skvnewdef*\skv@foreach@onlyinitially{}
+\skvrobustdef*\skv@foreach@assignonce#1{%
+ \edef\skv@foreach@onlyinitially{%
+ \skvexpandonce\skv@foreach@onlyinitially
+ \unexpanded{#1}%
+ }%
+}
+% \skv@foreach@addtocallback{<pre.or.post>}{<code.to.add>}
+\skvrobustdef*\skv@foreach@addtocallback#1#2{%
+ \skvcsedef{skv@foreach@#1callback}{%
+ \skvifcsundef{skv@foreach@#1callback}{}{%
+ \skvexpandcsonce{skv@foreach@#1callback}%
+ }%
+ % No \unexpanded for #2 here, since #2 is to be expanded:
+ #2%
+ }%
+}
+
+\skvnewlet\skv@foreach@codemark\relax
+\skvrobustdef*\skv@foreach@addtohook#1#2#3{%
+ \begingroup
+ \skvifdef#2{}{\def#2{}}%
+ \edef\x{\detokenize{\skv@foreach@codemark#3\skv@foreach@codemark}}%
+ \skvxifin\x{\skvoxdetok#2}{}{%
+ \edef#2{%
+ \skvifstrcmp{#1}{pre}{%
+ \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
+ \skvexpandonce{#2}%
+ }{%
+ \skvexpandonce{#2}%
+ \skv@foreach@codemark\unexpanded{#3}\skv@foreach@codemark
+ }%
+ }%
+ }%
+ \skvaftergroupdef#2\endgroup
+}
+
+% \prependtobeginforeach[<depths>]{<code>}
+\skvrobustdef*\prependtobeginforeach{%
+ \skv@testopt{\skv@atbeginforeach{pre}}{}%
+}
+% \appendtobeginforeach[<depths>]{<code>}
+\skvrobustdef*\appendtobeginforeach{%
+ \skv@testopt{\skv@atbeginforeach{app}}{}%
+}
+\skvnewlet\atbeginforeach\appendtobeginforeach
+\skvrobustdef*\skv@atbeginforeach#1[#2]#3{%
+ \skvifblank{#2}{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atbeginhook@\skvrom\@ne}{#3}%
+ }{%
+ \skvcommaloop{#2}\skv@tempa{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atbeginhook@\skvrom\number\skv@tempa}{#3}%
+ }%
+ }%
+}
+% \prependtoendforeach[<depths>]{<code>}
+\skvrobustdef*\prependtoendforeach{%
+ \skv@testopt{\skv@atendforeach{pre}}{}%
+}
+% \appendtoendforeach[<depths>]{<code>}
+\skvrobustdef*\appendtoendforeach{%
+ \skv@testopt{\skv@atendforeach{app}}{}%
+}
+\skvnewlet\atendforeach\appendtoendforeach
+\skvrobustdef*\skv@atendforeach#1[#2]#3{%
+ \skvifblank{#2}{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atendhook@\skvrom\@ne}{#3}%
+ }{%
+ \skvcommaloop{#2}\skv@tempa{%
+ \skvaftercsname{\skv@foreach@addtohook{#1}}%
+ {skv@foreach@atendhook@\skvrom\number\skv@tempa}{#3}%
+ }%
+ }%
+}
+% \atbeginforeachondepth{<depths>}{<code>}
+\skvrobustdef*\atbeginforeachondepth#1#2{%
+ \appendtobeginforeach[#1]{#2}%
+}
+% \atendforeachondepth{<depths>}{<code>}
+\skvrobustdef*\atendforeachondepth#1#2{%
+ \appendtoendforeach[#1]{#2}%
+}
+
+% \skv@foreach@fi must use \detokenize. Don't change to \string!
+\skvnewedef*\skv@foreach@fi{\detokenize{\fi}}
+\skvnewedef*\skv@foreach@if{\string\if}
+
+% \skv@foreach@ifacceptkv and \skv@foreach@maketester must come
+% before the initialization of keys:
+\skvrobustdef*\skv@foreach@ifacceptkv#1#2{%
+ \def\next{}%
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifnum0>\numexpr0\ifx\skv@prova\@empty-1\else
+ \ifx\skv@prova\@nnil-1\else+0\fi\fi\relax\relax
+ \skv@err{Invalid syntax '\detokenize{#1}'}\@ehd
+ \else
+ \edef\next{\unexpanded{#2}}%
+ \fi
+ \fi
+ \next
+}
+\skvrobustdef*\skv@foreach@ifholderisonecmd#1#2#3{%
+ \skvifntype{#2}{%
+ \skvifescaped{#2}{%
+ #3%
+ }{%
+ \skv@err{Value of key '#1' must
+ \MessageBreak be escaped: the holder macro
+ \MessageBreak to be evaluated}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key '#1' must
+ \MessageBreak be only one token: the holder
+ \MessageBreak macro to be evaluated}\@ehd
+ }%
+}
+% \skv@foreach@maketester{<cond>}<cond.tester.cmd>{<flag>}
+%
+% 1. Only balanced conditionals beginning with \if...\fi are allowed.
+% Restricting the type of allowed conditionals is necessary for
+% auto syntax checking.
+% 2. <flag> is either 0 or 1, signifying whether or not the condition
+% should be entered in postcallback.
+%
+% Examples: \ifnum\x>10\fi, \ifx\x\cmd\fi.
+%
+\skvrobustdef*\skv@foreach@maketester#1#2#3{%
+ % Make '#1' innocent in a macro, in case it contains parameter
+ % characters. \skv@prova will appear only in the error message.
+ \begingroup
+ \edef\skv@prova{\detokenize{#1}}%
+ \skvifblank{#1}{%
+ \skv@err{A blank conditional given in \string\newforeach}\@ehd
+ }{%
+ \skvxifin{\skv@foreach@fi\relax}{\detokenize{#1}\relax}{%
+ \skvxifin{\relax\skv@foreach@if}{\relax\detokenize{#1}}{%
+ \edef#2{\noexpand\skvifcondition\unexpanded{#1}}%
+ \ifnum#3=\@ne
+ \skv@foreach@addtocallback{post}{%
+ \unexpanded{\skvifcondition#1}{\noexpand\skvbreakloop}{\relax}%
+ }%
+ \fi
+ }{%
+ \skv@err{Illegal conditional '\skv@prova'}
+ {Invalid, possibly unbalanced, conditional '\skv@prova'}%
+ }%
+ }{%
+ \skv@err{Illegal conditional '\skv@prova'}\@ehd
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit#2%
+ \ifnum#3=\@ne
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+\begingroup
+\catcode`P=12 \lccode`P=112
+\catcode`T=12 \lccode`T=116
+\lowercase{\endgroup
+ \def\skv@foreach@strippoint#1#2{%
+ \def\reserved@a##1#1\relax{\def#2{##1}}%
+ \def\do##1.##2PT#1{%
+ \ifx\do##1\else##1%
+ \if\skv@foreach@keephighdecimals
+ \ifdim.##2pt>.5pt\relax##2\fi
+ \else
+ \if\skv@foreach@keepdecimals
+ \ifnum##2>\skvz@.##2\fi
+ \fi
+ \fi
+ \unexpanded{#1}%
+ \expandafter\do
+ \fi
+ }%
+ \edef#2{\expandafter\do#2#1\do.PT#1}%
+ \expandafter\reserved@a#2\relax
+ }
+}
+
+\quickkeys.define{skvforeach}{%
+ .exec/
+ \def\skv@foreach@parser{,}
+ \def\skv@foreach@subparser{/}
+ ;
+ parser/{,}/
+ \ifskvindef\else
+ \edef\skv@foreach@parser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@parser
+ \skvxifntype{\detokenize{#1}}{%
+ \begingroup
+ % It is assumed that every n-type parser and subparser
+ % must have catcode 12:
+ \skvexpandnext{\catcode`}\skv@foreach@parser=12\relax
+ \skv@rescan\skv@foreach@parser
+ \skvaftergroupdef\skv@foreach@parser\endgroup
+ }{}
+ \fi
+ ;
+ subparser/{/}/
+ \ifskvindef\else
+ \edef\skv@foreach@subparser{\unexpanded{#1}}
+ \skvstripouterbraces{2}\skv@foreach@subparser
+ \skvxifntype{\detokenize{#1}}{
+ \begingroup
+ \skvexpandnext{\catcode`}\skv@foreach@subparser=12\relax
+ \skv@rescan\skv@foreach@subparser
+ \skvaftergroupdef\skv@foreach@subparser\endgroup
+ }{}
+ \fi
+ ;
+ terminator,callback terminator/{;}/
+ \edef\skv@foreach@terminator{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@foreach@terminator
+ ;
+ list is a macro,macro list/true/
+ \edef\skv@foreach@listismacro{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % process up to = <nr>
+ % Maximum number of items to process:
+ process up to,process up to number/\@nil/
+ \ifskvindef\else
+ \def\skv@foreach@processupto{#1}%
+ \ifx\skv@foreach@processupto\@nnil\else
+ \skv@ensureinteger{process up to}{#1}%
+ \fi
+ \fi
+ ;
+ process empty list/true/
+ \edef\skv@foreach@processempty{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % Eg, exit when=\ifnum\x=20\fi
+ .exec/\let\skv@foreach@exittester\@secondoftwo;
+ loop stopper,exit when/\if01\fi/
+ \ifskvindef\else
+ \edef\skv@tempa{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@tempa
+ \expandafter\skv@foreach@maketester\expandafter
+ {\skv@tempa}\skv@foreach@exittester\@ne
+ \fi
+ ;
+ % Eg, 'evaluate = \x as \z using \numexpr\x*2'. 'as' and 'using', and the
+ % tokens after them, can be missing, but the formula must be complete.
+ evaluate/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parseevaluate{#1}%
+ }%
+ ;
+ % The evaluator \numexpr will invariably be used internally for this key.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ evaluate num,evaluate number/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{evaluate number}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using\numexpr#1}%
+ }%
+ }%
+ ;
+ % The evaluator \dimexpr will invariably be used internally for this key.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ evaluate dim,evaluate dimension/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{evaluate dimension}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using\dimexpr#1}%
+ }%
+ }%
+ ;
+ % Eg, 'expand=\x'.
+ % Fully expand holder macro. This is equivalent to, eg, edef\x{\x}.
+ % 'as' and 'using' are illegal here. This is only a shortcut for 'evaluate'.
+ expand,expanded/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@ifholderisonecmd{expand}{#1}{%
+ \skv@foreach@parseevaluate{#1as#1using#1}%
+ }%
+ }%
+ ;
+ % Eg, 'pgf parse = \x as \xe using \x*3'. 'as' and 'using', and the
+ % tokens after them, can be present or missing.
+ % \pgfmathparse is always used for this key.
+ pgf evaluate,pgf parse,pgfmath parse/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parsepgfmathparse{#1}%
+ }%
+ ;
+ % count in = \y all \x satisfying <condition> initially <value>
+ % Eg,
+ % count in = \p all \x satisfying \ifnum\x>4\fi, or
+ % count in = \p all \x satisfying \skvifnum\x>4
+ % The counting is not additive, meaning that the counter is initialized
+ % to zero on each depth.
+ count in,count/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parsecountin{#1}%
+ }%
+ ;
+ % Eg, 'remember=\x as \y initially A':
+ remember/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parseremember{#1}%
+ }%
+ ;
+ % Eg, 'recall=\x initially A'.
+ % 'recall' is as 'remember', but will save the value of the holder macro
+ % in \<foreachlast><holder>. 'as' is invalid/illegal here, since a
+ % retainer macro is built internally:
+ retain,recall,call up/\@nil/
+ \skv@foreach@ifacceptkv{#1}{%
+ \skv@foreach@parserecall{#1}%
+ }%
+ ;
+ item counter,counter/\@nil/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@nnil
+ \skv@err{Invalid empty value for key 'item counter'}\@ehd
+ \else
+ \skvifescaped{#1}{%
+ \let\skv@foreach@itemcounter\skv@prova
+ }{%
+ \skv@err{Non-escaped value '\detokenize{#1}'
+ \MessageBreak for key 'item counter'}\@ehd
+ }%
+ \fi
+ \fi
+ ;
+ list breaker/\listbreaker/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list breaker'}\@ehd
+ \else
+ \let\skv@listbreakertoks\skv@prova
+ \fi
+ \fi
+ ;
+ list pauser/\listpauser/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Invalid empty value for key 'list pauser'}\@ehd
+ \else
+ \let\skv@listpausertoks\skv@prova
+ \fi
+ \fi
+ ;
+ % Remember outside the loop the holder values. Of course, this
+ % means remembering only the latest values.
+ recover holder values,recover holder values after loop/true/
+ \edef\skv@foreach@recoverholders{0\skvifstrcmp{true}{#1}01}%
+ /true,false
+ ;
+ % This default value of 'link' is required by \skv@foreach@filllist:
+ .exec/\def\skv@foreach@link{\@nil};
+ link/\@nil/
+ \ifskvindef\else
+ \edef\skv@foreach@link{\unexpanded{#1}}%
+ \skvstripouterbraces{2}\skv@foreach@link
+ \ifnum0>\numexpr0\ifx\skv@foreach@link\@empty-1\else
+ \ifx\skv@foreach@link\@nnil-1\else+0\fi\fi\relax\relax
+ \skv@err{The key 'link' doesn't accept empty/blank values}\@ehd
+ \fi
+ \fi
+ ;
+ grow/\@nil/
+ \ifskvindef\else
+ \edef\skv@prova{\unexpanded{#1}}%
+ \ifx\skv@prova\@nnil
+ \skv@err{Value required for key 'grow'}\@ehd
+ \else
+ \skvcsedef{skv@foreach@grow#1}{00}
+ \edef\skv@prova{\skvifstrcmp{#1}{left}{right}{left}}%
+ \skvcsedef{skv@foreach@grow\skv@prova}{01}%
+ \fi
+ \fi
+ /left,right
+ ;
+ .exec/
+ \def\skv@foreach@growleft{01}
+ \def\skv@foreach@growright{01}
+ ;
+ grow left/true/
+ \ifskvindef\else
+ \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}10}
+ \fi
+ /true,false
+ ;
+ grow right/true/
+ \ifskvindef\else
+ \edef\skv@foreach@growright{0\skvifstrcmp{true}{#1}01}
+ \edef\skv@foreach@growleft{0\skvifstrcmp{true}{#1}10}
+ \fi
+ /true,false
+ ;
+ % Keep the decimals in rounded numbers or dimensions when list is
+ % auto-completed. The value value of this key is 'true'.
+ keep decimals/true/
+ \edef\skv@foreach@keepdecimals{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ keep high decimals,keep only high decimals/true/
+ \edef\skv@foreach@keephighdecimals{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ % This key means that, eg, for \x/\y, do \let\y=\x if \y has no
+ % user value, ie, if the user gives as an item 'a' instead of
+ % 'a/b' or 'a/a'.
+ inherit/true/
+ \edef\skv@foreach@inherit{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+ expand before fill/true/
+ \edef\skv@foreach@expandbeforefill{0\skvifstrcmp{true}{#1}01}
+ /true,false
+ ;
+}
+
+% The following keys don't need a default value:
+%
+% link,evaluate,*evaluate,evaluate num,*evaluate num,
+% evaluate dim,*evaluate dim,expand,*expand,count in,*count in,
+% loop stopper,process up to,grow
+%
+\skvinitializeqkeys{skvforeach}{%
+ parser,
+ subparser,
+ callback terminator,
+ list is a macro=false,
+ process up to,
+ process empty list=false,
+ item counter,
+ list breaker,
+ list pauser,
+ recover holder values=false,
+ grow left=false,
+ grow right=false,
+ keep decimals=true,
+ keep high decimals=false,
+ inherit=false,
+ expand before fill=false,
+}
+
+\skvnewdef*\skv@foreach@kvlist{}
+% \setupforeach{<kvlist>}
+\skvrobustdef*\setupforeach#1{%
+ \skvifblank{#1}{}{%
+ \skvaddtolist\skv@foreach@kvlist{#1}%
+ }%
+}
+\skvrobustdef*\skv@foreach@setkeys#1{%
+ \def\reserved@a{\quickkeys.set{skvforeach}}%
+ \expandafter\reserved@a\expandafter{\skv@foreach@kvlist,#1}%
+}
+
+% evaluate=<holder.macro> as <child.macro> using <formula>
+%
+% 1. Evaluation is done with \edef unless \pgfmathparse is present
+% in <formula>.
+%
+% 2. <formula> must be a valid formula, eg,
+%
+% \pgfmathparse\x*2
+% \pgfmathparse{exp(50)*\x*2+sin(.5*pi)*60}
+% \numexpr\x*2
+% \skvexpandonce\x
+%
+% or simply
+%
+% 'evaluate \x as \x using <empty>'
+%
+% The latter is equivalent to asking for full expansion. See also
+% the keys 'evaluate num', 'evaluate dim', and 'expand'.
+%
+% 3. This allows <formula> to be generic.
+%
+\skvrobustdef*\skv@foreach@parseevaluate#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@foreach@swafalse
+ \def\skv@tempd{}%
+ \def\skv@tempa##1as##2using##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find child macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provc\@empty
+ \skv@err{Value of key 'evaluate' has no formula or
+ \MessageBreak holder macro to be expanded}\@ehd
+ \fi
+ \skv@tempxifin{\pgfmathparse}{##3}{%
+ \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
+ \ifx\@nnil####1\@nnil
+ \skv@foreach@swatrue
+ \else
+ \skv@err{Invalid token \detokenize{####1}
+ \MessageBreak before \string\pgfmathparse}\@ehd
+ \fi
+ }%
+ \skv@tempc##3\skv@nil
+ }{%
+ \skv@tempxifin{\numexpr}{##3}{%
+ \def\skv@tempd{\relax}%
+ }{%
+ \skv@tempxifin{\dimexpr}{##3}{%
+ \def\skv@tempd{\relax}%
+ }{%
+ \def\skv@tempd{}%
+ }%
+ }%
+ }%
+ }%
+ \skv@tempxifin{using}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ % 'as' and 'using' are present: maybe there is a formula.
+ \skv@foreach@swbtrue
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'evaluate':
+ \MessageBreak there is 'using', but no 'as'}\@ehd
+ }%
+ }{%
+ % No formula given. Maybe the key is 'expand' or still 'evaluate'
+ % but without formula.
+ \skv@foreach@swbfalse
+ \skv@tempxifin{as}{#1}{%
+ \def\skv@tempb##1as##2##3\skv@nil{%
+ \ifx\@nnil##1\@nnil
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \ifx\@nnil##2%
+ \skv@err{Value of key 'evaluate' has no child macro}\@ehd
+ \else
+ \skv@tempa##1as##2using##1\skv@nil
+ \fi
+ \fi
+ }%
+ \skv@tempb#1{\@nnil}\skv@nil
+ }{%
+ % No 'as' or 'using': #1 should be only the holder macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'evaluate' has no holder macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ % Expand the holder macro:
+ \skv@tempa#1as#1using#1\skv@nil
+ }{%
+ \skv@err{Value of key 'evaluate': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \skv@foreach@addtocallback{afterpre}{%
+ \ifskv@foreach@swa
+ % <formula> has the syntax \pgfmathparse{\x}.
+ \skvexpandonce\skv@provc
+ \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
+ \else
+ % <formula> has the syntax \numexpr\x*2 or \dimexpr\x*2.
+ % \ifskv@foreach@swb is true when a formula has been given.
+ \edef\skvexpandonce\skv@provb{%
+ \ifskv@foreach@swb\noexpand\the\fi
+ \skvexpandonce\skv@provc\skv@tempd
+ }%
+ \fi
+ }%
+ \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
+}
+
+% pgfmath parse=<holder.macro> as <child.macro> using <formula>
+%
+% 1. Evaluation is always done with \pgfmathparse.
+%
+% 2. <formula> must be \pgfmathparse-able.
+%
+\skvrobustdef*\skv@foreach@parsepgfmathparse#1{%
+ \begingroup
+ \ifdefined\pgfmathparse\else
+ \skv@err{No \string\pgfmathparse; 'pgfmath' module not loaded}\@ehd
+ \fi
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@foreach@swafalse
+ \def\skv@tempa##1as##2using##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find child macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provc\@empty
+ \skv@err{Value of key 'pgfmath parse' has no formula or
+ \MessageBreak holder macro to be expanded}\@ehd
+ \fi
+ \skv@tempxifin{\pgfmathparse}{##3}{%
+ \def\skv@tempc####1\pgfmathparse####2\skv@nil{%
+ \ifx\@nnil####1\@nnil
+ \skv@foreach@swatrue
+ \else
+ \skv@err{Invalid token \detokenize{####1}
+ \MessageBreak before \string\pgfmathparse}\@ehd
+ \fi
+ }%
+ \expandafter\skv@tempc\skv@provc\skv@nil
+ }{%
+ \skv@tempxifin{\numexpr}{##3}{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak\noexpand\numexpr not allowed}\@ehd
+ }{%
+ \skv@tempxifin{\dimexpr}{##3}{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak\noexpand\dimexpr not allowed}\@ehd
+ }{%
+ \skv@foreach@swatrue
+ \edef\skv@provc{\noexpand\pgfmathparse{\skvexpandonce\skv@provc}}%
+ }%
+ }%
+ }%
+ }%
+ \skv@tempxifin{using}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ % 'as' and 'using' are present: maybe there is a formula.
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'pgfmath parse':
+ \MessageBreak there is 'using', but no 'as'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{as}{#1}{%
+ \def\skv@tempb##1as##2##3\skv@nil{%
+ \ifx\@nnil##1\@nnil
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \ifx\@nnil##2%
+ \skv@err{Value of key 'pgfmath parse' has no child macro}\@ehd
+ \else
+ \skv@tempa##1as##2using##1\skv@nil
+ \fi
+ \fi
+ }%
+ \skv@tempb#1{\@nnil}\skv@nil
+ }{%
+ % No 'as' or 'using': #1 should be only the holder macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'pgfmath parse' has no holder macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ % Evaluate the holder macro:
+ \skv@tempa#1as#1using#1\skv@nil
+ }{%
+ \skv@err{Value of key 'pgfmath parse': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \skv@foreach@addtocallback{afterpre}{%
+ \ifskv@foreach@swa
+ \skvexpandonce\skv@provc
+ \let\skvexpandonce\skv@provb\noexpand\pgfmathresult
+ \fi
+ }%
+ \skvaftergroupdef\skv@foreach@afterprecallback\endgroup
+}
+
+% count in = \y all \x satisfying <condition> initially <value>
+%
+% 1. <condition> must be a balanced and valid TeX conditional, like
+%
+% \ifnum\x>2\fi, \ifx\x\@empty\fi
+%
+% 2. The aim is to allow general conditions (not only those involving
+% numerals) to be submitted.
+%
+% 3. PGF's \foreach doesn't have this feature; it has only a general
+% counter, eg,
+%
+% '\foreach \x [count=\xi] in {a,...,e}'.
+%
+% Generic counting is available in \newforeach by default, without
+% user request. The macros \foreachcurrentitem, \foreachitemcount,
+% \foreachnextitem are always available on each nesting level. The
+% boolean \ifforeachlastitem is also always available, to indicate when
+% the last item of the list has been reached:
+%
+% \ifforeachlastitem \typeout{Processing last entry of the list} \fi
+%
+% 4. Counting is done from 1 (zero) unless <value> is given after
+% 'initially'.
+%
+\skvrobustdef*\skv@foreach@parsecountin#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \def\skv@tempa##1\skv@nil{%
+ \skv@tempxifin{initially}{##1}{%
+ \skv@tempb##1\skv@nil
+ }{%
+ \skv@tempb##1initially\skv@nil
+ }%
+ }%
+ \def\skv@tempb##1all##2satisfying##3initially##4\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \edef\skv@provd{\skvtrimspace{##4}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \expandafter\skvifntype\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token \skvoxdetok\skv@prova.
+ \MessageBreak I can't find counter macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ counter macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provd\@empty
+ \expandafter\def\skv@prova{0}%
+ \else
+ \skvifinteger\skv@provd{%
+ \expandafter\let\skv@prova\skv@provd
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ initial \skvoxdetok\skv@provd not an integer}\@ehd
+ }%
+ \fi
+ \skv@foreach@swafalse
+ \ifx\skv@provc\@empty
+ % No tester but there may be a holder macro to test. The holder
+ % macro, on its own, isn't sufficient to conduct a test:
+ \let\skv@foreach@itemcounter\skv@prova
+ \else
+ \ifx\skv@provb\@empty\else
+ % If there isn't a holder macro or quantity to test, then no
+ % test is possible:
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \expandafter\skvifntype\expandafter{\skv@provb}{}{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token \skvoxdetok\skv@provb.
+ \MessageBreak I can't find holder macro}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'count':\MessageBreak
+ holder macro \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \skv@foreach@swatrue
+ % \skv@tester is the second argument of \skv@foreach@maketester.
+ % \skv@tester is used in pushing the item counter:
+ \skvexpbracenext\skv@foreach@maketester\skv@provc\skv@tester\skvz@
+ \fi
+ \fi
+ }%
+ \skv@tempxifin{satisfying}{#1}{%
+ \skv@tempxifin{all}{#1}{%
+ % 'all' and 'satisfying' are present:
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'count':
+ \MessageBreak there is 'satisfying', but no 'all'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{all}{#1}{%
+ \skv@tempa#1satisfying\skv@nil
+ }{%
+ % No 'all' or 'satisfying': #1 should be only the counter macro:
+ \ifx\@nnil#1\@nnil
+ \skv@err{Value of key 'count' has no counter macro}\@ehd
+ \else
+ \skvifntype{#1}{%
+ \skv@tempa#1all satisfying\skv@nil
+ }{%
+ \skv@err{Value of key 'count in': more than 1
+ \MessageBreak token '\detokenize{#1}'.
+ \MessageBreak I can't find counter macro}\@ehd
+ }%
+ \fi
+ }%
+ }%
+ \ifskv@foreach@swa
+ \skv@foreach@addtocallback{afterpre}{%
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \def\skvexpandonce\skv@prova{\number\skv@prova}%
+ \noexpand\fi
+ \skvexpandonce\skv@tester{%
+ \noexpand\skvpushnumber\skvexpandonce\skv@prova
+ }{}%
+ }%
+ \fi
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@afterprecallback
+ \else
+ \skvcmdexit\skv@foreach@itemcounter
+ \fi
+ }%
+}
+
+% remember=<holder.macro> as <child.macro> initially <value>
+%
+\skvrobustdef*\skv@foreach@parseremember#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@tempxifin{(}{#1}{%
+ \skv@err{Value of key 'remember': '(' found.
+ \MessageBreak I don't accept this PGF format.
+ \MessageBreak remove the parenthesis '()'}\@ehd
+ }{}%
+ \def\skv@tempa##1as##2initially##3\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \edef\skv@provc{\skvtrimspace{##3}}%
+ \skv@foreach@swafalse
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'remember' has no holder macro:
+ \MessageBreak i.e., no macro that holds input}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@prova}{}{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak Holder macro \skvoxdetok\skv@prova not escaped}\@ehd
+ }%
+ \fi
+ \ifx\skv@provb\@empty
+ \skv@err{Value of key 'remember' has no child macro;
+ \MessageBreak i.e., no macro after 'as'}\@ehd
+ \else
+ \expandafter\skvifescaped\expandafter{\skv@provb}{%
+ \skv@foreach@swatrue
+ }{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak Child \skvoxdetok\skv@provb not escaped}\@ehd
+ }%
+ \fi
+ }%
+ \skv@tempxifin{initially}{#1}{%
+ \skv@tempxifin{as}{#1}{%
+ \skv@tempa#1\skv@nil
+ }{%
+ \skv@err{Value of key 'remember':
+ \MessageBreak There is 'initially', but no 'as'}\@ehd
+ }%
+ }{%
+ \skv@tempxifin{as}{#1}{%
+ \skv@tempa#1initially\skv@nil
+ }{%
+ % No 'as' and 'initially':
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \ifx\skv@prova\@empty\else
+ \skv@tempa#1as initially\skv@nil
+ \fi
+ }%
+ }%
+ \ifskv@foreach@swa
+ % Initially:
+ \skv@foreach@addtocallback{pre}{%
+ % Don't remove this \ifnum, otherwise the initial assignment
+ % will be overwritten on subsequent returns:
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \edef\skvexpandonce\skv@provb{%
+ \noexpand\unexpanded{\skvexpandonce\skv@provc}%
+ }%
+ \noexpand\fi
+ }%
+ \skv@foreach@addtocallback{post}{%
+ \let\skvexpandonce\skv@provb\skvexpandonce\skv@prova
+ }%
+ \fi
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@precallback
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+% recall=<holder.macro> initially <value>.
+%
+% This builds a retainer macro of the form \<foreachlast><holder.name>.
+%
+% 'as' is invalid/illegal here, since a retainer macro is built internally.
+%
+\skvrobustdef*\skv@foreach@parserecall#1{%
+ \begingroup
+ \def\skv@tempxifin##1##2{%
+ \skvxifin{\detokenize{##1}}{\detokenize{##2}}%
+ }%
+ \skv@tempxifin{(}{#1}{%
+ \skv@err{Value of key 'recall': '(' found.
+ \MessageBreak I don't accept this PGF format.
+ \MessageBreak remove the parenthesis '()'}\@ehd
+ }{}%
+ \skv@foreach@swafalse
+ \def\skv@tempa##1initially##2\skv@nil{%
+ \edef\skv@prova{\skvtrimspace{##1}}%
+ \edef\skv@provb{\skvtrimspace{##2}}%
+ \ifx\skv@prova\@empty
+ \skv@err{Value of key 'recall' has no holder macro:
+ \MessageBreak i.e., no macro that holds input}\@ehd
+ \else
+ \expandafter\skvifntype\expandafter{\skv@prova}{%
+ \expandafter\skvifescaped\expandafter{\skv@prova}{%
+ \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
+ \skv@foreach@swatrue
+ % Initially:
+ \skv@foreach@addtocallback{pre}{%
+ % Don't remove this \ifnum, otherwise the initial assignment
+ % will be overwritten on subsequent returns:
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \skvcsedef{foreachlast\skv@elt}{%
+ \noexpand\unexpanded{\skvexpandonce\skv@provb}%
+ }%
+ \noexpand\fi
+ }%
+ \skv@foreach@addtocallback{post}{%
+ \skvcslet{foreachlast\skv@elt}\skvexpandonce\skv@prova
+ }%
+ }{%
+ \skv@err{Value of key 'recall':
+ \MessageBreak \detokenize{#1} is not escaped}\@ehd
+ }%
+ }{%
+ \skv@err{Value of key 'recall':
+ \MessageBreak \detokenize{#1} is not one token}\@ehd
+ }%
+ \fi
+ }%
+ \skv@tempxifin{as}{#1}{%
+ \skv@err{Value of key 'recall': invalid 'as' found.
+ \MessageBreak This key doesn't expect 'as' since
+ \MessageBreak it automatically builds a retainer macro
+ \MessageBreak of the form \<foreachlast><holder.name>}\@ehd
+ }{%
+ \skv@tempxifin{initially}{#1}{%
+ \skv@tempa#1\skv@nil
+ }{%
+ \ifx\@nnil#1\@nnil\else
+ \skv@tempa#1initially\skv@nil
+ \fi
+ }%
+ }%
+ \skvexpanded{\endgroup
+ \ifskv@foreach@swa
+ \skvcmdexit\skv@foreach@precallback
+ \skvcmdexit\skv@foreach@postcallback
+ \fi
+ }%
+}
+
+% Eg, \skv@dots@in<value>\skv@nil...\skv@nnil\skv@stop
+\skvnewdef*\skv@dots@in#1...#2#3\skv@stop{%
+ \ifx\skv@nnil#2\in@false\else\in@true\fi
+}
+
+\skvrobustdef*\skv@foreach@latehookerr{%
+ \def\skv@foreach@latehook{%
+ \begingroup
+ \let\s\string
+ \skv@err{A \noexpand\newforeach hook (\s\prependtobeginforeach,
+ \MessageBreak\s\appendtobeginforeach, \s\atbeginforeach,
+ \MessageBreak\s\prependtoendforeach, \s\appendtoendforeach,
+ \MessageBreak or \s\atendforeach) has been illegally
+ \MessageBreak issued within \s\newforeach}
+ {\s\newforeach\space hook command shouldn't be issued
+ within \s\newforeach.}%
+ \endgroup
+ }%
+ \skvletmanytocmd{%
+ \prependtobeginforeach\appendtobeginforeach\atbeginforeach
+ \prependtoendforeach\appendtoendforeach\atendforeach
+ }\skv@foreach@latehook
+}
+
+\skvrobustdef*\skv@foreach@pushstate{%
+ \skvsavestate\skv@foreach@stack{%
+ \do\skv@foreach@parser\do\skv@foreach@subparser
+ \do\skv@foreach@listismacro
+ \do\skv@foreach@processupto\do\skv@foreach@processempty
+ \do\skv@foreach@exittester
+ \do\skv@foreach@grow\do\skv@foreach@growleft
+ \do\skv@foreach@growright
+ \do\skv@foreach@terminator\do\skv@foreach@recoverholders
+ \do\skv@foreach@callback
+ \do\skv@foreach@auxcallback
+ \do\skv@foreach@precallback
+ \do\skv@foreach@afterprecallback
+ \do\skv@foreach@postcallback
+ \do\skv@foreach@onlyinitially
+ \do\foreachlistremainder\do\skv@foreach@mainloop
+ \do\skv@foreach@getnext\do\skv@foreach@getrm
+ \do\skv@foreach@do@a\do\skv@foreach@do@b
+ \do\skv@foreach@holderlist
+ \do\skv@foreach@userlist
+ \do\skv@foreach@inherit
+ \do\skv@foreach@keepdecimals
+ \do\skv@foreach@keephighdecimals
+ \do\skv@foreach@itemcounter
+ \do\skv@foreach@link\do\skv@foreach@expandbeforefill
+ \do\skv@listbreakertoks\do\skv@listpausertoks
+ \do\foreachcurrentitem
+ \do\foreachnextitem
+ \do\foreachitemcount
+ \do\foreachprevitem
+ % The following commands are disabled on entry into the loop.
+ % Hence they need to be stacked:
+ \do\prependtobeginforeach
+ \do\appendtobeginforeach
+ \do\atbeginforeach
+ \do\prependtoendforeach
+ \do\appendtoendforeach
+ \do\atendforeach
+ }\foreachdepth
+}
+\skvrobustdef*\skv@foreach@popstate{%
+ \skvrestorestate\skv@foreach@stack\foreachdepth
+}
+\skvnewdef*\foreachnestdepth{\foreachdepth}
+\skvnewlet\skv@foreach@nil\relax
+\skvnewdef*\skv@foreach@nnil{\skv@foreach@nil}
+\skvrobustdef*\newforeach{\skv@testst\skv@newforeach@beginprescan}
+\skvrobustdef*\skv@newforeach@beginprescan{%
+ \edef\skv@foreach@st{0\ifskv@tempst0\else1\fi}%
+ \begingroup
+ \def\skv@tempa{%
+ \skvexpanded{\endgroup
+ \noexpand\skv@foreach@endprescan{\skvexpandonce\skv@tempb}%
+ }%
+ }%
+ \def\skv@tempb{}%
+ \let\bgroup\relax
+ \skvifnextchar[{%
+ \endgroup
+ \skv@foreach@scanarg
+ }{%
+ \skvifnextchar i{%
+ \endgroup
+ \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ }{%
+ \skvifnextchar\skv@orig@bgroup{%
+ \endgroup
+ \skv@err{\string\newforeach: no holder macro seen}\@ehd
+ }{%
+ \skv@foreach@collectholders
+ }%
+ }%
+ }%
+}
+\skvrobustdef*\skv@foreach@collectholders#1{%
+ \edef\skv@tempb{%
+ \skvexpandonce\skv@tempb\skvtrimspace{#1}%
+ }%
+ \skvifnextchar[{%
+ \skv@tempa
+ }{%
+ \skvifnextchar i{%
+ \skv@tempa[]%
+ }{%
+ \skvifnextchar\skv@orig@bgroup{%
+ \skv@tempa[]%
+ }{%
+ \skv@foreach@collectholders
+ }%
+ }%
+ }%
+}
+\skvrobustdef*\skv@foreach@endprescan#1[#2]{%
+ \skvifblank{#1}{%
+ \skv@err{\string\newforeach: no holder macros seen}\@ehd
+ }{%
+ \skv@foreach@scanarg[#2]#1%
+ }%
+}
+\skvrobustdef*\skv@foreach@scanarg{\skv@testopt\skv@foreach@a{}}
+\skvrobustdef*\skv@foreach@a[#1]{%
+ \skv@foreach@pushstate
+ \skv@foreach@latehookerr
+ % \foreachitemcount must be a macro, not a counter, because it is stacked:
+ \def\foreachitemcount{0}%
+ % Don't confuse item counters of various depths:
+ \skvundef\skv@foreach@itemcounter
+ \skvundef\skv@foreach@processupto
+ \def\skv@foreach@callback{}%
+ \def\skv@foreach@auxcallback{}%
+ \def\skv@foreach@precallback{}%
+ \def\skv@foreach@afterprecallback{}%
+ \def\skv@foreach@postcallback{}%
+ \def\skv@foreach@onlyinitially{}%
+ % The keys have to be set here, to determine if the list is a macro, etc.
+ % Since \skv@foreach@precallback are initialized in each nest, the
+ % keys have to be reset here.
+ \skv@foreach@setkeys{#1}%
+ \begingroup
+ % Collect item holders. Don't confuse explicit \bgroup for left brace:
+ \skv@cnta\skvz@
+ \def\skv@tempb{}%
+ \let\bgroup\relax
+ \skvifnextchar i\skv@foreach@c{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ }%
+}
+% #1: one holer macro or subparser.
+\skvrobustdef*\skv@foreach@b#1{%
+ \ifnum\skv@cnta=\skvz@
+ \skvifescaped{#1}{}{%
+ \skv@err{Token '\noexpand#1' is not escaped
+ \MessageBreak and can't be a holder macro}\@ehd
+ }%
+ \else
+ \ifnum\skv@cnta=\@ne
+ \skvifescaped{#1}{%
+ \skv@err{Token '\noexpand#1' cannot be a subparser;
+ \MessageBreak it seems to be a holder macro.
+ \MessageBreak I expected the subparser to be the
+ \MessageBreak second token here.}\@ehd
+ }{%
+ \edef\skv@prova{\skvtrimspace{#1}}%
+ \let\elt\skvexpandonce
+ \def\skv@elt{\elt\skv@foreach@subparser}%
+ \if\elt\skv@prova\skv@elt\else
+ % Don't stack \skv@warnsubparser:
+ \ifnum\skv@warnsubparser=\skvz@
+ \skvgadvanceno\skv@warnsubparser\@ne
+ \skv@warn{Scanned subparser '\elt\skv@prova' is different from
+ \MessageBreak the default or user-supplied subparser '\skv@elt'.
+ \MessageBreak I have used '\elt\skv@prova', but please submit
+ \MessageBreak '\elt\skv@prova' as the value of the key
+ 'subparser'
+ }%
+ \fi
+ \let\skv@foreach@subparser\skv@prova
+ \fi
+ }%
+ \fi
+ \fi
+ \advance\skv@cnta\@ne
+ \edef\skv@tempb{\skvexpandonce\skv@tempb\skvtrimspace{#1}}%
+ \skvifnextchar i\skv@foreach@c{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@d\skv@foreach@b
+ }%
+}
+\skvrobustdef*\skv@foreach@c#1#2{%
+ \skvifstrcmp{#1#2}{in}{%
+ \skv@foreach@d
+ }{%
+ \skv@err{I have seen 'i' but no expected 'in'}\@ehd
+ }%
+}
+\skvrobustdef*\skv@foreach@d{%
+ \ifx\skv@tempb\@empty
+ \skv@err{No item holder macros before 'in'
+ \MessageBreak or before left brace}\@ehd
+ \fi
+ \skvifnextchar\skv@orig@bgroup{%
+ \skv@foreach@e
+ }{%
+ \if\skv@foreach@listismacro
+ \expandafter\skv@foreach@e
+ \else
+ \if\skv@foreach@st
+ \expandafter\expandafter\expandafter\skv@foreach@e
+ \else
+ \def\reserved@a##1{%
+ \skvifmacro{##1}{%
+ \def\skv@ehd{Maybe a star (*) suffix or key 'list is
+ a macro' is missing.}%
+ }{%
+ \let\skv@ehd\@ehd
+ }%
+ \skv@err{I expected a left brace for beginning of list,
+ \MessageBreak since you haven't told me that your
+ \MessageBreak list is a macro. Instead I found '\detokenize{##1}'.
+ \MessageBreak If your list is indeed a macro, you can
+ \MessageBreak either put star (*) after \noexpand\newforeach
+ \MessageBreak or use the key 'list is a macro'%
+ }{%
+ \skv@ehd
+ }%
+ }%
+ \expandafter\expandafter\expandafter\reserved@a
+ \fi
+ \fi
+ }%
+}
+% #1: <list> or <listcmd>
+\skvrobustdef*\skv@foreach@e#1{%
+ \edef\skv@tempc{\unexpanded{#1}}%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@h{%
+ \skvifnextchar d\skv@foreach@f\skv@foreach@g
+ }%
+}
+\skvrobustdef*\skv@foreach@f#1#2{%
+ \skvifstrcmp{#1#2}{do}{%
+ \skvifnextchar\skv@orig@bgroup\skv@foreach@h\skv@foreach@g
+ }{%
+ \skv@err{I have seen 'd' but no the expected 'do'}\@ehd
+ }%
+}
+% We've exhausted all options for grabbing the callback, so now
+% look for terminator (default ;). If there is no terminator ahead,
+% the use of \skv@prova will trigger 'the use of ... does not match
+% its definition' or 'runaway argument ...'.
+\skvrobustdef*\skv@foreach@g{%
+ \def\skv@prova##1{%
+ \def\skv@prova####1##1{%
+ % Look out for a case like 'parser=<parser>'.
+ % Eg, \newforeach[parser=;]. In this case, the value ';' of
+ % key 'parser' will mistakenly be assumed to be the callback
+ % terminator. It should be enclosed in braces.
+ \skvxifin{\detokenize{parser=}\relax}{\detokenize{####1}\relax}{%
+ \skvxifin{[}{\detokenize{####1}}{%
+ \skv@err{Put '##1' in braces for key 'parser=##1'.
+ \MessageBreak Try [parser={##1}]}
+ {Maybe parser '##1' is the value of a key/option of
+ \noexpand\newforeach and needs to be enclosed in braces.
+ The '##1' I have just encountered doesn't seem to be the
+ one ending a TikZ object. Maybe you need to do [parser={##1}].}%
+ }{%
+ % Otherwise, let's try continue:
+ \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ }%
+ }{%
+ \skvexpanded{\noexpand\skv@foreach@h{\skvtrimspace{####1}##1}}%
+ }%
+ }%
+ \skv@prova
+ }%
+ % In case callback terminator is currently active:
+ \skv@rescan\skv@foreach@terminator
+ \expandafter\skv@prova\expandafter{\skv@foreach@terminator}%
+}
+% #1: callback
+\skvrobustdef*\skv@foreach@h#1{%
+ \skvexpanded{\endgroup
+ % The subparser may have changed along the way (see \skv@foreach@b):
+ \skvcmdexit\skv@foreach@subparser
+ \skv@foreach@i{\skvexpandonce\skv@tempb}{\skvexpandonce\skv@tempc}%
+ }{#1}%
+}
+% #1: holder macros
+% #2: List or list command
+% #3: Callback
+\skvrobustdef*\skv@foreach@i#1#2#3{%
+ \if\skv@foreach@st\else
+ \if\skv@foreach@listismacro
+ \def\skv@foreach@st{00}%
+ \else
+ \def\skv@foreach@st{01}%
+ \fi
+ \fi
+ \edef\skv@foreach@userlist{%
+ \if\skv@foreach@st
+ \expandafter\skvexpandonce
+ \else
+ \expandafter\unexpanded
+ \fi
+ {#2}%
+ }%
+ % Initial code, if any:
+ \skvcsuse{skv@foreach@atbeginhook@\skvrom\foreachdepth}%
+ \skvifdef\foreachprevitem{}{\def\foreachprevitem{}}%
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@parser]\skv@foreach@userlist
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@subparser]\skv@foreach@userlist
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ \def\skv@foreach@lookahead@a##1{%
+ \def\skv@foreach@continue{##1.}%
+ \futurelet\skv@foreach@next\skv@foreach@lookahead@b
+ }%
+ \def\skv@foreach@lookahead@b{%
+ \ifx\skv@foreach@next[%
+ \expandafter\skv@foreach@lookahead@c
+ \else
+ \ifx\skv@foreach@next(%
+ \expandafter\expandafter\expandafter\skv@foreach@lookahead@d
+ \else
+ \expandafter\expandafter\expandafter\skv@foreach@continue
+ \fi
+ \fi
+ }%
+ \def\skv@foreach@lookahead@c[##1]{\skv@foreach@continue[{##1}]}%
+ \def\skv@foreach@lookahead@d(##1){\skv@foreach@continue({##1})}%
+ \def\skv@foreach@mainloop##1{%
+ \def\skv@foreach@getnext####1##1####2\skv@foreach@stop{%
+ \edef\foreachnextitem{\skvexpandonce{\@gobble####1}}%
+ \ifx\foreachnextitem\skv@foreach@nnil
+ \foreachlastitemtrue
+ \def\foreachnextitem{}%
+ \fi
+ }%
+ \def\skv@foreach@do@a####1##1####2\skv@foreach@stop{%
+ \edef\foreachcurrentitem{\skvexpandonce{\@gobble####1}}%
+ \skvifx\foreachcurrentitem\skv@foreach@nnil{%
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ }{%
+ \skvifx\foreachcurrentitem\skv@listbreakertoks{%
+ \skv@foreach@getrm{####2}%
+ }{%
+ \skvifx\foreachcurrentitem\skv@listpausertoks{%
+ \message{^^J! List pause:
+ ^^JType x or X to quit, or <RETURN> to proceed^^J}%
+ \begingroup
+ \endlinechar\m@ne\global\read-1 to\@gtempa
+ \endgroup
+ \skvexpandarg\lowercase{\def\noexpand\@gtempa{\@gtempa}}%
+ \skvxifstrcmp\@gtempa{x}{%
+ \skv@foreach@getrm{####2}%
+ }{%
+ \skv@foreach@do@b{####2}%
+ }%
+ }{%
+ \skv@foreach@do@b{####2}%
+ }%
+ }%
+ }%
+ }%
+ \def\skv@foreach@do@b####1{%
+ \edef\foreachitemcount{\the\numexpr\foreachitemcount+1}%
+ \ifnum0=\numexpr
+ \ifx\skv@foreach@itemcounter\@undefined-1\else+0\fi
+ \ifx\skv@foreach@itemcounter\@empty-1\else+0\fi
+ \ifx\skv@foreach@itemcounter\@nnil-1\else+0\fi\relax\relax
+ \expandafter\let\skv@foreach@itemcounter\foreachitemcount
+ \fi
+ \skv@foreach@lookahead@a\skv@foreach@getnext####1\skv@foreach@stop
+ % In case the user decides to continue after \listpauser:
+ \skvifx\foreachcurrentitem\skv@listpausertoks{}{%
+ \expandafter\skv@foreach@callback\expandafter{\foreachcurrentitem}%
+ }%
+ \let\foreachprevitem\foreachcurrentitem
+ \ifx\skv@foreach@processupto\@undefined\else
+ \ifx\skv@foreach@processupto\@nnil\else
+ \ifnum\foreachitemcount<\skv@foreach@processupto\relax\else
+ \skvbreakloop
+ \fi
+ \fi
+ \fi
+ \skvifdefbool{skvbreakloop}{%
+ \skv@foreach@getrm{####1}%
+ }{%
+ \skv@foreach@lookahead@a\skv@foreach@do@a####1\skv@foreach@stop
+ }%
+ }%
+ \def\skv@foreach@getrm####1{%
+ \skvbreakloopfalse
+ \foreachlastitemfalse
+ \def\skv@prova########1\skv@foreach@nil##1{%
+ \edef\foreachlistremainder{\unexpanded{########1}}%
+ \skv@removetrailingparser{##1}\foreachlistremainder
+ }%
+ \skv@prova####1%
+ }%
+ \skvifx\skv@foreach@userlist\@empty{%
+ \if\skv@foreach@processempty\skv@foreach@callback{}\fi
+ }{%
+ \expandafter\skv@foreach@filllist\expandafter
+ {\skv@foreach@parser}\skv@foreach@userlist
+ \expandafter\skv@foreach@lookahead@a\expandafter\skv@foreach@do@a
+ \skv@foreach@userlist##1\skv@foreach@nil##1\skv@foreach@stop
+ }%
+ }%
+ \skv@foreach@makeprecode{#1}%
+ \if\skv@foreach@recoverholders\else
+ \expandafter\skvsavestate\expandafter\skv@foreach@holderstate
+ \expandafter{\skv@foreach@holderlist}\skv@foreach@sisterdepth
+ \fi
+ \skv@foreach@makeauxcallback{#3}%
+ \skvexpandbracenext\skv@foreach@mainloop\skv@foreach@parser
+ \skvcsuse{skv@foreach@atendhook@\skvrom\foreachdepth}%
+ \if\skv@foreach@recoverholders\else
+ \skvrestorestate\skv@foreach@holderstate\skv@foreach@sisterdepth
+ \fi
+ \skv@foreach@popstate
+}
+
+% \skv@foreach@makeprecode{<holder.list>}
+%
+% 'Holder macro' here means, eg, \x and \y in
+%
+% \newforeach \x/\y in {1/a,2/b,3/c}{<code>}
+%
+\skvrobustdef*\skv@foreach@makeprecode#1{%
+ \begingroup
+ \skv@cnta\skvz@
+ \def\skv@foreach@holderlist{}%
+ \def\skv@foreach@paramlist{}%
+ \def\skv@prevholder{}%
+ \def\skv@tempa{#1}%
+ \expandafter\skv@foreach@normalize\expandafter
+ [\skv@foreach@subparser]\skv@tempa
+ \skvtfor*\skv@prova:=\skv@tempa\do{%
+ \ifx\skv@prova\skv@foreach@subparser
+ \ifnum\skv@cnta=\skvz@
+ \skv@err{Subparser '\skvoxdetok\skv@foreach@subparser' can't come
+ first in the list\MessageBreak of holder macros}\@ehd
+ \else
+ % Eg, if subparser is slash (/), \skv@foreach@paramlist will have
+ % the syntax: ##1/##2/...:
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist\skvexpandonce\skv@prova
+ }%
+ \fi
+ \else
+ \advance\skv@cnta\@ne
+ \edef\skv@elt{\expandafter\skvremovescape\skv@prova}%
+ \edef\skv@foreach@precallback{%
+ \skvexpandonce\skv@foreach@precallback
+ % Each given item-holder macro is now defined in terms of
+ % parameters of skv@foreach@auxcallback:
+ \edef\skvexpandonce\skv@prova{%
+ \noexpand\unexpanded{####\number\skv@cnta}%
+ }%
+ % If the current holder has no value, use the value of last holder:
+ \ifnum\skv@cnta>\@ne
+ \if\skv@foreach@inherit
+ \noexpand\ifx\skvexpandonce\skv@prova\noexpand\@empty
+ \let\skvexpandonce\skv@prova\skvexpandonce\skv@prevholder
+ \noexpand\fi
+ \fi
+ \fi
+ }%
+ \edef\skv@foreach@holderlist{%
+ \skvexpandonce\skv@foreach@holderlist
+ % The \do is for the individual entries of the stack of
+ % \skv@foreach@holderlist. It is required for stacking the
+ % holder list:
+ \noexpand\do\skvexpandonce\skv@prova
+ }%
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist########\number\skv@cnta
+ }%
+ \let\skv@prevholder\skv@prova
+ \fi
+ }%
+ % Add one extra parameter character to absorb extra subparsers that are
+ % added for incomplete list items:
+ \edef\skv@foreach@paramlist{%
+ \skvexpandonce\skv@foreach@paramlist
+ \skvexpandonce\skv@foreach@subparser
+ ########\number\numexpr\skv@cnta+1\relax
+ }%
+ \skvexpanded{\endgroup
+ \skvcmdexit\skv@foreach@holderlist
+ \skvcmdexit\skv@foreach@paramlist
+ \skvcmdexit\skv@foreach@precallback
+ }%
+}
+
+% #1: callback
+\skvrobustdef*\skv@foreach@makeauxcallback#1{%
+ \begingroup
+ \def\skv@generatesubparser##1{%
+ \ifnum##1<10\skvexpandonce\skv@foreach@subparser
+ \expandafter\skv@generatesubparser
+ \expandafter{\number\numexpr##1+1\expandafter}%
+ \fi
+ }%
+ % Add extra subparsers in case some items aren't subparser-complete:
+ \edef\skv@tempa{\skv@generatesubparser{1}}%
+ \let\foreacheov\relax
+ \skvexpanded{\endgroup
+ % Define auxiliary callback:
+ \def\noexpand\skv@foreach@auxcallback\skv@foreach@paramlist\foreacheov{%
+ % Holder macro assignments:
+ \skvexpandonce\skv@foreach@precallback
+ % User tests/tasks, eg, if requested from 'evaluate' key:
+ \skvexpandonce\skv@foreach@afterprecallback
+ \noexpand\ifnum\noexpand\foreachitemcount=\@ne
+ \noexpand\skv@foreach@onlyinitially
+ \noexpand\fi
+ \unexpanded{#1}%
+ % User tests/tasks, eg, if requested from the keys 'remember',
+ % 'exit when', etc:
+ \skvexpandonce\skv@foreach@postcallback
+ }%
+ % Define the real callback:
+ \def\noexpand\skv@foreach@callback####1{%
+ \noexpand\skv@foreach@auxcallback####1\skv@tempa\foreacheov
+ }%
+ }%
+}
+\skvnewdef*\skv@ucalpha#1{%
+ \ifcase#1\or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or
+ K\or L\or M\or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or
+ X\or Y\or Z\else?\fi
+}
+\skvnewdef*\skv@lcalpha#1{%
+ \ifcase#1\or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or
+ k\or l\or m\or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or
+ x\or y\or z\else?\fi
+}
+\skvnewdef*\skv@alphamap{%
+ {A}{a}{1}{B}{b}{2}{C}{c}{3}{D}{d}{4}{E}{e}{5}{F}{f}{6}{G}{g}{7}{H}{h}{8}%
+ {I}{i}{9}{J}{j}{10}{K}{k}{11}{L}{l}{12}{M}{m}{13}{N}{n}{14}{O}{o}{15}%
+ {P}{p}{16}{Q}{q}{17}{R}{r}{18}{S}{s}{19}{T}{t}{20}{U}{u}{21}{V}{v}{22}%
+ {W}{w}{23}{X}{x}{24}{Y}{y}{25}{Z}{z}{26}%
+}
+% \skv@foreach@addtolist<parser><add.new><listcmd>
+\skvrobustdef*\skv@foreach@addtolist#1#2#3{%
+ \edef#3{\skvexpandonce#3\ifx#3\@empty\else\unexpanded{#1}\fi#2}%
+}
+\skvrobustdef*\skv@reverselumap#1{%
+ \def\skv@prova##1##2##3##4\skv@nil{%
+ \ifx\@nnil##1%
+ \expandafter\@gobble
+ \else
+ \expandafter\@iden
+ \fi
+ {\skv@prova##4\skv@nil{##1}{##2}{##3}}%
+ }%
+ \edef#1{\expandafter\skv@prova\skv@alphamap\@nnil{}{}\skv@nil}
+}
+
+\skvnewdef*\skv@foreach@ifloweralpha#1{%
+ \skvifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \skvifntype{#1}{%
+ \skvifnum`#1>96{%
+ \skvifnum`#1<123{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+\skvnewdef*\skv@foreach@ifupperalpha#1{%
+ \skvifblank{#1}{%
+ \@secondoftwo
+ }{%
+ \skvifntype{#1}{%
+ \skvifnum`#1>64{%
+ \skvifnum`#1<91{%
+ \@firstoftwo
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }{%
+ \@secondoftwo
+ }%
+ }%
+}
+
+% Parse list for 1,2,...,n,1,...,m. Return value in #1:
+%
+% \skv@foreach@filllist{<parser>}<listcmd>
+\skvrobustdef*\skv@foreach@filllist#1#2{%
+ \def\skv@inalphabetic{01}%
+ \def\skv@isupperalpha{01}%
+ % If the list is alphabetic, original unit is nil:
+ \def\skv@foreach@origunit{}%
+ \def\skv@foreach@filledlist{}%
+ \edef\skv@foreach@parser{\skvtrimspace{#1}}%
+ \ifx\skv@foreach@parser\@undefined
+ \def\skv@foreach@parser{,}%
+ \fi
+ \def\skv@foreach@iflinkgiven{%
+ \skvifdef\skv@foreach@link{%
+ \skvnotifx\skv@foreach@link\@nnil
+ }{%
+ \skv@err{List auto-completion: 'link' is undefined}\@ehd
+ }%
+ }%
+ \skvexpanded{%
+ \noexpand\skv@foreach@filllist@a
+ {\skvexpandonce\skv@foreach@parser}{\skvexpandonce{#2}}%
+ }%
+ \let#2\skv@foreach@filledlist
+}
+\skvnewlet\skvautofilllist\skv@foreach@filllist
+% \skv@foreach@filllist@a{<parser>}{<list>}
+\skvrobustdef*\skv@foreach@filllist@a#1#2{%
+ \edef\skv@tempa{\unexpanded{#2}}%
+ \skv@foreach@normalize[#1]\skv@tempa
+ \def\skv@prova##1{%
+ \skvxifin{...}{\detokenize{##1}}{%
+ \if\skv@foreach@expandbeforefill
+ \edef\skv@tempa{##1}%
+ \skv@foreach@normalize[#1]\skv@tempa
+ \else
+ \edef\skv@tempa{\unexpanded{##1}}%
+ \fi
+ \skvexpandargonce{\skv@foreach@filllist@b{#1}}{\skv@tempa}%
+ \skv@foreach@normalize[#1]\skv@foreach@filledlist
+ }{%
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \skvtrimspace{##1}%
+ }%
+ }%
+ }%
+ \expandafter\skv@prova\expandafter{\skv@tempa}%
+}
+% \skv@foreach@filllist@b{<parser>}{<list>}
+\skvrobustdef*\skv@foreach@filllist@b#1#2{%
+ \skvxiffound{\relax...}\in{\relax\detokenize{#2}}\then
+ \skv@err{I can't find lower limit before '...'}\@ehd
+ \else
+ \skvxiffound{\relax\detokenize{#1}...}\in{\relax\detokenize{#2}}\then
+ \skv@err{I can't find lower limit before '...'}\@ehd
+ \fi
+ \fi
+ % \newforeach format is '<parser>...<parser>':
+ \skvxifin{\detokenize{#1...#1}}{\detokenize{#2}}{%
+ \skv@foreach@splitonguide{#1}{#2}%
+ \def\skv@prova##1#1##2#1...#1##3#1##4#1##5\skv@nil{%
+ \skvifblank{##3}{%
+ \skv@err{I can't find upper limit number or dimension,
+ \MessageBreak i.e., after symbool '...'}\@ehd
+ }{%
+ % \skv@foreach@filllist@a may be reentered. Hence accumulate
+ % filled list:
+ \skviflacus{##1}\then\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist\unexpanded{##1}%
+ }%
+ \fi
+ % Complete the list:
+ \skv@foreach@filllist@c{#1}{##1}{##2}{##3}%
+ % In case the list is folded on ellipsis (...):
+ \skvifblank{##4}{}{\skv@foreach@filllist@a{#1}{##4#1##5}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa#1#1\skv@nil
+ }{%
+ % Not \newforeach format: try PGF's \foreach format:
+ \skv@foreach@trypgfformat{#1}{#2}%
+ }%
+}
+
+% \skv@foreach@zerostepwarn{<lower>}{<upper>}{<pt.or.nil>}
+\skvrobustdef*\skv@foreach@zerostepwarn#1#2#3{%
+ \skv@warn{The tokens '\detokenize{#1}', '\detokenize{#2}'
+ give nil step; '1#3' used. \MessageBreak
+ Maybe you used the font-dependent units \MessageBreak
+ 'ex' or 'em' before \skv@begindoc@string}%
+}
+
+% skv@foreach@filllist@c{<parser>}{<lower1>}{<lower2>}{<upperbound>}
+%
+% 1. No <guide> here.
+%
+\skvrobustdef*\skv@foreach@filllist@c#1#2#3#4{%
+ \skv@foreach@iflinkgiven{%
+ % <link> has been given by the user:
+ \skv@foreach@splitandgrow{#1}{#2}{#3}{#4}%
+ }{%
+ % No <link> has been given. The list has '...' but presumably no link.
+ % Note: If there're more than 1 alpha/Alpha character, both
+ % \skv@foreach@ifloweralpha and \skv@foreach@ifupperalpha will
+ % return false, since double aphabetic characters can't be grown.
+ % \skv@foreach@filllist@d{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+ \skv@foreach@filllist@d{#1}{}{#2}{#3}{#4}%
+ }%
+}
+
+% skv@foreach@fsplitandgrow{<parser>}{<lower1>}{<lower2>}{<upperbound>}
+%
+% {0\pi,0.5\pi,...,3\pi} : link = \pi ; grow left
+% {1--,4--,...,10--} : link = -- ; grow left
+% {2pt,4pt,...,10pt} : link = pt ; grow left (or no additional info.)
+% {A_1,C_1,...,Q_1} : link = _ ; grow left
+% {2^a,2^c,...,2^q} : link = ^ ; grow right
+%
+% 1. Automatically split and grow.
+% 2. We already know that the key 'link' will reject empty values.
+%
+\skvrobustdef*\skv@foreach@splitandgrow#1#2#3#4{%
+ \ifx\skv@foreach@growleft\skv@foreach@growright
+ \skv@err{I can't grow the list in both directions.
+ \MessageBreak Maybe you haven't indicated the
+ \MessageBreak direction of growth (left or right),
+ \MessageBreak or both directions are 'true'.}
+ {Try one of the keys 'grow=left or right',
+ \MessageBreak 'grow left=true or false',
+ 'grow right=true or false'}\@ehd
+ \fi
+ \begingroup
+ \def\skv@prova##1{%
+ \skv@foreach@swatrue
+ \skviflacus#2\then\else
+ \skvifin{##1}{#2}{}\skv@foreach@swafalse
+ \fi
+ \skvifin{##1}{#3}{}\skv@foreach@swafalse
+ \skvifin{##1}{#4}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa\else
+ \edef\skv@provb{\ifx\@nnil#2\@nnil\else\unexpanded{#2}, \fi}%
+ \skv@err{No link '##1' in one of
+ '\detokenize\expandafter{\skv@provb#3, #4}'}\@ehd
+ \fi
+ \def\skv@prova####1##1####2\skv@nil{%
+ \if\skv@foreach@growright
+ \edef\skv@prova{\skvtrimspace{####1##1}}%
+ \else
+ \edef\skv@prova{\skvtrimspace{##1####2}}%
+ \fi
+ \def\do########1{{\skvtrimspace{########1}}}%
+ % \skv@foreach@trypgfformat@a<parser><guide><lower1><lower2><upper>
+ \skvexpanded{\endgroup
+ \noexpand\skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}{\skvexpandonce\skv@prova}\do{#2}\do{#3}\do{#4}%
+ }%
+ }%
+ \skv@prova#3\skv@nil
+ }%
+ \expandafter\skv@prova\expandafter{\skv@foreach@link}%
+}
+%
+% \skv@foreach@splitonguide{<parser>}{<list>}
+%
+% Get the two elements before '...' or '<guide>,...'. In the case of skeyval
+% format, get the two elements before '...'. The PGF format uses <guide>,
+% shown in the following examples:
+%
+% PGF formats:
+% {a^1,a^3,a^...,a^9} : <guide> = a^
+% {A_1,B_1,..._1,E_1} : <guide> = _1
+% {1--,4--,...--,16--} : <guide> = --
+% {1pt,4pt,...pt,10pt} : <guide> = pt
+% {A_2pt,A_4pt,A_...pt,A_10pt} : <guide> = A_, pt
+%
+% skeyval formats:
+% {a^1,a^3,a^...,a^9} : no additional info. required
+% {A_1,B_1,..._1,E_1} : no additional info. required
+% {1--,4--,...--,16--} : no additional info. required
+% {1pt,4pt,...pt,10pt} : no additional info. required
+% {A_2pt,A_4pt,A_...,A_10pt} : no additional info. required
+%
+% {a^1,a^3,...,a^9} : link = ^, grow = right
+% {A_1,B_1,...,E_1} : link = _, grow = left
+% {1--,4--,...,16--} : link = --, grow = left
+% {1pt,4pt,...,10pt} : link = pt, grow = left (or addit. info.)
+% {A_2pt,A_4pt,...,A_10pt} : link = _, grow = right
+%
+% The items prior to the last 2 items before '<guide>...' or before '...'
+% are called 'before-the-last-2' (BL2). Collect in \skv@tempa BL2 items,
+% together with the rest of the list. Save in \skv@foreach@filledlist
+% the BL2 items.
+%
+% Return \skv@foreach@filledlist and \skv@tempa.
+%
+\skvrobustdef*\skv@foreach@splitonguide#1#2{%
+ % First count all the elements before '<guide>,...'. We're already
+ % sure that #2 contains '<guide>,...' or '...':
+ \begingroup
+ \skv@cnta\skvz@
+ \def\do##1#1{%
+ \skvifin{...}{##1}{%
+ \def\do####1\skv@nil{}%
+ }{%
+ \advance\skv@cnta\@ne
+ }%
+ \do
+ }%
+ \do#2#1\skv@nil
+ \ifnum\skv@cnta>\tw@
+ \skvsetno\skv@foreach@nra\m@ne
+ \def\do##1#1{%
+ \skvadvanceno\skv@foreach@nra\@ne
+ \ifnum\skv@foreach@nra=\numexpr\skv@cnta-\tw@\relax
+ \def\do####1\skv@nil{\def\skv@tempa{##1#1####1}}%
+ \else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist\unexpanded{##1}%
+ }%
+ \fi
+ \do
+ }%
+ \do#2#1\skv@nil
+ \else
+ \ifnum\skv@cnta=\@ne
+ \def\skv@tempa{#1#2}%
+ \else
+ \ifnum\skv@cnta=\tw@
+ \def\skv@tempa{#2}%
+ \else
+ \ifnum\skv@cnta=\skvz@
+ \skv@err{List <<\detokenize{#2}>>\MessageBreak
+ contains symbol '...' but not a lowerbound}\@ehd
+ \fi
+ \fi
+ \fi
+ \fi
+ \skvexpanded{\endgroup
+ \skvcmdexit\skv@foreach@filledlist\skvcmdexit\skv@tempa
+ }%
+}
+
+% \skv@foreach@trypgfformat{<parser>}{<list>}
+%
+% When we say, 'try PGF format', we don't actually mean the PGF format with
+% left and right guides, but the syntax '<guide>...' (ie, having only the
+% left-hand-side or only the right-hand-side guide). For example,
+% {A_2pt,A_4pt,A_...,A_10pt}. \skv@foreach@trypgfformat will auto-complete
+% this list without knowledge of the values of the keys 'link' and 'grow'.
+%
+% skeyval formats:
+%
+% {1pt,4pt,...pt,10pt} : no additional info. required
+% {A_2pt,A_4pt,A_...,A_10pt} : no additional info. required
+% {1pt,4pt,...,10pt} : link = pt, grow=right (or no addit. info.)
+% {A_2pt,A_4pt,...,A_10pt} : link =_, grow=right
+%
+% The general PGF format (with left and right guides) is illegal here,
+% because the skeyval-for package uses the location of the guide (left or
+% right of ...) to determine the direction of growth.
+%
+% {A_2pt,A_4pt,A_...pt,A_10pt}
+%
+\skvrobustdef*\skv@foreach@trypgfformat#1#2{%
+ \skv@foreach@splitonguide{#1}{#2}%
+ \def\skv@prova##1#1##2#1##3...##4#1##5#1##6#1##7\skv@nil{%
+ \skvifblank{##5}{%
+ \skv@err{I can't find upper limit number or dimension,
+ \MessageBreak i.e., after symbool '...'}\@ehd
+ }{%
+ % \skv@foreach@filllist@a may be reentered. Hence
+ \if\relax\detokenize{##1}\relax\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \skvtrimspace{##1}%
+ }%
+ \fi
+ \def\do####1{{\skvtrimspace{####1}}}%
+ \skvifblank{##3}{%
+ \skvifblank{##4}{%
+ \skv@err{No direction of growth before and/or after
+ \MessageBreak symbol '...'}\@ehd
+ }{%
+ \def\skv@foreach@growleft{00}%
+ \def\skv@foreach@growright{01}%
+ \skvexpanded{%
+ \skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}\do{##4}\do{##1}\do{##2}\do{##5}%
+ }%
+ }%
+ }{%
+ \skvifblank{##4}{%
+ \def\skv@foreach@growright{00}%
+ \def\skv@foreach@growleft{01}%
+ \skvexpanded{%
+ \skv@foreach@trypgfformat@a
+ {\unexpanded{#1}}\do{##3}\do{##1}\do{##2}\do{##5}%
+ }%
+ }{%
+ \skv@err{Having both '\detokenize{##3 and ##4}' in an
+ \MessageBreak ellipsis list is illegal in
+ \MessageBreak\noexpand\newforeach and \noexpand\newforeach.
+ \MessageBreak I know that PGF's \noexpand\foreach needs it,
+ \MessageBreak but I don't need it. I can
+ \MessageBreak auto-fill your list without it.}\@ehd
+ }%
+ }%
+ % In case the list is folded on ellipsis (...):
+ \skvifblank{##6}{}{\skv@foreach@filllist@a{#1}{##6#1##7}}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@tempa#1#1#1\skv@nil
+}
+%
+% \skv@foreach@trypgfformat@a{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+%
+% 1. Use the <guide> to get the contant and variable parts of the
+% elements.
+% 2. Use the variable parts to determine if the list is Alpah, alpha or
+% number type. In this format, the unit in dimension type of list may
+% appear in <guide>.
+% 3. Use the variable parts to work out the <step>.
+% 4. Call the relevant macro to fill the list.
+% 5. <lower1> has already been saved in \skv@foreach@filledlist.
+%
+\skvrobustdef*\skv@foreach@trypgfformat@a#1#2#3#4#5{%
+ \skv@foreach@swafalse
+ \skviflacus#3\then\else
+ \skvxifin{#2}{#3}{}\skv@foreach@swatrue
+ \fi
+ \skvxifin{#2}{#4}{}\skv@foreach@swatrue
+ \skvxifin{#2}{#5}{}\skv@foreach@swatrue
+ \ifskv@foreach@swa
+ \skv@err{Guide token '\detokenize{#2}' not found in some
+ \MessageBreak of the elements: I can't complete
+ \MessageBreak the current list. This may be
+ \MessageBreak due to wrong direction of growth}\@ehd
+ \fi
+ % Get from the left or right of 'link' (#2) the components that should be
+ % grown, without the link:
+ \def\skv@prova##1#2##2\skv@nil##3{%
+ \edef##3{\if\skv@foreach@growleft##1\else##2\fi}%
+ }%
+ % <lower1> is empty when there is only one element before ellipsis:
+ \skviflacus#3\then
+ \def\skv@tempa{}%
+ \else
+ \skv@prova#3\skv@nil\skv@tempa
+ \fi
+ \skv@prova#4\skv@nil\skv@tempb
+ \skv@prova#5\skv@nil\skv@tempc
+ \let\do\skvexpandonce
+ \skvexpandsecond
+ {\skv@foreach@filllist@d{#1}{#2}}%
+ {{\do\skv@tempa}{\do\skv@tempb}{\do\skv@tempc}}%
+}
+
+% \skv@foreach@filllist@d{<parser>}{<guide>}{<lower1>}{<lower2>}{<upper>}
+%
+% 1. Use the variable parts to determine if the list is Alpah, alpha or
+% number type. In this format, the unit in dimension type of list may
+% appear in <guide>.
+% 2. Use the variable parts to work out the <step>.
+% 3. Call the relevant macro to fill the list.
+% 4. <lower1> has already been saved in \skv@foreach@filledlist.
+%
+\skvrobustdef*\skv@foreach@filllist@d#1#2#3#4#5{%
+ \begingroup
+ \def\skv@templist{}%
+ \edef\skv@lowerlower{\ifx\@nnil#3\@nnil\else\unexpanded{#3}, \fi}%
+ \skv@foreach@ifloweralpha{#4}{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skv@foreach@ifloweralpha{#3}{}\skv@foreach@swafalse
+ \fi
+ \skv@foreach@ifloweralpha{#5}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1}%
+ \else
+ \edef\skv@foreach@step{\the\numexpr\lccode`#4-\lccode`#3}%
+ \ifnum\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1}%
+ \skv@foreach@zerostepwarn{#3}{#4}{}%
+ \fi
+ \fi
+ \def\skv@isupperalpha{01}%
+ % \skv@foreach@origunit remains nil on this branch:
+ \skv@foreach@fillalphabetic{#1}{#4}{#5}\skv@templist
+ % Also update the items already entered in \skv@foreach@filledlist.
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak aren't of the same type}\@ehd
+ \fi
+ }{%
+ \skv@foreach@ifupperalpha{#4}{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skv@foreach@ifupperalpha{#3}{}\skv@foreach@swafalse
+ \fi
+ \skv@foreach@ifupperalpha{#5}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1}%
+ \else
+ \edef\skv@foreach@step{\the\numexpr\uccode`#4-\uccode`#3}%
+ \ifnum\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1}%
+ \skv@foreach@zerostepwarn{#3}{#4}{}%
+ \fi
+ \fi
+ \def\skv@isupperalpha{00}%
+ % \skv@foreach@origunit remains nil on this branch:
+ \skv@foreach@fillalphabetic{#1}{#4}{#5}\skv@templist
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{The tokens '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak aren't of the same type}\@ehd
+ \fi
+ }{%
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skvifdimensionable{#3}{}\skv@foreach@swafalse
+ \fi
+ \skvifdimensionable{#4}{}\skv@foreach@swafalse
+ \let\skv@foreach@origunit\skv@dimunit
+ \skvifdimensionable{#5}{}\skv@foreach@swafalse
+ \ifx\skv@foreach@origunit\skv@dimunit\else
+ \skv@err{The units on \detokenize{'#4', '#5'} are different}\@ehd
+ \fi
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1pt}%
+ \else
+ \edef\skv@foreach@step{\the\dimexpr#4-#3}%
+ \ifdim\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1pt}%
+ \skv@foreach@zerostepwarn{#3}{#4}{pt}%
+ \fi
+ \fi
+ \skvexpandsecond{%
+ \skv@foreach@fillnumordim{#1}%
+ }{%
+ {#4}{#5}%
+ }\skv@templist
+ \skv@foreach@strippoint{#1}\skv@templist
+ % Attach the constant part to the elements of the completed list.
+ % <lower1> was saved earlier in \skv@foreach@trypgfformat, and
+ % <lower2> and <upper> have been saved while filling the list.
+ % Always strip point and restore original unit here.
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@foreach@swatrue
+ \ifx\@nnil#3\@nnil\else
+ \skvifdimensionable{#3pt}{}\skv@foreach@swafalse
+ \fi
+ \skvifdimensionable{#4pt}{}\skv@foreach@swafalse
+ \skvifdimensionable{#5pt}{}\skv@foreach@swafalse
+ \ifskv@foreach@swa
+ \ifx\@nnil#3\@nnil
+ \def\skv@foreach@step{1pt}%
+ \else
+ \edef\skv@foreach@step{\the\dimexpr#4pt-#3pt}%
+ \ifdim\skv@foreach@step=\skvz@
+ \def\skv@foreach@step{1pt}%
+ \skv@foreach@zerostepwarn{#3}{#4}{pt}%
+ \fi
+ \fi
+ % \skv@foreach@origunit remains nil on this branch:
+ \skvexpandsecond{%
+ \skv@foreach@fillnumordim{#1}%
+ }{%
+ {#4pt}{#5pt}%
+ }\skv@templist
+ \skv@foreach@strippoint{#1}\skv@templist
+ \skv@foreach@restoreguideandunit{#1}{#2}\skv@templist
+ \else
+ \skv@err{Sorry, the tokens
+ '\detokenize\expandafter{\skv@lowerlower#4, #5}'
+ \MessageBreak are unparsable. I have given up on them.
+ \MessageBreak Did you miss something syntactic?
+ \MessageBreak See manual for acceptable syntaxes}\@ehd
+ \fi
+ \fi
+ }%
+ }%
+ \skvaftergroupdef\skv@foreach@filledlist\endgroup
+}
+
+% Restore guide and, in the case of numerical sequences, 'original unit'.
+%
+% \skv@foreach@restoreguideandunit{<parser>}{<guide>}{<listcmd>}
+\skvrobustdef*\skv@foreach@restoreguideandunit#1#2#3{%
+ \def\do##1#1{%
+ \ifx\do##1\else
+ \edef\skv@foreach@filledlist{%
+ \skvaddlist{#1}\skv@foreach@filledlist
+ \if\skv@foreach@growleft
+ ##1\skv@foreach@origunit\unexpanded{#2}%
+ \else
+ \unexpanded{#2}##1\skv@foreach@origunit
+ \fi
+ }%
+ \expandafter\do
+ \fi
+ }%
+ \expandafter\do#3#1\do#1%
+}
+
+
+\skvrobustdef*\skv@foreach@getcomparator{%
+ \begingroup
+ % 'unit' isn't required in alphabetic sequences:
+ \if\skv@inalphabetic\else
+ \let\skvreversedo\@iden
+ \edef\skv@provb{\skvexpbracenext\skvreverse{\skv@foreach@step}}%
+ \def\skv@prova##1##2##3\skv@nil{%
+ \skvxifin{,\detokenize{##2##1},}{,\skvoxdetok\skv@validunit,}{%
+ \def\skv@foreach@unit{}%
+ }{%
+ \def\skv@foreach@unit{pt}%
+ }%
+ }%
+ \expandafter\skv@prova\skv@provb\skv@nil
+ \fi
+ \def\skv@prova##1##2\skv@nil{%
+ \edef\skv@foreach@stepisneg{0\if-##10\else1\fi}%
+ }%
+ \expandafter\skv@prova\skv@foreach@step\skv@nil
+ \edef\skv@comparator{\if\skv@foreach@stepisneg>\else<\fi}%
+ \let\do\skvcmdexit
+ \skvexpanded{\endgroup
+ \do\skv@foreach@stepisneg\do\skv@comparator
+ \if\skv@inalphabetic\else\do\skv@foreach@unit\fi
+ }%
+}
+% \skv@foreach@fillnumordim<parser><lower><upper><listcmd>
+\skvrobustdef*\skv@foreach@fillnumordim#1#2#3#4{%
+ \begingroup
+ \skv@foreach@getcomparator
+ \if\skv@foreach@stepisneg
+ \ifdim#3\skv@foreach@unit>#2\skv@foreach@unit\relax
+ \skv@err{Step '\skv@foreach@step' is negative but upperbound
+ \MessageBreak '\detokenize{#3}' is greater than lowerbound
+ '\detokenize{#2}'}\@ehd
+ \fi
+ \else
+ \ifdim#3\skv@foreach@unit<#2\skv@foreach@unit\relax
+ \skv@err{Step '\skv@foreach@step' is nonnegative but upperbound
+ \MessageBreak '\detokenize{#3}' is less than lowerbound
+ '\detokenize{#2}'}\@ehd
+ \fi
+ \fi
+ % The bounds may have decimal places. So the calculation has to be
+ % done with \dimexpr:
+ \skv@foreach@addtolist{#1}{\the\dimexpr#2\skv@foreach@unit}#4%
+ % Upper number:
+ \edef\skv@tempa{\the\dimexpr#3\skv@foreach@unit}%
+ % Lower number:
+ \edef\skv@tempb{\the\dimexpr#2\skv@foreach@unit}%
+ \ifdim\skv@tempa=\skv@tempb\relax\else
+ \def\do{%
+ \edef\skv@tempb{%
+ \the\dimexpr\skv@tempb+\skv@foreach@step\skv@foreach@unit\relax
+ }%
+ \ifdim\skv@tempb\skv@comparator\skv@tempa\relax
+ \skv@foreach@addtolist{#1}{\skvexpandonce\skv@tempb}#4%
+ \expandafter\do
+ \fi
+ }%
+ \do
+ % The last item has to in 'pt', so that 'pt' can be stripped:
+ \skv@foreach@addtolist{#1}{\the\dimexpr#3\skv@foreach@unit}#4%
+ \fi
+ \skvaftergroupdef#4\endgroup
+}
+
+% Fill Alpha or alpha:
+% \skv@foreach@fillalphabetic<parser><lower><upper><listcmd>
+\skvrobustdef*\skv@foreach@fillalphabetic#1#2#3#4{%
+ \begingroup
+ \def\skv@inalphabetic{00}%
+ \skv@foreach@getcomparator
+ \edef\skv@type{%
+ \if\skv@isupperalpha Upper\else Lower\fi case alphabetic%
+ }%
+ \edef\reserved@a{\if-\skv@foreach@step\else\skv@foreach@step\fi}%
+ \skvoifinteger\reserved@a{}{%
+ \skv@err{List is '\skv@type' type but\MessageBreak
+ step '\skv@foreach@step' isn't an integer}\@ehd
+ }%
+ \skv@foreach@addtolist{#1}{#2}#4%
+ \skvifstrcmp{#2}{#3}{}{%
+ \edef\skv@lowerlimit{#2}%
+ \edef\skv@upperlimit{#3}%
+ \skvexpandnext{\chardef\skv@lowerlimit`}\skv@lowerlimit\relax
+ \skvexpandnext{\chardef\skv@upperlimit`}\skv@upperlimit\relax
+ \edef\skv@lowerlimit{%
+ \the\numexpr\skv@lowerlimit-\if\skv@isupperalpha 64\else 96\fi
+ }%
+ \edef\skv@upperlimit{%
+ \the\numexpr\skv@upperlimit-\if\skv@isupperalpha 64\else 96\fi
+ }%
+ \edef\skv@charcase{\the\numexpr\skv@lowerlimit+\skv@foreach@step}%
+ \skvrecurse
+ \if\skv@isupperalpha
+ \edef\skv@tempa{\skv@ucalpha\skv@charcase}%
+ \else
+ \edef\skv@tempa{\skv@lcalpha\skv@charcase}%
+ \fi
+ \skv@foreach@addtolist{#1}\skv@tempa#4%
+ \edef\skv@charcase{\the\numexpr\skv@charcase+\skv@foreach@step}%
+ \while
+ \ifnum\skv@charcase\skv@comparator\skv@upperlimit\relax
+ \fi
+ \skv@foreach@addtolist{#1}{#3}#4%
+ }%
+ \skvaftergroupdef#4\endgroup
+}
+
+\skv@for@restorecatcodes
+\endinput