diff options
author | Karl Berry <karl@freefriends.org> | 2008-11-07 01:22:49 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2008-11-07 01:22:49 +0000 |
commit | 3dd6d2ce5083791e0574668e2d2b76d32b248ed8 (patch) | |
tree | 3fc08ff582641658fd6da6925af1a255fb40645d /Master/texmf-dist/tex/generic/xstring/xstring.tex | |
parent | be3631d25628ae81ce5039afc758db5ec49026ba (diff) |
xstring 1.4, and ignore its stale .tds.zip (4nov08)
git-svn-id: svn://tug.org/texlive/trunk@11208 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/xstring/xstring.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/xstring/xstring.tex | 909 |
1 files changed, 557 insertions, 352 deletions
diff --git a/Master/texmf-dist/tex/generic/xstring/xstring.tex b/Master/texmf-dist/tex/generic/xstring/xstring.tex index fc87bcb824a..ff173dcadab 100644 --- a/Master/texmf-dist/tex/generic/xstring/xstring.tex +++ b/Master/texmf-dist/tex/generic/xstring/xstring.tex @@ -1,9 +1,9 @@ % __________________________________________________ % | | % | | -% | xstring v1.3a | +% | xstring v1.4 | % | | -% | September 29 2008 | +% | November 4 2008 | % | | % |__________________________________________________| % @@ -25,7 +25,7 @@ % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Christian Tellechea -% +% ------------------------------------------------------------------- % This work consists of the files % xstring.tex (this file) % xstring.sty @@ -35,13 +35,14 @@ % test_latex.tex, test_latex.pdf (test file with LaTeX) % test_etex.tex, test_etex.pdf (test file with Plain eTeX) % -\def\xstringversion {1.3a} -\def\xstringdate {2008/09/29} -\def\xstringfrenchdate {29 septembre 2008} -\def\xstringenglishdate{September $29^{\mathrm{th}}$ 2008} +\def\xstringversion {1.4} +\def\xstringdate {2008/11/04} +\def\xstringfrenchdate {4 novembre 2008} +\def\xstringenglishdate{November $4^{\mathrm{th}}$ 2008} \edef\CurrentAtCatcode{\the\catcode`\@} \catcode`\@=11 \newwrite\@xs@unused% pour les messages +\newcount\@xs@count \newcount\integerpart% pour les tests sur les nombres \newcount\decimalpart @@ -53,12 +54,12 @@ \let\reserved@d=#1% \def\reserved@a{#2}% \def\reserved@b{#3}% - \futurelet\@let@token\@ifnch} + \futurelet\@let@arg\@ifnch} \def\@ifnch{% - \ifx\@let@token\@sptoken + \ifx\@let@arg\@sptoken \let\reserved@c\@xifnch \else - \ifx\@let@token\reserved@d + \ifx\@let@arg\reserved@d \let\reserved@c\reserved@a \else \let\reserved@c\reserved@b @@ -66,7 +67,7 @@ \fi \reserved@c} \def\:{\let\@sptoken= } \: - \def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch} + \def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@arg\@ifnch} \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} \long\def\@testopt#1#2{\@ifnextchar[{#1}{#1[{#2}]}} \def\@empty{} @@ -74,6 +75,7 @@ % Gestion des messages d'erreur \def\@xs@linenumber{on input line \the\inputlineno} + \def\@xs@errorwrite#1#2{% \begingroup \newlinechar`\^^J% @@ -111,7 +113,7 @@ % Définit \@xs@ReadVerb qui lit un argument entre délimiteurs verb \def\setverbdelim#1{% définit quel est le délimiteur de verb - \expandafter\ifx\expandafter\@empty\@xs@gobblefirstchar#1\@nil\@empty + \expandafter\ifx\expandafter\@empty\detokenize\expandafter{\@xs@gobblefirstchar#1}\@empty \else \@xs@warningwrite{verb delimiter is not a single char}% \fi @@ -125,19 +127,17 @@ \@xs@MakeVerb} % A l'aide d'un pont d'\expandafter, développe d'un niveau toutes -% les lexèmes de #1 puis et assigne le résultat à \@xs@result@expandallonelevel -\def\@xs@expandallonelevel#1#2\@nil{% - \expandafter\expandafter\expandafter\def% plein d'expandafter - \expandafter\expandafter\expandafter\@xs@result@expandallonelevel% pour développer #1 d'un niveau - \expandafter\expandafter\expandafter{\expandafter\@xs@result@expandallonelevel#1}% et l'ajouter à \@xs@result@expandallonelevel +% les uneités syntaxiques de #1 puis et assigne le résultat à \@xs@reserved@A +\def\@xs@expandallonelevel#1#2\@xs@nil{% + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@A\expandafter{#1}% \ifx\@empty#2\@empty \else - \def\@xs@next{\@xs@expandallonelevel#2\@nil}% + \def\@xs@next{\@xs@expandallonelevel#2\@xs@nil}% \expandafter\@xs@next \fi}% s'il reste des sc, on boucle -\def\@xs@notestcs#1\@nil{\relax}% -\def\@xs@testcs#1#2\@nil{% +\def\@xs@notestcs#1\@xs@nil{\relax}% +\def\@xs@testcs#1#2\@xs@nil{% \ifx\@empty#2\@empty \else% si la séquence de contrôle n'est pas seule, on gueule \@xs@errorwrite{third argument or its expansion^^Jis not a single control sequence! Use \string\scancs* instead of \string\scancs (see manual).}{With \scancs, the third argument (or one of its expansion) cannot contain^^Jmore than one control sequence. If so, use the starred version \scancs*,^^Jand read manual for more information about this starred version...}% @@ -149,7 +149,7 @@ % puis on invoque \detokenize à la fin \def\scancs{% \@ifstar% - {\@xs@warningwrite{\string\scancs* has limitations:^^Jif third argument or its expansion have braces or spaces,^^Jthey will be removed when scanned}% + {\@xs@warningwrite{\string\scancs* has limitations: ^^Jif third argument or its expansion have braces or spaces,^^Jthey will be removed when scanned}% \def\@xs@testornot{\@xs@notestcs}% \@xs@scancs}% {\def\@xs@testornot{\@xs@testcs}% @@ -159,32 +159,33 @@ % #1 : profondeur à développer avant de verbatimiser % #2 : nom de la sc recevant la chaine verb % #3 : nom de la sc à développer et à transformer en verb - \def\@xs@expandalltodepth##1\@nil{% développe de #1 niveaux toutes les sc de #3 et l'assigne à \@xs@result@scancs - \def\@xs@result@expandallonelevel{}% + \def\@xs@expandalltodepth##1{% développe de #1 niveaux toutes les sc de #3 et l'assigne à \@xs@reserved@B + \let\@xs@reserved@A\@empty%\def\@xs@reserved@A{}% \ifnum##1<#1\relax% tant que la profondeur de développement n'est pas atteinte - \expandafter\@xs@testornot\@xs@result@scancs\@nil% on teste éventuellement si le développement comporte 1 seule sc - \expandafter\@xs@expandallonelevel\@xs@result@scancs\@nil% on développe tout d'un niveau - \expandafter\def\expandafter\@xs@result@scancs\expandafter{\@xs@result@expandallonelevel}% - \def\@xs@next{\expandafter\@xs@expandalltodepth\number\numexpr##1+1\relax\@nil}% + \expandafter\@xs@testornot\@xs@reserved@B\@xs@nil% on teste éventuellement si le développement comporte 1 seule sc + \expandafter\@xs@expandallonelevel\@xs@reserved@B\@xs@nil% on développe tout d'un niveau + \let\@xs@reserved@B\@xs@reserved@A%\expandafter\def\expandafter\@xs@reserved@B\expandafter{\@xs@reserved@A}% + \def\@xs@next{\expandafter\@xs@expandalltodepth\expandafter{\number\numexpr##1+1}}% \expandafter\@xs@next% et on recommence \fi}% - \def\@xs@result@scancs{#3}% - \@xs@expandalltodepth0\@nil - \expandafter\def\expandafter#2\expandafter{\detokenize\expandafter{\@xs@result@scancs}}} + \def\@xs@reserved@B{#3}% + \@xs@expandalltodepth\z@ + \expandafter\def\expandafter#2\expandafter{\detokenize\expandafter{\@xs@reserved@B}}} -% Cette macro développe #2 au maximum (ce qui doit donner du texte), +% Cette macro développe éventuellement #2 % puis le transforme en token et l'assigne à #1 -% On ouvre un groupe dans lequel un \@nil est inséré à la fin du fichier virtuel -% lu avec \scantokens. Ce \@nil sert à l'argument délimité de \@xs@AssignResult -\def\tokenize#1#2{% +\begingroup% on ouvre un groupe où... +\catcode\z@12\relax% ...le caractère 0 a 12 pour catcode +\gdef\tokenize#1#2{% \begingroup - %\expandafter\@xs@def\expandafter\@xs@expansion@tokenize\expandafter{#2}% on développe en accord avec \fullexpandarg ou \noexpandarg - \@xs@def\@xs@expansion@tokenize{#2}% on développe en accord avec \fullexpandarg ou \noexpandarg ## Correction [v1.1] ## - \def\@xs@AssignResult##1\@nil{\def#1{##1}}% on assigne en tenant compte du \@nil qui vient de la fin du fichier virtuel - \everyeof{\@nil}% met un \@nil à la fin du fichier virtuel + \@xs@def\@xs@reserved@A{#2}% on développe en accord avec \fullexpandarg ou \noexpandarg + \def\@xs@AssignResult^^00##1^^00\@xs@nil{\gdef#1{##1}}% on assigne en tenant compte du \@xs@nil qui vient de la fin du fichier virtuel + \everyeof{\@xs@nil}% met un \@xs@nil à la fin du fichier virtuel \endlinechar\m@ne - \expandafter\expandafter\expandafter\endgroup% on retarde la fermeture du groupe - \expandafter\@xs@AssignResult\scantokens\expandafter{\@xs@expansion@tokenize}}% pout faire l'assignation + \catcode\z@12\relax + \expandafter\@xs@AssignResult\scantokens\expandafter{\expandafter^^00\@xs@reserved@A^^00}% on fait l'assignation + \endgroup}% +\endgroup % Macro très simple qui assigne ou affiche le résultat, selon la présence % ou non de #2 qui est l'argument optionnel venant en dernière position des macros @@ -192,38 +193,65 @@ \expandafter\ifx\expandafter\@empty\detokenize{#2}\@empty% pas de nom ? #1% on affiche #1 \else% il y a un nom donc - \edef#2{#1}% on assigne #1 dans #3 avec edef + \def#2{#1}% on assigne #1 dans #2 avec edef \fi} % Pas d'expansion des arguments \def\normalexpandarg{% \let\@xs@def\def% on définit \@xs@call avec \def - \def\@xs@expand##1{\expandafter\unexpanded\expandafter{##1}}} + \def\@xs@expand##1{\unexpanded\expandafter{##1}}} +\let\noexpandarg\normalexpandarg% synonyme + +% 1-développement de la 1è sc des arguments et non développement des autres +\def\expandarg{% + \let\@xs@def\def% on définit \@xs@call avec \def + \def\@xs@expand##1{\unexpanded\expandafter\expandafter\expandafter{##1}}} -% Expansion des arguments +% Développement maximum des arguments \def\fullexpandarg{% \let\@xs@def\edef% on définit\@xs@call avec \edef \def\@xs@expand##1{##1}}% et on neutralise \@xs@expand -% Cette macro interne renvoie le 1er caractère de la chaine passée en argument -\def\@xs@firstchar#1{% - \expandafter\ifx\expandafter\@empty\@xs@beforespace#1 \@nil\@empty - \ifx\@empty#1\@empty\else\space\fi +\def\saveexpandmode{\let\@xs@saved@def\@xs@defarg\let\@xs@saved@expand\@xs@expand} +\def\restoreexpandmode{\let\@xs@defarg\@xs@saved@def\let\@xs@expand\@xs@saved@expand} + +% Cette macro interne prend la 1ere unité syntaxique de #1 et assigne le résultat à #2 +\def\@xs@returnfirstsyntaxunit#1#2{% + \def\@xs@returnfirstsyntaxunit@i##1##2\@xs@nil{% + \ifx\@xs@toks\bgroup + \begingroup + \escapechar48\relax% 0 est le caractère d'échappement + \expandafter\if\expandafter0\expandafter\@xs@returnfirstsyntaxunit@i\detokenize{#1}\@xs@nil + \def\@xs@reserved@A{\def#2{##1}}% si commence par 0, ##1 est un «\bgroup» + \let\@xs@toks0\relax + \else + \def\@xs@reserved@A{\def#2{{##1}}}% si ne commence pas par 0, ##1 est un groupe {...} + \fi + \expandafter\endgroup + \@xs@reserved@A + \else + \def#2{##1}% + \fi}% + \let\@xs@toks0\relax + \expandafter\ifx\expandafter\@empty\@xs@beforespace#1 \@xs@nil\@empty + \ifx\@empty#1\@empty\let#2\@empty\else\def#2{ }\fi \else - \@xs@returnfirstchar#1\@nil + \futurelet\@xs@toks\@xs@returnfirstsyntaxunit@i#1\@xs@nil \fi} -% Cette macro interne enlève le 1er caractère de la chaine passée en argument -\def\@xs@removefirstchar#1{% - \expandafter\ifx\expandafter\@empty\@xs@beforespace#1 \@nil\@empty - \ifx\@empty#1\@empty\else\@xs@afterspace#1\@nil\fi +% Cette macro interne enlève la 1ere unité syntaxique de #1 et assigne le résultat à #2 +\def\@xs@removefirstsyntaxunit#1#2{% + \expandafter\ifx\expandafter\@empty\@xs@beforespace#1 \@xs@nil\@empty + \ifx\@empty#1\@empty\def#2{}\else\expandafter\def\expandafter#2\expandafter{\@xs@behindspace#1\@xs@nil}\fi \else - \@xs@gobblefirstchar#1\@nil + \expandafter\def\expandafter#2\expandafter{\@xs@gobblefirstchar#1}% \fi} -\def\@xs@beforespace#1 #2\@nil{#1} -\def\@xs@afterspace#1 #2\@nil{#2} -\def\@xs@gobblefirstchar#1#2\@nil{#2} -\def\@xs@returnfirstchar#1#2\@nil{#1} + +% Macros à arguments délimités pour les macros ci dessus +\def\@xs@beforespace#1 #2\@xs@nil{#1} +\def\@xs@behindspace#1 #2\@xs@nil{#2} +\def\@xs@gobblefirstchar#1{} +\def\@xs@returnfirstsyntaxunit@i#1#2\@xs@nil{#1} % Cette macro interne est utilisée dans les macros étoilées pour : % 1) développer l'argument selon qu'on a choisit \fullexpandarg @@ -231,35 +259,43 @@ % 2) Ensuite, on détokenize ce développement de façon n'avoir plus que % des catcodes de 10 pour les espaces et 12 pour le reste. \def\@xs@expand@and@detokenize#1#2{% - \@xs@def#1{#2}% on développe #2 selon \fullexpandarg ou \normalexpandarg + \def#1{#2}% + \expandafter\edef\expandafter#1\expandafter{\@xs@expand#1}% on développe #2 selon le mode de développement \edef#1{\detokenize\expandafter{#1}}}% puis on détokenize et on assigne à #1 -\def\@xs@expand@and@assign#1#2{% - \@xs@def#1{#2}}% on développe #2 selon \fullexpandarg ou \normalexpandarg +\def\@xs@expand@and@assign#1#2{\@xs@def#1{#2}}% on développe #2 selon \fullexpandarg ou \normalexpandarg \def\@xs@expand@and@addtomacro#1#2{\edef#1{\unexpanded\expandafter{#1}#2}} \def\@xs@argstring{0########1########2########3########4########5########6########7########8########9} % \@xs@DefArg{3} met dans la sc \@xs@myarg le texte "####1####2####3" -\def\@xs@DefArg#1{\def\@xs@defarg0##1#1##2\@nil{\def\@xs@myarg{##1#1}}\expandafter\@xs@defarg\@xs@argstring\@nil} +\def\@xs@DefArg#1{\def\@xs@defarg0##1#1##2\@xs@nil{\def\@xs@myarg{##1#1}}\expandafter\@xs@defarg\@xs@argstring\@xs@nil} % \@xs@DefArg@{3} met dans la sc \@xs@myarg le texte "[####1]####2####3####4" \def\@xs@DefArg@#1{\expandafter\@xs@defarg@\expandafter{\number\numexpr#1+1}} -\def\@xs@defarg@#1{\def\@xs@defarg0##11##2#1##3\@nil{\def\@xs@myarg{[##11]##2#1}}\expandafter\@xs@defarg\@xs@argstring\@nil} +\def\@xs@defarg@#1{\def\@xs@defarg0##11##2#1##3\@xs@nil{\def\@xs@myarg{[##11]##2#1}}\expandafter\@xs@defarg\@xs@argstring\@xs@nil} % \@xs@OneArg{3} met dans la sc \@xs@myarg le texte "####3" \def\@xs@OneArg#1{\expandafter\@xs@onearg\expandafter{\number\numexpr#1-1}{#1}} -\def\@xs@onearg#1#2{\def\@xs@defarg##1#1##2#2##3\@nil{\def\@xs@myarg{##2#2}}\expandafter\@xs@defarg\@xs@argstring\@nil} +\def\@xs@onearg#1#2{\def\@xs@defarg##1#1##2#2##3\@xs@nil{\def\@xs@myarg{##2#2}}\expandafter\@xs@defarg\@xs@argstring\@xs@nil} -\def\@xs@BuildLines#1#2{% #1 : numéro du 1er argument et % #2 : nombre de lignes +\def\@xs@BuildLines#1#2#3{% #1 : numéro du 1er argument; #2 : nombre de lignes; #3 argument optionnel \def\@xs@newlines{}% \def\@xs@newargs{}% - \def\@xs@buildlines##1\@nil{% + \def\@xs@buildlines##1{% \expandafter\@xs@OneArg\expandafter{\number\numexpr##1+#1-1}% - \@xs@expand@and@addtomacro\@xs@newlines{\noexpand\@xs@assign{\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname}{\@xs@myarg}}% - \@xs@expand@and@addtomacro\@xs@newargs{{\noexpand\@xs@expand\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname}}% + \@xs@expand@and@addtomacro\@xs@newlines{\noexpand\@xs@assign\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname{\@xs@myarg}}% + \ifnum##1=\@ne% si c'est le premier argument + \ifx\@empty#3\@empty + \@xs@expand@and@addtomacro\@xs@newargs{{\noexpand\@xs@expand\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname}}% + \else% et s'il y a un argument optionnel alors, on met des crochets + \@xs@expand@and@addtomacro\@xs@newargs{[\noexpand\@xs@expand\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname]}% + \fi + \else + \@xs@expand@and@addtomacro\@xs@newargs{{\noexpand\@xs@expand\expandafter\noexpand\csname @xs@arg@\romannumeral\numexpr##1\endcsname}}% + \fi \ifnum##1<#2\relax - \def\@xs@next{\expandafter\@xs@buildlines\number\numexpr##1+1\relax\@nil}% + \def\@xs@next{\expandafter\@xs@buildlines\expandafter{\number\numexpr##1+1}}% \expandafter\@xs@next - \fi} - \@xs@buildlines1\@nil} + \fi}% + \@xs@buildlines\@ne} \def\@xs@newmacro#1#2#3#4#5{% % #1 : nom de la macro publique @@ -267,112 +303,180 @@ % #3 : nombre d'arguments obligatoires % #4 : utilisation de testopt (1 si oui, 0 si non) % #5 : code de la macro - \edef\@xs@macronameroot{@xs@\expandafter\@xs@gobblefirstchar\string#1\@nil}% - \edef\@macro@name{\expandafter\noexpand\csname\@xs@macronameroot @\ifx\@empty#2\@empty @\fi\endcsname}% - \edef\@xs@temp@{% + \edef\@xs@reserved@A{@xs@\expandafter\@xs@gobblefirstchar\string#1}% + \edef\@xs@reserved@C{\expandafter\noexpand\csname\@xs@reserved@A @\ifx\@empty#2\@empty @\fi\endcsname}% + \edef\@xs@reserved@B{% \def\noexpand#1{\noexpand\@ifstar - {\noexpand\let\noexpand\@xs@assign\noexpand\@xs@expand@and@detokenize\expandafter\noexpand\@macro@name}% - {\noexpand\let\noexpand\@xs@assign\noexpand\@xs@expand@and@assign\expandafter\noexpand\@macro@name}}% + {\let\noexpand\@xs@assign\noexpand\@xs@expand@and@detokenize\expandafter\noexpand\@xs@reserved@C}% + {\let\noexpand\@xs@assign\noexpand\@xs@expand@and@assign\expandafter\noexpand\@xs@reserved@C}}% \ifx\@empty#2\@empty \else - \def\expandafter\noexpand\@macro@name{\noexpand\@ifnextchar[% - {\expandafter\noexpand\csname\@xs@macronameroot @@\endcsname}% - {\expandafter\noexpand\csname\@xs@macronameroot @@\endcsname[#2]}}% + \def\expandafter\noexpand\@xs@reserved@C{\noexpand\@ifnextchar[% + {\expandafter\noexpand\csname\@xs@reserved@A @@\endcsname}% + {\expandafter\noexpand\csname\@xs@reserved@A @@\endcsname[#2]}}% \fi}% -% Que fait \@xs@temp@ ? Il définit : -% si #2 est vide : \NOM{\@ifstar{\let\@xs@assign\@xs@expand@and@detokenize\@xs@NOM@@}{\let\@xs@assign\@xs@expand@and@assign\@xs@NOM@@}} -% si #2 existe : \NOM{\@ifstar{\let\@xs@assign\@xs@expand@and@detokenize\@xs@NOM@}{\let\@xs@assign\@xs@expand@and@assign\@xs@NOM@}} -% \@xs@NOM@{\@ifnextchar[{\@xs@NOM@@}{\@xs@NOM@@[#2]}} - \@xs@temp@ + % Que fait \@xs@reserved@B ? Il définit : + % si #2 est vide : \NOM{\@ifstar{\let\@xs@assign\@xs@expand@and@detokenize\@xs@NOM@@}{\let\@xs@assign\@xs@expand@and@assign\@xs@NOM@@}} + % si #2 existe : \NOM{\@ifstar{\let\@xs@assign\@xs@expand@and@detokenize\@xs@NOM@}{\let\@xs@assign\@xs@expand@and@assign\@xs@NOM@}} + % \@xs@NOM@{\@ifnextchar[{\@xs@NOM@@}{\@xs@NOM@@[#2]}} + \@xs@reserved@B \ifx\@empty#2\@empty - \@xs@BuildLines{1}{#3}% + \@xs@BuildLines1{#3}{#2}% \@xs@DefArg{#3}% \else - \@xs@BuildLines{2}{#3}% + \expandafter\@xs@BuildLines\expandafter1\expandafter{\number\numexpr#3+1}{#2}% \@xs@DefArg@{#3}% \fi - \edef\@xs@temp@{\def\expandafter\noexpand\csname\@xs@macronameroot @@\endcsname\@xs@myarg}% - \edef\@xs@temp@@{\unexpanded\expandafter{\@xs@newlines}\edef\noexpand\@xs@call}% - \edef\@xs@temp@@@{\noexpand\noexpand\expandafter\noexpand\csname\@xs@macronameroot\endcsname\ifx\@empty#2\@empty\else[\unexpanded{\@xs@expand{##1}}]\fi\unexpanded\expandafter{\@xs@newargs}}% - \ifnum#4=\@ne\edef\@xs@temp@@@{\noexpand\noexpand\noexpand\@testopt{\unexpanded\expandafter{\@xs@temp@@@}}\unexpanded{{}}}\fi - \@xs@expand@and@addtomacro\@xs@temp@@{{\unexpanded\expandafter{\@xs@temp@@@}}\noexpand\@xs@call}% - \@xs@expand@and@addtomacro\@xs@temp@{{\unexpanded\expandafter{\@xs@temp@@}}}% -% Que fait \@xs@temp@ ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : -% \def\@xs@NOM@@[##1]##2##3##4{% -% \@xs@assign{\@xs@arg@i}{##2}% -% \@xs@assign{\@xs@arg@ii}{##3}% -% \@xs@assign{\@xs@arg@iii}{##4}% -% si #4=0: \edef\@xs@call{\noexpand\@xs@NOM[\@xs@expand{##1}]{\@xs@expand\@xs@arg@i}{\@xs@expand\@xs@arg@ii}{\@xs@expand\@xs@arg@iii}}% -% si #4=1: \edef\@xs@call{\noexpand\@testopt{\noexpand\@xs@NOM[\@xs@expand{##1}]{\@xs@expand\@xs@arg@i}{\@xs@expand\@xs@arg@ii}{\@xs@expand\@xs@arg@iii}}{}}% -% \@xs@call} - \@xs@temp@ - \edef\@xs@temp@{\def\expandafter\noexpand\csname\@xs@macronameroot\endcsname\@xs@myarg\ifnum#4=\@ne[\unexpanded{##}\number\numexpr\ifx\@empty#2\@empty#3+1\else#3+2\fi]\fi{\unexpanded{#5}}}% -% Que fait \@xs@temp@ ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : -% \def \@xs@NOM[##1]##2##3##4[##5]{#5} - \@xs@temp@} - -\def\@xs@strip@delimit#1\@delimit#2\@nil{#1} -% Cette macro coupe la chaine #1 après la #3ème occurrence de la sous chaine #2 -% \@xs@beforeoccurwith : contient ce qui se trouve avant cette occurrence y compris l'occurrence -% \@xs@beforeoccurwithout : idem mais sans l'occurrence -% \@xs@behindoccur : contient ce qui se trouve après l'occurrence + \edef\@xs@reserved@B{\def\expandafter\noexpand\csname\@xs@reserved@A @@\endcsname\@xs@myarg}% + \edef\@xs@reserved@C{\unexpanded\expandafter{\@xs@newlines}\edef\noexpand\@xs@call}% + \edef\@xs@reserved@D{\noexpand\noexpand\expandafter\noexpand\csname\@xs@reserved@A\endcsname\unexpanded\expandafter{\@xs@newargs}}% + \ifnum#4=\@ne\edef\@xs@reserved@D{\noexpand\noexpand\noexpand\@testopt{\unexpanded\expandafter{\@xs@reserved@D}}\unexpanded{{}}}\fi + \@xs@expand@and@addtomacro\@xs@reserved@C{{\unexpanded\expandafter{\@xs@reserved@D}}\noexpand\@xs@call}% + \@xs@expand@and@addtomacro\@xs@reserved@B{{\unexpanded\expandafter{\@xs@reserved@C}}}% + % Que fait \@xs@reserved@B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : + % \def\@xs@NOM@@[##1]##2##3##4{% + % \@xs@def\@xs@arg@i{##1}\@xs@assign\@xs@arg@ii{##2}\@xs@assign\@xs@arg@iii{##3}\@xs@asign\@xs@arg@iv{##4}% + % si #4=0: \edef\@xs@call{\noexpand\@xs@NOM[\@xs@expand\@xs@arg@i]{\@xs@expand\@xs@arg@ii}{\@xs@expand\@xs@arg@iii}{\@xs@expand\@xs@arg@iv}}% + % si #4=1: \edef\@xs@call{\noexpand\@testopt{\noexpand\@xs@NOM[\@xs@expand\@xs@arg@i]{\@xs@expand\@xs@arg@i}{\@xs@expand\@xs@arg@ii}{\@xs@expand\@xs@arg@iii}{\@xs@expand\@xs@arg@iv}}{}}% + % \@xs@call} + \@xs@reserved@B + \edef\@xs@reserved@B{\def\expandafter\noexpand\csname\@xs@reserved@A\endcsname\@xs@myarg\ifnum#4=\@ne[\unexpanded{##}\number\numexpr\ifx\@empty#2\@empty#3+1\else#3+2\fi]\fi{\unexpanded{#5}}}% + % Que fait \@xs@reserved@B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : + % \def \@xs@NOM[##1]##2##3##4[##5]{#5} + \@xs@reserved@B} + +\@xs@newmacro\StrRemoveBraces{}{1}{1}{% + \let\@xs@reserved@C\@empty + \def\@xs@reserved@A{#1}% + \@xs@StrRemoveBraces@i + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#2}} +\def\@xs@StrRemoveBraces@i{% + \expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@A}\@xs@reserved@B + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@A}\@xs@reserved@A + \ifx\bgroup\@xs@toks + \ifx\@xs@exploregroups\@empty% on explore les groupes ? + \begingroup + \let\@xs@reserved@C\@empty + \expandafter\def\expandafter\@xs@reserved@A\@xs@reserved@B + \@xs@StrRemoveBraces@i + \expandafter + \endgroup + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\@xs@reserved@C}% + \else + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\@xs@reserved@B + \fi + \else + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@C\expandafter{\@xs@reserved@B}% + \fi + \expandafter\let\expandafter\@xs@next\ifx\@empty\@xs@reserved@A\relax\else\@xs@StrRemoveBraces@i\fi + \@xs@next}% + +\def\@xs@strip@delimit#1\@delimit#2\@xs@nil{#1} +% \@xs@cutafteroccur coupe l'argument #1 après la #3ème occurrence de #2 +% #4 : contient ce qui se trouve avant cette occurrence y compris l'occurrence +% #5 : idem mais sans l'occurrence +% #6 : contient ce qui se trouve après l'occurrence % si l'occurrence n'existe pas ou qu'un des arguments est vide, toutes les chaines renvoyées sont vides -\def\@xs@cutafteroccur#1#2#3{% #1 est la chaine, #2 est le pattern, #3 est la nième occurence souhaitée - \def\@xs@cutafteroccur@i##1\@nil##2#2##3\@nil{% ##1 est le compteur - \def\@xs@next{\relax}% - \ifx\@empty##3\@empty% rien après cette occurrence ? - \def\@xs@beforeoccurwith{}\def\@xs@beforeoccurwithout{}\def\@xs@behindoccur{}% occurrence non trouvée -> on met tout à \empty +% utilise \@xs@reserved@A -> \@xs@reserved@B +\def\@xs@cutafteroccur#1#2#3#4#5#6{% + \def\@xs@cutafteroccur@i{% + \ifx#6\@empty% on a fini de parcourir #6 ? + \let\@xs@next\relax% on sort de la macro \else - \ifnum##1<#3\relax% tant que le nombre d'occurrence n'est pas atteint - \expandafter\def\expandafter\@xs@beforeoccurwith\expandafter{\@xs@beforeoccurwith##2#2}% on ajoute la chaine restante - \def\@xs@next{\expandafter\@xs@cutafteroccur@i\number\numexpr##1+1\relax\@nil##3\@nil}% on recommence après être sorti des \if...\fi + \expandafter\@xs@IfBeginWith@i\expandafter{#6}{#2}% + {\global\advance\@xs@count\@ne + \ifnum\@xs@count<#3\relax\@xs@addtomacro#5{#2}\@xs@gaddtomacro\@xs@beforeoccur{#2}\fi + \let#6\@xs@reserved@A}% on enlève le motif à #6 + {\expandafter\@xs@returnfirstsyntaxunit\expandafter{#6}\@xs@reserved@A% #6 ne commence pas par le motif : on prend la 1ere unité syntaxique + \expandafter\@xs@removefirstsyntaxunit\expandafter{#6}#6% puis on l'enlève + \@xs@exploregroups + \ifx\bgroup\@xs@toks% si cette unité syntaxique est un groupe {...} + \begingroup% alors on ouvre un groupe + \expandafter\def\expandafter#6\@xs@reserved@A% + \let#4\@empty\let#5\@empty% on initialise dans ce nouveau groupe + \@xs@cutafteroccur@i% puis une récursivité + \ifx#4\@empty% si l'occurrence n'est pas trouvée dans ce groupe + \def\@xs@next{% on en sort après avoir rajouté à #5 du groupe de niveau au dessus le #5 de ce groupe + \expandafter\endgroup + \expandafter\@xs@addtomacro\expandafter#5\expandafter{\expandafter{#5}}}% + \else + \let\@xs@next\endgroup% sinon, on sort du groupe + \fi + \@xs@next + \else + \expandafter\@xs@gaddtomacro\expandafter\@xs@beforeoccur\expandafter{\@xs@reserved@A}% + \expandafter\@xs@addtomacro\expandafter#5\expandafter{\@xs@reserved@A}% + \fi}% + \ifnum\@xs@count=#3\relax% l'occurrence est atteinte... + \global\let#5#5\global\let#6#6% on passe à la globalité si jamais on est dans un groupe + \expandafter\gdef\expandafter#4\expandafter{#5#2}% on rajoute le pattern à #5 + \let\@xs@next\relax% et on sort de la macro \else - \expandafter\def\expandafter\@xs@beforeoccurwithout\expandafter{\@xs@beforeoccurwith##2}% on ajoute la chaine restante une dernière fois sans le pattern ici - \expandafter\def\expandafter\@xs@beforeoccurwith\expandafter{\@xs@beforeoccurwith##2#2}% et avec le pattern ici - \expandafter\def\expandafter\@xs@behindoccur\expandafter{\@xs@strip@delimit##3\@nil}% + \let\@xs@next\@xs@cutafteroccur@i% \fi \fi \@xs@next}% - \def\@xs@beforeoccurwith{}\def\@xs@beforeoccurwithout{}\def\@xs@behindoccur{}% - \ifnum#3>\z@ - \ifx\@empty#2\@empty\@xs@ArgEmpty\else\@xs@cutafteroccur@i\@ne\@nil#1\@delimit#2\@nil\fi - \else\@xs@BadNumArg\fi} + \let#4\@empty\let#5\@empty\def#6{#1}\let\@xs@beforeoccur\@empty\@xs@count\z@ + \@xs@cutafteroccur@i + \ifx\@empty#4\let#5#4\let#6#4\fi}% occurrence pas trouvée +% utilise \@xs@reserved@A -> \@xs@reserved@D \@xs@newmacro\IfSubStr{1}{2}{0}{% - \@xs@cutafteroccur{#2}{#3}{#1}% - \ifx\@xs@behindoccur\@xs@beforeoccurwith + \@xs@cutafteroccur{#2}{#3}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \ifx\@xs@reserved@C\@empty \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi} \@xs@newmacro\IfBeginWith{}{2}{0}{% - \@xs@cutafteroccur{#1}{#2}{\@ne}% - \def\@xs@next{#2}% - \ifx\@xs@next\@xs@beforeoccurwith - \expandafter\@firstoftwo + \ifx\@empty#2\@empty + \let\@xs@next\@secondoftwo \else - \expandafter\@secondoftwo - \fi} + \def\@xs@next{\@xs@IfBeginWith@i{#1}{#2}}% + \fi + \@xs@next} +\def\@xs@IfBeginWith@i#1#2{% + \ifx\@empty#2\@empty% #2 est vide, tous les tests sont passés avec succès : on renvoie #3 + \let\@xs@next\@firstoftwo + \else + \ifx\@empty#1\@empty + \let\@xs@next\@secondoftwo% #1 est vide, c'est que #2 est + long que #1 : on renvoie #4 + \else + \@xs@returnfirstsyntaxunit{#1}\@xs@reserved@A + \@xs@returnfirstsyntaxunit{#2}\@xs@reserved@B + \ifx\@xs@reserved@A\@xs@reserved@B% il y a égalité... + \@xs@removefirstsyntaxunit{#1}\@xs@reserved@A% on enlève les 1ere unités syntaxiques + \@xs@removefirstsyntaxunit{#2}\@xs@reserved@B + \def\@xs@next{% et on recommence avec ces arguments racourcis d'1 token + \expandafter\expandafter\expandafter\@xs@IfBeginWith@i + \expandafter\expandafter\expandafter{\expandafter\@xs@reserved@A\expandafter}\expandafter{\@xs@reserved@B}}% + \else + \let\@xs@next\@secondoftwo + \fi + \fi + \fi + \@xs@next} \@xs@newmacro\IfEndWith{}{2}{0}{% - \@xs@StrCount{#1}{#2}[\@xs@result@If]% - \ifnum\@xs@result@If=\z@ - \let\@xs@result@If\@secondoftwo% + \@xs@StrCount{#1}{#2}[\@xs@reserved@A]% + \ifnum\@xs@reserved@A=\z@ + \let\@xs@reserved@A\@secondoftwo% \else - \ifx\@empty\@xs@after@StrCount - \let\@xs@result@If\@firstoftwo% + \ifx\@empty\@xs@StrCount@afterlastocccur + \let\@xs@reserved@A\@firstoftwo% \else - \let\@xs@result@If\@secondoftwo% + \let\@xs@reserved@A\@secondoftwo% \fi \fi - \@xs@result@If} + \@xs@reserved@A} \@xs@newmacro\IfSubStrBefore{1,1}{3}{0}{\@xs@IfSubStrBefore@i[#1]{#2}{#3}{#4}} \def\@xs@IfSubStrBefore@i[#1,#2]#3#4#5{% - \@xs@cutafteroccur{#3}{#5}{#2}% - \expandafter\@xs@cutafteroccur\expandafter{\@xs@beforeoccurwithout}{#4}{#1}% - \ifx\@xs@behindoccur\@xs@beforeoccurwith + \ifx\@xs@exploregroups\@empty\let\@xs@reserved@C\@empty\def\@xs@reserved@A{#3}\@xs@StrRemoveBraces@i\else\def\@xs@reserved@C{#3}\fi + \expandafter\@xs@cutafteroccur\expandafter{\@xs@reserved@C}{#5}{#2}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \expandafter\@xs@cutafteroccur\expandafter{\@xs@reserved@D}{#4}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \ifx\@xs@reserved@C\@empty \expandafter\@secondoftwo \else \expandafter\@firstoftwo @@ -381,291 +485,388 @@ \@xs@newmacro\IfSubStrBehind{1,1}{3}{0}{\@xs@IfSubStrBehind@i[#1]{#2}{#3}{#4}} \def\@xs@IfSubStrBehind@i[#1,#2]#3#4#5{\@xs@IfSubStrBefore@i[#2,#1]{#3}{#5}{#4}} -% tests sur les nombres \IfInteger et \IfDecimal -\def\@xs@putXifempty#1{#1\ifx\@empty#1\@empty X\fi} -\def\@xs@formatnumber#1{% +\def\@xs@formatnumber#1#2{% \ifx\@empty#1\@empty - 0X% si vide, renvoie 0X + \def#2{0X}% si vide, renvoie 0X \else - \expandafter\ifx\@xs@returnfirstchar#1\@nil+% si commence par un +, renvoie +0<nombre> - +0\expandafter\@xs@putXifempty\expandafter{\@xs@gobblefirstchar#1\@nil}% + \@xs@returnfirstsyntaxunit{#1}\@xs@reserved@A + \def\@xs@reserved@B{+}% + \ifx\@xs@reserved@A\@xs@reserved@B + \@xs@removefirstsyntaxunit{#1}\@xs@reserved@C + \ifx\@empty\@xs@reserved@C + \def#2{+0X}% + \else + \expandafter\def\expandafter#2\expandafter{\expandafter+\expandafter0\@xs@reserved@C}% + \fi \else - \expandafter\ifx\@xs@returnfirstchar#1\@nil-% si commence par un -, renvoie -0<nombre> - -0\expandafter\@xs@putXifempty\expandafter{\@xs@gobblefirstchar#1\@nil}% + \def\@xs@reserved@B{-}% + \ifx\@xs@reserved@A\@xs@reserved@B + \@xs@removefirstsyntaxunit{#1}\@xs@reserved@A + \ifx\@empty\@xs@reserved@A + \def#2{-0X}% + \else + \expandafter\def\expandafter#2\expandafter{\expandafter-\expandafter0\@xs@reserved@A}% + \fi \else - 0#1% si ne commence ni par + ni par -, renvoie 0<nombre> + \def#2{0#1}% \fi \fi \fi} \@xs@newmacro\IfInteger{}{1}{0}{% - \@xs@def\@xs@formattednumber{\@xs@formatnumber{#1}}% + \expandafter\@xs@formatnumber\expandafter{\detokenize{#1}}\@xs@reserved@A \decimalpart\z@ - \afterassignment\@xs@defafterinteger\integerpart=\@xs@formattednumber\relax\@nil - \if\relax\@xs@afterinteger + \afterassignment\@xs@defafterinteger\integerpart\@xs@reserved@A\relax\@xs@nil + \ifx\@empty\@xs@afterinteger \expandafter\@firstoftwo \else + \expandafter\tokenize\expandafter\@xs@afterinteger\expandafter{\@xs@afterinteger}% \expandafter\@secondoftwo \fi} \@xs@newmacro\IfDecimal{}{1}{0}{% - \@xs@def\@xs@formattednumber{\@xs@formatnumber{#1}}% + \expandafter\@xs@formatnumber\expandafter{\detokenize{#1}}\@xs@reserved@A \decimalpart\z@ - \afterassignment\@xs@defafterinteger\integerpart=\@xs@formattednumber\relax\@nil - \expandafter\@xs@testdot\@xs@afterinteger\@nil - \if\relax\@xs@afterdecimal + \afterassignment\@xs@defafterinteger\integerpart\@xs@reserved@A\relax\@xs@nil + \expandafter\@xs@testdot\@xs@afterinteger\@xs@nil + \ifx\@empty\@xs@afterdecimal \expandafter\@firstoftwo \else + \expandafter\tokenize\expandafter\@xs@afterdecimal\expandafter{\@xs@afterdecimal}% \expandafter\@secondoftwo \fi} -\def\@xs@defafterinteger#1\@nil{\def\@xs@afterinteger{#1}}% +\def\@xs@defafterinteger#1\relax\@xs@nil{\def\@xs@afterinteger{#1}} \def\@xs@testdot{\@ifnextchar.{\@xs@readdecimalpart}{\@xs@testcomma}} \def\@xs@testcomma{\@ifnextchar,{\@xs@readdecimalpart}{\@xs@endnumber}} -\def\@xs@readdecimalpart#1#2\@nil{% - \if\relax#2\def\@xs@formattednumber{0X}\else\def\@xs@formattednumber{0#2}\fi - \afterassignment\@xs@defafterinteger\decimalpart=\@xs@formattednumber\@nil - \expandafter\@xs@endnumber\@xs@afterinteger\@nil} -\def\@xs@endnumber#1\@nil{\def\@xs@afterdecimal{#1}} +\def\@xs@readdecimalpart#1#2\@xs@nil{% + \ifx\@empty#2\@empty\def\@xs@reserved@A{0X}\else\def\@xs@reserved@A{0#2}\fi + \afterassignment\@xs@defafterinteger\decimalpart\@xs@reserved@A\relax\@xs@nil + \expandafter\@xs@endnumber\@xs@afterinteger\@xs@nil} +\def\@xs@endnumber#1\@xs@nil{\def\@xs@afterdecimal{#1}} % test d'égalité sur des chaines (et des chaines contenant des nombres) -\def\@xs@IfStrEqFalse@#1#2{\let\@xs@result@If\@secondoftwo} -\def\@xs@IfStrEqFalse@@#1#2{% renvoie vrai si les 2 arg sont décimaux et s'ils sont égaux, faux sinon +\def\@xs@IfStrEqFalse@i#1#2{\let\@xs@reserved@A\@secondoftwo} +\def\@xs@IfStrEqFalse@ii#1#2{% renvoie vrai si les 2 arg sont décimaux et s'ils sont égaux, faux sinon \@xs@IfDecimal{#1}% {\@xs@IfDecimal{#2}% - {\ifdim#1pt=#2pt\let\@xs@result@If\@firstoftwo\else\let\@xs@result@If\@secondoftwo\fi}% les 2 sont décimaux : on fait le test - {\let\@xs@result@If\@secondoftwo}}% un seul est décimal - {\let\@xs@result@If\@secondoftwo}}% #1 n'est pas décimal - -\def\@xs@TestEqu@l#1#2{% teste si les 2 arguments sont égaux - \def\@xs@tempa{#1}\def\@xs@tempb{#2}% - \ifx\@xs@tempa\@xs@tempb - \let\@xs@result@If\@firstoftwo% égalité parfaite des 2 chaines + {\ifdim#1pt=#2pt\let\@xs@reserved@A\@firstoftwo\else\let\@xs@reserved@A\@secondoftwo\fi}% les 2 sont décimaux : on fait le test + {\let\@xs@reserved@A\@secondoftwo}}% un seul est décimal + {\let\@xs@reserved@A\@secondoftwo}}% #1 n'est pas décimal + +\def\@xs@TestEqual#1#2{% teste si les 2 arguments sont égaux + \def\@xs@reserved@A{#1}\def\@xs@reserved@B{#2}% + \ifx\@xs@reserved@A\@xs@reserved@B + \let\@xs@reserved@A\@firstoftwo% égalité parfaite des 2 chaines \else - \@xs@IfStrEqFalse{#1}{#2}% + \@xs@reserved@D{#1}{#2}% \fi - \@xs@result@If} + \@xs@reserved@A} \@xs@newmacro\IfStrEq{}{2}{0}{% teste si les deux chaines sont égales - \let\@xs@IfStrEqFalse\@xs@IfStrEqFalse@ - \@xs@TestEqu@l{#1}{#2}} + \let\@xs@reserved@D\@xs@IfStrEqFalse@i + \@xs@TestEqual{#1}{#2}} \@xs@newmacro\IfEq{}{2}{0}{% teste si les 2 arguments (chaine ou nombre) sont égaux - \let\@xs@IfStrEqFalse\@xs@IfStrEqFalse@@ - \@xs@TestEqu@l{#1}{#2}} + \let\@xs@reserved@D\@xs@IfStrEqFalse@ii + \@xs@TestEqual{#1}{#2}} -\def\IfStrEqCase{\@ifstar{\def\@xs@IfEqName{\IfStrEq*}\@xs@IfStrCase@@}{\def\@xs@IfEqName{\IfStrEq}\@xs@IfStrCase@@}} -\def\@xs@IfStrCase@@#1#2{\@testopt{\@xs@IfStringCase{#1}{#2}}{}} +\def\IfStrEqCase{\@ifstar{\def\@xs@reserved@E{\IfStrEq*}\@xs@IfStrCase}{\def\@xs@reserved@E{\IfStrEq}\@xs@IfStrCase}} +\def\@xs@IfStrCase#1#2{\@testopt{\@xs@IfStringCase{#1}{#2}}{}} -\def\IfEqCase{\@ifstar{\def\@xs@IfEqName{\IfEq*}\@xs@IfEqCase@@}{\def\@xs@IfEqName{\IfEq}\@xs@IfEqCase@@}} -\def\@xs@IfEqCase@@#1#2{\@testopt{\@xs@IfStringCase{#1}{#2}}{}} +\def\IfEqCase{\@ifstar{\def\@xs@reserved@E{\IfEq*}\@xs@IfEqCase}{\def\@xs@reserved@E{\IfEq}\@xs@IfEqCase}} +\def\@xs@IfEqCase#1#2{\@testopt{\@xs@IfStringCase{#1}{#2}}{}} \def\@xs@IfStringCase#1#2[#3]{% - \def\@xs@testcase##1##2##3\@nil{% lit les 2 premiers lexèmes dans ##1 et ##2. Les autres dans ##3 - \@xs@IfEqName{#1}{##1}% + \def\@xs@testcase##1##2##3\@xs@nil{% lit les 2 premieres unités syntaxiques dans ##1 et ##2. Les autres dans ##3 + \@xs@reserved@E{#1}{##1}% {##2}% le test est positif, on exécute le code correspondant {\ifx\@empty##3\@empty% le test est négatif \def\@xs@next{#3}% s'il n'y a plus de cas, on exécute le code <autres cas> \else - \def\@xs@next{\@xs@testcase##3\@nil}% sinon, on recommence avec ce qui reste + \def\@xs@next{\@xs@testcase##3\@xs@nil}% sinon, on recommence avec ce qui reste \fi \@xs@next}}% - \@xs@testcase#2\@nil} + \@xs@testcase#2\@xs@nil} + % Renvoie ce qui est à gauche de l'occurence n°#1 de la sous chaine #3 dans la chaine \@xs@newmacro\StrBefore{1}{2}{1}{% - \@xs@cutafteroccur{#2}{#3}{#1}% - \@xs@ReturnResult{\@xs@beforeoccurwithout}{#4}} + \@xs@cutafteroccur{#2}{#3}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@D}{#4}} % Renvoie ce qui est à droite de l'occurence n°#1 de la sous chaine #3 dans la chaine #2 \@xs@newmacro\StrBehind{1}{2}{1}{% - \@xs@cutafteroccur{#2}{#3}{#1}% - \@xs@ReturnResult{\@xs@behindoccur}{#4}} + \@xs@cutafteroccur{#2}{#3}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@E}{#4}} % Renvoie ce qui est strictement compris entre les occurrences n°#1 et n°#2 % des chaines #4 et #5 dans la chaine #3 \@xs@newmacro\StrBetween{1,1}{3}{1}{\@xs@StrBetween@i[#1]{#2}{#3}{#4}[#5]} \def\@xs@StrBetween@i[#1,#2]#3#4#5[#6]{% - \@xs@cutafteroccur{#3}{#5}{#2}% - \expandafter\@xs@cutafteroccur\expandafter{\@xs@beforeoccurwithout}{#4}{#1}% - \@xs@ReturnResult{\@xs@behindoccur}{#6}} - + \begingroup + \noexploregroups + \@xs@cutafteroccur{#3}{#5}{#2}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \expandafter\@xs@cutafteroccur\expandafter{\@xs@reserved@D}{#4}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \expandafter + \endgroup + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@E}{#6}} + +\def\@xs@addtomacro#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}} +\def\@xs@gaddtomacro#1#2{\expandafter\gdef\expandafter#1\expandafter{#1#2}} +\def\exploregroups{\def\@xs@exploregroups{}} +\def\noexploregroups{\def\@xs@exploregroups{\let\@xs@toks0\relax}} +\def\saveexploremode{\let\@xs@saveexploremode\@xs@exploregroups} +\def\restoreexploremode{\let\@xs@exploregroups\@xs@saveexploremode} % Remplace les #1 premières occurences de la chaine #3 % par la chaine #4 dans la chaine #2 +% utilise \@xs@reserved@A -> \@xs@reserved@E \@xs@newmacro\StrSubstitute{0}{3}{1}{% - \ifx\@empty#3\@empty% si #3 est vide, on ne fait rien + \ifx\@empty#3\@empty% si #4 est vide, on ne fait rien \@xs@ArgEmpty% warning - \edef\@xs@result@StrSubstitute{#2}% + \@xs@ReturnResult{#2}{#5}% \else - \edef\@xs@result@StrSubstitute{}% on initialise à vide, histoire d'enlever le statut undefined - \ifnum#1>\z@ - \def\@xs@StrSubstitute@i##1\@nil##2#3##3\@nil{% ici, on compte les occurrences : ##1 est le compteur - \edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##2#4}% on recopie jusqu'à la 1ere occurrence, et on remplace #3 par #4 - \@xs@IfSubStr[1]{##3}{#3}% tant que la chaine restante contient #3 - {\ifnum##1<#1\relax% tant qu'on n'a pas atteint la bonne occurrence, - \def\@xs@next{\expandafter\@xs@StrSubstitute@i\number\numexpr##1+1\relax\@nil##3\@nil}% - \else - \def\@xs@next{\edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##3}}% - \fi - \@xs@next} - {\edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##3}}}% si on ne peut plus substituter, on rajoute ce qui reste - \@xs@IfSubStr[1]{#2}{#3}% - {\@xs@StrSubstitute@i1\@nil#2\@nil}% si #2 contient #3, on exécute la macro - {\edef\@xs@result@StrSubstitute{#2}}% sinon, on renvoie la chaine #2 + \@xs@StrSubstitute@i[#1]{#2}{#3}{#4}{#5}% + \fi}% +\def\@xs@StrSubstitute@i[#1]#2#3#4#5{% + \def\@xs@StrSubstitute@ii{% + \ifx\@xs@reserved@C\@empty% on a fini de parcourir \@xs@reserved@C ? + \let\@xs@next\relax% on sort de la macro \else - \def\@xs@StrSubstitute@i##1#3##2\@nil{% ici, on ne compte pas les occurrences - \edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##1#4}% on recopie jusqu'à la 1ere occurrence, et on remplace #3 par #4 - \@xs@IfSubStr[1]{##2}{#3}% ...tant que la chaine restante contient #3 - {\@xs@StrSubstitute@i##2\@nil}% on recommence - {\edef\@xs@result@StrSubstitute{\@xs@result@StrSubstitute##2}}}% si on ne peut plus substituter, on rajoute ce qui reste - \@xs@IfSubStr[1]{#2}{#3}% - {\@xs@StrSubstitute@i#2\@nil}% si #2 contient #3, on exécute la macro - {\edef\@xs@result@StrSubstitute{#2}}% sinon, on renvoie la chaine #2 + \ifnum\@xs@count=#1\relax + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@D\expandafter{\@xs@reserved@C}% + \let\@xs@next\relax + \else + \expandafter\@xs@IfBeginWith@i\expandafter{\@xs@reserved@C}{#3}% + {\@xs@addtomacro\@xs@reserved@D{#4}% \@xs@reserved@C commence par le motif --> on substitue + \global\advance\@xs@count\@ne + \let\@xs@reserved@C\@xs@reserved@A}% on enlève le motif à \@xs@reserved@C + {\expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@A% \@xs@reserved@C ne commence pas par le motif : on prend la 1ere unité syntaxique + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@C% puis on l'enlève + \@xs@exploregroups + \ifx\bgroup\@xs@toks% si cette unité syntaxique est un groupe {...} + \begingroup% alors on ouvre un groupe + \expandafter\def\expandafter\@xs@reserved@C\@xs@reserved@A% \@xs@reserved@C devient l'intérieur de {...} + \let\@xs@reserved@D\@empty% #4 est initialisé à vide dans ce nouveau groupe + \@xs@StrSubstitute@ii% on lance la macro avec ces nouvelles définitions + \expandafter% on retarde la fermeture du groupe + \endgroup% pour ajouter \@xs@reserved@D de ce groupe au \@xs@reserved@D du groupe supérieur + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@D\expandafter{\expandafter{\@xs@reserved@D}}% + \else + \expandafter\@xs@addtomacro\expandafter\@xs@reserved@D\expandafter{\@xs@reserved@A}% + \fi}% + \let\@xs@next\@xs@StrSubstitute@ii% + \fi \fi - \fi - \@xs@ReturnResult{\@xs@result@StrSubstitute}{#5}} + \@xs@next}% + \def\@xs@reserved@D{}\def\@xs@reserved@C{#2}% + \@xs@count\ifnum#1>\z@\z@\else\@ne\fi + \@xs@StrSubstitute@ii + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@D}{#5}} % Supprime les #1 premières occurrences de #3 dans #2 \@xs@newmacro\StrDel{0}{2}{1}{\@xs@StrSubstitute[#1]{#2}{#3}{}[#4]} -% Compte combien de caractères contient la chaine #1 ? +% Compte combien d'unités syntaxiques contient la chaine #1 ? \@xs@newmacro\StrLen{}{1}{1}{% - \def\@xs@StrLen@i##1{% ##1 est le compteur - \ifx\@empty\@xs@remain@StrLen - \@xs@ReturnResult{\number\numexpr##1}{#2}% + \def\@xs@reserved@C{#1}% + \@xs@count\z@ + \@xs@StrLen@i + \expandafter\@xs@ReturnResult\expandafter{\number\@xs@count}{#2}} +\def\@xs@StrLen@i{% + \ifx\@xs@reserved@C\@empty + \else + \expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@A + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@C + \@xs@exploregroups + \ifx\bgroup\@xs@toks + \begingroup + \expandafter\def\expandafter\@xs@reserved@C\@xs@reserved@A + \@xs@StrLen@i + \endgroup \else - \edef\@xs@remain@StrLen{\expandafter\@xs@removefirstchar\expandafter{\@xs@remain@StrLen}}% - \def\@xs@next{\expandafter\@xs@StrLen@i\expandafter{\number\numexpr##1+1}}% - \expandafter\@xs@next - \fi}% - \def\@xs@remain@StrLen{#1}% - \@xs@StrLen@i\z@} + \global\advance\@xs@count\@ne + \fi% + \expandafter\@xs@StrLen@i + \fi} +% % Cette macro coupe la chaine #2 après l'unité syntaxique n°#1 +% % Le début est assigné dans #3 et la fin dans #4 \@xs@newmacro\StrSplit{}{2}{0}{\@xs@StrSplit@i{#2}{#1}} \def\@xs@StrSplit@i#1#2#3#4{% -% Cette macro coupe la chaine #2 après le caractère n°#1 -% Le début est assigné dans #3 et la fin dans #4 - \def\@xs@StrSplit@ii##1\@nil{% - \def\@xs@next{\relax}% - \ifnum##1<#1\relax% tant que c'est pas fini - \edef#3{#3\expandafter\@xs@firstchar\expandafter{#4}}% prend le 1er caractère l'ajoute au résultat final - \edef#4{\expandafter\@xs@removefirstchar\expandafter{#4}}% puis l'enlève de la chaine - \ifx\@empty#4\@empty + \def\@xs@StrSplit@ii{% + \ifx#4\@empty + \let\@xs@next\relax + \else + \expandafter\@xs@returnfirstsyntaxunit\expandafter{#4}\@xs@reserved@A + \expandafter\@xs@removefirstsyntaxunit\expandafter{#4}#4% + \@xs@exploregroups + \ifx\bgroup\@xs@toks + \begingroup + \expandafter\def\expandafter#4\@xs@reserved@A + \let#3\@empty + \@xs@StrSplit@ii + \ifx#4\@empty + \def\@xs@next{% + \expandafter\endgroup + \expandafter\@xs@addtomacro\expandafter#3\expandafter{\expandafter{#3}}}% + \else + \let\@xs@next\endgroup + \fi + \@xs@next + \else + \global\advance\@xs@count\@ne + \expandafter\@xs@addtomacro\expandafter#3\expandafter{\@xs@reserved@A}% + \fi + \ifnum\@xs@count=#1\relax + \global\let#3#3\global\let#4#4% + \let\@xs@next\relax \else - \def\@xs@next{\expandafter\@xs@StrSplit@ii\number\numexpr##1+1\relax\@nil}% on recommence sauf s'il ne reste plus rien + \let\@xs@next\@xs@StrSplit@ii \fi \fi \@xs@next}% - \def#3{}\def#4{#2}% - \@xs@StrSplit@ii0\@nil} + \let#3\@empty\def#4{#2}\@xs@count\z@ + \@xs@StrSplit@ii} % De la chaine #1, renvoie ce qui se trouve entre les positions % #2 et #3, caractères aux positions compris ! \@xs@newmacro\StrMid{}{3}{1}{% - \@xs@StrSplit{#1}{#3}\@xs@BeforeMid\@xs@BehindMid - \expandafter\expandafter\expandafter\@xs@StrSplit\expandafter\expandafter\expandafter{\expandafter\@xs@BeforeMid\expandafter}\expandafter{\number\numexpr#2-1}\@xs@BeforeMid\@xs@BehindMid - \@xs@ReturnResult{\@xs@BehindMid}{#4}} + \begingroup + \noexploregroups + \@xs@StrSplit{#1}{#3}\@xs@reserved@B\@xs@reserved@C + \expandafter\expandafter\expandafter\@xs@StrSplit\expandafter\expandafter\expandafter{\expandafter\@xs@reserved@B\expandafter}\expandafter{\number\numexpr#2-1}\@xs@reserved@B\@xs@reserved@C + \expandafter\endgroup + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#4}} % supprime #2 caractères à gauche dans la chaine #1 \@xs@newmacro\StrGobbleLeft{}{2}{1}{% - \@xs@StrSplit@i{#2}{#1}\@xs@call\@xs@result@StrGobbleLeft - \@xs@ReturnResult{\@xs@result@StrGobbleLeft}{#3}} + \@xs@StrSplit@i{#2}{#1}\@xs@reserved@B\@xs@reserved@C + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#3}} % extrait de #1 la chaine à gauche de longueur #2 \@xs@newmacro\StrLeft{}{2}{1}{% - \@xs@StrSplit@i{#2}{#1}\@xs@result@StrLeft\@xs@call - \@xs@ReturnResult{\@xs@result@StrLeft}{#3}} + \@xs@StrSplit@i{#2}{#1}\@xs@reserved@B\@xs@reserved@C + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@B}{#3}} % supprime #2 caractères à droite dans la chaine #1 \@xs@newmacro\StrGobbleRight{}{2}{1}{% - \@xs@StrLen{#1}[\@xs@Len@StrGobbleRight]% - \expandafter\@xs@StrSplit@i\expandafter{\numexpr\@xs@Len@StrGobbleRight-#2}{#1}\@xs@result@StrGobbleRight\@xs@call - \@xs@ReturnResult{\@xs@result@StrGobbleRight}{#3}} + \@xs@StrLen{#1}[\@xs@reserved@E]% + \expandafter\@xs@StrSplit@i\expandafter{\number\numexpr\@xs@reserved@E-#2}{#1}\@xs@reserved@C\@xs@reserved@D + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#3}} % renvoie #2 caractères à la droite de la chaine #1 \@xs@newmacro\StrRight{}{2}{1}{% - \@xs@StrLen{#1}[\@xs@Len@StrRight]% - \expandafter\@xs@StrSplit@i\expandafter{\numexpr\@xs@Len@StrRight-#2}{#1}\@xs@call\@xs@result@StrRight - \@xs@ReturnResult{\@xs@result@StrRight}{#3}} + \@xs@StrLen{#1}[\@xs@reserved@E]% + \expandafter\@xs@StrSplit@i\expandafter{\number\numexpr\@xs@reserved@E-#2}{#1}\@xs@reserved@C\@xs@reserved@D + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@D}{#3}} \@xs@newmacro\StrChar{}{2}{1}{% \ifnum#2<\@ne \@xs@ReturnResult{}{#3}% \else - \expandafter\@xs@StrSplit@i\expandafter{\numexpr#2-1}{#1}\@xs@call\@xs@result@StrChar - \@xs@ReturnResult{\expandafter\@xs@firstchar\expandafter{\@xs@result@StrChar}}{#3}% + \expandafter\@xs@StrSplit@i\expandafter{\number\numexpr#2-1}{#1}\@xs@reserved@C\@xs@reserved@D + \expandafter\@xs@StrSplit@i\expandafter{\expandafter1\expandafter}\expandafter{\@xs@reserved@D}\@xs@reserved@C\@xs@reserved@D + \expandafter\@xs@ReturnResult\expandafter{\@xs@reserved@C}{#3}% \fi} % Combien de fois compte t-on #2 dans #1 ? +% utilise \@xs@reserved@A -> \@xs@reserved@C en mode arg \@xs@newmacro\StrCount{}{2}{1}{% \ifx\@empty#2\@empty \@xs@ArgEmpty - \edef\@xs@after@StrCount{}% + \def\@xs@StrCount@afterlastocccur{}% \@xs@ReturnResult{0}{#3}% \else - \def\@xs@StrCount@i##1\@nil##2#2##3\@nil{% ##1 est le compteur - \ifx\@empty##3\@empty - \edef\@xs@after@StrCount{\ifnum\numexpr##1=\z@\else\@xs@strip@delimit##2\@nil\fi}% - \@xs@ReturnResult{##1}{#3}% - \else - \def\@xs@next{\expandafter\@xs@StrCount@i\number\numexpr##1+1\relax\@nil##3\@nil}% - \expandafter\@xs@next - \fi}% - \@xs@StrCount@i0\@nil#1\@delimit#2\@nil + \@xs@StrCount@i{#1}{#2}{#3}% \fi} +\def\@xs@StrCount@i#1#2#3{% + \def\@xs@StrCount@ii{% + \ifx\@xs@reserved@C\@empty% on a fini de parcourir \@xs@reserved@C ? + \let\@xs@next\relax% on sort de la macro + \else + \expandafter\@xs@IfBeginWith@i\expandafter{\@xs@reserved@C}{#2}% + {\global\advance\@xs@count\@ne + \let\@xs@StrCount@afterlastocccur\@xs@reserved@A + \let\@xs@reserved@C\@xs@reserved@A}% on enlève le motif à \@xs@reserved@C + {\expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@A% \@xs@reserved@C ne commence pas par le motif : on prend la 1ere unité syntaxique + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@C% puis on l'enlève + \@xs@exploregroups + \ifx\bgroup\@xs@toks% si cette unité syntaxique est un groupe {...} + \begingroup% alors on ouvre un groupe + \expandafter\def\expandafter\@xs@reserved@C\@xs@reserved@A% \@xs@reserved@C devient l'intérieur de {...} + \@xs@StrCount@ii% on lance la macro avec ces nouvelles définitions + \endgroup + \fi}% + \let\@xs@next\@xs@StrCount@ii + \fi + \@xs@next}% + \def\@xs@reserved@C{#1}\def\@xs@StrCount@afterlastocccur{#1}% + \@xs@count\z@ + \@xs@StrCount@ii + \expandafter\@xs@ReturnResult\expandafter{\number\@xs@count}{#3}} % renvoie la position de l'occurrence #1 de la sous chaine #3 dans la chaine #2 \@xs@newmacro\StrPosition{1}{2}{1}{% - \@xs@cutafteroccur{#2}{#3}{#1}% - \ifx\@xs@beforeoccurwith\@xs@afteroccur + \@xs@cutafteroccur{#2}{#3}{#1}\@xs@reserved@C\@xs@reserved@D\@xs@reserved@E + \ifx\@xs@reserved@C\@xs@reserved@D \@xs@ReturnResult{0}{#4}% \else - \expandafter\@xs@StrLen\expandafter{\@xs@beforeoccurwithout}[\@xs@next]% - \@xs@ReturnResult{\number\numexpr\@xs@next+1}{#4}% + \ifx\@empty\@xs@exploregroups% on explore les groupes ? + \expandafter\@xs@StrLen\expandafter{\@xs@beforeoccur}[\@xs@reserved@D]% + \else + \expandafter\@xs@StrLen\expandafter{\@xs@reserved@D}[\@xs@reserved@D]% + \fi + \expandafter\@xs@ReturnResult\expandafter{\number\numexpr\@xs@reserved@D+1}{#4}% \fi} -\def\comparestrict{\let\@xs@comparecoeff\@ne} -\def\comparenormal{\let\@xs@comparecoeff\z@} +\def\comparestrict{\def\@xs@comparecoeff{1}} +\def\comparenormal{\def\@xs@comparecoeff{0}} +\def\savecomparemode{\let\@xs@saved@comparecoeff\@xs@comparecoeff} +\def\restorecomparemode{\let\@xs@comparecoeff\@xs@saved@comparecoeff} % Compare les deux arguments #1 et #2 -% Renvoie 0 s'ils sont égaux et renvoie la position -% du premier caractère différent sinon +% Renvoie 0 s'ils sont égaux et renvoie la +% position du premier token différent sinon \@xs@newmacro\StrCompare{}{2}{1}{% - \@xs@IfStrEq{#1}{#2}% - {\@xs@ReturnResult{0}{#3}}% - {\ifx\@empty\@xs@stringB - \def\@xs@next{\@xs@ReturnResult{0}{#3}}% si la plus petite chaîne est vide, on renvoie 0 - \else - \def\@xs@next{\@xs@StrCompare@i{#1}{#2}{#3}}% - \fi - \@xs@next}} -\def\@xs@StrCompare@i#1#2#3{% - \def\@xs@StrCompare@ii##1\@nil{% ##1 est la position - \ifx\@empty\@xs@stringB% il n'y a plus de caractères à tester... - \def\@xs@next{\@xs@ReturnResult{\number\numexpr##1*\@xs@comparecoeff}{#3}}% ...on a passé tous les tests : #2 *en entier* apparaît exactement au début de #1 et on renvoie donc 0 ou la position + \def\@xs@reserved@A{#1}% + \def\@xs@reserved@B{#2}% + \ifx\@xs@reserved@B\@xs@reserved@A + \@xs@ReturnResult{0}{#3}% \else - \expandafter\@xs@StrSplit@i\expandafter\@ne\expandafter{\@xs@stringA}\@xs@currentcharA\@xs@stringA - \expandafter\@xs@StrSplit@i\expandafter\@ne\expandafter{\@xs@stringB}\@xs@currentcharB\@xs@stringB - \ifx\@xs@currentcharB\@xs@currentcharA - \def\@xs@next{\expandafter\@xs@StrCompare@ii\number\numexpr##1+1\relax\@nil}% les 2 caractères sont égaux, on recommence - \else - \def\@xs@next{\@xs@ReturnResult{##1}{#3}}% les 2 caractères sont différents : on renvoie la position + \def\@xs@next{\@xs@StrCompare@i{#1}{#2}{#3}}% + \expandafter\@xs@next + \fi} + +\def\@xs@StrCompare@i#1#2#3{% + \def\@xs@StrCompare@iii##1{% + \def\@xs@next{% + \expandafter\@xs@ReturnResult\expandafter + {\number\numexpr##1\ifx\@empty\@xs@reserved@C*\@xs@comparecoeff\else\ifx\@empty\@xs@reserved@D*\@xs@comparecoeff\fi\fi\relax}{#3}}}% + \def\@xs@StrCompare@ii##1{% ##1 est la position + \expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@A + \expandafter\@xs@returnfirstsyntaxunit\expandafter{\@xs@reserved@D}\@xs@reserved@B + \ifx\@xs@reserved@B\@xs@reserved@A + \ifx\@xs@reserved@A\@empty + \@xs@StrCompare@iii{##1}% les 2 unités syntaxiques sont égales, on renvoie la position + \else + \def\@xs@next{\expandafter\@xs@StrCompare@ii\expandafter{\number\numexpr##1+1}}% les 2 unités syntaxiques sont égales et non vides, on recommence + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@C}\@xs@reserved@C + \expandafter\@xs@removefirstsyntaxunit\expandafter{\@xs@reserved@D}\@xs@reserved@D + \fi + \else% les 2 caractères sont différents : on renvoie la position + \@xs@StrCompare@iii{##1}% \fi - \fi - \@xs@next}% - \@xs@StrLen{#1}[\@xs@LenA@StrCompare]% - \@xs@StrLen{#2}[\@xs@LenB@StrCompare]% - \ifnum\@xs@LenB@StrCompare<\@xs@LenA@StrCompare\relax - \def\@xs@stringA{#1}\def\@xs@stringB{#2}% - \else - \def\@xs@stringA{#2}\def\@xs@stringB{#1}% - \fi - \@xs@StrCompare@ii1\@nil} + \@xs@next}% + \def\@xs@reserved@C{#1}\def\@xs@reserved@D{#2}% + \@xs@StrCompare@ii1} % Restaure le code de @ \catcode`\@=\CurrentAtCatcode\relax -% Définit le délimiteur verb et le développement des arguments par défaut et le mode de comparaison -\setverbdelim{|} -\fullexpandarg -\comparenormal +% Définit le délimiteur verb +% définit les différents modes et les mémorise +\setverbdelim{|}% +\fullexpandarg\saveexpandmode +\comparenormal\savecomparemode +\noexploregroups\saveexploremode \endinput % % Historique @@ -674,67 +875,71 @@ % 7/7/2008 : - Package publié sur CTAN. %------------------------------------------------------------ % v1.1 15/8/2008 -% - Le package ne nécessite plus LaTeX et est désormais -% utilisable sous Plain eTeX. +% - Le package ne nécessite plus LaTeX et est désormais utilisable sous Plain +% eTeX. % - Ajout des macros \IfInteger et \IfDecimal. -% Pour cette dernière, la partie entière et la partie -% décimale sont récupérables dans les compteurs -% \integerpart et \decimalpart. Ce qu'il reste après -% qu'un caractère non attendu soit rencontré est -% dispo dans \@xs@remainafterdecimal +% Pour cette dernière, la partie entière et la partie décimale sont +% récupérables dans les compteurs \integerpart et \decimalpart. Ce qu'il +% reste après qu'un caractère non attendu soit rencontré est dispo dans +% \@xs@remainafterdecimal % - Correction d'un bug dans \tokenize : -% suppression de l'expansion avec \normalexpandarg -% pour éviter le bug avec les lettres accentuées -% dans l'exemple : \tokenize\aa{éù} +% suppression de l'expansion avec \normalexpandarg pour éviter le bug +% avec les lettres accentuées dans l'exemple : \tokenize\aa{éù} % - Amélioration du code de la plupart des macros. -% - Écriture d'une routine \@xs@newmacro définissant les -% macros. +% - Écriture d'une routine \@xs@newmacro définissant les macros. % - Suppression de tous les compteurs grace à \numexpr. % - Nouvelles fonctionnalités internes dans : % \IfSubStr -% ajout des chaines se trouvant avant et après -% l'occurrence testée dans les sc -% \@xs@behind@IfSubStr et \@xs@before@IfSubStr +% ajout des chaines se trouvant avant et après l'occurrence testée dans +% les sc \@xs@behind@IfSubStr et \@xs@before@IfSubStr % \StrCount -% a) ajout de ce qui se trouve après la dernière -% occurrence dans la sc \@xs@after@StrCount +% a) ajout de ce qui se trouve après la dernière occurrence dans la sc% +% \@xs@StrCount@afterlastocccur % b) la macro ne dépend plus d'aucune autre %------------------------------------------------------------ % v1.2 23/8/2008 -% - Amélioration du code de \StrMid \StrGobbleLeft, -% \StrLeft, \StrGobbleRight et \StrRight à l'aide -% de la nouvelle macro \@xs@StrSplit@i +% - Amélioration du code de \StrMid \StrGobbleLeft, \StrLeft, \StrGobbleRight +% et \StrRight à l'aide de la nouvelle macro \@xs@StrSplit@i % - Nouveau test \IfStrEq qui compare 2 chaines -% - Nouveau test \IfEq qui compare 2 chaines (ou -% 2 nombres si les 2 chaines contiennent un nombre) -% - Correction d'un bug dans \@xs@formatnumber. La macro -% n'envisageait pas le cas où son argument était vide -% ce qui faiasait planter \IfDecimal{}{V}{F} et -% \IfInteger{}{V}{F} +% - Nouveau test \IfEq qui compare 2 chaines (ou 2 nombres si les 2 chaines +% contiennent un nombre) +% - Correction d'un bug dans \@xs@formatnumber. La macro n'envisageait pas le +% cas où son argument était vide ce qui faiasait planter \IfDecimal{}{V}{F} +% et \IfInteger{}{V}{F} %------------------------------------------------------------ % v1.3 21/9/2008 -% - Amélioration du code, mise en place de récursivités -% terminales dans toutes les macros récursives, -% simplification de \@xs@TestEqu@l en utilisant \ifx +% - Amélioration du code, mise en place de récursivités terminales dans toutes +% les macros récursives, simplification de \@xs@TestEqual en utilisant \ifx % - Nouvelles macros \IfStrEqCase et \IfEqCase -% Teste si une chaîne est égale à plusieurs -% chaînes donnée et exécute un code spécifique +% Teste si une chaîne est égale à plusieurs chaînes donnée et exécute un +% code spécifique % - Création de la macro publique \StrSplit % Coupe la chaine en 2 à une position donnée % - Nouvelle macro \StrCompare -% Compare 2 chaînes et renvoie la position du -% 1er caractère différent. Renvoie 0 si elles sont -% égales +% Compare 2 chaînes et renvoie la position du 1er caractère différent. +% Renvoie 0 si elles sont égales. %------------------------------------------------------------ % v1.3a 29/9/2008 % - Correction d'un bug : \expandafter#1 -% dans les macros \IfSubStrBefore et \StrBetween -% qui buggue si #1 est un nombre > 9 ! -% - Ré écriture de \@xs@firstchar et \@xs@gobblefirstchar -% qui deviennent purement développables. +% dans les macros \IfSubStrBefore et \StrBetween qui buggue si #1 est un +% nombre > 9 ! +% - Ré écriture de \@xs@returnfirstsyntaxunit et \@xs@gobblefirstchar qui +% deviennent purement développables. % - Ré écriture de \StrLen % - Nouvelle macro interne \@xs@cutafteroccur -% Coupe la chaine après la nième occurrence d'une -% sous chaine. -% - Code amélioré de \StrMid, \StrLeft, \StrGobbleLeft, -% \StrRight, \StrGobbleRight grace à \@xs@cutafteroccur
\ No newline at end of file +% Coupe la chaine après la nième occurrence d'une sous chaine. +% - Code amélioré de \StrMid, \StrLeft, \StrGobbleLeft, \StrRight, +% \StrGobbleRight grace à \@xs@cutafteroccur +%------------------------------------------------------------ +% v1.4 4/11/2008 +% - xstring traite ses arguments par unité syntaxique, et donc toutes les +% macros internes ont été ré-écrites à cette fin. +% - Le manuel a été ré-écrit, et rendu plus clair et mieux structuré. +% - Nouvelle fonctionnalité : \expandarg +% le 1er lexème de chaque argument est 1-développé avant que la macro ne +% soit appelée. Si un argument comporte plus qu'1 lexème, il faut passer +% par \scancs*[1] pour 1-développer toutes les unités syntaxiques. +% - Correction de 2 erreurs dans le manuel anglais : 0 est la valeur par +% défaut dans \StrSubstitute et \StrDel +% - Cohérence dans les nom des séquences de contrôles temporaires qui sont +% \@xs@reserved@A -> \@xs@reserved@E
\ No newline at end of file |